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

ImpactDetails
Access ControlScope: 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.
AvailabilityScope: Availability

DoS: Crash, Exit, or Restart - Fuse manipulation may cause system instability.
ConfidentialityScope: Confidentiality

Unauthorized Memory Access - Bypassing security allows access to protected data.
IntegrityScope: 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.


  • 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

  1. MITRE Corporation. "CWE-1253: Incorrect Selection of Fuse Values." https://cwe.mitre.org/data/definitions/1253.html
  2. ARM. "TrustZone Security" - Fuse-based Configuration
  3. NXP. "Secure Boot Architecture" - OTP Fuse Programming