Improper Translation of Security Attributes by Fabric Bridge

Description

Improper Translation of Security Attributes by Fabric Bridge occurs when a bridge that converts between different fabric protocols fails to correctly translate security attributes, potentially mapping untrusted agents to trusted ones or vice versa. Fabric bridges integrate IP blocks using different protocols such as AHB, AXI, and OCP. These protocols use dedicated signals to convey security attributes—such as HPROT (AHB), AxPROT (AXI), and MReqInfo/SRespInfo (OCP)—indicating initiator identity, privilege level, and transaction type. Vulnerable bridges mishandle these signal translations, enabling access control bypass, privilege escalation, or denial of service attacks.

Risk

Improper security attribute translation has severe implications. Untrusted agents mapped to trusted. Trusted agents mapped to untrusted (DoS). Access control bypass enabled. Privilege escalation possible. Unauthorized memory access. Code execution by untrusted agents. Security boundaries violated. High likelihood when bridge mappings are incomplete.

Solution

The translation must map signals in such a way that untrusted agents cannot map to trusted agents or vice-versa during architecture and design and implementation phases. Create complete mapping tables covering all possible input values. Verify that no untrusted combination can produce a trusted output. Use formal verification to prove mapping correctness. Test all protocol combinations during pre-silicon and post-silicon validation.

Common Consequences

ImpactDetails
ConfidentialityScope: Confidentiality

Unauthorized read access through incorrectly elevated trust level.
IntegrityScope: Integrity

Memory modification by agents mapped to higher trust.
Access ControlScope: Access Control

Protection bypass through attribute mistranslation.

Example Code

Vulnerable Code

// Vulnerable: OCP to AHB bridge with incomplete security mapping

module vulnerable_ocp2ahb_bridge (
    input  wire        clk,
    input  wire        rst_n,

    // OCP interface
    input  wire [4:0]  ocp_mreqinfo,    // OCP security info
    input  wire [31:0] ocp_maddr,
    input  wire [31:0] ocp_mdata,
    input  wire        ocp_mcmd_valid,

    // AHB interface
    output reg  [1:0]  ahb_hprot,       // AHB protection signals
    output reg  [31:0] ahb_haddr,
    output reg  [31:0] ahb_hwdata,
    output reg         ahb_htrans_valid
);

    // OCP MReqInfo encoding (example):
    // [4:3] = Security level (00=secure, 01=non-secure, 10/11=reserved)
    // [2:0] = Master ID

    // AHB HPROT encoding:
    // [1] = Privileged (1=privileged, 0=user)
    // [0] = Data/Opcode (1=data, 0=opcode)

    // VULNERABLE: Incomplete translation logic
    always @(*) begin
        case (ocp_mreqinfo[4:2])  // Only checking bits 4:2!
            3'b000: ahb_hprot = 2'b11;  // Secure -> Privileged data
            3'b001: ahb_hprot = 2'b00;  // Non-secure -> User opcode

            // VULNERABLE: Missing cases for other values
            // 3'b010, 3'b011, 3'b100, 3'b101, 3'b110, 3'b111 not handled!

            default: ahb_hprot = 2'b00;  // VULNERABLE: Default is user
            // But this allows untrusted OCP values to get user access
            // when they should be rejected entirely
        endcase
    end

    // VULNERABLE: Bit [1:0] of mreqinfo ignored
    // Attacker can use mreqinfo values like 5'b00011 (bits 4:2 = 000)
    // to get privileged access (ahb_hprot = 2'b11)
    // even though they're not actually secure

    always @(posedge clk) begin
        if (ocp_mcmd_valid) begin
            ahb_haddr <= ocp_maddr;
            ahb_hwdata <= ocp_mdata;
            ahb_htrans_valid <= 1'b1;
        end
    end

endmodule

// Vulnerable: AXI to APB bridge with security attribute loss
module vulnerable_axi2apb_bridge (
    input  wire        clk,
    input  wire        rst_n,

    // AXI interface
    input  wire [2:0]  axi_awprot,      // AXI write protection
    input  wire [2:0]  axi_arprot,      // AXI read protection
    input  wire [31:0] axi_awaddr,
    input  wire [31:0] axi_wdata,
    input  wire        axi_awvalid,
    input  wire        axi_arvalid,

    // APB interface (simpler, fewer security signals)
    output reg  [31:0] apb_paddr,
    output reg  [31:0] apb_pwdata,
    output reg  [2:0]  apb_pprot,       // APB protection
    output reg         apb_psel
);

    // AXI AxPROT encoding:
    // [0] = Privileged (1=privileged)
    // [1] = Non-secure (1=non-secure)
    // [2] = Instruction (1=instruction access)

    // VULNERABLE: Security bits not fully translated
    always @(posedge clk) begin
        if (axi_awvalid) begin
            apb_paddr <= axi_awaddr;
            apb_pwdata <= axi_wdata;

            // VULNERABLE: Only copying privilege bit
            apb_pprot[0] <= axi_awprot[0];  // Privileged

            // VULNERABLE: Secure/non-secure not translated!
            // APB pprot[1] should be set from AXI awprot[1]
            apb_pprot[1] <= 1'b0;  // Always appears secure!

            apb_pprot[2] <= axi_awprot[2];  // Data/instruction

            apb_psel <= 1'b1;

            // Attack: Non-secure AXI transaction (awprot[1]=1)
            // becomes secure APB transaction (pprot[1]=0)
            // Bypasses security checks on APB side
        end
    end

endmodule

Fixed Code

// Fixed: OCP to AHB bridge with complete security mapping

module secure_ocp2ahb_bridge (
    input  wire        clk,
    input  wire        rst_n,

    // OCP interface
    input  wire [4:0]  ocp_mreqinfo,
    input  wire [31:0] ocp_maddr,
    input  wire [31:0] ocp_mdata,
    input  wire        ocp_mcmd_valid,

    // AHB interface
    output reg  [1:0]  ahb_hprot,
    output reg  [31:0] ahb_haddr,
    output reg  [31:0] ahb_hwdata,
    output reg         ahb_htrans_valid,
    output reg         translation_error  // FIXED: Error signal
);

    // OCP MReqInfo encoding:
    // [4:3] = Security level (00=secure-priv, 01=secure-user, 10=nonsec-priv, 11=nonsec-user)
    // [2:0] = Master ID (000-111)

    // AHB HPROT encoding:
    // [1] = Privileged (1=privileged, 0=user)
    // [0] = Data/Opcode (1=data, 0=opcode)
    // Plus we track secure/non-secure separately

    reg ahb_nonsecure;  // Additional signal for TrustZone-aware AHB

    // FIXED: Complete translation covering all input values
    always @(*) begin
        translation_error = 1'b0;

        // FIXED: Examine all relevant bits of mreqinfo
        case (ocp_mreqinfo[4:3])  // Security level
            2'b00: begin  // Secure privileged
                ahb_hprot = 2'b11;      // Privileged, data
                ahb_nonsecure = 1'b0;   // Secure
            end
            2'b01: begin  // Secure user
                ahb_hprot = 2'b01;      // User, data
                ahb_nonsecure = 1'b0;   // Secure
            end
            2'b10: begin  // Non-secure privileged
                ahb_hprot = 2'b11;      // Privileged, data
                ahb_nonsecure = 1'b1;   // Non-secure
            end
            2'b11: begin  // Non-secure user
                ahb_hprot = 2'b01;      // User, data
                ahb_nonsecure = 1'b1;   // Non-secure
            end
            default: begin
                // FIXED: Reject invalid values
                ahb_hprot = 2'b01;      // Default to lowest privilege
                ahb_nonsecure = 1'b1;   // Default to non-secure
                translation_error = 1'b1;
            end
        endcase

        // FIXED: Also validate master ID is in expected range
        if (ocp_mreqinfo[2:0] > 3'b011) begin
            // Unknown master - reject or demote
            translation_error = 1'b1;
        end
    end

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            ahb_htrans_valid <= 1'b0;
        end else if (ocp_mcmd_valid) begin
            // FIXED: Only forward if translation is valid
            if (!translation_error) begin
                ahb_haddr <= ocp_maddr;
                ahb_hwdata <= ocp_mdata;
                ahb_htrans_valid <= 1'b1;
            end else begin
                ahb_htrans_valid <= 1'b0;
            end
        end else begin
            ahb_htrans_valid <= 1'b0;
        end
    end

endmodule

// Fixed: AXI to APB bridge with complete security translation
module secure_axi2apb_bridge (
    input  wire        clk,
    input  wire        rst_n,

    // AXI interface
    input  wire [2:0]  axi_awprot,
    input  wire [2:0]  axi_arprot,
    input  wire [31:0] axi_awaddr,
    input  wire [31:0] axi_wdata,
    input  wire        axi_awvalid,
    input  wire        axi_arvalid,

    // APB interface
    output reg  [31:0] apb_paddr,
    output reg  [31:0] apb_pwdata,
    output reg  [2:0]  apb_pprot,
    output reg         apb_psel,
    output reg         apb_pnsec  // FIXED: Explicit non-secure signal
);

    // AXI AxPROT encoding:
    // [0] = Privileged (1=privileged)
    // [1] = Non-secure (1=non-secure)
    // [2] = Instruction (1=instruction access)

    // APB PPROT encoding (should match):
    // [0] = Privileged
    // [1] = Non-secure
    // [2] = Instruction

    // FIXED: Complete bit-by-bit translation
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            apb_psel <= 1'b0;
            apb_pprot <= 3'b000;
            apb_pnsec <= 1'b1;  // Default non-secure
        end else if (axi_awvalid) begin
            apb_paddr <= axi_awaddr;
            apb_pwdata <= axi_wdata;

            // FIXED: Translate ALL protection bits
            apb_pprot[0] <= axi_awprot[0];  // Privileged
            apb_pprot[1] <= axi_awprot[1];  // FIXED: Non-secure properly translated
            apb_pprot[2] <= axi_awprot[2];  // Instruction/data

            // FIXED: Also provide explicit secure/non-secure signal
            apb_pnsec <= axi_awprot[1];

            apb_psel <= 1'b1;
        end else begin
            apb_psel <= 1'b0;
        end
    end

endmodule

// Fixed: Generic protocol bridge with validation
module secure_protocol_bridge #(
    parameter SRC_SECURITY_WIDTH = 5,
    parameter DST_SECURITY_WIDTH = 3
) (
    input  wire                          clk,
    input  wire                          rst_n,
    input  wire [SRC_SECURITY_WIDTH-1:0] src_security,
    input  wire                          src_valid,
    output reg  [DST_SECURITY_WIDTH-1:0] dst_security,
    output reg                           dst_valid,
    output reg                           mapping_error
);

    // FIXED: Explicit mapping table (ROM or logic)
    // Maps every possible source value to destination value
    // Invalid/reserved source values map to error

    function [DST_SECURITY_WIDTH:0] translate_security;
        input [SRC_SECURITY_WIDTH-1:0] src;
        reg [DST_SECURITY_WIDTH-1:0] dst;
        reg error;
        begin
            error = 1'b0;
            case (src)
                // FIXED: Exhaustive mapping
                5'b00000: dst = 3'b000;  // Secure privileged
                5'b00001: dst = 3'b001;  // Secure user
                5'b00010: dst = 3'b010;  // Non-secure privileged
                5'b00011: dst = 3'b011;  // Non-secure user
                // ... add all valid mappings

                // FIXED: All other values are invalid
                default: begin
                    dst = 3'b011;  // Map to lowest trust
                    error = 1'b1;
                end
            endcase
            translate_security = {error, dst};
        end
    endfunction

    wire [DST_SECURITY_WIDTH:0] translation_result;
    assign translation_result = translate_security(src_security);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            dst_security <= {DST_SECURITY_WIDTH{1'b1}};  // Lowest trust
            dst_valid <= 1'b0;
            mapping_error <= 1'b0;
        end else if (src_valid) begin
            dst_security <= translation_result[DST_SECURITY_WIDTH-1:0];
            mapping_error <= translation_result[DST_SECURITY_WIDTH];

            // FIXED: Only forward if mapping is valid
            dst_valid <= ~translation_result[DST_SECURITY_WIDTH];
        end else begin
            dst_valid <= 1'b0;
        end
    end

endmodule

CVE Examples

  • CVE-2020-8705: Fabric bridge in certain Intel processors incorrectly translated security attributes allowing privilege escalation.
  • CVE-2019-11157: Protocol bridge mishandled security signals enabling unauthorized access.

  • CWE-284: Improper Access Control (parent)
  • CWE-1203: Peripherals, On-chip Fabric, and Interface/IO Problems (category)
  • CWE-1292: Incorrect Conversion of Security Identifiers (related)
  • CWE-863: Incorrect Authorization (related)

References

  1. MITRE Corporation. "CWE-1311: Improper Translation of Security Attributes by Fabric Bridge." https://cwe.mitre.org/data/definitions/1311.html
  2. ARM. "AMBA Protocol Specifications"
  3. OCP-IP. "Open Core Protocol Specification"