Fehlerhafte Verkettung oder Granularität von Debug-Komponenten

Beschreibung

Fehlerhafte Verkettung oder Granularität von Debug-Komponenten tritt auf, wenn die Debug-Komponenten eines Produkts fehlerhafte Verkettungs- oder Granularitätskonfigurationen enthalten. Die Debug-Infrastruktur in Chips umfasst typischerweise Test Access Ports (TAPs), Scan-Zellen zur Beobachtung interner Komponenten und hierarchische Tracing-Hubs. Logikfehler während des Designs oder der Synthese können die Verbindung dieser Debug-Komponenten falsch konfigurieren und potenziell unbeabsichtigte Zugriffsberechtigungen schaffen, die Sicherheitskontrollen umgehen. Zum Beispiel gewährt die Implementierung einer Daisy-Chain-TAP-Struktur, wenn eine hierarchische Autorisierung erforderlich wäre, unbefugten Zugriff auf interne TAPs, die separate Anmeldeinformationen erfordern sollten.

Risiko

Fehlerhafte Debug-Komponentenverkettung hat schwerwiegende Auswirkungen. Privilegieneskalation durch Debug-Schnittstellen. Umgehung von Schutzmechanismen. Unbefugte Codeausführung. Speichermodifikation über Debug. Kompromittierte Vertraulichkeit. Authentifizierungsumgehung. Unbefugter Zugriff auf interne Komponenten. Gesamte Debug-Hierarchie durch einzelnen Zugangspunkt exponiert. Mittlere Ausnutzungswahrscheinlichkeit.

Lösung

Stellen Sie sicher, dass Debug-Komponenten ordnungsgemäß verkettet sind und ihre Granularität auf verschiedenen Authentifizierungsebenen beibehalten wird. Überprüfen Sie die Debug-Architektur während der Entwurfsphase. Implementieren Sie hierarchische TAP-Strukturen mit separater Authentifizierung für sensible Komponenten. Testen Sie den Debug-Zugriff auf verschiedenen Autorisierungsebenen in Pre-Silicon- und Post-Silicon-Tests. Verwenden Sie formale Verifikation der Debug-Konnektivität. Dokumentieren Sie beabsichtigte Debug-Zugriffsrichtlinien und verifizieren Sie, dass die Implementierung übereinstimmt.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Vertraulichkeit

Unbefugter Zugriff auf interne Register und Speicher.
IntegritätBereich: Integrität

Speichermodifikation durch unsachgemäß exponiertes Debug.
ZugriffskontrolleBereich: Zugriffskontrolle, Authentifizierung

Debug-Authentifizierung durch fehlerhafte Verkettung umgangen.
VerfügbarkeitBereich: Verfügbarkeit

Systemstörung durch unbefugte Debug-Befehle.

Beispielcode und Lösung

Verwundbarer Code

// VERWUNDBAR: Fehlerhafte TAP-Verkettung - Daisy-Chain wo Hierarchie nötig

module vulnerable_tap_controller (
    input  wire        tck,
    input  wire        tms,
    input  wire        tdi,
    input  wire        trst_n,
    output wire        tdo,
    output wire        cpu_debug_enable,
    output wire        secure_debug_enable,
    output wire        key_debug_enable  // VERWUNDBAR: Sensibler Schlüsselzugriff
);

    // VERWUNDBAR: Alle TAPs in einzelner Daisy-Chain
    // Keine separate Authentifizierung für sensible TAPs

    wire cpu_tap_tdo;
    wire secure_tap_tdo;
    wire key_tap_tdo;

    // TAP-Zustandsmaschine
    reg [3:0] state;
    reg [7:0] instruction;

    // VERWUNDBAR: Daisy-Chain aller TAPs
    // Sobald ein TAP zugegriffen wird, sind alle zugänglich

    cpu_tap u_cpu_tap (
        .tck(tck), .tms(tms),
        .tdi(tdi),              // Eingabe von oben
        .trst_n(trst_n),
        .tdo(cpu_tap_tdo),      // Ausgabe zum nächsten
        .debug_enable(cpu_debug_enable)
    );

    // VERWUNDBAR: Sicherer TAP verkettet ohne separate Auth
    secure_tap u_secure_tap (
        .tck(tck), .tms(tms),
        .tdi(cpu_tap_tdo),      // VERWUNDBAR: Vom CPU-TAP verkettet
        .trst_n(trst_n),
        .tdo(secure_tap_tdo),
        .debug_enable(secure_debug_enable)
    );

    // VERWUNDBAR: Schlüssel-TAP auch in derselben Kette
    key_tap u_key_tap (
        .tck(tck), .tms(tms),
        .tdi(secure_tap_tdo),   // VERWUNDBAR: Ohne Auth verkettet
        .trst_n(trst_n),
        .tdo(key_tap_tdo),
        .debug_enable(key_debug_enable)
    );

    assign tdo = key_tap_tdo;   // VERWUNDBAR: Volle Kette exponiert

    // Angriff: Zugriff TDI -> durch CPU-TAP schieben -> sicheren TAP erreichen -> Schlüssel-TAP erreichen
    // Keine Authentifizierung für sensible Komponenten erforderlich

endmodule

// VERWUNDBAR: Fehlerhafte Granularität - einzelne Entsperrung für alles
module vulnerable_debug_unlock (
    input  wire        clk,
    input  wire        rst_n,
    input  wire [63:0] unlock_key,
    input  wire        unlock_request,
    output reg         all_debug_enabled  // VERWUNDBAR: Einzelner Aktivierungsschalter für alles
);

    // VERWUNDBAR: Ein Schlüssel entsperrt alles
    localparam MASTER_KEY = 64'hDEAD_BEEF_CAFE_BABE;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            all_debug_enabled <= 1'b0;
        end else if (unlock_request) begin
            // VERWUNDBAR: Einzelne Prüfung aktiviert alles Debug
            if (unlock_key == MASTER_KEY) begin
                all_debug_enabled <= 1'b1;  // Aktiviert CPU-, Sicher- und Schlüssel-Debug!
            end
        end
    end

endmodule

// VERWUNDBAR: Fehlende Granularität in Scan-Kette
module vulnerable_scan_controller (
    input  wire        scan_enable,
    input  wire        scan_in,
    output wire        scan_out,

    // Interne Register einschließlich sensibler
    output wire [127:0] aes_key_shadow,      // VERWUNDBAR: Schlüssel über Scan zugänglich
    output wire [255:0] private_key_shadow   // VERWUNDBAR: Privater Schlüssel zugänglich
);

    // VERWUNDBAR: Alle Register in einzelner Scan-Kette
    // Keine Trennung zwischen sensiblen und nicht-sensiblen Daten

    reg [127:0] aes_key_reg;
    reg [255:0] private_key_reg;
    reg [31:0]  status_reg;
    reg [31:0]  config_reg;

    // VERWUNDBAR: Einzelne Scan-Kette enthält alles
    assign aes_key_shadow = aes_key_reg;
    assign private_key_shadow = private_key_reg;

    // Volle Scan-Kette: scan_in -> config -> status -> aes_key -> private_key -> scan_out
    // Angreifer kann alle Werte einschließlich Schlüssel herausschieben

endmodule

Sichere Lösung

// SICHER: Hierarchische TAP-Struktur mit ordnungsgemäßer Authentifizierung

module secure_tap_controller (
    input  wire        tck, tms, tdi, trst_n,
    output wire        tdo,
    input  wire        basic_auth_valid,
    input  wire        secure_auth_valid,
    input  wire        key_auth_valid,
    output wire        cpu_debug_enable,
    output wire        secure_debug_enable,
    output wire        key_debug_enable
);

    // SICHER: Hierarchische TAP-Struktur mit separater Authentifizierung

    // SICHER: TAP-Router mit Authentifizierungsgating
    tap_router u_router (
        .tck(tck), .tms(tms), .tdi(tdi), .trst_n(trst_n), .tdo(tdo),
        .basic_auth(basic_auth_valid),
        .secure_auth(secure_auth_valid),
        .key_auth(key_auth_valid),
        // TAP-Auswahl-Ausgaben und -Eingaben...
    );

    // SICHER: Basis-TAP - Produktionstest
    basic_tap u_basic_tap (
        .tck(tck), .tms(tms), .tdi(tdi), .trst_n(trst_n),
        .selected(basic_tap_selected),
        .tdo(basic_tap_tdo)
    );

    // SICHER: CPU-TAP - erfordert Basis-Authentifizierung
    cpu_tap u_cpu_tap (
        .tck(tck), .tms(tms), .tdi(tdi), .trst_n(trst_n),
        .selected(cpu_tap_selected & basic_auth_valid),  // SICHER: Gegated
        .debug_enable(cpu_debug_enable)
    );

    // SICHER: Sicherer TAP - erfordert erweiterte Authentifizierung
    secure_tap u_secure_tap (
        .tck(tck), .tms(tms), .tdi(tdi), .trst_n(trst_n),
        .selected(secure_tap_selected & secure_auth_valid),  // SICHER: Gegated
        .debug_enable(secure_debug_enable)
    );

    // SICHER: Schlüssel-TAP - erfordert höchste Authentifizierung
    key_tap u_key_tap (
        .tck(tck), .tms(tms), .tdi(tdi), .trst_n(trst_n),
        .selected(key_tap_selected & key_auth_valid),  // SICHER: Gegated
        .debug_enable(key_debug_enable)
    );

endmodule

// SICHER: Granulare Debug-Entsperrung mit separaten Stufen
module secure_debug_unlock (
    input  wire        clk, rst_n,
    input  wire [63:0] basic_unlock_key,
    input  wire        basic_unlock_request,
    input  wire [127:0] secure_unlock_key,
    input  wire        secure_unlock_request,
    input  wire [255:0] key_unlock_key,
    input  wire        key_unlock_request,
    output reg         basic_debug_enabled,
    output reg         secure_debug_enabled,
    output reg         key_debug_enabled
);

    // SICHER: Separate Schlüssel für jede Stufe (aus OTP)
    // SICHER: Ratenbegrenzung für Entsperrversuche
    reg [3:0] basic_fail_count, secure_fail_count, key_fail_count;
    localparam MAX_ATTEMPTS = 4'd5;

    // SICHER: Sperrung bei zu vielen Fehlversuchen
    wire basic_locked = (basic_fail_count >= MAX_ATTEMPTS);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            basic_debug_enabled <= 1'b0;
            secure_debug_enabled <= 1'b0;
            key_debug_enabled <= 1'b0;
        end else begin
            // SICHER: Basis-Stufe Entsperrung
            if (basic_unlock_request && !basic_locked) begin
                if (basic_unlock_key == basic_key_otp) begin
                    basic_debug_enabled <= 1'b1;
                end else begin
                    basic_fail_count <= basic_fail_count + 1;
                end
            end

            // SICHER: Sichere Stufe erfordert zuerst Basis
            if (secure_unlock_request && basic_debug_enabled) begin
                // ... Sichere Entsperrlogik
            end

            // SICHER: Schlüssel-Stufe erfordert zuerst Sicher
            if (key_unlock_request && secure_debug_enabled) begin
                // ... Schlüssel-Entsperrlogik
            end
        end
    end

endmodule

// SICHER: Scan-Kette mit ordnungsgemäßer Granularität
module secure_scan_controller (
    input  wire        scan_enable,
    input  wire        scan_in,
    input  wire        secure_scan_auth,  // SICHER: Separate Auth für sicheren Scan
    output wire        scan_out
);

    // SICHER: Separate Scan-Ketten für verschiedene Sicherheitsstufen
    // SICHER: Schlüssel NICHT in irgendeiner Scan-Kette
    // Schlüssel in isoliertem Block ohne Scan-Fähigkeit gespeichert

    // SICHER: Nur nicht-sensible Register in Scan-Kette
    scan_chain #(.WIDTH(64)) u_public_scan (
        .scan_enable(scan_enable),
        .scan_in(scan_in),
        .scan_out(scan_out),
        .regs({status_reg, config_reg})
    );

    // SICHER: Kein Scan-Pfad zu kryptographischen Schlüsseln
    // Schlüssel in isoliertem Block ohne Scan-Fähigkeit gespeichert

    assign scan_out = public_scan_out;

endmodule

// SICHER: TAP-Router mit Authentifizierung
module tap_router (
    input  wire        tck,
    input  wire        tms,
    input  wire        tdi,
    input  wire        trst_n,
    output reg         tdo,

    input  wire        basic_auth,
    input  wire        secure_auth,
    input  wire        key_auth,

    output reg         basic_tap_sel,
    output reg         cpu_tap_sel,
    output reg         secure_tap_sel,
    output reg         key_tap_sel,

    input  wire        basic_tap_tdo,
    input  wire        cpu_tap_tdo,
    input  wire        secure_tap_tdo,
    input  wire        key_tap_tdo
);

    // SICHER: Routing basierend auf IR-Wert UND Authentifizierung
    reg [3:0] current_ir;

    always @(*) begin
        // Standard: kein TAP ausgewählt
        basic_tap_sel = 1'b0;
        cpu_tap_sel = 1'b0;
        secure_tap_sel = 1'b0;
        key_tap_sel = 1'b0;
        tdo = 1'b0;

        case (current_ir)
            4'h0: begin  // Basis-TAP - immer zugänglich
                basic_tap_sel = 1'b1;
                tdo = basic_tap_tdo;
            end

            4'h1: begin  // CPU-TAP - erfordert Basis-Auth
                if (basic_auth) begin
                    cpu_tap_sel = 1'b1;
                    tdo = cpu_tap_tdo;
                end
                // SICHER: Kein Zugriff ohne Auth
            end

            4'h2: begin  // Sicherer TAP - erfordert sichere Auth
                if (secure_auth) begin
                    secure_tap_sel = 1'b1;
                    tdo = secure_tap_tdo;
                end
            end

            4'h3: begin  // Schlüssel-TAP - erfordert Schlüssel-Auth
                if (key_auth) begin
                    key_tap_sel = 1'b1;
                    tdo = key_tap_tdo;
                end
            end

            default: begin
                // Ungültiger IR - kein Zugriff
            end
        endcase
    end

endmodule

CVE-Beispiele

  • CVE-2021-33097: Debug-Ketten-Fehlkonfiguration in Prozessor ermöglichte unbefugten Zugriff auf sichere Debug-Funktionen.
  • CVE-2019-11090: JTAG-Daisy-Chain exponierte sichere Komponenten ohne ordnungsgemäße Authentifizierung.

Verwandte CWEs

  • CWE-284: Unsachgemäße Zugriffskontrolle (übergeordnet)
  • CWE-1207: Debug- und Testprobleme (Kategorie)
  • CWE-1295: Debug-Nachrichten enthüllen unnötige Informationen (verwandt)
  • CWE-1244: Internes Asset unsicherem Debug-Zugriff ausgesetzt (verwandt)

Referenzen

  1. MITRE Corporation. "CWE-1296: Incorrect Chaining or Granularity of Debug Components." https://cwe.mitre.org/data/definitions/1296.html
  2. IEEE 1149.1: Standard Test Access Port and Boundary-Scan Architecture
  3. CAPEC-702: Exploiting Incorrect Chaining or Granularity of Hardware Debug Components