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

ImpactDetails
ConfidentialityScope: Confidentiality

Sensitive configuration data may be exposed in storage.
IntegrityScope: Integrity

Configuration can be modified while in storage, leading to compromised system state.
AvailabilityScope: 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.

  • 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

  1. 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
  2. NIST. "Guidelines for Power Management Security"
  3. ARM. "TrustZone Power State Management"