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
| Impact | Details |
|---|---|
| Access Control | Scope: Access Control Bypass Protection Mechanism - Uninitialized registers may allow unauthorized access. |
| Authentication | Scope: Authentication Bypass Authentication - Security checks may be bypassed before initialization. |
| Authorization | Scope: 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.
Related CWEs
- 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
- MITRE Corporation. "CWE-1271: Uninitialized Value on Reset for Registers Holding Security Settings." https://cwe.mitre.org/data/definitions/1271.html
- ARM. "TrustZone Security Extensions Reset Behavior"
- Intel. "Platform Security Best Practices"