Incorrect Selection of Fuse Values
Description
Incorrect Selection of Fuse Values occurs when a product relies on an unblown fuse to establish a secure system state. Since fuses default to logic 0 (unblown) and can be blown to logic 1 but not easily reset, using negative logic creates a vulnerability. Fuses store security configuration data and are directional—once blown to 1, they cannot return to 0 without specialized equipment. The weakness emerges when system security logic depends on fuses remaining unblown, allowing attackers to blow fuses and transition the system into an insecure state.
Risk
Incorrect fuse logic has severe security implications. Secure boot may be disabled by blowing fuses. Debug interfaces may be re-enabled. Security features may be bypassed. JTAG access may be unlocked. Firmware signature verification may be skipped. Production security may be compromised. Device integrity may be permanently damaged. Attackers gain persistent access through hardware modification.
Solution
Design logic so that blown fuses do not transition the product into an exploitable insecure state. Use positive logic where security is maintained or increased when fuses are blown. Ensure default (unblown) state is the less secure state. Make blown fuses enable security features rather than disable them. Implement redundant fuse checks. Add tamper detection for fuse manipulation. Use fuse redundancy with majority voting.
Common Consequences
| Impact | Details |
|---|---|
| Access Control | Scope: Access Control Bypass Protection Mechanism - If security logic uses negative logic, an attacker might blow the fuse and drive the system to an insecure state. |
| Availability | Scope: Availability DoS: Crash, Exit, or Restart - Fuse manipulation may cause system instability. |
| Confidentiality | Scope: Confidentiality Unauthorized Memory Access - Bypassing security allows access to protected data. |
| Integrity | Scope: Integrity Memory Modification or Unauthorized Code Execution - Security bypass allows running unauthorized code. |
Example Code
Vulnerable Code
// Vulnerable: Negative logic fuse for secure boot
module vulnerable_secure_boot_fuse (
input wire clk,
input wire reset_n,
input wire fuse_secure_boot, // 0 = secure boot ON, 1 = secure boot OFF
input wire firmware_signature_valid,
output reg boot_allowed
);
// VULNERABLE: Negative logic
// Fuse defaults to 0 (unblown) = secure boot enabled
// Attacker can blow fuse to 1 = secure boot disabled
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_allowed <= 1'b0;
end
else begin
// VULNERABLE: Check fuse with negative logic
if (fuse_secure_boot == 1'b0) begin
// Fuse not blown - require signature verification
boot_allowed <= firmware_signature_valid;
end
else begin
// VULNERABLE: Fuse blown - skip verification!
// Attacker blows fuse to bypass secure boot
boot_allowed <= 1'b1;
end
end
end
endmodule
// Vulnerable: Debug lock with negative logic
module vulnerable_debug_fuse (
input wire clk,
input wire reset_n,
input wire fuse_debug_lock, // 0 = debug locked, 1 = debug unlocked
input wire debug_request,
output reg debug_allowed
);
// VULNERABLE: Negative logic for debug lock
// Fuse defaults to 0 = debug locked
// Attacker blows fuse to 1 = debug unlocked
always @(*) begin
if (fuse_debug_lock == 1'b0) begin
// Fuse not blown - debug locked
debug_allowed = 1'b0;
end
else begin
// VULNERABLE: Fuse blown - debug unlocked!
debug_allowed = debug_request;
end
end
endmodule
// Vulnerable: Security level fuse with wrong default
module vulnerable_security_level_fuse (
input wire clk,
input wire reset_n,
input wire [1:0] fuse_security_level, // 00 = highest, 11 = lowest
input wire [1:0] required_level,
output reg access_allowed
);
// VULNERABLE: Unblown fuses (00) = highest security
// Attacker can blow fuses to reduce security level
always @(*) begin
// Lower number = higher security
// VULNERABLE: Blowing fuses lowers security
if (fuse_security_level <= required_level) begin
access_allowed = 1'b1;
end
else begin
access_allowed = 1'b0;
end
end
// Attack: Blow both fuses to get level 11 (lowest)
// This grants access to everything
endmodule
// Vulnerable: Firmware reading fuse with negative logic
#define FUSE_REGISTER 0x40000000
#define FUSE_SECURE_BOOT_BIT 0
uint32_t read_fuse(void) {
return *(volatile uint32_t*)FUSE_REGISTER;
}
void vulnerable_boot_check(void) {
uint32_t fuses = read_fuse();
// VULNERABLE: Negative logic
// Bit 0 = 0 means secure boot enabled
// Bit 0 = 1 means secure boot disabled
if ((fuses & (1 << FUSE_SECURE_BOOT_BIT)) == 0) {
// Fuse not blown - perform secure boot
if (!verify_firmware_signature()) {
halt_boot("Signature verification failed");
}
}
else {
// VULNERABLE: Fuse blown - skip verification
// Attacker can blow this fuse to load unsigned firmware
}
continue_boot();
}
// Vulnerable: Debug enable fuse
void vulnerable_debug_init(void) {
uint32_t fuses = read_fuse();
// VULNERABLE: Fuse bit 1 = 0 means debug disabled
// Fuse bit 1 = 1 means debug enabled
if (fuses & (1 << 1)) {
// VULNERABLE: Blown fuse enables debug!
enable_jtag();
enable_uart_debug();
}
}
Fixed Code
// Fixed: Positive logic fuse for secure boot
module secure_boot_fuse (
input wire clk,
input wire reset_n,
input wire fuse_secure_boot, // 0 = dev mode, 1 = production secure
input wire firmware_signature_valid,
output reg boot_allowed
);
// FIXED: Positive logic
// Fuse defaults to 0 (unblown) = development mode (less secure)
// Fuse blown to 1 = production mode (secure boot required)
// Attacker cannot un-blow fuse to disable security
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_allowed <= 1'b0;
end
else begin
// FIXED: Positive logic - blown fuse enforces security
if (fuse_secure_boot == 1'b1) begin
// Production mode - require signature verification
boot_allowed <= firmware_signature_valid;
end
else begin
// Development mode - may allow unsigned for dev
// But this is the DEFAULT state, not attackable
boot_allowed <= 1'b1; // Or still require signature
end
end
end
endmodule
// Fixed: Debug lock with positive logic
module secure_debug_fuse (
input wire clk,
input wire reset_n,
input wire fuse_debug_disable, // 0 = debug available, 1 = debug locked
input wire debug_request,
output reg debug_allowed
);
// FIXED: Positive logic for debug lock
// Fuse defaults to 0 = debug available (development)
// Fuse blown to 1 = debug permanently locked (production)
// Attacker cannot un-blow fuse to re-enable debug
always @(*) begin
if (fuse_debug_disable == 1'b1) begin
// FIXED: Blown fuse = debug locked forever
debug_allowed = 1'b0;
end
else begin
// Unblown = debug available (dev mode default)
debug_allowed = debug_request;
end
end
endmodule
// Fixed: Security level fuse with correct encoding
module secure_security_level_fuse (
input wire clk,
input wire reset_n,
input wire [1:0] fuse_security_level, // 00 = lowest, 11 = highest
input wire [1:0] required_level,
output reg access_allowed
);
// FIXED: Unblown fuses (00) = lowest security (dev default)
// Blowing fuses INCREASES security level
// Attacker cannot increase their access by blowing fuses
always @(*) begin
// FIXED: Higher fuse value = higher security
// Blowing fuses can only restrict access, not grant it
if (fuse_security_level >= required_level) begin
access_allowed = 1'b1;
end
else begin
access_allowed = 1'b0;
end
end
// Attack attempt: Blowing fuses increases security level
// This only makes access MORE restricted, not less
endmodule
// Fixed: Redundant fuse checking
module secure_redundant_fuse (
input wire clk,
input wire reset_n,
input wire fuse_secure_a, // Primary secure boot fuse
input wire fuse_secure_b, // Redundant secure boot fuse
input wire fuse_secure_c, // Second redundant fuse
input wire firmware_signature_valid,
output reg boot_allowed,
output reg tamper_detected
);
// FIXED: Use redundant fuses with majority voting
wire [1:0] secure_vote;
assign secure_vote = fuse_secure_a + fuse_secure_b + fuse_secure_c;
// FIXED: Detect tampering (fuses should match)
wire fuses_consistent;
assign fuses_consistent = (fuse_secure_a == fuse_secure_b) &&
(fuse_secure_b == fuse_secure_c);
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
boot_allowed <= 1'b0;
tamper_detected <= 1'b0;
end
else begin
// FIXED: Check for inconsistent fuses (tampering)
if (!fuses_consistent) begin
tamper_detected <= 1'b1;
boot_allowed <= 1'b0; // Fail secure
end
// FIXED: Majority voting (at least 2 of 3)
else if (secure_vote >= 2'd2) begin
// Production mode - require signature
boot_allowed <= firmware_signature_valid;
end
else begin
// Development mode
boot_allowed <= 1'b1;
end
end
end
endmodule
// Fixed: Firmware reading fuse with positive logic
#define FUSE_REGISTER 0x40000000
#define FUSE_PRODUCTION_MODE_BIT 0
#define FUSE_DEBUG_LOCKED_BIT 1
uint32_t read_fuse(void) {
return *(volatile uint32_t*)FUSE_REGISTER;
}
void secure_boot_check(void) {
uint32_t fuses = read_fuse();
// FIXED: Positive logic
// Bit 0 = 0 means development mode (default)
// Bit 0 = 1 means production mode (secure boot enforced)
if (fuses & (1 << FUSE_PRODUCTION_MODE_BIT)) {
// FIXED: Blown fuse = must verify signature
if (!verify_firmware_signature()) {
halt_boot("Signature verification failed");
}
}
else {
// Development mode - may log warning
log_warning("Running in development mode without signature check");
// Even in dev mode, signature verification is recommended
}
continue_boot();
}
// Fixed: Debug disable fuse
void secure_debug_init(void) {
uint32_t fuses = read_fuse();
// FIXED: Fuse bit 1 = 0 means debug available (dev default)
// Fuse bit 1 = 1 means debug permanently disabled (production)
if (fuses & (1 << FUSE_DEBUG_LOCKED_BIT)) {
// FIXED: Blown fuse = debug locked forever
disable_jtag();
disable_uart_debug();
log_info("Debug interfaces permanently disabled");
}
else {
// Development mode - debug available
enable_jtag();
enable_uart_debug();
log_warning("Debug interfaces enabled - development mode");
}
}
// Fixed: Redundant fuse check
void secure_boot_redundant(void) {
uint32_t fuses = read_fuse();
// Read three redundant fuse bits
int fuse_a = (fuses >> 0) & 1;
int fuse_b = (fuses >> 1) & 1;
int fuse_c = (fuses >> 2) & 1;
// FIXED: Check for tampering (inconsistent fuses)
if (fuse_a != fuse_b || fuse_b != fuse_c) {
halt_boot("Fuse tampering detected!");
}
// FIXED: Majority voting
int production_mode = (fuse_a + fuse_b + fuse_c) >= 2;
if (production_mode) {
if (!verify_firmware_signature()) {
halt_boot("Signature verification failed");
}
}
}
CVE Examples
Fuse logic vulnerabilities have been found in various devices where attackers could blow fuses to disable secure boot, re-enable debug interfaces, or bypass security features. Examples include devices where blowing a single fuse could disable signature verification.
Related CWEs
- CWE-693: Protection Mechanism Failure (parent)
- CWE-1278: Missing Protection Against Hardware Reverse Engineering (related)
- CWE-1338: Improper Protections Against Hardware Overwriting of Security-Configured Fuses (related)
References
- MITRE Corporation. "CWE-1253: Incorrect Selection of Fuse Values." https://cwe.mitre.org/data/definitions/1253.html
- ARM. "TrustZone Security" - Fuse-based Configuration
- NXP. "Secure Boot Architecture" - OTP Fuse Programming