Improperly Preserved Integrity of Hardware Configuration State During a Power Save/Restore Operation
Description
Improperly Preserved Integrity of Hardware Configuration State During a Power Save/Restore Operation occurs when a product performs a power save/restore operation but does not ensure that the integrity of the configuration state is maintained and/or verified between the beginning and ending of the operation. During power-down operations, hardware IP saves its state to persistent storage like flash memory. The vulnerability occurs when attackers with storage access modify this saved configuration to compromise privileges, disable protections, or damage hardware. Without validation upon restoration, the system activates potentially harmful configurations.
Risk
Improper state preservation has severe implications. Denial of service through corrupted state. Privilege escalation via modified configuration. Protection mechanisms disabled. Execution logic altered. Hardware damage possible. System instability and crashes. Unexpected states activated. Performance and reliability degraded. High likelihood of exploitation when state is stored in accessible memory.
Solution
Implement cryptographic hash integrity checking within the IP during architecture and design phase. Store hashes in power-protected internal registers, compare them during restore, and halt if mismatches occur. Use a trusted external agent to hash and validate configuration before powering down and after restoration. Store configuration in a protected environment only accessible to trusted agents.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality | Scope: Confidentiality Sensitive configuration data may be exposed in storage. |
| Integrity | Scope: Integrity Configuration can be modified while in storage, leading to compromised system state. |
| Availability | Scope: Availability Corrupted configuration causes system instability, crashes, or denial of service. |
Example Code
Vulnerable Code
// Vulnerable: Power save/restore without integrity verification
module vulnerable_power_manager (
input wire clk,
input wire rst_n,
input wire power_save_request,
input wire power_restore_request,
// Configuration registers
input wire [31:0] config_reg_0,
input wire [31:0] config_reg_1,
input wire [31:0] config_reg_2,
input wire [31:0] config_reg_3,
input wire [7:0] security_level,
input wire protection_enable,
// External storage interface (e.g., flash)
output reg [31:0] storage_addr,
output reg [31:0] storage_wdata,
input wire [31:0] storage_rdata,
output reg storage_write,
output reg storage_read,
// Restored configuration outputs
output reg [31:0] restored_config_0,
output reg [31:0] restored_config_1,
output reg [31:0] restored_config_2,
output reg [31:0] restored_config_3,
output reg [7:0] restored_security_level,
output reg restored_protection_enable
);
localparam IDLE = 3'b000;
localparam SAVE_STATE = 3'b001;
localparam RESTORE_STATE = 3'b010;
localparam DONE = 3'b011;
reg [2:0] state;
reg [2:0] save_counter;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
storage_write <= 1'b0;
storage_read <= 1'b0;
end else begin
case (state)
IDLE: begin
if (power_save_request) begin
state <= SAVE_STATE;
save_counter <= 3'b0;
end else if (power_restore_request) begin
state <= RESTORE_STATE;
save_counter <= 3'b0;
end
end
SAVE_STATE: begin
// VULNERABLE: Just save configuration without protection
case (save_counter)
3'd0: begin
storage_addr <= 32'h0000;
storage_wdata <= config_reg_0;
storage_write <= 1'b1;
end
3'd1: begin
storage_addr <= 32'h0004;
storage_wdata <= config_reg_1;
end
3'd2: begin
storage_addr <= 32'h0008;
storage_wdata <= config_reg_2;
end
3'd3: begin
storage_addr <= 32'h000C;
storage_wdata <= config_reg_3;
end
3'd4: begin
storage_addr <= 32'h0010;
storage_wdata <= {protection_enable, 23'b0, security_level};
// VULNERABLE: No integrity hash computed or stored
end
3'd5: begin
storage_write <= 1'b0;
state <= DONE;
end
endcase
save_counter <= save_counter + 1;
end
RESTORE_STATE: begin
// VULNERABLE: Restore without verification
storage_read <= 1'b1;
case (save_counter)
3'd0: begin
storage_addr <= 32'h0000;
end
3'd1: begin
// VULNERABLE: No validation of restored data
restored_config_0 <= storage_rdata;
storage_addr <= 32'h0004;
end
3'd2: begin
restored_config_1 <= storage_rdata;
storage_addr <= 32'h0008;
end
3'd3: begin
restored_config_2 <= storage_rdata;
storage_addr <= 32'h000C;
end
3'd4: begin
restored_config_3 <= storage_rdata;
storage_addr <= 32'h0010;
end
3'd5: begin
// VULNERABLE: Blindly trust stored security settings
restored_security_level <= storage_rdata[7:0];
restored_protection_enable <= storage_rdata[24];
// Attacker could have modified storage to:
// - Elevate security_level to gain privileges
// - Disable protection_enable
storage_read <= 1'b0;
state <= DONE;
end
endcase
save_counter <= save_counter + 1;
end
DONE: begin
state <= IDLE;
end
endcase
end
end
endmodule
// Vulnerable: Software power management without integrity
#include <stdint.h>
#include <string.h>
typedef struct {
uint32_t config_reg_0;
uint32_t config_reg_1;
uint32_t config_reg_2;
uint32_t config_reg_3;
uint8_t security_level;
uint8_t protection_enabled;
// VULNERABLE: No integrity field
} device_state_t;
// VULNERABLE: Save state without integrity protection
void vulnerable_save_state(const device_state_t* state, void* storage) {
// VULNERABLE: Just copy state to storage
memcpy(storage, state, sizeof(device_state_t));
// No hash or signature computed
// Attacker with storage access can modify state
}
// VULNERABLE: Restore state without verification
void vulnerable_restore_state(device_state_t* state, const void* storage) {
// VULNERABLE: Blindly restore from storage
memcpy(state, storage, sizeof(device_state_t));
// No verification that state wasn't tampered with
// Modified state now active
// Apply restored (potentially malicious) configuration
apply_security_level(state->security_level);
set_protection(state->protection_enabled);
}
Fixed Code
// Fixed: Power save/restore with integrity verification
module secure_power_manager (
input wire clk,
input wire rst_n,
input wire power_save_request,
input wire power_restore_request,
// Configuration registers
input wire [31:0] config_reg_0,
input wire [31:0] config_reg_1,
input wire [31:0] config_reg_2,
input wire [31:0] config_reg_3,
input wire [7:0] security_level,
input wire protection_enable,
// External storage interface
output reg [31:0] storage_addr,
output reg [31:0] storage_wdata,
input wire [31:0] storage_rdata,
output reg storage_write,
output reg storage_read,
// Restored configuration outputs
output reg [31:0] restored_config_0,
output reg [31:0] restored_config_1,
output reg [31:0] restored_config_2,
output reg [31:0] restored_config_3,
output reg [7:0] restored_security_level,
output reg restored_protection_enable,
// Status outputs
output reg restore_valid,
output reg integrity_error
);
// FIXED: Power-protected register to hold integrity hash
// This register maintains value through sleep (battery-backed or always-on domain)
reg [255:0] saved_hash; // SHA-256 hash
// FIXED: Temporary storage for restored data before validation
reg [31:0] temp_config [0:4];
reg [255:0] computed_hash;
reg [255:0] stored_hash;
localparam IDLE = 4'b0000;
localparam SAVE_CONFIG = 4'b0001;
localparam COMPUTE_SAVE_HASH = 4'b0010;
localparam SAVE_HASH = 4'b0011;
localparam RESTORE_CONFIG = 4'b0100;
localparam RESTORE_HASH = 4'b0101;
localparam COMPUTE_VERIFY_HASH = 4'b0110;
localparam VERIFY_HASH = 4'b0111;
localparam APPLY_CONFIG = 4'b1000;
localparam ERROR_STATE = 4'b1001;
localparam DONE = 4'b1010;
reg [3:0] state;
reg [2:0] counter;
// FIXED: Hash computation module
wire [255:0] hash_result;
wire hash_done;
reg hash_start;
reg [159:0] hash_input;
sha256_core u_sha256 (
.clk(clk),
.rst_n(rst_n),
.start(hash_start),
.data(hash_input),
.hash(hash_result),
.done(hash_done)
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
restore_valid <= 1'b0;
integrity_error <= 1'b0;
storage_write <= 1'b0;
storage_read <= 1'b0;
hash_start <= 1'b0;
end else begin
case (state)
IDLE: begin
restore_valid <= 1'b0;
integrity_error <= 1'b0;
if (power_save_request) begin
state <= SAVE_CONFIG;
counter <= 3'b0;
end else if (power_restore_request) begin
state <= RESTORE_CONFIG;
counter <= 3'b0;
end
end
SAVE_CONFIG: begin
// Save configuration to storage
storage_write <= 1'b1;
case (counter)
3'd0: begin storage_addr <= 32'h0000; storage_wdata <= config_reg_0; end
3'd1: begin storage_addr <= 32'h0004; storage_wdata <= config_reg_1; end
3'd2: begin storage_addr <= 32'h0008; storage_wdata <= config_reg_2; end
3'd3: begin storage_addr <= 32'h000C; storage_wdata <= config_reg_3; end
3'd4: begin
storage_addr <= 32'h0010;
storage_wdata <= {protection_enable, 23'b0, security_level};
end
3'd5: begin
storage_write <= 1'b0;
state <= COMPUTE_SAVE_HASH;
end
endcase
counter <= counter + 1;
end
COMPUTE_SAVE_HASH: begin
// FIXED: Compute hash of configuration
hash_input <= {config_reg_0, config_reg_1, config_reg_2,
config_reg_3, protection_enable, security_level};
hash_start <= 1'b1;
if (hash_done) begin
hash_start <= 1'b0;
saved_hash <= hash_result; // FIXED: Store in protected register
state <= SAVE_HASH;
counter <= 3'b0;
end
end
SAVE_HASH: begin
// FIXED: Also save hash to storage (defense in depth)
storage_write <= 1'b1;
case (counter)
3'd0: begin storage_addr <= 32'h0020; storage_wdata <= saved_hash[31:0]; end
3'd1: begin storage_addr <= 32'h0024; storage_wdata <= saved_hash[63:32]; end
// ... continue for full hash
3'd7: begin
storage_write <= 1'b0;
state <= DONE;
end
endcase
counter <= counter + 1;
end
RESTORE_CONFIG: begin
// FIXED: Restore to temporary buffer first
storage_read <= 1'b1;
case (counter)
3'd0: storage_addr <= 32'h0000;
3'd1: begin temp_config[0] <= storage_rdata; storage_addr <= 32'h0004; end
3'd2: begin temp_config[1] <= storage_rdata; storage_addr <= 32'h0008; end
3'd3: begin temp_config[2] <= storage_rdata; storage_addr <= 32'h000C; end
3'd4: begin temp_config[3] <= storage_rdata; storage_addr <= 32'h0010; end
3'd5: begin
temp_config[4] <= storage_rdata;
storage_read <= 1'b0;
state <= COMPUTE_VERIFY_HASH;
end
endcase
counter <= counter + 1;
end
COMPUTE_VERIFY_HASH: begin
// FIXED: Compute hash of restored data
hash_input <= {temp_config[0], temp_config[1], temp_config[2],
temp_config[3], temp_config[4][24], temp_config[4][7:0]};
hash_start <= 1'b1;
if (hash_done) begin
hash_start <= 1'b0;
computed_hash <= hash_result;
state <= VERIFY_HASH;
end
end
VERIFY_HASH: begin
// FIXED: Compare computed hash with saved hash
if (computed_hash == saved_hash) begin
// Integrity verified
state <= APPLY_CONFIG;
end else begin
// FIXED: Integrity failure - halt
state <= ERROR_STATE;
integrity_error <= 1'b1;
end
end
APPLY_CONFIG: begin
// FIXED: Only apply after verification
restored_config_0 <= temp_config[0];
restored_config_1 <= temp_config[1];
restored_config_2 <= temp_config[2];
restored_config_3 <= temp_config[3];
restored_security_level <= temp_config[4][7:0];
restored_protection_enable <= temp_config[4][24];
restore_valid <= 1'b1;
state <= DONE;
end
ERROR_STATE: begin
// FIXED: Halt on integrity error
// Don't apply configuration
// System must be reset or manually recovered
end
DONE: begin
state <= IDLE;
end
endcase
end
end
endmodule
// Fixed: Software power management with integrity verification
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
typedef struct {
uint32_t config_reg_0;
uint32_t config_reg_1;
uint32_t config_reg_2;
uint32_t config_reg_3;
uint8_t security_level;
uint8_t protection_enabled;
uint8_t reserved[2];
uint8_t hash[32]; // FIXED: SHA-256 hash for integrity
} protected_device_state_t;
// FIXED: Compute integrity hash
void compute_state_hash(const protected_device_state_t* state, uint8_t* hash) {
// Hash everything except the hash field itself
sha256_context ctx;
sha256_init(&ctx);
sha256_update(&ctx, &state->config_reg_0, sizeof(state->config_reg_0));
sha256_update(&ctx, &state->config_reg_1, sizeof(state->config_reg_1));
sha256_update(&ctx, &state->config_reg_2, sizeof(state->config_reg_2));
sha256_update(&ctx, &state->config_reg_3, sizeof(state->config_reg_3));
sha256_update(&ctx, &state->security_level, sizeof(state->security_level));
sha256_update(&ctx, &state->protection_enabled, sizeof(state->protection_enabled));
sha256_final(&ctx, hash);
}
// FIXED: Save state with integrity protection
bool secure_save_state(protected_device_state_t* state, void* storage) {
// FIXED: Compute integrity hash before saving
compute_state_hash(state, state->hash);
// Save state including hash to storage
memcpy(storage, state, sizeof(protected_device_state_t));
// FIXED: Also store hash in protected (battery-backed) register
store_hash_in_protected_register(state->hash);
return true;
}
// FIXED: Restore state with verification
bool secure_restore_state(protected_device_state_t* state, const void* storage) {
protected_device_state_t temp_state;
uint8_t computed_hash[32];
uint8_t protected_hash[32];
// FIXED: Restore to temporary buffer
memcpy(&temp_state, storage, sizeof(protected_device_state_t));
// FIXED: Compute hash of restored configuration
compute_state_hash(&temp_state, computed_hash);
// FIXED: Get expected hash from protected register
get_hash_from_protected_register(protected_hash);
// FIXED: Verify integrity
if (secure_memcmp(computed_hash, protected_hash, 32) != 0) {
// Integrity failure
log_security_event("State integrity verification failed");
return false;
}
// FIXED: Also verify against stored hash
if (secure_memcmp(computed_hash, temp_state.hash, 32) != 0) {
log_security_event("Stored hash mismatch");
return false;
}
// FIXED: Integrity verified - apply configuration
memcpy(state, &temp_state, sizeof(protected_device_state_t));
// Apply verified configuration
apply_security_level(state->security_level);
set_protection(state->protection_enabled);
return true;
}
CVE Examples
- CVE-2020-8705: Power state restoration in certain Intel processors didn't properly verify configuration integrity.
- CVE-2019-11139: Voltage glitching during power transitions affected secure state.
Related CWEs
- CWE-284: Improper Access Control (parent)
- CWE-345: Insufficient Verification of Data Authenticity (peer)
- CWE-1271: Uninitialized Value on Reset for Registers Holding Security Settings (peer)
- CWE-1206: Power, Clock, Thermal, and Reset Concerns (category)
References
- MITRE Corporation. "CWE-1304: Improperly Preserved Integrity of Hardware Configuration State During a Power Save/Restore Operation." https://cwe.mitre.org/data/definitions/1304.html
- NIST. "Guidelines for Power Management Security"
- ARM. "TrustZone Power State Management"