Missing Support for Security Features in On-chip Fabrics or Buses

Description

Missing Support for Security Features in On-chip Fabrics or Buses occurs when on-chip fabrics or buses either do not support or are not configured to support privilege separation or other security features, such as access control. The weakness manifests when on-chip communication infrastructure lacks mechanisms to transport security attributes (privilege levels, identity, access control data) between bus masters and slaves. Even when supported, these features may remain unconfigured during RTL generation, rendering them ineffective and leaving security-critical communications unprotected.

Risk

Missing security features in fabrics has severe implications. No privilege separation possible. Security attributes not transported. Access control impossible to enforce. All masters appear equally trusted. Protected peripherals accessible by anyone. Secure and non-secure worlds cannot be separated. TrustZone-style isolation fails. Side-channel attacks between domains. Medium likelihood when using protocols with optional security or during cost-optimized designs.

Solution

Implement security checks at fabric bridges or intermediate modules. Segregate unsecured buses from security-critical peripherals. Connect security-sensitive assets to buses supporting security features. Configure optional security signals (e.g., MReqInfo/SRespInfo in OCP, AxPROT in AXI) during RTL generation. Perform architecture and design reviews to ensure fabric specifications include required security signals.

Common Consequences

ImpactDetails
Access ControlScope: Access Control

Unable to enforce privilege separation or access restrictions.
ConfidentialityScope: Confidentiality

Unauthorized memory read access due to missing security attributes.
IntegrityScope: Integrity

Memory modification possible when access control cannot be enforced.
AvailabilityScope: Availability

Denial of service through unauthorized access to critical resources.

Example Code

Vulnerable Code

// Vulnerable: APB bus without sufficient security signals

module vulnerable_apb_interconnect (
    input  wire        clk,
    input  wire        rst_n,

    // Master interface
    input  wire [31:0] master_paddr,
    input  wire [31:0] master_pwdata,
    input  wire        master_pwrite,
    input  wire        master_psel,
    input  wire        master_penable,
    // VULNERABLE: No PPROT signal!
    // APB2 has limited PPROT (only 3 bits)

    // Slave 0 - Secure peripheral
    output reg  [31:0] slave0_paddr,
    output reg  [31:0] slave0_pwdata,
    output reg         slave0_pwrite,
    output reg         slave0_psel,
    output reg         slave0_penable,

    // Slave 1 - Normal peripheral
    output reg  [31:0] slave1_paddr,
    output reg  [31:0] slave1_pwdata,
    output reg         slave1_pwrite,
    output reg         slave1_psel,
    output reg         slave1_penable
);

    // Address decode
    wire select_slave0 = (master_paddr[31:16] == 16'h4000);
    wire select_slave1 = (master_paddr[31:16] == 16'h4001);

    // VULNERABLE: No security attribute forwarding
    // Cannot distinguish secure vs non-secure transactions
    // All masters appear the same to slaves

    always @(*) begin
        // Forward to slave 0 (secure peripheral)
        slave0_paddr = master_paddr;
        slave0_pwdata = master_pwdata;
        slave0_pwrite = master_pwrite;
        slave0_psel = master_psel && select_slave0;
        slave0_penable = master_penable;
        // VULNERABLE: No protection signals to slave!

        // Forward to slave 1
        slave1_paddr = master_paddr;
        slave1_pwdata = master_pwdata;
        slave1_pwrite = master_pwrite;
        slave1_psel = master_psel && select_slave1;
        slave1_penable = master_penable;
    end

    // Attack:
    // 1. Non-secure master accesses secure peripheral at 0x4000_xxxx
    // 2. Bus has no way to indicate non-secure status
    // 3. Secure peripheral cannot enforce access control
    // 4. Non-secure world reads/writes secure data

endmodule

// Vulnerable: OCP fabric with unconfigured security signals
module vulnerable_ocp_master (
    input  wire        clk,
    input  wire        rst_n,

    // Master signals
    input  wire [31:0] request_addr,
    input  wire [31:0] request_data,
    input  wire        request_valid,
    input  wire        request_write,

    // OCP interface
    output reg  [31:0] MAddr,
    output reg  [31:0] MData,
    output reg  [2:0]  MCmd,
    // VULNERABLE: MReqInfo not connected!
    // output reg [4:0] MReqInfo,  // Security info - NOT USED

    input  wire        SCmdAccept,
    input  wire [31:0] SData,
    input  wire [1:0]  SResp
);

    // OCP command encoding
    localparam OCP_IDLE  = 3'b000;
    localparam OCP_WRITE = 3'b001;
    localparam OCP_READ  = 3'b010;

    // VULNERABLE: Security information not included in transactions
    // MReqInfo should carry privilege level and security state

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            MCmd <= OCP_IDLE;
        end else if (request_valid) begin
            MAddr <= request_addr;
            MData <= request_data;
            MCmd <= request_write ? OCP_WRITE : OCP_READ;

            // VULNERABLE: MReqInfo never set
            // Slave cannot determine transaction security level
        end else begin
            MCmd <= OCP_IDLE;
        end
    end

    // Vulnerability: Even if slave checks MReqInfo,
    // it will see default/undefined value

endmodule
// Vulnerable: Software using bus without security features

#include <stdint.h>

// VULNERABLE: Memory-mapped access without security context
void vulnerable_write_peripheral(uint32_t addr, uint32_t value) {
    // Direct memory access
    // No way to specify privilege level
    // No way to indicate secure/non-secure
    *(volatile uint32_t*)addr = value;
}

uint32_t vulnerable_read_peripheral(uint32_t addr) {
    // VULNERABLE: Bus doesn't carry security attributes
    // Peripheral cannot validate the access
    return *(volatile uint32_t*)addr;
}

// Attack: Non-secure code can access secure peripherals
// because the bus doesn't support security separation

Fixed Code

// Fixed: APB interconnect with security signals

module secure_apb_interconnect (
    input  wire        clk,
    input  wire        rst_n,

    // Master interface with security
    input  wire [31:0] master_paddr,
    input  wire [31:0] master_pwdata,
    input  wire        master_pwrite,
    input  wire        master_psel,
    input  wire        master_penable,
    input  wire [2:0]  master_pprot,    // FIXED: Protection signals
    // pprot[0] = privileged
    // pprot[1] = non-secure
    // pprot[2] = instruction/data

    // Slave 0 - Secure peripheral
    output reg  [31:0] slave0_paddr,
    output reg  [31:0] slave0_pwdata,
    output reg         slave0_pwrite,
    output reg         slave0_psel,
    output reg         slave0_penable,
    output reg  [2:0]  slave0_pprot,    // FIXED: Forward protection

    // Slave 1 - Normal peripheral
    output reg  [31:0] slave1_paddr,
    output reg  [31:0] slave1_pwdata,
    output reg         slave1_pwrite,
    output reg         slave1_psel,
    output reg         slave1_penable,
    output reg  [2:0]  slave1_pprot,

    // Access control
    output reg         access_denied
);

    wire select_slave0 = (master_paddr[31:16] == 16'h4000);
    wire select_slave1 = (master_paddr[31:16] == 16'h4001);

    // FIXED: Secure slave access control
    // Slave 0 requires secure (pprot[1] = 0) and privileged (pprot[0] = 1)
    wire slave0_access_ok = (master_pprot[0] == 1'b1) &&   // Privileged
                            (master_pprot[1] == 1'b0);     // Secure

    always @(*) begin
        access_denied = 1'b0;

        // FIXED: Forward with security checks
        slave0_paddr = master_paddr;
        slave0_pwdata = master_pwdata;
        slave0_pwrite = master_pwrite;
        slave0_pprot = master_pprot;  // FIXED: Forward protection signals

        if (select_slave0) begin
            // FIXED: Enforce access control at interconnect level
            if (slave0_access_ok) begin
                slave0_psel = master_psel;
                slave0_penable = master_penable;
            end else begin
                // FIXED: Block non-secure or unprivileged access
                slave0_psel = 1'b0;
                slave0_penable = 1'b0;
                access_denied = 1'b1;
            end
        end else begin
            slave0_psel = 1'b0;
            slave0_penable = 1'b0;
        end

        // Slave 1 - accessible to all
        slave1_paddr = master_paddr;
        slave1_pwdata = master_pwdata;
        slave1_pwrite = master_pwrite;
        slave1_psel = master_psel && select_slave1;
        slave1_penable = master_penable;
        slave1_pprot = master_pprot;
    end

endmodule

// Fixed: OCP master with security signals configured
module secure_ocp_master (
    input  wire        clk,
    input  wire        rst_n,

    // Master signals with security context
    input  wire [31:0] request_addr,
    input  wire [31:0] request_data,
    input  wire        request_valid,
    input  wire        request_write,
    input  wire [1:0]  request_privilege,  // 00=user, 01=priv, 10=secure, 11=secure-priv
    input  wire [2:0]  request_master_id,

    // OCP interface with security
    output reg  [31:0] MAddr,
    output reg  [31:0] MData,
    output reg  [2:0]  MCmd,
    output reg  [4:0]  MReqInfo,          // FIXED: Security information
    // MReqInfo[4:3] = privilege level
    // MReqInfo[2:0] = master ID

    input  wire        SCmdAccept,
    input  wire [31:0] SData,
    input  wire [1:0]  SResp,
    input  wire [1:0]  SRespInfo          // FIXED: Response security info
);

    localparam OCP_IDLE  = 3'b000;
    localparam OCP_WRITE = 3'b001;
    localparam OCP_READ  = 3'b010;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            MCmd <= OCP_IDLE;
            MReqInfo <= 5'b00000;
        end else if (request_valid) begin
            MAddr <= request_addr;
            MData <= request_data;
            MCmd <= request_write ? OCP_WRITE : OCP_READ;

            // FIXED: Include security information in transaction
            MReqInfo[4:3] <= request_privilege;
            MReqInfo[2:0] <= request_master_id;
        end else begin
            MCmd <= OCP_IDLE;
        end
    end

endmodule

// Fixed: AXI-based secure interconnect
module secure_axi_interconnect (
    input  wire        clk,
    input  wire        rst_n,

    // Master interface
    input  wire [31:0] m_axi_awaddr,
    input  wire [2:0]  m_axi_awprot,      // FIXED: Write protection
    input  wire        m_axi_awvalid,
    input  wire [31:0] m_axi_araddr,
    input  wire [2:0]  m_axi_arprot,      // FIXED: Read protection
    input  wire        m_axi_arvalid,

    // Slave interface
    output reg  [31:0] s_axi_awaddr,
    output reg  [2:0]  s_axi_awprot,
    output reg         s_axi_awvalid,
    output reg  [31:0] s_axi_araddr,
    output reg  [2:0]  s_axi_arprot,
    output reg         s_axi_arvalid,

    output reg         security_violation
);

    // FIXED: AXI protection bit definitions
    // AxPROT[0] = privileged (1) / unprivileged (0)
    // AxPROT[1] = non-secure (1) / secure (0)
    // AxPROT[2] = instruction (1) / data (0)

    // FIXED: Define secure address ranges
    localparam SECURE_BASE = 32'h1000_0000;
    localparam SECURE_SIZE = 32'h0100_0000;

    wire write_to_secure = (m_axi_awaddr >= SECURE_BASE) &&
                           (m_axi_awaddr < SECURE_BASE + SECURE_SIZE);
    wire read_from_secure = (m_axi_araddr >= SECURE_BASE) &&
                            (m_axi_araddr < SECURE_BASE + SECURE_SIZE);

    // FIXED: Check security attributes for secure region access
    wire write_secure_ok = !m_axi_awprot[1];  // Secure access
    wire read_secure_ok = !m_axi_arprot[1];   // Secure access

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            s_axi_awvalid <= 1'b0;
            s_axi_arvalid <= 1'b0;
            security_violation <= 1'b0;
        end else begin
            security_violation <= 1'b0;

            // FIXED: Write channel with security check
            if (m_axi_awvalid) begin
                if (write_to_secure && !write_secure_ok) begin
                    // FIXED: Block non-secure access to secure region
                    s_axi_awvalid <= 1'b0;
                    security_violation <= 1'b1;
                end else begin
                    s_axi_awaddr <= m_axi_awaddr;
                    s_axi_awprot <= m_axi_awprot;
                    s_axi_awvalid <= 1'b1;
                end
            end else begin
                s_axi_awvalid <= 1'b0;
            end

            // FIXED: Read channel with security check
            if (m_axi_arvalid) begin
                if (read_from_secure && !read_secure_ok) begin
                    s_axi_arvalid <= 1'b0;
                    security_violation <= 1'b1;
                end else begin
                    s_axi_araddr <= m_axi_araddr;
                    s_axi_arprot <= m_axi_arprot;
                    s_axi_arvalid <= 1'b1;
                end
            end else begin
                s_axi_arvalid <= 1'b0;
            end
        end
    end

endmodule

CVE Examples

  • CVE-2020-8705: Platform fabric in Intel processors lacked proper security signal propagation.
  • CVE-2019-0090: Intel CSME used buses without adequate security feature support.

  • CWE-693: Protection Mechanism Failure (parent)
  • CWE-1198: Privilege Separation and Access Control Issues (category)
  • CWE-1311: Improper Translation of Security Attributes by Fabric Bridge (related)
  • CWE-1317: Improper Access Control in Fabric Bridge (related)

References

  1. MITRE Corporation. "CWE-1318: Missing Support for Security Features in On-chip Fabrics or Buses." https://cwe.mitre.org/data/definitions/1318.html
  2. ARM. "AMBA APB Protocol Specification"
  3. OCP-IP. "Open Core Protocol Specification"
  4. ARM. "AMBA AXI and ACE Protocol Specification"