Unsachgemäß erhaltene Integrität des Hardware-Konfigurationszustands während einer Energiespar-/Wiederherstellungsoperation

Beschreibung

Die unsachgemäß erhaltene Integrität des Hardware-Konfigurationszustands während einer Energiespar-/Wiederherstellungsoperation tritt auf, wenn ein Produkt eine Energiespar-/Wiederherstellungsoperation durchführt, aber nicht sicherstellt, dass die Integrität des Konfigurationszustands zwischen Beginn und Ende der Operation aufrechterhalten und/oder verifiziert wird. Während des Herunterfahrens speichert Hardware-IP ihren Zustand in persistentem Speicher wie Flash-Speicher. Die Schwachstelle tritt auf, wenn Angreifer mit Speicherzugriff diese gespeicherte Konfiguration ändern, um Privilegien zu kompromittieren, Schutzmaßnahmen zu deaktivieren oder Hardware zu beschädigen. Ohne Validierung bei der Wiederherstellung aktiviert das System potenziell schädliche Konfigurationen.

Risiko

Unsachgemäße Zustandserhaltung hat schwerwiegende Auswirkungen. Denial of Service durch beschädigten Zustand. Privilegienerweiterung durch modifizierte Konfiguration. Schutzmechanismen deaktiviert. Ausführungslogik verändert. Hardwareschäden möglich. Systeminstabilität und Abstürze. Unerwartete Zustände aktiviert. Leistung und Zuverlässigkeit beeinträchtigt. Hohe Ausnutzungswahrscheinlichkeit, wenn der Zustand in zugänglichem Speicher abgelegt wird.

Lösung

Implementieren Sie kryptografische Hash-Integritätsprüfungen innerhalb der IP während der Architektur- und Entwurfsphase. Speichern Sie Hashes in stromgeschützten internen Registern, vergleichen Sie sie während der Wiederherstellung und halten Sie an, wenn Abweichungen auftreten. Verwenden Sie einen vertrauenswürdigen externen Agenten zum Hashen und Validieren der Konfiguration vor dem Herunterfahren und nach der Wiederherstellung. Speichern Sie die Konfiguration in einer geschützten Umgebung, die nur für vertrauenswürdige Agenten zugänglich ist.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Vertraulichkeit

Sensible Konfigurationsdaten können im Speicher offengelegt werden.
IntegritätBereich: Integrität

Konfiguration kann während der Speicherung modifiziert werden, was zu einem kompromittierten Systemzustand führt.
VerfügbarkeitBereich: Verfügbarkeit

Beschädigte Konfiguration verursacht Systeminstabilität, Abstürze oder Denial of Service.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Energiespar-/Wiederherstellung ohne Integritätsprüfung

module vulnerable_power_manager (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        power_save_request,
    input  wire        power_restore_request,

    // Konfigurationsregister
    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,

    // Externe Speicherschnittstelle (z.B. 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,

    // Wiederhergestellte Konfigurationsausgänge
    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
                    // VERWUNDBAR: Konfiguration einfach ohne Schutz speichern
                    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};
                            // VERWUNDBAR: Kein Integritäts-Hash berechnet oder gespeichert
                        end
                        3'd5: begin
                            storage_write <= 1'b0;
                            state <= DONE;
                        end
                    endcase
                    save_counter <= save_counter + 1;
                end

                RESTORE_STATE: begin
                    // VERWUNDBAR: Wiederherstellung ohne Verifizierung
                    storage_read <= 1'b1;
                    case (save_counter)
                        3'd0: begin
                            storage_addr <= 32'h0000;
                        end
                        3'd1: begin
                            // VERWUNDBAR: Keine Validierung der wiederhergestellten Daten
                            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
                            // VERWUNDBAR: Blind gespeicherten Sicherheitseinstellungen vertrauen
                            restored_security_level <= storage_rdata[7:0];
                            restored_protection_enable <= storage_rdata[24];
                            // Angreifer hätte den Speicher ändern können um:
                            // - security_level zu erhöhen für Privilegien
                            // - protection_enable zu deaktivieren
                            storage_read <= 1'b0;
                            state <= DONE;
                        end
                    endcase
                    save_counter <= save_counter + 1;
                end

                DONE: begin
                    state <= IDLE;
                end
            endcase
        end
    end

endmodule
// VERWUNDBAR: Software-Energieverwaltung ohne Integrität

#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;
    // VERWUNDBAR: Kein Integritätsfeld
} device_state_t;

// VERWUNDBAR: Zustand ohne Integritätsschutz speichern
void vulnerable_save_state(const device_state_t* state, void* storage) {
    // VERWUNDBAR: Zustand einfach in Speicher kopieren
    memcpy(storage, state, sizeof(device_state_t));

    // Kein Hash oder Signatur berechnet
    // Angreifer mit Speicherzugriff kann Zustand ändern
}

// VERWUNDBAR: Zustand ohne Verifizierung wiederherstellen
void vulnerable_restore_state(device_state_t* state, const void* storage) {
    // VERWUNDBAR: Blind aus Speicher wiederherstellen
    memcpy(state, storage, sizeof(device_state_t));

    // Keine Verifizierung, ob Zustand manipuliert wurde
    // Modifizierter Zustand jetzt aktiv

    // Wiederhergestellte (potenziell bösartige) Konfiguration anwenden
    apply_security_level(state->security_level);
    set_protection(state->protection_enabled);
}

Sichere Lösung

// SICHER: Energiespar-/Wiederherstellung mit Integritätsprüfung

module secure_power_manager (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        power_save_request,
    input  wire        power_restore_request,

    // Konfigurationsregister
    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,

    // Externe Speicherschnittstelle
    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,

    // Wiederhergestellte Konfigurationsausgänge
    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,

    // Statusausgänge
    output reg         restore_valid,
    output reg         integrity_error
);

    // SICHER: Stromgeschütztes Register zum Halten des Integritäts-Hashes
    // Dieses Register behält seinen Wert während des Schlafmodus (batteriegepuffert oder Always-On-Domäne)
    reg [255:0] saved_hash;  // SHA-256 Hash

    // SICHER: Temporärer Speicher für wiederhergestellte Daten vor Validierung
    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;

    // SICHER: Hash-Berechnungsmodul
    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
                    // Konfiguration im Speicher sichern
                    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
                    // SICHER: Hash der Konfiguration berechnen
                    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;  // SICHER: In geschütztem Register speichern
                        state <= SAVE_HASH;
                        counter <= 3'b0;
                    end
                end

                SAVE_HASH: begin
                    // SICHER: Hash auch im Speicher sichern (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
                        // ... für vollständigen Hash fortsetzen
                        3'd7: begin
                            storage_write <= 1'b0;
                            state <= DONE;
                        end
                    endcase
                    counter <= counter + 1;
                end

                RESTORE_CONFIG: begin
                    // SICHER: Zuerst in temporären Puffer wiederherstellen
                    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
                    // SICHER: Hash der wiederhergestellten Daten berechnen
                    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
                    // SICHER: Berechneten Hash mit gespeichertem Hash vergleichen
                    if (computed_hash == saved_hash) begin
                        // Integrität verifiziert
                        state <= APPLY_CONFIG;
                    end else begin
                        // SICHER: Integritätsfehler - anhalten
                        state <= ERROR_STATE;
                        integrity_error <= 1'b1;
                    end
                end

                APPLY_CONFIG: begin
                    // SICHER: Nur nach Verifizierung anwenden
                    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
                    // SICHER: Bei Integritätsfehler anhalten
                    // Konfiguration nicht anwenden
                    // System muss zurückgesetzt oder manuell wiederhergestellt werden
                end

                DONE: begin
                    state <= IDLE;
                end
            endcase
        end
    end

endmodule
// SICHER: Software-Energieverwaltung mit Integritätsprüfung

#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];  // SICHER: SHA-256 Hash für Integrität
} protected_device_state_t;

// SICHER: Integritäts-Hash berechnen
void compute_state_hash(const protected_device_state_t* state, uint8_t* hash) {
    // Alles ausser dem Hash-Feld selbst hashen
    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);
}

// SICHER: Zustand mit Integritätsschutz speichern
bool secure_save_state(protected_device_state_t* state, void* storage) {
    // SICHER: Integritäts-Hash vor dem Speichern berechnen
    compute_state_hash(state, state->hash);

    // Zustand einschließlich Hash im Speicher sichern
    memcpy(storage, state, sizeof(protected_device_state_t));

    // SICHER: Hash auch in geschütztem (batteriegepuffertem) Register speichern
    store_hash_in_protected_register(state->hash);

    return true;
}

// SICHER: Zustand mit Verifizierung wiederherstellen
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];

    // SICHER: In temporären Puffer wiederherstellen
    memcpy(&temp_state, storage, sizeof(protected_device_state_t));

    // SICHER: Hash der wiederhergestellten Konfiguration berechnen
    compute_state_hash(&temp_state, computed_hash);

    // SICHER: Erwarteten Hash aus geschütztem Register holen
    get_hash_from_protected_register(protected_hash);

    // SICHER: Integrität verifizieren
    if (secure_memcmp(computed_hash, protected_hash, 32) != 0) {
        // Integritätsfehler
        log_security_event("Zustandsintegritätsprüfung fehlgeschlagen");
        return false;
    }

    // SICHER: Auch gegen gespeicherten Hash verifizieren
    if (secure_memcmp(computed_hash, temp_state.hash, 32) != 0) {
        log_security_event("Gespeicherte Hash-Abweichung");
        return false;
    }

    // SICHER: Integrität verifiziert - Konfiguration anwenden
    memcpy(state, &temp_state, sizeof(protected_device_state_t));

    // Verifizierte Konfiguration anwenden
    apply_security_level(state->security_level);
    set_protection(state->protection_enabled);

    return true;
}

CVE-Beispiele

  • CVE-2020-8705: Energiezustandswiederherstellung in bestimmten Intel-Prozessoren prüfte die Konfigurationsintegrität nicht ordnungsgemäß.
  • CVE-2019-11139: Spannungs-Glitching während Energieübergängen beeinflusste den sicheren Zustand.

Verwandte CWEs

  • CWE-284: Improper Access Control (Eltern)
  • 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 (Kategorie)

Referenzen

  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"