Hardware Child Block Incorrectly Connected to Parent System
Description
Hardware Child Block Incorrectly Connected to Parent System occurs when signals between a hardware IP component and the parent system design are incorrectly connected causing security risks. Hardware IP components require proper communication with parent systems for correct functionality. Incorrect connections, while potentially avoiding functional problems, can introduce security vulnerabilities. For example, when a reset input connects to a debug mode reset instead of a system-wide hard reset, compromising data integrity, or when security level signals are grounded instead of properly connected.
Risk
Incorrect signal connections have severe security implications. Security levels may be incorrectly assigned. Debug signals may be improperly routed. Reset behavior may be compromised. Interrupts may be lost or misdirected. Access control may be bypassed. Privilege separation may fail. Information may leak across security domains. System security assumptions may be violated.
Solution
Use system-level verification to ensure that components are correctly connected and that design security requirements are not violated due to interactions between various IP blocks. Review integration code for signal connection errors. Implement formal verification of security-critical signal paths. Document expected connections and verify against implementation. Test security functionality after integration.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality | Scope: Confidentiality Read Memory - Incorrect connections may expose sensitive data. |
| Integrity | Scope: Integrity Modify Memory - Security controls may be bypassed. |
| Availability | Scope: Availability DoS - System may malfunction due to incorrect signaling. |
| Access Control | Scope: Access Control Bypass Protection Mechanism - Security level signals may be compromised. |
Example Code
Vulnerable Code
// Vulnerable: TrustZone security level grounded instead of connected
module vulnerable_system_integration (
input wire clk,
input wire reset_n,
// AXI master interface from CPU
input wire [31:0] cpu_awaddr,
input wire cpu_awvalid,
input wire cpu_awprot_secure, // CPU security level signal
output wire cpu_awready,
// AXI slave interface to memory
output wire [31:0] mem_awaddr,
output wire mem_awvalid,
output wire mem_awprot_secure, // Memory security level
input wire mem_awready
);
// VULNERABLE: Security level signal grounded to 0 (secure)
// instead of connected to CPU output
axi_interconnect interconnect_inst (
.clk(clk),
.reset_n(reset_n),
// Master interface
.s_awaddr(cpu_awaddr),
.s_awvalid(cpu_awvalid),
// VULNERABLE: Grounded to secure level instead of connected
.s_awprot_secure(1'b0), // Should be: cpu_awprot_secure
.s_awready(cpu_awready),
// Slave interface
.m_awaddr(mem_awaddr),
.m_awvalid(mem_awvalid),
.m_awprot_secure(mem_awprot_secure),
.m_awready(mem_awready)
);
// Problem: All transactions appear as "secure"
// Non-secure world can access secure memory!
endmodule
// Vulnerable: Interrupt signals not connected
module vulnerable_csr_integration (
input wire clk,
input wire reset_n,
// CSR interface
input wire [7:0] csr_addr,
input wire [31:0] csr_write_data,
input wire csr_write,
output wire [31:0] csr_read_data,
// Interrupt signals (should be connected)
output wire tamper_interrupt,
output wire error_interrupt,
output wire overflow_interrupt
);
// CSR register file instance
csr_register_file csr_inst (
.clk(clk),
.reset_n(reset_n),
.addr(csr_addr),
.write_data(csr_write_data),
.write_enable(csr_write),
.read_data(csr_read_data),
// VULNERABLE: Interrupt ports left unconnected
.tamper_int(), // Should be: tamper_interrupt
.error_int(), // Should be: error_interrupt
.overflow_int() // Should be: overflow_interrupt
);
// VULNERABLE: Interrupts are lost
// System never notified of security events!
// Tamper attempts go undetected
endmodule
// Vulnerable: Reset signal incorrectly connected
module vulnerable_reset_connection (
input wire clk,
input wire system_hard_reset_n,
input wire debug_soft_reset_n,
// Security subsystem
output wire security_reset_n
);
// Security subsystem needs hard reset to clear sensitive state
security_controller sec_ctrl (
.clk(clk),
// VULNERABLE: Connected to debug reset instead of hard reset
.reset_n(debug_soft_reset_n), // Should be: system_hard_reset_n
.security_reset_n(security_reset_n)
);
// Problem: Debug reset doesn't clear security state
// Sensitive data persists across debug resets
// Attacker can use debug reset to preserve access
endmodule
// Vulnerable: Software misconfiguration mirroring hardware issues
#include <stdint.h>
// VULNERABLE: Wrong register address definitions
// Copy-paste error from different chip version
#define SECURITY_CTRL_BASE 0x40001000 // Wrong! Should be 0x40002000
#define CRYPTO_ENGINE_BASE 0x40002000 // Wrong! Should be 0x40003000
typedef struct {
volatile uint32_t ctrl;
volatile uint32_t status;
volatile uint32_t key[8];
} crypto_regs_t;
void vulnerable_crypto_init(void) {
// VULNERABLE: Accessing wrong peripheral due to address error
crypto_regs_t* crypto = (crypto_regs_t*)CRYPTO_ENGINE_BASE;
// Actually writing to different peripheral!
crypto->ctrl = 0x01; // Enable crypto (but wrong address)
// Problem: Security controller at 0x40002000 is modified
// Crypto engine at 0x40003000 is not configured
// Security may be disabled instead of enabling crypto!
}
// VULNERABLE: Interrupt handler connected to wrong interrupt
void vulnerable_interrupt_setup(void) {
// Connect tamper handler to wrong interrupt number
register_interrupt_handler(
IRQ_TIMER, // VULNERABLE: Should be IRQ_TAMPER
tamper_handler
);
// Timer interrupts trigger tamper handler
// Tamper events never handled!
}
Fixed Code
// Fixed: TrustZone security level properly connected
module secure_system_integration (
input wire clk,
input wire reset_n,
// AXI master interface from CPU
input wire [31:0] cpu_awaddr,
input wire cpu_awvalid,
input wire cpu_awprot_secure,
output wire cpu_awready,
// AXI slave interface to memory
output wire [31:0] mem_awaddr,
output wire mem_awvalid,
output wire mem_awprot_secure,
input wire mem_awready,
// Debug/verification outputs
output wire security_mismatch
);
// FIXED: Security level signal properly connected
wire internal_security_level;
axi_interconnect interconnect_inst (
.clk(clk),
.reset_n(reset_n),
// Master interface
.s_awaddr(cpu_awaddr),
.s_awvalid(cpu_awvalid),
// FIXED: Properly connected to CPU output
.s_awprot_secure(cpu_awprot_secure),
.s_awready(cpu_awready),
// Slave interface
.m_awaddr(mem_awaddr),
.m_awvalid(mem_awvalid),
.m_awprot_secure(mem_awprot_secure),
.m_awready(mem_awready),
// FIXED: Internal signal for verification
.security_level_internal(internal_security_level)
);
// FIXED: Verify security signal propagation
assign security_mismatch = (cpu_awprot_secure != internal_security_level);
endmodule
// Fixed: Interrupt signals properly connected
module secure_csr_integration (
input wire clk,
input wire reset_n,
// CSR interface
input wire [7:0] csr_addr,
input wire [31:0] csr_write_data,
input wire csr_write,
output wire [31:0] csr_read_data,
// Interrupt signals - properly declared and connected
output wire tamper_interrupt,
output wire error_interrupt,
output wire overflow_interrupt,
// Combined interrupt for system
output wire system_interrupt
);
// Internal interrupt signals
wire int_tamper;
wire int_error;
wire int_overflow;
// CSR register file instance
csr_register_file csr_inst (
.clk(clk),
.reset_n(reset_n),
.addr(csr_addr),
.write_data(csr_write_data),
.write_enable(csr_write),
.read_data(csr_read_data),
// FIXED: All interrupt ports properly connected
.tamper_int(int_tamper),
.error_int(int_error),
.overflow_int(int_overflow)
);
// FIXED: Connect to outputs
assign tamper_interrupt = int_tamper;
assign error_interrupt = int_error;
assign overflow_interrupt = int_overflow;
// FIXED: Combined interrupt for system-level handling
assign system_interrupt = int_tamper | int_error | int_overflow;
endmodule
// Fixed: Reset signal correctly connected
module secure_reset_connection (
input wire clk,
input wire system_hard_reset_n,
input wire debug_soft_reset_n,
// Security subsystem
output wire security_reset_n
);
// FIXED: Security subsystem connected to correct reset
security_controller sec_ctrl (
.clk(clk),
// FIXED: Connected to hard reset
.reset_n(system_hard_reset_n),
.security_reset_n(security_reset_n)
);
// Security state properly cleared on system reset
endmodule
// Fixed: Connection verification module
module connection_verifier (
input wire clk,
input wire reset_n,
// Signals to verify
input wire [31:0] expected_security_level,
input wire [31:0] actual_security_level,
input wire expected_interrupt,
input wire actual_interrupt,
input wire expected_reset,
input wire actual_reset,
// Verification outputs
output reg connection_error,
output reg [7:0] error_code
);
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
connection_error <= 1'b0;
error_code <= 8'h00;
end
else begin
connection_error <= 1'b0;
// FIXED: Verify security level connection
if (expected_security_level != actual_security_level) begin
connection_error <= 1'b1;
error_code <= 8'h01; // Security level mismatch
end
// FIXED: Verify interrupt connection
if (expected_interrupt != actual_interrupt) begin
connection_error <= 1'b1;
error_code <= 8'h02; // Interrupt connection error
end
// FIXED: Verify reset connection
if (expected_reset != actual_reset) begin
connection_error <= 1'b1;
error_code <= 8'h03; // Reset connection error
end
end
end
endmodule
// Fixed: Formal verification assertions
module formal_connection_check (
input wire clk,
input wire cpu_secure,
input wire interconnect_secure,
input wire memory_secure
);
// FIXED: Formal assertions to verify connections
`ifdef FORMAL
// Security level must propagate correctly
always @(posedge clk) begin
assert(cpu_secure == interconnect_secure);
assert(interconnect_secure == memory_secure);
end
// Cover property to ensure security transitions
cover property (@(posedge clk) cpu_secure == 1'b1);
cover property (@(posedge clk) cpu_secure == 1'b0);
`endif
endmodule
// Fixed: Software with verified register addresses
#include <stdint.h>
#include <stdbool.h>
// FIXED: Verified register addresses from datasheet
#define SECURITY_CTRL_BASE 0x40002000 // Verified
#define CRYPTO_ENGINE_BASE 0x40003000 // Verified
#define INTERRUPT_CTRL_BASE 0x40004000 // Verified
// FIXED: Signature bytes for peripheral identification
#define CRYPTO_ENGINE_ID 0x43525950 // "CRYP"
#define SECURITY_CTRL_ID 0x53454355 // "SECU"
typedef struct {
volatile uint32_t id; // Peripheral ID register
volatile uint32_t ctrl;
volatile uint32_t status;
volatile uint32_t key[8];
} crypto_regs_t;
// FIXED: Verify peripheral before use
bool verify_peripheral(volatile uint32_t* base, uint32_t expected_id) {
return (*base == expected_id);
}
bool secure_crypto_init(void) {
crypto_regs_t* crypto = (crypto_regs_t*)CRYPTO_ENGINE_BASE;
// FIXED: Verify we're accessing the correct peripheral
if (!verify_peripheral(&crypto->id, CRYPTO_ENGINE_ID)) {
log_error("Crypto engine not found at expected address");
return false;
}
// Now safe to configure
crypto->ctrl = 0x01; // Enable crypto
return true;
}
// FIXED: Correct interrupt setup with verification
typedef struct {
int irq_number;
const char* name;
void (*handler)(void);
} interrupt_mapping_t;
static const interrupt_mapping_t interrupt_table[] = {
{IRQ_TAMPER, "Tamper", tamper_handler},
{IRQ_ERROR, "Error", error_handler},
{IRQ_OVERFLOW, "Overflow", overflow_handler},
{IRQ_TIMER, "Timer", timer_handler},
};
bool secure_interrupt_setup(void) {
// FIXED: Register handlers from verified table
for (int i = 0; i < sizeof(interrupt_table)/sizeof(interrupt_table[0]); i++) {
if (!register_interrupt_handler(
interrupt_table[i].irq_number,
interrupt_table[i].handler)) {
log_error("Failed to register %s interrupt",
interrupt_table[i].name);
return false;
}
}
// FIXED: Verify all security interrupts are registered
if (!verify_interrupt_registered(IRQ_TAMPER)) {
log_error("Tamper interrupt not registered");
return false;
}
return true;
}
// FIXED: Self-test for peripheral connections
bool test_peripheral_connections(void) {
bool all_passed = true;
// Test crypto engine
if (!verify_peripheral(
(volatile uint32_t*)CRYPTO_ENGINE_BASE,
CRYPTO_ENGINE_ID)) {
log_error("Crypto engine connection failed");
all_passed = false;
}
// Test security controller
if (!verify_peripheral(
(volatile uint32_t*)SECURITY_CTRL_BASE,
SECURITY_CTRL_ID)) {
log_error("Security controller connection failed");
all_passed = false;
}
// Test interrupts by triggering and verifying
if (!test_interrupt_path(IRQ_TAMPER)) {
log_error("Tamper interrupt path failed");
all_passed = false;
}
return all_passed;
}
CVE Examples
Hardware integration vulnerabilities have been found in various SoC designs where security-critical signals were incorrectly connected, leading to privilege escalation or bypass of security controls.
Related CWEs
- CWE-284: Improper Access Control (parent)
- CWE-1197: Integration Issues (category)
- CWE-1396: Access Control (comprehensive category)
- CWE-1254: Incorrect Comparison Logic Granularity (related)
References
- MITRE Corporation. "CWE-1276: Hardware Child Block Incorrectly Connected to Parent System." https://cwe.mitre.org/data/definitions/1276.html
- ARM. "AMBA Integration Guidelines"
- Synopsys. "IP Integration Best Practices"