Improper Protection Against Voltage and Clock Glitches
Description
Improper Protection Against Voltage and Clock Glitches occurs when a device lacks appropriate circuitry or sensors to detect and mitigate voltage and clock glitches that could compromise sensitive information or software. Devices implementing security features like secure boot establish a chain of trust through signature verification before executing subsequent stages. Hardware and firmware work together to configure secure states via access control settings. However, without proper defenses, attackers can exploit fault-injection techniques—specifically voltage and clock glitches—to bypass these security measures.
Risk
Vulnerability to glitch attacks has severe security implications. Secure boot may be bypassable. Signature verification may be defeated. Access control decisions may be corrupted. Cryptographic operations may produce wrong results. Security state machines may skip states. Debug locks may be bypassed. Privilege escalation may be possible. Arbitrary code execution may be achieved.
Solution
Implement Tunable Replica Circuits (TRCs) or Razor flip-flops to detect timing violations. Deploy platform-level glitch detection sensors. Add redundancy to security-critical code sections. Implement double-checking of security decisions. Use error-detecting codes for critical data. Add voltage and clock monitors. Design security checks to be glitch-resistant. Consider hardware security modules for critical operations.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality, Integrity, Availability, Access Control | Scope: All Multiple impacts including privilege escalation, protection mechanism bypass, unauthorized memory access, and arbitrary code execution. |
Example Code
Vulnerable Code
// Vulnerable: Single security check easily bypassed by glitch
bool verify_firmware_signature(const uint8_t* firmware, size_t size,
const uint8_t* signature) {
// VULNERABLE: Single point of failure for glitch attack
bool valid = crypto_verify_signature(firmware, size, signature, public_key);
if (valid) { // <-- GLITCH TARGET: Skip this check
return true;
} else {
return false;
}
}
void vulnerable_secure_boot(void) {
load_firmware_to_memory();
// VULNERABLE: Single signature check
if (verify_firmware_signature(firmware, fw_size, fw_signature)) {
// Attacker glitches here to skip verification
execute_firmware();
} else {
halt_boot();
}
}
// Vulnerable: Security decision based on single comparison
void vulnerable_password_check(const char* input) {
// VULNERABLE: Single comparison, glitch can bypass
if (strcmp(input, stored_password) == 0) { // <-- GLITCH TARGET
grant_access();
} else {
deny_access();
}
}
// Vulnerable: Security flag easily corrupted
volatile bool security_enabled = true;
void vulnerable_security_gate(void) {
// VULNERABLE: Single flag check
if (security_enabled) { // <-- GLITCH can corrupt this read
enforce_security_policy();
}
// If glitch causes security_enabled to read as false, security bypassed
}
// Vulnerable: Security state machine without glitch protection
module vulnerable_secure_boot_fsm (
input wire clk,
input wire reset_n,
input wire signature_valid,
output reg boot_authorized,
output reg [2:0] boot_state
);
parameter IDLE = 3'h0;
parameter VERIFY = 3'h1;
parameter AUTHORIZED = 3'h2;
parameter DENIED = 3'h3;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_state <= IDLE;
boot_authorized <= 1'b0;
end
else begin
case (boot_state)
IDLE: begin
boot_state <= VERIFY;
end
VERIFY: begin
// VULNERABLE: Single check, no redundancy
if (signature_valid) begin // <-- GLITCH TARGET
boot_state <= AUTHORIZED;
boot_authorized <= 1'b1;
end else begin
boot_state <= DENIED;
end
end
AUTHORIZED: begin
// Boot proceeds
end
DENIED: begin
// Boot halted
end
endcase
end
end
endmodule
// Vulnerable: No voltage/clock glitch detection
module vulnerable_crypto_core (
input wire clk,
input wire reset_n,
input wire [127:0] data_in,
input wire [127:0] key,
output reg [127:0] data_out
);
// VULNERABLE: No glitch detection
// Glitch during crypto operation can produce wrong/weak output
always @(posedge clk) begin
data_out <= aes_encrypt(data_in, key);
// If clock glitched, encryption may be incomplete/wrong
end
endmodule
Fixed Code
// Fixed: Redundant security checks resist glitch attacks
bool verify_firmware_signature_secure(const uint8_t* firmware, size_t size,
const uint8_t* signature) {
// FIXED: Multiple independent verification passes
volatile bool valid1 = crypto_verify_signature(firmware, size, signature, public_key);
// Add timing jitter to make glitch timing harder
random_delay();
volatile bool valid2 = crypto_verify_signature(firmware, size, signature, public_key);
// Different verification method
volatile bool valid3 = crypto_verify_signature_alt(firmware, size, signature, public_key);
// FIXED: All three must agree
if (valid1 && valid2 && valid3) {
// Triple-check the decision
if (valid1 == true && valid2 == true && valid3 == true) {
return true;
}
}
return false;
}
void secure_boot_with_redundancy(void) {
load_firmware_to_memory();
// FIXED: Multiple verification with different timing
volatile int verify_count = 0;
for (int i = 0; i < 3; i++) {
random_delay(); // Variable timing
if (verify_firmware_signature(firmware, fw_size, fw_signature)) {
verify_count++;
}
}
// FIXED: Require all verifications to pass
if (verify_count == 3) {
// Final check before execution
if (verify_count == 3) {
execute_firmware();
}
} else {
halt_boot();
}
}
// Fixed: Glitch-resistant comparison
bool secure_compare(const char* a, const char* b, size_t len) {
volatile uint8_t result = 0;
volatile uint8_t result2 = 0;
// First pass
for (size_t i = 0; i < len; i++) {
result |= a[i] ^ b[i];
}
random_delay();
// Second pass (different direction)
for (size_t i = len; i > 0; i--) {
result2 |= a[i-1] ^ b[i-1];
}
// Both must indicate match
return (result == 0) && (result2 == 0) && (result == result2);
}
// Fixed: Security flag with redundancy
volatile bool security_enabled_1 = true;
volatile bool security_enabled_2 = true;
volatile uint32_t security_checksum = SECURITY_ENABLED_CHECKSUM;
void secure_security_gate(void) {
// FIXED: Multiple flags and checksum
bool flag1 = security_enabled_1;
bool flag2 = security_enabled_2;
bool checksum_valid = (security_checksum == SECURITY_ENABLED_CHECKSUM);
// All three must agree
if (flag1 && flag2 && checksum_valid) {
if (flag1 == flag2) {
enforce_security_policy();
}
} else {
// Inconsistency detected - possible attack
security_violation_handler();
}
}
// Fixed: Security state machine with glitch detection
module secure_boot_fsm (
input wire clk,
input wire reset_n,
input wire signature_valid,
input wire voltage_glitch_detected,
input wire clock_glitch_detected,
output reg boot_authorized,
output reg [2:0] boot_state,
output reg security_violation
);
parameter IDLE = 3'h0;
parameter VERIFY_1 = 3'h1;
parameter VERIFY_2 = 3'h2;
parameter VERIFY_3 = 3'h3;
parameter AUTHORIZED = 3'h4;
parameter DENIED = 3'h5;
reg [2:0] verify_count;
reg [2:0] verify_pass_count;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_state <= IDLE;
boot_authorized <= 1'b0;
security_violation <= 1'b0;
verify_count <= 3'h0;
verify_pass_count <= 3'h0;
end
// FIXED: Check for glitch attacks
else if (voltage_glitch_detected || clock_glitch_detected) begin
boot_state <= DENIED;
security_violation <= 1'b1;
boot_authorized <= 1'b0;
end
else begin
case (boot_state)
IDLE: begin
boot_state <= VERIFY_1;
verify_count <= 3'h0;
verify_pass_count <= 3'h0;
end
VERIFY_1: begin
// FIXED: First verification
if (signature_valid) verify_pass_count <= verify_pass_count + 1;
boot_state <= VERIFY_2;
end
VERIFY_2: begin
// FIXED: Second verification (different timing)
if (signature_valid) verify_pass_count <= verify_pass_count + 1;
boot_state <= VERIFY_3;
end
VERIFY_3: begin
// FIXED: Third verification
if (signature_valid) verify_pass_count <= verify_pass_count + 1;
// FIXED: All three verifications must pass
if (verify_pass_count == 3'd2 && signature_valid) begin
boot_state <= AUTHORIZED;
boot_authorized <= 1'b1;
end else begin
boot_state <= DENIED;
end
end
AUTHORIZED: begin
// Continue monitoring for glitches
if (voltage_glitch_detected || clock_glitch_detected) begin
boot_authorized <= 1'b0;
security_violation <= 1'b1;
end
end
DENIED: begin
boot_authorized <= 1'b0;
end
endcase
end
end
endmodule
// Fixed: Glitch detection circuitry
module glitch_detector (
input wire clk,
input wire reset_n,
input wire voltage_sense,
input wire clock_in,
output reg voltage_glitch,
output reg clock_glitch
);
// Voltage glitch detection using window comparator
reg [7:0] voltage_history;
parameter VOLTAGE_MIN = 8'd100;
parameter VOLTAGE_MAX = 8'd200;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
voltage_glitch <= 1'b0;
end
else begin
// Detect voltage outside normal range
if (voltage_sense < VOLTAGE_MIN || voltage_sense > VOLTAGE_MAX) begin
voltage_glitch <= 1'b1;
end
end
end
// Clock glitch detection using Razor flip-flop concept
reg clock_sample_1, clock_sample_2;
reg clock_edge_count;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
clock_glitch <= 1'b0;
clock_sample_1 <= 1'b0;
clock_sample_2 <= 1'b0;
end
else begin
clock_sample_1 <= clock_in;
clock_sample_2 <= clock_sample_1;
// Detect unexpected clock edges
if (clock_sample_1 != clock_sample_2) begin
clock_edge_count <= clock_edge_count + 1;
if (clock_edge_count > expected_edges) begin
clock_glitch <= 1'b1;
end
end
end
end
endmodule
CVE Examples
- CVE-2019-17391: Secure boot bypass via lack of anti-glitch protection
- CVE-2021-33478: Boot shell access through impulse attacks
- Plundervolt and CLKSCREW attacks exploiting DVFS interfaces
Related CWEs
- CWE-1384: Improper Handling of Physical or Environmental Conditions (parent)
- CWE-1332: Improper Handling of Faults that Lead to Instruction Skips (peer)
- CWE-1256: Privileged Access to Power Management Features (related)
References
- MITRE Corporation. "CWE-1247: Improper Protection Against Voltage and Clock Glitches." https://cwe.mitre.org/data/definitions/1247.html
- Plundervolt Attack Research
- CLKSCREW: Exploiting DVFS for Security Bypass