Kryptographische Operationen werden ausgeführt, bevor unterstützende Einheiten bereit sind
Beschreibung
Kryptographische Operationen werden ausgeführt, bevor unterstützende Einheiten bereit sind, tritt auf, wenn kryptographische Operationen durchgeführt werden, ohne sicherzustellen, dass die unterstützenden Eingaben bereit sind, gültige Daten zu liefern, was das kryptographische Ergebnis kompromittieren kann. Kryptographische Hardware-Einheiten hängen von anderen Hardware-Komponenten ab, um sicher zu funktionieren. Beispiele umfassen Zufallszahlengeneratoren (RNG), die Entropie liefern, und Fuse-Einheiten, die Verschlüsselungsschlüssel bereitstellen. Die Ausführung von Krypto-Einheiten, bevor diese Abhängigkeiten bereit sind, produziert unsichere Ergebnisse, wie die Verwendung eines vorhersagbaren Seeds anstelle echter Zufälligkeit.
Risiko
Vorzeitige kryptographische Operationen haben schwerwiegende Sicherheitsauswirkungen. Zufallszahlen können vorhersagbar sein. Schlüssel sind möglicherweise nicht ordnungsgemäß geladen. Verschlüsselung kann schwache Werte verwenden. Signaturen können fälschbar sein. Authentifizierung kann umgangen werden. Kryptographische Sicherheit wird untergraben. Seitenkanalangriffe werden einfacher. Das gesamte Sicherheitsmodell kann zusammenbrechen.
Lösung
Verwenden Sie Best Practices beim Design kryptographischer Systeme. Verifizieren Sie kontinuierlich, dass kryptographische Eingaben gültige Informationen liefern. Implementieren Sie Ready-Signale und Handshaking zwischen Komponenten. Verifizieren Sie die RNG-Gesundheit vor der Verwendung. Stellen Sie sicher, dass Schlüsselmaterial vollständig geladen ist, bevor Operationen beginnen. Verwenden Sie Statusregister, um die Bereitschaft der Einheiten zu bestätigen. Implementieren Sie Fehlerbehandlung für nicht bereite Zustände.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Bereich: Zugriffskontrolle Schutzmechanismus umgehen - Schwache Kryptographie ermöglicht Bypass. |
| Vertraulichkeit | Bereich: Vertraulichkeit Speicher lesen - Vorhersagbare Kryptographie kann gebrochen werden. |
| Integrität | Bereich: Integrität Speicher modifizieren - Signaturen können fälschbar sein. |
| Authentifizierung | Bereich: Authentifizierung Authentifizierung umgehen - Schwache Schlüssel ermöglichen Identitätsfälschung. |
Beispielcode und Lösung
Verwundbarer Code
// VERWUNDBAR: Krypto-Operationen bevor RNG bereit ist
module vulnerable_crypto_system (
input wire clk,
input wire reset_n,
input wire start_crypto,
input wire [127:0] plaintext,
output reg [127:0] ciphertext,
output reg crypto_done
);
// RNG-Signale
wire [127:0] rng_output;
wire rng_ready;
// Schlüsselsignale
wire [127:0] key_from_fuse;
wire key_ready;
// RNG-Instanz
rng_unit rng (
.clk(clk),
.reset_n(reset_n),
.random_data(rng_output),
.ready(rng_ready)
);
// Fuse-Einheit-Instanz
fuse_unit fuses (
.clk(clk),
.reset_n(reset_n),
.key_out(key_from_fuse),
.ready(key_ready)
);
// VERWUNDBAR: Krypto-Operation ohne Bereitschaftsprüfung
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
ciphertext <= 128'h0;
crypto_done <= 1'b0;
end
else if (start_crypto) begin
// VERWUNDBAR: Verwendet RNG-Ausgabe, auch wenn RNG nicht bereit ist
// rng_output kann nur Nullen oder vorhersagbar sein
// VERWUNDBAR: Verwendet Schlüssel, auch wenn Fuse-Einheit nicht bereit ist
// key_from_fuse kann nur Nullen sein
ciphertext <= aes_encrypt(plaintext, key_from_fuse) ^ rng_output;
crypto_done <= 1'b1;
// Problem: Wenn RNG nicht bereit, ist IV/Nonce vorhersagbar
// Problem: Wenn Fuses nicht bereit, ist Schlüssel null/schwach
end
end
endmodule
// VERWUNDBAR: RNG mit Fallback auf schwachen Seed
module vulnerable_rng (
input wire clk,
input wire reset_n,
input wire request_random,
output reg [127:0] random_data,
output reg data_valid
);
wire entropy_ready;
wire [127:0] entropy_bits;
entropy_source entropy (
.clk(clk),
.reset_n(reset_n),
.entropy_out(entropy_bits),
.ready(entropy_ready)
);
reg self_test_passed;
// VERWUNDBAR: Fallback auf schwachen Seed, wenn Entropie nicht bereit
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
random_data <= 128'h0;
data_valid <= 1'b0;
self_test_passed <= 1'b0;
end
else if (request_random) begin
if (entropy_ready && self_test_passed) begin
// Gut: Echte Entropie verwenden
random_data <= entropy_bits;
data_valid <= 1'b1;
end
else begin
// VERWUNDBAR: Fallback auf hartcodierten Seed
random_data <= 128'hDEADBEEF_CAFEBABE_12345678_87654321;
data_valid <= 1'b1; // Behauptet gültig, ist aber vorhersagbar!
end
end
end
endmodule
// VERWUNDBAR: Software-Krypto ohne Prüfung der RNG-Bereitschaft
#include <stdint.h>
#define RNG_STATUS_REG 0x40001000
#define RNG_DATA_REG 0x40001004
#define RNG_READY_BIT 0x01
// VERWUNDBAR: IV generieren ohne RNG-Prüfung
void vulnerable_generate_iv(uint8_t* iv, size_t len) {
volatile uint32_t* rng_data = (volatile uint32_t*)RNG_DATA_REG;
// VERWUNDBAR: Keine Prüfung, ob RNG bereit ist
// RNG sammelt möglicherweise noch Entropie nach Reset
for (size_t i = 0; i < len; i += 4) {
// RNG könnte nur Nullen zurückgeben, wenn nicht bereit!
uint32_t random = *rng_data;
memcpy(iv + i, &random, 4);
}
// Wenn direkt nach Reset aufgerufen, kann IV vorhersagbar sein
// Verschlüsselung kann gebrochen werden, wenn Angreifer IV kennt
}
// VERWUNDBAR: Schlüssel verwenden, bevor Fuse-Einheit bereit ist
void vulnerable_load_key(void) {
volatile uint32_t* fuse_key = (volatile uint32_t*)FUSE_KEY_BASE;
// VERWUNDBAR: Keine Prüfung, ob Fuse-Einheit Initialisierung abgeschlossen hat
// Schlüssel kann während Power-Up-Sequenz nur Nullen sein
uint8_t key[16];
for (int i = 0; i < 4; i++) {
uint32_t word = fuse_key[i]; // Kann null sein!
memcpy(key + i*4, &word, 4);
}
// Wenn Schlüssel nur Nullen ist, ist Verschlüsselung nutzlos
aes_set_key(key);
}
// VERWUNDBAR: Verschlüsseln mit potenziell schwachen Parametern
void vulnerable_encrypt(const uint8_t* plaintext, size_t len,
uint8_t* ciphertext) {
uint8_t iv[16];
vulnerable_generate_iv(iv, 16); // Kann vorhersagbar sein!
vulnerable_load_key(); // Kann null sein!
// Verschlüsselung mit schwachem IV und Schlüssel ist brechbar
aes_cbc_encrypt(plaintext, len, iv, ciphertext);
}
Sichere Lösung
// SICHER: Krypto-Operationen erst nach Bereitschaft der unterstützenden Einheiten
module secure_crypto_system (
input wire clk,
input wire reset_n,
input wire start_crypto,
input wire [127:0] plaintext,
output reg [127:0] ciphertext,
output reg crypto_done,
output reg crypto_error
);
// RNG-Signale
wire [127:0] rng_output;
wire rng_ready;
wire rng_health_ok;
// Schlüsselsignale
wire [127:0] key_from_fuse;
wire key_ready;
wire key_valid;
// RNG-Instanz mit Gesundheitsprüfung
secure_rng_unit rng (
.clk(clk),
.reset_n(reset_n),
.random_data(rng_output),
.ready(rng_ready),
.health_ok(rng_health_ok)
);
// Fuse-Einheit-Instanz
secure_fuse_unit fuses (
.clk(clk),
.reset_n(reset_n),
.key_out(key_from_fuse),
.ready(key_ready),
.valid(key_valid)
);
// Zustandsmaschine für Krypto-Operation
reg [2:0] state;
parameter IDLE = 3'd0;
parameter WAIT_RNG = 3'd1;
parameter WAIT_KEY = 3'd2;
parameter ENCRYPT = 3'd3;
parameter DONE = 3'd4;
parameter ERROR = 3'd5;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
ciphertext <= 128'h0;
crypto_done <= 1'b0;
crypto_error <= 1'b0;
state <= IDLE;
end
else begin
case (state)
IDLE: begin
crypto_done <= 1'b0;
crypto_error <= 1'b0;
if (start_crypto) begin
state <= WAIT_RNG;
end
end
WAIT_RNG: begin
// SICHER: Warten bis RNG bereit und gesund ist
if (rng_ready && rng_health_ok) begin
state <= WAIT_KEY;
end
else if (!rng_health_ok) begin
// RNG-Gesundheitsprüfung fehlgeschlagen
state <= ERROR;
end
// Timeout-Behandlung könnte hier hinzugefügt werden
end
WAIT_KEY: begin
// SICHER: Warten bis Schlüssel bereit und gültig ist
if (key_ready && key_valid) begin
state <= ENCRYPT;
end
else if (key_ready && !key_valid) begin
// Schlüsselvalidierung fehlgeschlagen
state <= ERROR;
end
end
ENCRYPT: begin
// SICHER: Alle Abhängigkeiten erfüllt, sicher zu verschlüsseln
ciphertext <= aes_encrypt(plaintext, key_from_fuse) ^ rng_output;
state <= DONE;
end
DONE: begin
crypto_done <= 1'b1;
state <= IDLE;
end
ERROR: begin
crypto_error <= 1'b1;
state <= IDLE;
end
endcase
end
end
endmodule
// SICHER: RNG mit ordnungsgemäßer Gesundheitsprüfung
module secure_rng_unit (
input wire clk,
input wire reset_n,
input wire request_random,
output reg [127:0] random_data,
output reg ready,
output reg health_ok
);
wire entropy_ready;
wire [127:0] entropy_bits;
entropy_source entropy (
.clk(clk),
.reset_n(reset_n),
.entropy_out(entropy_bits),
.ready(entropy_ready)
);
// SICHER: Gesundheitsprüfungszustand
reg [2:0] health_state;
reg [7:0] startup_count;
reg self_test_passed;
parameter HEALTH_INIT = 3'd0;
parameter HEALTH_STARTUP = 3'd1;
parameter HEALTH_CONTINUOUS = 3'd2;
parameter HEALTH_FAILED = 3'd3;
// Vorherige Ausgabe für kontinuierliche Tests
reg [127:0] previous_output;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
random_data <= 128'h0;
ready <= 1'b0;
health_ok <= 1'b0;
health_state <= HEALTH_INIT;
startup_count <= 8'h0;
self_test_passed <= 1'b0;
end
else begin
case (health_state)
HEALTH_INIT: begin
// SICHER: Warten bis Entropiequelle stabilisiert ist
ready <= 1'b0;
health_ok <= 1'b0;
if (entropy_ready) begin
health_state <= HEALTH_STARTUP;
startup_count <= 8'h0;
end
end
HEALTH_STARTUP: begin
// SICHER: Start-Gesundheitstests ausführen
if (entropy_ready) begin
// Proben sammeln und statistische Tests ausführen
if (run_startup_tests(entropy_bits)) begin
startup_count <= startup_count + 1;
end
else begin
health_state <= HEALTH_FAILED;
end
// Mehrere bestandene Proben erforderlich
if (startup_count >= 8'd64) begin
self_test_passed <= 1'b1;
health_state <= HEALTH_CONTINUOUS;
ready <= 1'b1;
health_ok <= 1'b1;
end
end
end
HEALTH_CONTINUOUS: begin
// SICHER: Kontinuierliche Gesundheitsüberwachung
ready <= 1'b1;
health_ok <= 1'b1;
if (request_random && entropy_ready) begin
// SICHER: Auf festgefahrene Ausgabe prüfen
if (entropy_bits == previous_output) begin
// Wiederholung erkannt - möglicher Fehler
health_state <= HEALTH_FAILED;
end
else begin
random_data <= entropy_bits;
previous_output <= entropy_bits;
end
end
end
HEALTH_FAILED: begin
// SICHER: RNG fehlgeschlagen - keine Ausgabe liefern
ready <= 1'b0;
health_ok <= 1'b0;
random_data <= 128'h0;
// Reset erforderlich zur Wiederherstellung
end
endcase
end
end
endmodule
// SICHER: Software-Krypto mit ordnungsgemäßen Bereitschaftsprüfungen
#include <stdint.h>
#include <stdbool.h>
#define RNG_STATUS_REG 0x40001000
#define RNG_DATA_REG 0x40001004
#define RNG_READY_BIT 0x01
#define RNG_HEALTH_BIT 0x02
// SICHER: RNG-Status vor Verwendung prüfen
static bool is_rng_ready(void) {
volatile uint32_t* rng_status = (volatile uint32_t*)RNG_STATUS_REG;
uint32_t status = *rng_status;
// Sowohl Ready- als auch Health-Bits prüfen
return (status & RNG_READY_BIT) && (status & RNG_HEALTH_BIT);
}
// SICHER: Auf RNG mit Timeout warten
static bool wait_for_rng(uint32_t timeout_ms) {
uint32_t start = get_tick_count();
while (!is_rng_ready()) {
if (get_tick_count() - start > timeout_ms) {
log_error("RNG-Timeout - nicht bereit");
return false;
}
// Kleine Verzögerung, um Register nicht zu überhämmern
delay_us(100);
}
return true;
}
// SICHER: IV nur generieren, wenn RNG bereit ist
bool secure_generate_iv(uint8_t* iv, size_t len) {
volatile uint32_t* rng_data = (volatile uint32_t*)RNG_DATA_REG;
// SICHER: Warten bis RNG bereit ist
if (!wait_for_rng(1000)) {
return false;
}
for (size_t i = 0; i < len; i += 4) {
// SICHER: Verifizieren, dass RNG vor jedem Lesevorgang noch gesund ist
if (!is_rng_ready()) {
log_error("RNG wurde während IV-Generierung ungesund");
return false;
}
uint32_t random = *rng_data;
// SICHER: Plausibilitätsprüfung - offensichtlich schlechte Werte ablehnen
static uint32_t previous = 0;
if (random == previous || random == 0 || random == 0xFFFFFFFF) {
log_error("RNG-Ausgabe verdächtig");
return false;
}
previous = random;
memcpy(iv + i, &random, 4);
}
return true;
}
// SICHER: Schlüssel nur laden, wenn Fuse-Einheit bereit ist
bool secure_load_key(uint8_t* key_out) {
volatile uint32_t* fuse_status = (volatile uint32_t*)FUSE_STATUS_REG;
volatile uint32_t* fuse_key = (volatile uint32_t*)FUSE_KEY_BASE;
// SICHER: Warten bis Fuse-Einheit Initialisierung abgeschlossen hat
uint32_t start = get_tick_count();
while (!(*fuse_status & FUSE_READY_BIT)) {
if (get_tick_count() - start > 1000) {
log_error("Fuse-Einheit nicht bereit");
return false;
}
delay_us(100);
}
// SICHER: Schlüsselgültigkeit prüfen
if (!(*fuse_status & FUSE_KEY_VALID_BIT)) {
log_error("Fuse-Schlüssel nicht gültig");
return false;
}
// Schlüssel lesen
for (int i = 0; i < 4; i++) {
uint32_t word = fuse_key[i];
memcpy(key_out + i*4, &word, 4);
}
// SICHER: Verifizieren, dass Schlüssel nicht nur Nullen oder Einsen ist
if (is_key_weak(key_out, 16)) {
log_error("Schwacher Schlüssel aus Fuses erkannt");
secure_memzero(key_out, 16);
return false;
}
return true;
}
// SICHER: Nur mit gültigen Parametern verschlüsseln
bool secure_encrypt(const uint8_t* plaintext, size_t len,
uint8_t* ciphertext) {
uint8_t iv[16];
uint8_t key[16];
// SICHER: IV mit Verifizierung generieren
if (!secure_generate_iv(iv, 16)) {
log_error("IV-Generierung fehlgeschlagen");
return false;
}
// SICHER: Schlüssel mit Verifizierung laden
if (!secure_load_key(key)) {
log_error("Schlüssel-Laden fehlgeschlagen");
secure_memzero(iv, 16);
return false;
}
// Jetzt sicher zu verschlüsseln
bool result = aes_cbc_encrypt(plaintext, len, key, iv, ciphertext);
// Sensible Daten löschen
secure_memzero(key, 16);
secure_memzero(iv, 16);
return result;
}
CVE-Beispiele
Kryptographische Timing-Schwachstellen wurden in verschiedenen Systemen gefunden, bei denen Krypto-Operationen fortführen, bevor die RNG-Initialisierung abgeschlossen war, was zu vorhersagbaren Schlüsseln oder IVs führte, die ausgenutzt werden könnten.
Verwandte CWEs
- CWE-665: Unsachgemäße Initialisierung (Eltern)
- CWE-696: Falsche Verhaltensreihenfolge (Eltern)
- CWE-1205: Sicherheitsprimitive und Kryptographie-Probleme (Kategorie)
- CWE-330: Verwendung unzureichend zufälliger Werte (verwandt)
- CAPEC-97: Kryptoanalyse (Angriffsmuster)
Referenzen
- MITRE Corporation. "CWE-1279: Cryptographic Operations are run Before Supporting Units are Ready." https://cwe.mitre.org/data/definitions/1279.html
- NIST SP 800-90B. "Recommendation for the Entropy Sources Used for Random Bit Generation"
- FIPS 140-3. "Security Requirements for Cryptographic Modules"