Fehlerhafte Auswahl von Fuse-Werten

Beschreibung

Fehlerhafte Auswahl von Fuse-Werten tritt auf, wenn ein Produkt auf eine nicht durchgebrannte Fuse angewiesen ist, um einen sicheren Systemzustand herzustellen. Da Fuses standardmäßig auf Logik 0 (nicht durchgebrannt) stehen und auf Logik 1 durchgebrannt, aber nicht einfach zurückgesetzt werden können, erzeugt die Verwendung negativer Logik eine Schwachstelle. Fuses speichern Sicherheitskonfigurationsdaten und sind gerichtet -- einmal auf 1 durchgebrannt, können sie ohne Spezialausrüstung nicht auf 0 zurückkehren. Die Schwachstelle entsteht, wenn die Sicherheitslogik des Systems davon abhängt, dass Fuses nicht durchgebrannt bleiben, wodurch Angreifer Fuses durchbrennen und das System in einen unsicheren Zustand überführen können.

Risiko

Fehlerhafte Fuse-Logik hat schwerwiegende Sicherheitsauswirkungen. Secure Boot kann durch Durchbrennen von Fuses deaktiviert werden. Debug-Schnittstellen können wieder aktiviert werden. Sicherheitsfunktionen können umgangen werden. JTAG-Zugriff kann entsperrt werden. Firmware-Signaturüberprüfung kann übersprungen werden. Produktionssicherheit kann kompromittiert werden. Geräteintegrität kann dauerhaft beschädigt werden. Angreifer erlangen persistenten Zugang durch Hardware-Modifikation.

Lösung

Entwerfen Sie Logik so, dass durchgebrannte Fuses das Produkt nicht in einen ausnutzbaren unsicheren Zustand überführen. Verwenden Sie positive Logik, bei der die Sicherheit beibehalten oder erhöht wird, wenn Fuses durchgebrannt werden. Stellen Sie sicher, dass der Standard-Zustand (nicht durchgebrannt) der weniger sichere Zustand ist. Lassen Sie durchgebrannte Fuses Sicherheitsfunktionen aktivieren statt deaktivieren. Implementieren Sie redundante Fuse-Prüfungen. Fügen Sie Manipulationserkennung für Fuse-Manipulation hinzu. Verwenden Sie Fuse-Redundanz mit Mehrheitsentscheidung.

Häufige Auswirkungen

AuswirkungDetails
ZugriffskontrolleUmfang: Zugriffskontrolle

Schutzmechanismus umgehen - Wenn Sicherheitslogik negative Logik verwendet, könnte ein Angreifer die Fuse durchbrennen und das System in einen unsicheren Zustand treiben.
VerfügbarkeitUmfang: Verfügbarkeit

DoS: Absturz, Beendigung oder Neustart - Fuse-Manipulation kann Systeminstabilität verursachen.
VertraulichkeitUmfang: Vertraulichkeit

Unbefugter Speicherzugriff - Umgehung der Sicherheit ermöglicht Zugriff auf geschützte Daten.
IntegritätUmfang: Integrität

Speichermodifikation oder unbefugte Codeausführung - Sicherheitsumgehung ermöglicht die Ausführung unbefugten Codes.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Negative Logik-Fuse für Secure Boot

module vulnerable_secure_boot_fuse (
    input wire clk,
    input wire reset_n,
    input wire fuse_secure_boot,    // 0 = Secure Boot AN, 1 = Secure Boot AUS
    input wire firmware_signature_valid,
    output reg boot_allowed
);

    // VERWUNDBAR: Negative Logik
    // Fuse standardmäßig 0 (nicht durchgebrannt) = Secure Boot aktiviert
    // Angreifer kann Fuse auf 1 durchbrennen = Secure Boot deaktiviert

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            boot_allowed <= 1'b0;
        end
        else begin
            // VERWUNDBAR: Fuse mit negativer Logik prüfen
            if (fuse_secure_boot == 1'b0) begin
                // Fuse nicht durchgebrannt - Signaturüberprüfung erforderlich
                boot_allowed <= firmware_signature_valid;
            end
            else begin
                // VERWUNDBAR: Fuse durchgebrannt - Überprüfung überspringen!
                // Angreifer brennt Fuse durch, um Secure Boot zu umgehen
                boot_allowed <= 1'b1;
            end
        end
    end

endmodule

// VERWUNDBAR: Debug-Sperre mit negativer Logik
module vulnerable_debug_fuse (
    input wire clk,
    input wire reset_n,
    input wire fuse_debug_lock,     // 0 = Debug gesperrt, 1 = Debug entsperrt
    input wire debug_request,
    output reg debug_allowed
);

    // VERWUNDBAR: Negative Logik für Debug-Sperre
    // Fuse standardmäßig 0 = Debug gesperrt
    // Angreifer brennt Fuse auf 1 = Debug entsperrt

    always @(*) begin
        if (fuse_debug_lock == 1'b0) begin
            // Fuse nicht durchgebrannt - Debug gesperrt
            debug_allowed = 1'b0;
        end
        else begin
            // VERWUNDBAR: Fuse durchgebrannt - Debug entsperrt!
            debug_allowed = debug_request;
        end
    end

endmodule

// VERWUNDBAR: Sicherheitsstufen-Fuse mit falschem Standard
module vulnerable_security_level_fuse (
    input wire clk,
    input wire reset_n,
    input wire [1:0] fuse_security_level,  // 00 = höchste, 11 = niedrigste
    input wire [1:0] required_level,
    output reg access_allowed
);

    // VERWUNDBAR: Nicht durchgebrannte Fuses (00) = höchste Sicherheit
    // Angreifer kann Fuses durchbrennen, um Sicherheitsstufe zu senken

    always @(*) begin
        // Niedrigere Zahl = höhere Sicherheit
        // VERWUNDBAR: Durchbrennen von Fuses senkt Sicherheit
        if (fuse_security_level <= required_level) begin
            access_allowed = 1'b1;
        end
        else begin
            access_allowed = 1'b0;
        end
    end

    // Angriff: Beide Fuses durchbrennen für Stufe 11 (niedrigste)
    // Dies gewährt Zugriff auf alles

endmodule
// VERWUNDBAR: Firmware liest Fuse mit negativer Logik

#define FUSE_REGISTER 0x40000000
#define FUSE_SECURE_BOOT_BIT 0

uint32_t read_fuse(void) {
    return *(volatile uint32_t*)FUSE_REGISTER;
}

void vulnerable_boot_check(void) {
    uint32_t fuses = read_fuse();

    // VERWUNDBAR: Negative Logik
    // Bit 0 = 0 bedeutet Secure Boot aktiviert
    // Bit 0 = 1 bedeutet Secure Boot deaktiviert
    if ((fuses & (1 << FUSE_SECURE_BOOT_BIT)) == 0) {
        // Fuse nicht durchgebrannt - Secure Boot durchführen
        if (!verify_firmware_signature()) {
            halt_boot("Signaturüberprüfung fehlgeschlagen");
        }
    }
    else {
        // VERWUNDBAR: Fuse durchgebrannt - Überprüfung überspringen
        // Angreifer kann diese Fuse durchbrennen, um unsignierte Firmware zu laden
    }

    continue_boot();
}

// VERWUNDBAR: Debug-Aktivierungs-Fuse
void vulnerable_debug_init(void) {
    uint32_t fuses = read_fuse();

    // VERWUNDBAR: Fuse-Bit 1 = 0 bedeutet Debug deaktiviert
    // Fuse-Bit 1 = 1 bedeutet Debug aktiviert
    if (fuses & (1 << 1)) {
        // VERWUNDBAR: Durchgebrannte Fuse aktiviert Debug!
        enable_jtag();
        enable_uart_debug();
    }
}

Sichere Lösung

// SICHER: Positive Logik-Fuse für Secure Boot

module secure_boot_fuse (
    input wire clk,
    input wire reset_n,
    input wire fuse_secure_boot,    // 0 = Entwicklungsmodus, 1 = Produktion sicher
    input wire firmware_signature_valid,
    output reg boot_allowed
);

    // SICHER: Positive Logik
    // Fuse standardmäßig 0 (nicht durchgebrannt) = Entwicklungsmodus (weniger sicher)
    // Fuse auf 1 durchgebrannt = Produktionsmodus (Secure Boot erforderlich)
    // Angreifer kann Fuse nicht ent-brennen, um Sicherheit zu deaktivieren

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            boot_allowed <= 1'b0;
        end
        else begin
            // SICHER: Positive Logik - durchgebrannte Fuse erzwingt Sicherheit
            if (fuse_secure_boot == 1'b1) begin
                // Produktionsmodus - Signaturüberprüfung erforderlich
                boot_allowed <= firmware_signature_valid;
            end
            else begin
                // Entwicklungsmodus - kann unsigniert für Entwicklung erlauben
                // Aber dies ist der STANDARD-Zustand, nicht angreifbar
                boot_allowed <= 1'b1;  // Oder dennoch Signatur erfordern
            end
        end
    end

endmodule

// SICHER: Debug-Sperre mit positiver Logik
module secure_debug_fuse (
    input wire clk,
    input wire reset_n,
    input wire fuse_debug_disable,  // 0 = Debug verfügbar, 1 = Debug gesperrt
    input wire debug_request,
    output reg debug_allowed
);

    // SICHER: Positive Logik für Debug-Sperre
    // Fuse standardmäßig 0 = Debug verfügbar (Entwicklung)
    // Fuse auf 1 durchgebrannt = Debug dauerhaft gesperrt (Produktion)
    // Angreifer kann Fuse nicht ent-brennen, um Debug wieder zu aktivieren

    always @(*) begin
        if (fuse_debug_disable == 1'b1) begin
            // SICHER: Durchgebrannte Fuse = Debug für immer gesperrt
            debug_allowed = 1'b0;
        end
        else begin
            // Nicht durchgebrannt = Debug verfügbar (Entwicklungsmodus-Standard)
            debug_allowed = debug_request;
        end
    end

endmodule

// SICHER: Sicherheitsstufen-Fuse mit korrekter Kodierung
module secure_security_level_fuse (
    input wire clk,
    input wire reset_n,
    input wire [1:0] fuse_security_level,  // 00 = niedrigste, 11 = höchste
    input wire [1:0] required_level,
    output reg access_allowed
);

    // SICHER: Nicht durchgebrannte Fuses (00) = niedrigste Sicherheit (Entwicklungsstandard)
    // Durchbrennen von Fuses ERHÖHT Sicherheitsstufe
    // Angreifer kann seinen Zugriff nicht durch Durchbrennen von Fuses erhöhen

    always @(*) begin
        // SICHER: Höherer Fuse-Wert = höhere Sicherheit
        // Durchbrennen von Fuses kann nur Zugriff einschränken, nicht gewähren
        if (fuse_security_level >= required_level) begin
            access_allowed = 1'b1;
        end
        else begin
            access_allowed = 1'b0;
        end
    end

    // Angriffsversuch: Durchbrennen von Fuses erhöht Sicherheitsstufe
    // Dies macht den Zugriff NUR restriktiver, nicht weniger

endmodule

// SICHER: Redundante Fuse-Prüfung
module secure_redundant_fuse (
    input wire clk,
    input wire reset_n,
    input wire fuse_secure_a,       // Primäre Secure-Boot-Fuse
    input wire fuse_secure_b,       // Redundante Secure-Boot-Fuse
    input wire fuse_secure_c,       // Zweite redundante Fuse
    input wire firmware_signature_valid,
    output reg boot_allowed,
    output reg tamper_detected
);

    // SICHER: Redundante Fuses mit Mehrheitsentscheidung verwenden
    wire [1:0] secure_vote;
    assign secure_vote = fuse_secure_a + fuse_secure_b + fuse_secure_c;

    // SICHER: Manipulation erkennen (Fuses sollten übereinstimmen)
    wire fuses_consistent;
    assign fuses_consistent = (fuse_secure_a == fuse_secure_b) &&
                              (fuse_secure_b == fuse_secure_c);

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            boot_allowed <= 1'b0;
            tamper_detected <= 1'b0;
        end
        else begin
            // SICHER: Auf inkonsistente Fuses prüfen (Manipulation)
            if (!fuses_consistent) begin
                tamper_detected <= 1'b1;
                boot_allowed <= 1'b0;  // Ausfallsicher
            end
            // SICHER: Mehrheitsentscheidung (mindestens 2 von 3)
            else if (secure_vote >= 2'd2) begin
                // Produktionsmodus - Signatur erforderlich
                boot_allowed <= firmware_signature_valid;
            end
            else begin
                // Entwicklungsmodus
                boot_allowed <= 1'b1;
            end
        end
    end

endmodule
// SICHER: Firmware liest Fuse mit positiver Logik

#define FUSE_REGISTER 0x40000000
#define FUSE_PRODUCTION_MODE_BIT 0
#define FUSE_DEBUG_LOCKED_BIT 1

uint32_t read_fuse(void) {
    return *(volatile uint32_t*)FUSE_REGISTER;
}

void secure_boot_check(void) {
    uint32_t fuses = read_fuse();

    // SICHER: Positive Logik
    // Bit 0 = 0 bedeutet Entwicklungsmodus (Standard)
    // Bit 0 = 1 bedeutet Produktionsmodus (Secure Boot erzwungen)
    if (fuses & (1 << FUSE_PRODUCTION_MODE_BIT)) {
        // SICHER: Durchgebrannte Fuse = Signatur muss überprüft werden
        if (!verify_firmware_signature()) {
            halt_boot("Signaturüberprüfung fehlgeschlagen");
        }
    }
    else {
        // Entwicklungsmodus - Warnung protokollieren
        log_warning("Läuft im Entwicklungsmodus ohne Signaturprüfung");
        // Auch im Entwicklungsmodus wird Signaturüberprüfung empfohlen
    }

    continue_boot();
}

// SICHER: Debug-Deaktivierungs-Fuse
void secure_debug_init(void) {
    uint32_t fuses = read_fuse();

    // SICHER: Fuse-Bit 1 = 0 bedeutet Debug verfügbar (Entwicklungsstandard)
    // Fuse-Bit 1 = 1 bedeutet Debug dauerhaft deaktiviert (Produktion)
    if (fuses & (1 << FUSE_DEBUG_LOCKED_BIT)) {
        // SICHER: Durchgebrannte Fuse = Debug für immer gesperrt
        disable_jtag();
        disable_uart_debug();
        log_info("Debug-Schnittstellen dauerhaft deaktiviert");
    }
    else {
        // Entwicklungsmodus - Debug verfügbar
        enable_jtag();
        enable_uart_debug();
        log_warning("Debug-Schnittstellen aktiviert - Entwicklungsmodus");
    }
}

// SICHER: Redundante Fuse-Prüfung
void secure_boot_redundant(void) {
    uint32_t fuses = read_fuse();

    // Drei redundante Fuse-Bits lesen
    int fuse_a = (fuses >> 0) & 1;
    int fuse_b = (fuses >> 1) & 1;
    int fuse_c = (fuses >> 2) & 1;

    // SICHER: Auf Manipulation prüfen (inkonsistente Fuses)
    if (fuse_a != fuse_b || fuse_b != fuse_c) {
        halt_boot("Fuse-Manipulation erkannt!");
    }

    // SICHER: Mehrheitsentscheidung
    int production_mode = (fuse_a + fuse_b + fuse_c) >= 2;

    if (production_mode) {
        if (!verify_firmware_signature()) {
            halt_boot("Signaturüberprüfung fehlgeschlagen");
        }
    }
}

CVE-Beispiele

Fuse-Logik-Schwachstellen wurden in verschiedenen Geräten gefunden, bei denen Angreifer Fuses durchbrennen könnten, um Secure Boot zu deaktivieren, Debug-Schnittstellen wieder zu aktivieren oder Sicherheitsfunktionen zu umgehen. Beispiele umfassen Geräte, bei denen das Durchbrennen einer einzigen Fuse die Signaturüberprüfung deaktivieren könnte.


Verwandte CWEs

  • CWE-693: Versagen des Schutzmechanismus (übergeordnet)
  • CWE-1278: Fehlender Schutz gegen Hardware-Reverse-Engineering (verwandt)
  • CWE-1338: Unsachgemäßer Schutz gegen Hardware-Überschreiben von sicherheitskonfigurierten Fuses (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-1253: Incorrect Selection of Fuse Values." https://cwe.mitre.org/data/definitions/1253.html
  2. ARM. "TrustZone Security" - Fuse-basierte Konfiguration
  3. NXP. "Secure Boot Architecture" - OTP Fuse Programming