Incorrect Chaining or Granularity of Debug Components
Description
Incorrect Chaining or Granularity of Debug Components occurs when a product's debug components contain incorrect chaining or granularity configurations. Debug infrastructure in chips typically includes Test Access Ports (TAPs), scan cells for internal component observation, and hierarchical tracing hubs. Logic errors during design or synthesis can misconfigure how these debug components interconnect, potentially creating unintended access permissions that bypass security controls. For example, implementing a daisy-chained TAP structure when hierarchical authorization was required grants unauthorized access to internal TAPs that should require separate credentials.
Risk
Incorrect debug component chaining has severe implications. Privilege escalation through debug interfaces. Protection mechanism bypass. Unauthorized code execution. Memory modification via debug. Compromised confidentiality. Authentication bypass. Unauthorized access to internal components. Entire debug hierarchy exposed through single access point. Medium likelihood of exploitation.
Solution
Ensure that debug components are properly chained and their granularity is maintained at different authentication levels. Review debug architecture during design phase. Implement hierarchical TAP structures with separate authentication for sensitive components. Test debug access at various authorization levels in both pre-silicon and post-silicon testing. Use formal verification of debug connectivity. Document intended debug access policies and verify implementation matches.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality | Scope: Confidentiality Unauthorized access to internal registers and memory. |
| Integrity | Scope: Integrity Memory modification through improperly exposed debug. |
| Access Control | Scope: Access Control, Authentication Debug authentication bypassed through incorrect chaining. |
| Availability | Scope: Availability System disruption through unauthorized debug commands. |
Example Code
Vulnerable Code
// Vulnerable: Incorrect TAP chaining - daisy chain where hierarchy needed
module vulnerable_tap_controller (
input wire tck,
input wire tms,
input wire tdi,
input wire trst_n,
output wire tdo,
// Debug access signals
output wire cpu_debug_enable,
output wire secure_debug_enable,
output wire key_debug_enable // VULNERABLE: Sensitive key access
);
// VULNERABLE: All TAPs in single daisy chain
// No separate authentication for sensitive TAPs
wire cpu_tap_tdo;
wire secure_tap_tdo;
wire key_tap_tdo;
// TAP state machine
reg [3:0] state;
reg [7:0] instruction;
// VULNERABLE: Daisy-chain all TAPs together
// Once any TAP is accessed, all are accessible
cpu_tap u_cpu_tap (
.tck(tck),
.tms(tms),
.tdi(tdi), // Input from top
.trst_n(trst_n),
.tdo(cpu_tap_tdo), // Output to next
.debug_enable(cpu_debug_enable)
);
// VULNERABLE: Secure TAP chained without separate auth
secure_tap u_secure_tap (
.tck(tck),
.tms(tms),
.tdi(cpu_tap_tdo), // VULNERABLE: Chained from CPU TAP
.trst_n(trst_n),
.tdo(secure_tap_tdo),
.debug_enable(secure_debug_enable)
);
// VULNERABLE: Key TAP also in same chain
key_tap u_key_tap (
.tck(tck),
.tms(tms),
.tdi(secure_tap_tdo), // VULNERABLE: Chained without auth
.trst_n(trst_n),
.tdo(key_tap_tdo),
.debug_enable(key_debug_enable)
);
assign tdo = key_tap_tdo; // VULNERABLE: Full chain exposed
// Attack: Access TDI -> shift through CPU TAP -> reach secure TAP -> reach key TAP
// No authentication required for sensitive components
endmodule
// Vulnerable: Incorrect granularity - single unlock for all
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 // VULNERABLE: Single enable for all
);
// VULNERABLE: One key unlocks everything
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
// VULNERABLE: Single check enables all debug
if (unlock_key == MASTER_KEY) begin
all_debug_enabled <= 1'b1; // Enables CPU, secure, and key debug!
end
end
end
endmodule
// Vulnerable: Missing granularity in scan chain
module vulnerable_scan_controller (
input wire scan_enable,
input wire scan_in,
output wire scan_out,
// Internal registers including sensitive ones
output wire [127:0] aes_key_shadow, // VULNERABLE: Key accessible via scan
output wire [255:0] private_key_shadow // VULNERABLE: Private key accessible
);
// VULNERABLE: All registers in single scan chain
// No separation between sensitive and non-sensitive data
reg [127:0] aes_key_reg;
reg [255:0] private_key_reg;
reg [31:0] status_reg;
reg [31:0] config_reg;
// VULNERABLE: Single scan chain includes everything
assign aes_key_shadow = aes_key_reg;
assign private_key_shadow = private_key_reg;
// Full scan chain: scan_in -> config -> status -> aes_key -> private_key -> scan_out
// Attacker can shift out all values including keys
endmodule
Fixed Code
// Fixed: Hierarchical TAP structure with proper authentication
module secure_tap_controller (
input wire tck,
input wire tms,
input wire tdi,
input wire trst_n,
output wire tdo,
// Authentication signals
input wire basic_auth_valid,
input wire secure_auth_valid,
input wire key_auth_valid,
// Debug access signals
output wire cpu_debug_enable,
output wire secure_debug_enable,
output wire key_debug_enable
);
// FIXED: Hierarchical TAP structure with separate authentication
// Level 1: Basic TAP (always accessible for production test)
wire basic_tap_tdo;
wire basic_tap_selected;
// Level 2: CPU debug TAP (requires basic authentication)
wire cpu_tap_tdo;
wire cpu_tap_selected;
// Level 3: Secure TAP (requires enhanced authentication)
wire secure_tap_tdo;
wire secure_tap_selected;
// Level 4: Key TAP (requires highest authentication)
wire key_tap_tdo;
wire key_tap_selected;
// FIXED: TAP router with authentication gating
tap_router u_router (
.tck(tck),
.tms(tms),
.tdi(tdi),
.trst_n(trst_n),
.tdo(tdo),
// Authentication inputs
.basic_auth(basic_auth_valid),
.secure_auth(secure_auth_valid),
.key_auth(key_auth_valid),
// TAP selection outputs (authentication-gated)
.basic_tap_sel(basic_tap_selected),
.cpu_tap_sel(cpu_tap_selected),
.secure_tap_sel(secure_tap_selected),
.key_tap_sel(key_tap_selected),
// TAP data inputs
.basic_tap_tdo(basic_tap_tdo),
.cpu_tap_tdo(cpu_tap_tdo),
.secure_tap_tdo(secure_tap_tdo),
.key_tap_tdo(key_tap_tdo)
);
// FIXED: Basic TAP - production test
basic_tap u_basic_tap (
.tck(tck),
.tms(tms),
.tdi(tdi),
.trst_n(trst_n),
.selected(basic_tap_selected),
.tdo(basic_tap_tdo)
);
// FIXED: CPU TAP - requires basic authentication
cpu_tap u_cpu_tap (
.tck(tck),
.tms(tms),
.tdi(tdi),
.trst_n(trst_n),
.selected(cpu_tap_selected & basic_auth_valid), // FIXED: Gated
.tdo(cpu_tap_tdo),
.debug_enable(cpu_debug_enable)
);
// FIXED: Secure TAP - requires secure authentication
secure_tap u_secure_tap (
.tck(tck),
.tms(tms),
.tdi(tdi),
.trst_n(trst_n),
.selected(secure_tap_selected & secure_auth_valid), // FIXED: Gated
.tdo(secure_tap_tdo),
.debug_enable(secure_debug_enable)
);
// FIXED: Key TAP - requires key authentication
key_tap u_key_tap (
.tck(tck),
.tms(tms),
.tdi(tdi),
.trst_n(trst_n),
.selected(key_tap_selected & key_auth_valid), // FIXED: Gated
.tdo(key_tap_tdo),
.debug_enable(key_debug_enable)
);
endmodule
// Fixed: Granular debug unlock with separate levels
module secure_debug_unlock (
input wire clk,
input wire rst_n,
// Separate unlock interfaces for each level
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,
// Separate enable outputs
output reg basic_debug_enabled,
output reg secure_debug_enabled,
output reg key_debug_enabled
);
// FIXED: Separate keys for each level (from OTP)
wire [63:0] basic_key_otp;
wire [127:0] secure_key_otp;
wire [255:0] key_key_otp;
// FIXED: Rate limiting for unlock attempts
reg [3:0] basic_fail_count;
reg [3:0] secure_fail_count;
reg [3:0] key_fail_count;
localparam MAX_ATTEMPTS = 4'd5;
// FIXED: Lockout on too many failures
wire basic_locked = (basic_fail_count >= MAX_ATTEMPTS);
wire secure_locked = (secure_fail_count >= MAX_ATTEMPTS);
wire key_locked = (key_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;
basic_fail_count <= 4'd0;
secure_fail_count <= 4'd0;
key_fail_count <= 4'd0;
end else begin
// FIXED: Basic level unlock
if (basic_unlock_request && !basic_locked) begin
if (basic_unlock_key == basic_key_otp) begin
basic_debug_enabled <= 1'b1;
basic_fail_count <= 4'd0;
end else begin
basic_fail_count <= basic_fail_count + 1;
end
end
// FIXED: Secure level requires basic first
if (secure_unlock_request && !secure_locked && basic_debug_enabled) begin
if (secure_unlock_key == secure_key_otp) begin
secure_debug_enabled <= 1'b1;
secure_fail_count <= 4'd0;
end else begin
secure_fail_count <= secure_fail_count + 1;
end
end
// FIXED: Key level requires secure first
if (key_unlock_request && !key_locked && secure_debug_enabled) begin
if (key_unlock_key == key_key_otp) begin
key_debug_enabled <= 1'b1;
key_fail_count <= 4'd0;
end else begin
key_fail_count <= key_fail_count + 1;
end
end
end
end
endmodule
// Fixed: Scan chain with proper granularity
module secure_scan_controller (
input wire scan_enable,
input wire scan_in,
input wire secure_scan_auth, // FIXED: Separate auth for secure scan
output wire scan_out,
// Non-sensitive scan access
output wire [31:0] status_shadow,
output wire [31:0] config_shadow
);
// FIXED: Separate scan chains for different security levels
// Public scan chain - general registers
wire public_scan_out;
// FIXED: Secure registers excluded from scan chain entirely
// Or use separate authenticated secure scan chain
reg [31:0] status_reg;
reg [31:0] config_reg;
// FIXED: Keys are NOT in any scan chain
// Keys stored in isolated block without scan capability
// reg [127:0] aes_key_reg; // NOT SCANNABLE
// reg [255:0] private_key_reg; // NOT SCANNABLE
// FIXED: Only non-sensitive registers in scan chain
assign status_shadow = status_reg;
assign config_shadow = config_reg;
// FIXED: Secure scan only with authentication
scan_chain #(.WIDTH(64)) u_public_scan (
.scan_enable(scan_enable),
.scan_in(scan_in),
.scan_out(public_scan_out),
.regs({status_reg, config_reg})
);
// FIXED: No scan path to cryptographic keys
// Keys are isolated in non-scannable block
assign scan_out = public_scan_out;
endmodule
// Fixed: TAP router with authentication
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
);
// FIXED: Route based on IR value AND authentication
reg [3:0] current_ir;
always @(*) begin
// Default: no TAP selected
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 // Basic TAP - always accessible
basic_tap_sel = 1'b1;
tdo = basic_tap_tdo;
end
4'h1: begin // CPU TAP - requires basic auth
if (basic_auth) begin
cpu_tap_sel = 1'b1;
tdo = cpu_tap_tdo;
end
// FIXED: No access without auth
end
4'h2: begin // Secure TAP - requires secure auth
if (secure_auth) begin
secure_tap_sel = 1'b1;
tdo = secure_tap_tdo;
end
end
4'h3: begin // Key TAP - requires key auth
if (key_auth) begin
key_tap_sel = 1'b1;
tdo = key_tap_tdo;
end
end
default: begin
// Invalid IR - no access
end
endcase
end
endmodule
CVE Examples
- CVE-2021-33097: Debug chain misconfiguration in processor allowed unauthorized access to secure debug features.
- CVE-2019-11090: JTAG daisy chain exposed secure components without proper authentication.
Related CWEs
- CWE-284: Improper Access Control (parent)
- CWE-1207: Debug and Test Problems (category)
- CWE-1295: Debug Messages Revealing Unnecessary Information (related)
- CWE-1244: Internal Asset Exposed to Unsafe Debug Access (related)
References
- MITRE Corporation. "CWE-1296: Incorrect Chaining or Granularity of Debug Components." https://cwe.mitre.org/data/definitions/1296.html
- IEEE 1149.1: Standard Test Access Port and Boundary-Scan Architecture
- CAPEC-702: Exploiting Incorrect Chaining or Granularity of Hardware Debug Components