Semiconductor Defects in Hardware Logic with Security-Sensitive Implications

Description

Semiconductor Defects in Hardware Logic with Security-Sensitive Implications occurs when security-sensitive hardware modules contain semiconductor defects. Semiconductors can fail through various mechanisms including manufacturing/packaging defects and degradation from prolonged use or extreme conditions. Specific failure mechanisms include encapsulation failure, die-attach failure, wire-bond failure, bulk-silicon defects, oxide-layer faults, and aluminum-metal faults including electromigration and corrosion. These defects manifest as faults where chip-internal signals or registers remain stuck at 0 or 1 and fail to switch as expected.

Risk

Semiconductor defects in security hardware have severe implications. Access control logic may fail open. Security checks may be bypassed due to stuck signals. Cryptographic operations may produce wrong results. Authentication logic may malfunction. Security state machines may not function correctly. Protection mechanisms may fail silently. Denial of service may occur. Trust anchors may be compromised.

Solution

Implement post-manufacturing silicon testing using fault models like stuck-at-0 or stuck-at-1 to achieve good test coverage. Operate hardware within specifications to avoid accelerated degradation from extreme temperatures or voltage. Use redundant logic for security-critical functions. Implement runtime fault detection. Design for fail-secure behavior. Monitor security hardware health. Use burn-in testing to detect early failures.

Common Consequences

ImpactDetails
Availability, Access ControlScope: Availability, Access Control

DoS: Instability, Bypass Protection Mechanism - If faults occur in security-sensitive hardware modules, security objectives may be compromised, leading to denial of service or protection bypass.

Example Code

Vulnerable Code

// Vulnerable: Firewall without defect detection

module vulnerable_noc_firewall (
    input wire clk,
    input wire reset_n,
    input wire [31:0] source_id,
    input wire [31:0] dest_addr,
    input wire [3:0] access_type,
    output reg access_allowed
);

    // Access control rules
    parameter SECURE_REGION_START = 32'h8000_0000;
    parameter SECURE_REGION_END = 32'h8FFF_FFFF;
    parameter TRUSTED_SOURCE_ID = 32'h0000_0001;

    // VULNERABLE: No detection of stuck-at faults
    wire is_secure_region = (dest_addr >= SECURE_REGION_START) &&
                            (dest_addr <= SECURE_REGION_END);
    wire is_trusted_source = (source_id == TRUSTED_SOURCE_ID);

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_allowed <= 1'b0;
        end
        else begin
            if (is_secure_region) begin
                // VULNERABLE: If is_trusted_source stuck at 1, all access allowed
                access_allowed <= is_trusted_source;
            end else begin
                access_allowed <= 1'b1;
            end
        end
    end

    // Manufacturing defect: is_trusted_source signal stuck at 1
    // Result: All sources appear trusted, security bypassed

endmodule

// Vulnerable: Security comparator without fault detection
module vulnerable_key_comparator (
    input wire clk,
    input wire [127:0] input_key,
    input wire [127:0] stored_key,
    output reg key_match
);

    // VULNERABLE: Single comparison, no defect detection
    always @(posedge clk) begin
        key_match <= (input_key == stored_key);
    end

    // Defect: If key_match signal stuck at 1, any key accepted

endmodule

// Vulnerable: Access control with no redundancy
module vulnerable_access_controller (
    input wire clk,
    input wire reset_n,
    input wire request_access,
    input wire [7:0] privilege_level,
    input wire [7:0] required_level,
    output reg access_granted
);

    // VULNERABLE: Single privilege check
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_granted <= 1'b0;
        end
        else if (request_access) begin
            // VULNERABLE: If privilege_level[7] stuck at 1, always max privilege
            access_granted <= (privilege_level >= required_level);
        end
    end

endmodule
// Vulnerable: Firmware assuming correct hardware behavior

void vulnerable_security_check(void) {
    // Reads from security hardware
    uint32_t security_status = read_security_register();

    // VULNERABLE: Assumes hardware is functioning correctly
    // If register stuck at 0x00000001 (security OK), check always passes
    if (security_status == SECURITY_OK) {
        allow_operation();
    } else {
        deny_operation();
    }
}

// Vulnerable: No health check of security hardware
void vulnerable_init(void) {
    // Initialize security hardware
    init_security_module();

    // VULNERABLE: No verification that hardware is functioning correctly
    // A stuck-at fault in the security module would go undetected

    continue_boot();
}

Fixed Code

// Fixed: Firewall with defect detection

module secure_noc_firewall (
    input wire clk,
    input wire reset_n,
    input wire [31:0] source_id,
    input wire [31:0] dest_addr,
    input wire [3:0] access_type,
    output reg access_allowed,
    output reg fault_detected
);

    parameter SECURE_REGION_START = 32'h8000_0000;
    parameter SECURE_REGION_END = 32'h8FFF_FFFF;
    parameter TRUSTED_SOURCE_ID = 32'h0000_0001;

    // FIXED: Redundant logic with different implementations
    wire is_secure_region_a = (dest_addr >= SECURE_REGION_START) &&
                              (dest_addr <= SECURE_REGION_END);
    wire is_secure_region_b = (dest_addr[31:28] == 4'h8);  // Different check

    wire is_trusted_source_a = (source_id == TRUSTED_SOURCE_ID);
    wire is_trusted_source_b = (source_id[31:0] == 32'h0000_0001);  // Explicit

    // FIXED: Detect stuck-at faults through comparison
    wire region_check_consistent = (is_secure_region_a == is_secure_region_b);
    wire source_check_consistent = (is_trusted_source_a == is_trusted_source_b);

    // FIXED: Built-in self-test pattern
    reg [31:0] test_counter;
    reg in_self_test;
    wire test_pass;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_allowed <= 1'b0;
            fault_detected <= 1'b0;
            test_counter <= 32'h0;
            in_self_test <= 1'b1;
        end
        else if (in_self_test) begin
            // FIXED: Periodic self-test
            test_counter <= test_counter + 1;
            if (test_counter == 32'hFFFF) begin
                in_self_test <= 1'b0;
                // Verify test results
                if (!test_pass) begin
                    fault_detected <= 1'b1;
                end
            end
        end
        else begin
            // Check for inconsistencies (indicates fault)
            if (!region_check_consistent || !source_check_consistent) begin
                fault_detected <= 1'b1;
                access_allowed <= 1'b0;  // Fail secure
            end
            else if (is_secure_region_a) begin
                // Both redundant checks must agree
                access_allowed <= is_trusted_source_a && is_trusted_source_b;
            end else begin
                access_allowed <= 1'b1;
            end
        end
    end

endmodule

// Fixed: Security comparator with fault detection
module secure_key_comparator (
    input wire clk,
    input wire reset_n,
    input wire [127:0] input_key,
    input wire [127:0] stored_key,
    input wire compare_enable,
    output reg key_match,
    output reg fault_detected
);

    // FIXED: Multiple comparison methods
    wire match_method_a = (input_key == stored_key);
    wire match_method_b = ((input_key ^ stored_key) == 128'h0);

    // FIXED: XOR result for stuck-at detection
    wire [127:0] xor_result = input_key ^ stored_key;
    wire all_zero = (xor_result == 128'h0);

    // Counter for detecting stuck signals
    reg [7:0] match_history;
    reg [7:0] mismatch_history;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            key_match <= 1'b0;
            fault_detected <= 1'b0;
            match_history <= 8'h0;
            mismatch_history <= 8'h0;
        end
        else if (compare_enable) begin
            // FIXED: Both methods must agree
            if (match_method_a == match_method_b) begin
                key_match <= match_method_a && all_zero;
            end else begin
                // Inconsistency = fault
                fault_detected <= 1'b1;
                key_match <= 1'b0;
            end

            // FIXED: Track history to detect stuck-at
            if (match_method_a) begin
                match_history <= {match_history[6:0], 1'b1};
            end else begin
                mismatch_history <= {mismatch_history[6:0], 1'b1};
            end

            // Detect if always matching (stuck at 1)
            if (match_history == 8'hFF) begin
                fault_detected <= 1'b1;
            end
        end
    end

endmodule

// Fixed: Access controller with redundancy
module secure_access_controller (
    input wire clk,
    input wire reset_n,
    input wire request_access,
    input wire [7:0] privilege_level,
    input wire [7:0] required_level,
    input wire [7:0] privilege_level_shadow,  // Redundant copy
    output reg access_granted,
    output reg fault_detected
);

    // FIXED: Compare primary and shadow privilege levels
    wire privilege_consistent = (privilege_level == privilege_level_shadow);

    // FIXED: Two different comparison methods
    wire check_a = (privilege_level >= required_level);
    wire check_b = ((privilege_level - required_level) < 8'h80);  // No underflow = pass

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_granted <= 1'b0;
            fault_detected <= 1'b0;
        end
        else if (request_access) begin
            // FIXED: Check for inconsistencies
            if (!privilege_consistent) begin
                fault_detected <= 1'b1;
                access_granted <= 1'b0;  // Fail secure
            end
            else if (check_a != check_b) begin
                // Comparison methods disagree = fault
                fault_detected <= 1'b1;
                access_granted <= 1'b0;
            end
            else begin
                access_granted <= check_a && check_b;
            end
        end
    end

endmodule
// Fixed: Firmware with hardware health verification

void secure_security_check(void) {
    // FIXED: Verify hardware is functioning before trusting it
    if (!verify_security_hardware_health()) {
        security_failure_handler();
        return;
    }

    uint32_t security_status = read_security_register();

    // FIXED: Read multiple times and compare
    uint32_t status_2 = read_security_register();
    uint32_t status_3 = read_security_register();

    if (security_status != status_2 || status_2 != status_3) {
        // Inconsistent reads = possible fault
        security_failure_handler();
        return;
    }

    if (security_status == SECURITY_OK) {
        allow_operation();
    } else {
        deny_operation();
    }
}

// Fixed: Hardware health verification
bool verify_security_hardware_health(void) {
    // Run built-in self-test
    if (!run_security_bist()) {
        return false;
    }

    // Test with known patterns
    write_test_register(TEST_PATTERN_A);
    if (read_test_register() != TEST_PATTERN_A) {
        return false;  // Stuck-at fault detected
    }

    write_test_register(TEST_PATTERN_B);
    if (read_test_register() != TEST_PATTERN_B) {
        return false;
    }

    // Test all bits toggle
    write_test_register(0x55555555);
    if (read_test_register() != 0x55555555) {
        return false;
    }

    write_test_register(0xAAAAAAAA);
    if (read_test_register() != 0xAAAAAAAA) {
        return false;
    }

    return true;
}

// Periodic health check during operation
void periodic_health_check(void) {
    static uint32_t check_counter = 0;

    check_counter++;
    if (check_counter >= HEALTH_CHECK_INTERVAL) {
        check_counter = 0;

        if (!verify_security_hardware_health()) {
            log_error("Security hardware fault detected!");
            enter_safe_mode();
        }
    }
}

CVE Examples

Semiconductor defects in security hardware have been identified in various chips where manufacturing defects or aging caused security logic to malfunction.


  • CWE-693: Protection Mechanism Failure (parent)
  • CWE-1195: Manufacturing and Life Cycle Management Concerns (category member)
  • CWE-1206: Power, Clock, Thermal, and Reset Concerns (category member)
  • CWE-1388: Physical Access Issues and Concerns (category member)

References

  1. MITRE Corporation. "CWE-1248: Semiconductor Defects in Hardware Logic with Security-Sensitive Implications." https://cwe.mitre.org/data/definitions/1248.html
  2. Bailey, Brian. "Why Chips Die."
  3. Lakshminarayan, V. "What Causes Semiconductor Devices to Fail"
  4. CAPEC-624: Hardware Fault Injection