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
| Auswirkung | Details |
|---|---|
| Verfügbarkeit, Zugriffskontrolle | Umfang: 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
- MITRE Corporation. "CWE-1248: Semiconductor Defects in Hardware Logic with Security-Sensitive Implications." https://cwe.mitre.org/data/definitions/1248.html
- Bailey, Brian. "Why Chips Die."
- Lakshminarayan, V. "What Causes Semiconductor Devices to Fail"
- CAPEC-624: Hardware Fault Injection