Uninitialized Value on Reset for Registers Holding Security Settings

Description

Uninitialized Value on Reset for Registers Holding Security Settings occurs when security-critical logic is not set to a known value upon system reset. During device startup, uninitialized registers create a window of vulnerability before security mechanisms are properly established. Registers may contain random or indeterminate values after reset if not explicitly initialized, potentially leaving the system in an insecure state until software completes initialization.

Risk

Uninitialized security registers have severe security implications. Debug interfaces may be unlocked. Protection mechanisms may be disabled. Access controls may be ineffective. Security policies may default to permissive. Authentication may be bypassed. Cryptographic functions may be compromised. Attackers can exploit the initialization window. Repeated resets may probabilistically achieve insecure states.

Solution

All registers holding security-critical information should be set to a specific secure value on reset. Conduct design checks to identify uninitialized flip-flops in security-critical functions. Use hardware reset values that default to the most secure state. Implement secure-by-default initialization. Verify reset behavior through simulation and testing. Document all security register reset values.

Common Consequences

ImpactDetails
Access ControlScope: Access Control

Bypass Protection Mechanism - Uninitialized registers may allow unauthorized access.
AuthenticationScope: Authentication

Bypass Authentication - Security checks may be bypassed before initialization.
AuthorizationScope: Authorization

Gain Privileges - Attackers may gain elevated privileges during insecure window.

Example Code

Vulnerable Code

// Vulnerable: JTAG lock without reset initialization

module vulnerable_jtag_controller (
    input wire clk,
    input wire reset_n,
    input wire jtag_tck,
    input wire jtag_tms,
    input wire jtag_tdi,
    output wire jtag_tdo,
    // Lock control
    input wire lock_command,
    output reg jtag_locked
);

    // VULNERABLE: No reset value for jtag_locked
    // After reset, jtag_locked has indeterminate value

    always @(posedge clk) begin
        if (lock_command) begin
            jtag_locked <= 1'b1;
        end
        // VULNERABLE: No reset handling
        // jtag_locked could be 0 or 1 after power-on
    end

    // VULNERABLE: Debug access depends on uninitialized register
    wire debug_allowed = !jtag_locked;

    // Attack: Attacker repeatedly resets device
    // Eventually jtag_locked powers up as 0
    // Debug interface is accessible!

endmodule

// Vulnerable: Security configuration without initialization
module vulnerable_security_config (
    input wire clk,
    input wire reset_n,
    input wire [7:0] config_addr,
    input wire [31:0] config_data,
    input wire config_write,
    output reg secure_boot_enabled,
    output reg encryption_enabled,
    output reg debug_disabled,
    output reg tamper_response_enabled
);

    // VULNERABLE: No reset initialization
    // All security settings are indeterminate after reset

    always @(posedge clk) begin
        if (config_write) begin
            case (config_addr)
                8'h00: secure_boot_enabled <= config_data[0];
                8'h01: encryption_enabled <= config_data[0];
                8'h02: debug_disabled <= config_data[0];
                8'h03: tamper_response_enabled <= config_data[0];
            endcase
        end
        // VULNERABLE: No reset clause
        // Settings are undefined until software configures them
    end

    // System operates with undefined security posture after reset
    // Until software runs initialization sequence

endmodule

// Vulnerable: Access control without reset
module vulnerable_access_control (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire [31:0] address,
    input wire access_request,
    output reg access_granted
);

    // Access permission bits - one per agent
    reg [15:0] permission_bits;

    // VULNERABLE: permission_bits not initialized on reset
    // Could be all 1s (everything permitted) or random

    always @(posedge clk) begin
        if (access_request) begin
            // VULNERABLE: Check against uninitialized permissions
            access_granted <= permission_bits[agent_id];
        end
    end

endmodule
// Vulnerable: Software relying on hardware initialization

#include <stdint.h>

#define SECURITY_CONFIG_BASE 0x40000000

typedef struct {
    volatile uint32_t secure_boot;
    volatile uint32_t encryption;
    volatile uint32_t debug_lock;
    volatile uint32_t tamper_response;
} security_config_t;

void vulnerable_boot(void) {
    security_config_t* config = (security_config_t*)SECURITY_CONFIG_BASE;

    // VULNERABLE: Assumes hardware initialized registers to secure values
    // But hardware may not have reset initialization

    if (config->secure_boot) {
        // May never be true if register is uninitialized
        verify_firmware_signature();
    }

    // VULNERABLE: Reading uninitialized register
    if (config->debug_lock == 0) {
        // Debug appears unlocked due to uninitialized register
        // Attacker can access debug interface!
        enable_debug_interface();
    }

    // System may boot in insecure state
    boot_firmware();
}

// VULNERABLE: Race condition in initialization
void vulnerable_late_initialization(void) {
    security_config_t* config = (security_config_t*)SECURITY_CONFIG_BASE;

    // VULNERABLE: Security configuration happens late in boot
    // Window of vulnerability exists from reset to here

    // ... many other initialization steps first ...

    // Finally configure security (too late!)
    config->secure_boot = 1;
    config->encryption = 1;
    config->debug_lock = 1;
    config->tamper_response = 1;
}

Fixed Code

// Fixed: JTAG lock with secure reset initialization

module secure_jtag_controller (
    input wire clk,
    input wire reset_n,
    input wire jtag_tck,
    input wire jtag_tms,
    input wire jtag_tdi,
    output wire jtag_tdo,
    input wire lock_command,
    input wire unlock_auth,      // Authenticated unlock
    output reg jtag_locked
);

    // FIXED: Explicit reset to locked state
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            // FIXED: Default to locked (secure) state on reset
            jtag_locked <= 1'b1;
        end
        else begin
            if (lock_command) begin
                jtag_locked <= 1'b1;
            end
            else if (unlock_auth) begin
                // Only unlock with proper authentication
                jtag_locked <= 1'b0;
            end
        end
    end

    // Debug only allowed when explicitly unlocked
    wire debug_allowed = !jtag_locked;

endmodule

// Fixed: Security configuration with secure defaults
module secure_security_config (
    input wire clk,
    input wire reset_n,
    input wire [7:0] config_addr,
    input wire [31:0] config_data,
    input wire config_write,
    input wire privileged_access,  // Only privileged can modify
    output reg secure_boot_enabled,
    output reg encryption_enabled,
    output reg debug_disabled,
    output reg tamper_response_enabled,
    output reg config_locked       // Prevent further changes
);

    // FIXED: All security settings initialized to secure defaults on reset
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            // FIXED: Secure defaults on reset
            secure_boot_enabled <= 1'b1;       // Secure boot ON
            encryption_enabled <= 1'b1;         // Encryption ON
            debug_disabled <= 1'b1;             // Debug OFF
            tamper_response_enabled <= 1'b1;    // Tamper response ON
            config_locked <= 1'b0;              // Allow initial config
        end
        else if (config_write && privileged_access && !config_locked) begin
            case (config_addr)
                8'h00: secure_boot_enabled <= config_data[0];
                8'h01: encryption_enabled <= config_data[0];
                8'h02: debug_disabled <= config_data[0];
                8'h03: tamper_response_enabled <= config_data[0];
                8'hFF: config_locked <= config_data[0];  // Lock config
            endcase
        end
    end

endmodule

// Fixed: Access control with secure reset
module secure_access_control (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire [31:0] address,
    input wire access_request,
    input wire privileged_config,
    input wire [15:0] new_permissions,
    output reg access_granted
);

    // Access permission bits
    reg [15:0] permission_bits;

    // FIXED: Initialize to most restrictive permissions
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            // FIXED: Default deny all except agent 0 (secure master)
            permission_bits <= 16'h0001;
            access_granted <= 1'b0;
        end
        else begin
            // Update permissions only from privileged context
            if (privileged_config) begin
                permission_bits <= new_permissions;
            end

            if (access_request) begin
                access_granted <= permission_bits[agent_id];
            end
        end
    end

endmodule

// Fixed: Comprehensive security initialization verification
module security_init_checker (
    input wire clk,
    input wire reset_n,
    input wire [31:0] security_reg_0,
    input wire [31:0] security_reg_1,
    input wire [31:0] security_reg_2,
    input wire [31:0] security_reg_3,
    output reg init_verified,
    output reg init_failed
);

    // Expected secure values after reset
    parameter EXPECTED_REG_0 = 32'h0000_0001;  // Secure boot
    parameter EXPECTED_REG_1 = 32'h0000_0001;  // Encryption
    parameter EXPECTED_REG_2 = 32'h0000_0001;  // Debug locked
    parameter EXPECTED_REG_3 = 32'h0000_0001;  // Tamper enabled

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            init_verified <= 1'b0;
            init_failed <= 1'b0;
        end
        else begin
            // FIXED: Verify security registers after reset
            if (security_reg_0 == EXPECTED_REG_0 &&
                security_reg_1 == EXPECTED_REG_1 &&
                security_reg_2 == EXPECTED_REG_2 &&
                security_reg_3 == EXPECTED_REG_3) begin
                init_verified <= 1'b1;
                init_failed <= 1'b0;
            end
            else begin
                init_verified <= 1'b0;
                init_failed <= 1'b1;
            end
        end
    end

endmodule
// Fixed: Software with proper initialization handling

#include <stdint.h>
#include <stdbool.h>

#define SECURITY_CONFIG_BASE 0x40000000

typedef struct {
    volatile uint32_t secure_boot;
    volatile uint32_t encryption;
    volatile uint32_t debug_lock;
    volatile uint32_t tamper_response;
    volatile uint32_t init_status;
} security_config_t;

// FIXED: Verify hardware initialization
bool verify_security_init(void) {
    security_config_t* config = (security_config_t*)SECURITY_CONFIG_BASE;

    // FIXED: Verify hardware initialized to secure defaults
    if (config->secure_boot != 1) {
        log_error("Secure boot not initialized");
        return false;
    }

    if (config->encryption != 1) {
        log_error("Encryption not initialized");
        return false;
    }

    if (config->debug_lock != 1) {
        log_error("Debug not locked by default");
        return false;
    }

    if (config->tamper_response != 1) {
        log_error("Tamper response not initialized");
        return false;
    }

    return true;
}

void secure_boot(void) {
    // FIXED: Verify security initialization FIRST
    if (!verify_security_init()) {
        // Hardware not properly initialized - halt
        log_error("Security initialization failed - halting");
        secure_halt();
        return;
    }

    security_config_t* config = (security_config_t*)SECURITY_CONFIG_BASE;

    // Now safe to proceed - hardware is in known secure state
    if (config->secure_boot) {
        if (!verify_firmware_signature()) {
            log_error("Firmware signature verification failed");
            secure_halt();
            return;
        }
    }

    // Proceed with boot
    boot_firmware();
}

// FIXED: Early security initialization
void __attribute__((section(".init"))) early_security_init(void) {
    security_config_t* config = (security_config_t*)SECURITY_CONFIG_BASE;

    // FIXED: Set secure defaults immediately at boot
    // Even before C runtime initialization

    config->secure_boot = 1;
    config->encryption = 1;
    config->debug_lock = 1;
    config->tamper_response = 1;

    // Memory barrier to ensure writes complete
    __asm__ volatile("dmb sy" ::: "memory");

    // Verify writes took effect
    if (config->debug_lock != 1) {
        // Failed to lock - halt
        while(1) { __asm__ volatile("wfi"); }
    }
}

CVE Examples

Register initialization vulnerabilities have been found in various hardware designs where security registers powered up in indeterminate states, allowing attackers to repeatedly reset devices until achieving an insecure configuration.


  • CWE-909: Missing Initialization of Resource (parent)
  • CWE-1206: Power, Clock, Thermal, and Reset Concerns (category)
  • CWE-1304: Improperly Preserved Integrity of Hardware Configuration State (related)
  • CAPEC-74: Manipulating State (attack pattern)

References

  1. MITRE Corporation. "CWE-1271: Uninitialized Value on Reset for Registers Holding Security Settings." https://cwe.mitre.org/data/definitions/1271.html
  2. ARM. "TrustZone Security Extensions Reset Behavior"
  3. Intel. "Platform Security Best Practices"