Halbleiterdefekte in Hardware-Logik mit sicherheitsrelevanten Auswirkungen

Beschreibung

Halbleiterdefekte in Hardware-Logik mit sicherheitsrelevanten Auswirkungen tritt auf, wenn sicherheitsrelevante Hardware-Module Halbleiterdefekte enthalten. Halbleiter können durch verschiedene Mechanismen ausfallen, darunter Fertigungs-/Verpackungsdefekte und Degradation durch Langzeitnutzung oder extreme Bedingungen. Spezifische Ausfallmechanismen umfassen Kapselungsversagen, Die-Attach-Versagen, Drahtbondversagen, Bulk-Silizium-Defekte, Oxidschichtfehler und Aluminium-Metallfehler einschließlich Elektromigration und Korrosion. Diese Defekte manifestieren sich als Fehler, bei denen chipinterne Signale oder Register auf 0 oder 1 hängen bleiben und nicht wie erwartet umschalten.

Risiko

Halbleiterdefekte in Sicherheitshardware haben schwerwiegende Auswirkungen. Zugriffskontrolllogik kann ausfallen und offen bleiben. Sicherheitsüberprüfungen können aufgrund hängengebliebener Signale umgangen werden. Kryptografische Operationen können falsche Ergebnisse liefern. Authentifizierungslogik kann fehlfunktionieren. Sicherheitszustandsautomaten funktionieren möglicherweise nicht korrekt. Schutzmechanismen können stillschweigend ausfallen. Denial of Service kann auftreten. Vertrauensanker können kompromittiert werden.

Lösung

Implementieren Sie Post-Manufacturing-Silizium-Tests unter Verwendung von Fehlermodellen wie Stuck-at-0 oder Stuck-at-1, um eine gute Testabdeckung zu erreichen. Betreiben Sie Hardware innerhalb der Spezifikationen, um beschleunigte Degradation durch extreme Temperaturen oder Spannung zu vermeiden. Verwenden Sie redundante Logik für sicherheitskritische Funktionen. Implementieren Sie Laufzeit-Fehlererkennung. Entwerfen Sie für ausfallsicheres Verhalten. Überwachen Sie den Zustand der Sicherheitshardware. Verwenden Sie Burn-In-Tests zur Erkennung früher Ausfälle.

Häufige Auswirkungen

AuswirkungDetails
Verfügbarkeit, ZugriffskontrolleUmfang: Verfügbarkeit, Zugriffskontrolle

DoS: Instabilität, Schutzmechanismus umgehen - Wenn Fehler in sicherheitsrelevanten Hardware-Modulen auftreten, können Sicherheitsziele kompromittiert werden, was zu Denial of Service oder Schutzumgehung führt.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Firewall ohne Defekterkennung

module vulnerable_noc_firewall (
    input wire clk,
    input wire reset_n,
    input wire [31:0] source_id,
    input wire [31:0] dest_addr,
    input wire [3:0] access_type,
    output reg access_allowed
);

    // Zugriffskontrollregeln
    parameter SECURE_REGION_START = 32'h8000_0000;
    parameter SECURE_REGION_END = 32'h8FFF_FFFF;
    parameter TRUSTED_SOURCE_ID = 32'h0000_0001;

    // VERWUNDBAR: Keine Erkennung von Stuck-at-Fehlern
    wire is_secure_region = (dest_addr >= SECURE_REGION_START) &&
                            (dest_addr <= SECURE_REGION_END);
    wire is_trusted_source = (source_id == TRUSTED_SOURCE_ID);

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_allowed <= 1'b0;
        end
        else begin
            if (is_secure_region) begin
                // VERWUNDBAR: Wenn is_trusted_source auf 1 hängt, wird aller Zugriff erlaubt
                access_allowed <= is_trusted_source;
            end else begin
                access_allowed <= 1'b1;
            end
        end
    end

    // Fertigungsdefekt: is_trusted_source-Signal auf 1 hängengeblieben
    // Ergebnis: Alle Quellen erscheinen vertrauenswürdig, Sicherheit umgangen

endmodule

// VERWUNDBAR: Sicherheitskomparator ohne Fehlererkennung
module vulnerable_key_comparator (
    input wire clk,
    input wire [127:0] input_key,
    input wire [127:0] stored_key,
    output reg key_match
);

    // VERWUNDBAR: Einzelner Vergleich, keine Defekterkennung
    always @(posedge clk) begin
        key_match <= (input_key == stored_key);
    end

    // Defekt: Wenn key_match-Signal auf 1 hängt, wird jeder Schlüssel akzeptiert

endmodule

// VERWUNDBAR: Zugriffskontrolle ohne Redundanz
module vulnerable_access_controller (
    input wire clk,
    input wire reset_n,
    input wire request_access,
    input wire [7:0] privilege_level,
    input wire [7:0] required_level,
    output reg access_granted
);

    // VERWUNDBAR: Einzelne Berechtigungsprüfung
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_granted <= 1'b0;
        end
        else if (request_access) begin
            // VERWUNDBAR: Wenn privilege_level[7] auf 1 hängt, immer maximale Berechtigung
            access_granted <= (privilege_level >= required_level);
        end
    end

endmodule
// VERWUNDBAR: Firmware geht von korrektem Hardware-Verhalten aus

void vulnerable_security_check(void) {
    // Aus Sicherheitshardware lesen
    uint32_t security_status = read_security_register();

    // VERWUNDBAR: Nimmt an, dass Hardware korrekt funktioniert
    // Wenn Register auf 0x00000001 (Sicherheit OK) hängt, besteht Prüfung immer
    if (security_status == SECURITY_OK) {
        allow_operation();
    } else {
        deny_operation();
    }
}

// VERWUNDBAR: Keine Integritätsprüfung der Sicherheitshardware
void vulnerable_init(void) {
    // Sicherheitshardware initialisieren
    init_security_module();

    // VERWUNDBAR: Keine Überprüfung, ob Hardware korrekt funktioniert
    // Ein Stuck-at-Fehler im Sicherheitsmodul würde unentdeckt bleiben

    continue_boot();
}

Sichere Lösung

// SICHER: Firewall mit Defekterkennung

module secure_noc_firewall (
    input wire clk,
    input wire reset_n,
    input wire [31:0] source_id,
    input wire [31:0] dest_addr,
    input wire [3:0] access_type,
    output reg access_allowed,
    output reg fault_detected
);

    parameter SECURE_REGION_START = 32'h8000_0000;
    parameter SECURE_REGION_END = 32'h8FFF_FFFF;
    parameter TRUSTED_SOURCE_ID = 32'h0000_0001;

    // SICHER: Redundante Logik mit verschiedenen Implementierungen
    wire is_secure_region_a = (dest_addr >= SECURE_REGION_START) &&
                              (dest_addr <= SECURE_REGION_END);
    wire is_secure_region_b = (dest_addr[31:28] == 4'h8);  // Andere Prüfung

    wire is_trusted_source_a = (source_id == TRUSTED_SOURCE_ID);
    wire is_trusted_source_b = (source_id[31:0] == 32'h0000_0001);  // Explizit

    // SICHER: Stuck-at-Fehler durch Vergleich erkennen
    wire region_check_consistent = (is_secure_region_a == is_secure_region_b);
    wire source_check_consistent = (is_trusted_source_a == is_trusted_source_b);

    // SICHER: Eingebautes Selbsttest-Muster
    reg [31:0] test_counter;
    reg in_self_test;
    wire test_pass;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_allowed <= 1'b0;
            fault_detected <= 1'b0;
            test_counter <= 32'h0;
            in_self_test <= 1'b1;
        end
        else if (in_self_test) begin
            // SICHER: Periodischer Selbsttest
            test_counter <= test_counter + 1;
            if (test_counter == 32'hFFFF) begin
                in_self_test <= 1'b0;
                // Testergebnisse überprüfen
                if (!test_pass) begin
                    fault_detected <= 1'b1;
                end
            end
        end
        else begin
            // Auf Inkonsistenzen prüfen (zeigt Fehler an)
            if (!region_check_consistent || !source_check_consistent) begin
                fault_detected <= 1'b1;
                access_allowed <= 1'b0;  // Ausfallsicher
            end
            else if (is_secure_region_a) begin
                // Beide redundanten Prüfungen müssen übereinstimmen
                access_allowed <= is_trusted_source_a && is_trusted_source_b;
            end else begin
                access_allowed <= 1'b1;
            end
        end
    end

endmodule

// SICHER: Sicherheitskomparator mit Fehlererkennung
module secure_key_comparator (
    input wire clk,
    input wire reset_n,
    input wire [127:0] input_key,
    input wire [127:0] stored_key,
    input wire compare_enable,
    output reg key_match,
    output reg fault_detected
);

    // SICHER: Mehrere Vergleichsmethoden
    wire match_method_a = (input_key == stored_key);
    wire match_method_b = ((input_key ^ stored_key) == 128'h0);

    // SICHER: XOR-Ergebnis zur Stuck-at-Erkennung
    wire [127:0] xor_result = input_key ^ stored_key;
    wire all_zero = (xor_result == 128'h0);

    // Zähler zur Erkennung hängengebliebener Signale
    reg [7:0] match_history;
    reg [7:0] mismatch_history;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            key_match <= 1'b0;
            fault_detected <= 1'b0;
            match_history <= 8'h0;
            mismatch_history <= 8'h0;
        end
        else if (compare_enable) begin
            // SICHER: Beide Methoden müssen übereinstimmen
            if (match_method_a == match_method_b) begin
                key_match <= match_method_a && all_zero;
            end else begin
                // Inkonsistenz = Fehler
                fault_detected <= 1'b1;
                key_match <= 1'b0;
            end

            // SICHER: Verlauf verfolgen zur Stuck-at-Erkennung
            if (match_method_a) begin
                match_history <= {match_history[6:0], 1'b1};
            end else begin
                mismatch_history <= {mismatch_history[6:0], 1'b1};
            end

            // Erkennen, ob immer passend (auf 1 hängengeblieben)
            if (match_history == 8'hFF) begin
                fault_detected <= 1'b1;
            end
        end
    end

endmodule

// SICHER: Zugriffskontrolle mit Redundanz
module secure_access_controller (
    input wire clk,
    input wire reset_n,
    input wire request_access,
    input wire [7:0] privilege_level,
    input wire [7:0] required_level,
    input wire [7:0] privilege_level_shadow,  // Redundante Kopie
    output reg access_granted,
    output reg fault_detected
);

    // SICHER: Primäre und Schatten-Berechtigungslevels vergleichen
    wire privilege_consistent = (privilege_level == privilege_level_shadow);

    // SICHER: Zwei verschiedene Vergleichsmethoden
    wire check_a = (privilege_level >= required_level);
    wire check_b = ((privilege_level - required_level) < 8'h80);  // Kein Unterlauf = bestanden

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_granted <= 1'b0;
            fault_detected <= 1'b0;
        end
        else if (request_access) begin
            // SICHER: Auf Inkonsistenzen prüfen
            if (!privilege_consistent) begin
                fault_detected <= 1'b1;
                access_granted <= 1'b0;  // Ausfallsicher
            end
            else if (check_a != check_b) begin
                // Vergleichsmethoden stimmen nicht überein = Fehler
                fault_detected <= 1'b1;
                access_granted <= 1'b0;
            end
            else begin
                access_granted <= check_a && check_b;
            end
        end
    end

endmodule
// SICHER: Firmware mit Hardware-Integritätsüberprüfung

void secure_security_check(void) {
    // SICHER: Hardware-Funktionalität vor Vertrauen überprüfen
    if (!verify_security_hardware_health()) {
        security_failure_handler();
        return;
    }

    uint32_t security_status = read_security_register();

    // SICHER: Mehrmals lesen und vergleichen
    uint32_t status_2 = read_security_register();
    uint32_t status_3 = read_security_register();

    if (security_status != status_2 || status_2 != status_3) {
        // Inkonsistente Lesevorgänge = möglicher Fehler
        security_failure_handler();
        return;
    }

    if (security_status == SECURITY_OK) {
        allow_operation();
    } else {
        deny_operation();
    }
}

// SICHER: Hardware-Integritätsüberprüfung
bool verify_security_hardware_health(void) {
    // Eingebauten Selbsttest durchführen
    if (!run_security_bist()) {
        return false;
    }

    // Mit bekannten Mustern testen
    write_test_register(TEST_PATTERN_A);
    if (read_test_register() != TEST_PATTERN_A) {
        return false;  // Stuck-at-Fehler erkannt
    }

    write_test_register(TEST_PATTERN_B);
    if (read_test_register() != TEST_PATTERN_B) {
        return false;
    }

    // Testen, ob alle Bits umschalten
    write_test_register(0x55555555);
    if (read_test_register() != 0x55555555) {
        return false;
    }

    write_test_register(0xAAAAAAAA);
    if (read_test_register() != 0xAAAAAAAA) {
        return false;
    }

    return true;
}

// Periodische Integritätsprüfung während des Betriebs
void periodic_health_check(void) {
    static uint32_t check_counter = 0;

    check_counter++;
    if (check_counter >= HEALTH_CHECK_INTERVAL) {
        check_counter = 0;

        if (!verify_security_hardware_health()) {
            log_error("Sicherheitshardware-Fehler erkannt!");
            enter_safe_mode();
        }
    }
}

CVE-Beispiele

Halbleiterdefekte in Sicherheitshardware wurden in verschiedenen Chips identifiziert, bei denen Fertigungsdefekte oder Alterung dazu führten, dass Sicherheitslogik fehlerhaft funktionierte.


Verwandte CWEs

  • CWE-693: Versagen des Schutzmechanismus (übergeordnet)
  • CWE-1195: Fertigungs- und Lebenszyklusmanagement-Probleme (Kategoriemitglied)
  • CWE-1206: Strom-, Takt-, Thermal- und Reset-Probleme (Kategoriemitglied)
  • CWE-1388: Probleme und Bedenken beim physischen Zugriff (Kategoriemitglied)

Referenzen

  1. MITRE Corporation. "CWE-1248: Semiconductor Defects in Hardware Logic with Security-Sensitive Implications." https://cwe.mitre.org/data/definitions/1248.html
  2. Bailey, Brian. "Why Chips Die."
  3. Lakshminarayan, V. "What Causes Semiconductor Devices to Fail"
  4. CAPEC-624: Hardware Fault Injection