Improper Restriction of Security Token Assignment

Description

Improper Restriction of Security Token Assignment occurs when Systems-on-Chip use security tokens to differentiate which actions are permitted from various entities, but these tokens are improperly protected. Security tokens identify which agent initiated an action (read, write, program, reset, fetch, compute, etc.) and define their trust level and privileges. The vulnerability stems from improperly restricting the assignment to trusted components, enabling malicious agents to modify their tokens and masquerade as legitimate entities.

Risk

Improper token protection has severe security implications. Malicious agents can spoof trusted transactions. Privilege escalation becomes possible. Access control can be bypassed. Unauthorized code may be executed. Memory may be modified without authorization. System security boundaries are violated. Attackers can assume any identity. Denial of service attacks become possible.

Solution

Conduct security token assignment review checks for design inconsistencies. Test token definition and programming flows in pre-silicon and post-silicon environments. Prevent any agent from modifying security tokens except through secure hardware mechanisms. Use hardware-enforced token assignment. Implement token integrity verification. Make tokens immutable after assignment. Use cryptographic protection for token values.

Common Consequences

ImpactDetails
AuthorizationScope: Authorization

Privilege Escalation - Malicious agents can modify tokens to gain higher privileges.
Access ControlScope: Access Control

Bypass Protection Mechanism - Token spoofing allows bypassing access control checks.
IntegrityScope: Integrity

Modify Memory - Unauthorized memory modification through spoofed transactions.

Example Code

Vulnerable Code

// Vulnerable: Mutable security tokens

module vulnerable_token_system (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire [3:0] token_write_data,
    input wire token_write_enable,
    input wire [31:0] bus_addr,
    input wire [31:0] bus_data,
    input wire bus_write,
    input wire bus_read,
    output reg [31:0] bus_read_data,
    output reg access_granted
);

    // Security token storage for each agent
    reg [3:0] agent_tokens [0:15];

    // Security levels: 0=untrusted, 1=user, 2=supervisor, 3=secure
    parameter SECURE_REGION_START = 32'h8000_0000;
    parameter SECURE_REGION_END = 32'h8FFF_FFFF;
    parameter REQUIRED_TOKEN = 4'd3;  // Secure level required

    // VULNERABLE: Any agent can modify any token
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            // Initialize all agents with low privilege
            integer i;
            for (i = 0; i < 16; i = i + 1) begin
                agent_tokens[i] <= 4'd0;  // Untrusted
            end
        end
        else if (token_write_enable) begin
            // VULNERABLE: No check on who is writing the token
            // Any agent can elevate its own or others' tokens
            agent_tokens[agent_id] <= token_write_data;
        end
    end

    // Access control using tokens
    wire is_secure_region = (bus_addr >= SECURE_REGION_START) &&
                            (bus_addr <= SECURE_REGION_END);
    wire agent_token = agent_tokens[agent_id];

    always @(*) begin
        if (is_secure_region) begin
            // Check agent's token
            access_granted = (agent_token >= REQUIRED_TOKEN);
        end
        else begin
            access_granted = 1'b1;
        end
    end

    // Attack scenario:
    // 1. Malicious agent has token 0 (untrusted)
    // 2. Agent writes token_write_data=3, token_write_enable=1
    // 3. Agent now has token 3 (secure) - can access secure region

endmodule

// Vulnerable: Token can be modified through register interface
module vulnerable_aux_controller (
    input wire clk,
    input wire reset_n,
    input wire [7:0] reg_addr,
    input wire [31:0] reg_write_data,
    input wire reg_write,
    output reg [3:0] my_token,
    output reg [31:0] reg_read_data
);

    // Internal registers
    reg [31:0] config_reg;
    reg [31:0] status_reg;

    // Token storage register
    reg [3:0] token_reg;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            token_reg <= 4'd2;  // Initialized as user level
            config_reg <= 32'h0;
            status_reg <= 32'h0;
        end
        else if (reg_write) begin
            case (reg_addr)
                8'h00: config_reg <= reg_write_data;
                8'h04: status_reg <= reg_write_data;
                // VULNERABLE: Token can be written!
                8'h08: token_reg <= reg_write_data[3:0];
                default: ;
            endcase
        end
    end

    assign my_token = token_reg;

    // Attack: Write to reg_addr 0x08 to change token value

endmodule
// Vulnerable: Software token modification

#include <stdint.h>

#define TOKEN_REGISTER_BASE 0x10000000
#define MAX_AGENTS 16

typedef struct {
    uint32_t token;
    uint32_t permissions;
    uint32_t reserved[2];
} agent_token_t;

volatile agent_token_t* token_table = (volatile agent_token_t*)TOKEN_REGISTER_BASE;

// VULNERABLE: Any code can call this to modify tokens
void vulnerable_set_token(int agent_id, uint32_t new_token) {
    if (agent_id < MAX_AGENTS) {
        // VULNERABLE: No privilege check
        // Any agent can modify any token
        token_table[agent_id].token = new_token;
    }
}

// VULNERABLE: Token check can be bypassed
int vulnerable_check_access(int agent_id, uint32_t resource_id) {
    // Read agent's token
    uint32_t token = token_table[agent_id].token;

    // VULNERABLE: Token was already modified by attacker
    if (token >= REQUIRED_TOKEN_LEVEL) {
        return ACCESS_GRANTED;
    }
    return ACCESS_DENIED;
}

// Attack:
// 1. Attacker is agent 5 with token 0
// 2. Attacker calls vulnerable_set_token(5, HIGHEST_TOKEN)
// 3. Attacker now passes all token checks

Fixed Code

// Fixed: Immutable security tokens with hardware enforcement

module secure_token_system (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire [3:0] token_write_data,
    input wire token_write_enable,
    input wire secure_master,          // True only for secure master
    input wire token_program_mode,     // One-time programming mode
    input wire [31:0] bus_addr,
    input wire [31:0] bus_data,
    input wire bus_write,
    input wire bus_read,
    output reg [31:0] bus_read_data,
    output reg access_granted,
    output reg token_violation
);

    // Security token storage
    reg [3:0] agent_tokens [0:15];
    reg token_locked [0:15];  // Lock flag for each token

    // Parameters
    parameter SECURE_REGION_START = 32'h8000_0000;
    parameter SECURE_REGION_END = 32'h8FFF_FFFF;
    parameter REQUIRED_TOKEN = 4'd3;

    // FIXED: Token modification with strict controls
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            integer i;
            for (i = 0; i < 16; i = i + 1) begin
                agent_tokens[i] <= 4'd0;
                token_locked[i] <= 1'b0;
            end
            token_violation <= 1'b0;
        end
        else if (token_write_enable) begin
            // FIXED: Multiple checks required for token modification
            if (!secure_master) begin
                // FIXED: Only secure master can modify tokens
                token_violation <= 1'b1;
            end
            else if (!token_program_mode) begin
                // FIXED: Must be in programming mode
                token_violation <= 1'b1;
            end
            else if (token_locked[agent_id]) begin
                // FIXED: Cannot modify locked tokens
                token_violation <= 1'b1;
            end
            else begin
                // FIXED: Legitimate token assignment
                agent_tokens[agent_id] <= token_write_data;
                // FIXED: Lock token after assignment
                token_locked[agent_id] <= 1'b1;
            end
        end
    end

    // Access control
    wire is_secure_region = (bus_addr >= SECURE_REGION_START) &&
                            (bus_addr <= SECURE_REGION_END);

    always @(*) begin
        if (is_secure_region) begin
            // FIXED: Use hardware-controlled token
            access_granted = (agent_tokens[agent_id] >= REQUIRED_TOKEN);
        end
        else begin
            access_granted = 1'b1;
        end
    end

endmodule

// Fixed: Hardware-enforced immutable token
module secure_aux_controller (
    input wire clk,
    input wire reset_n,
    input wire [7:0] reg_addr,
    input wire [31:0] reg_write_data,
    input wire reg_write,
    input wire fuse_token_valid,       // Fuse-based token
    input wire [3:0] fuse_token_value, // Immutable from fuses
    output wire [3:0] my_token,
    output reg [31:0] reg_read_data,
    output reg token_tamper_attempt
);

    // Internal registers
    reg [31:0] config_reg;
    reg [31:0] status_reg;

    // FIXED: Token comes from hardware fuses, not software
    assign my_token = fuse_token_valid ? fuse_token_value : 4'd0;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            config_reg <= 32'h0;
            status_reg <= 32'h0;
            token_tamper_attempt <= 1'b0;
        end
        else if (reg_write) begin
            case (reg_addr)
                8'h00: config_reg <= reg_write_data;
                8'h04: status_reg <= reg_write_data;
                // FIXED: Token register is read-only
                8'h08: begin
                    // Attempt to write token - flag as tamper
                    token_tamper_attempt <= 1'b1;
                    // Value NOT modified
                end
                default: ;
            endcase
        end
    end

    // Read interface
    always @(*) begin
        case (reg_addr)
            8'h00: reg_read_data = config_reg;
            8'h04: reg_read_data = status_reg;
            8'h08: reg_read_data = {28'h0, my_token};  // Read-only
            default: reg_read_data = 32'h0;
        endcase
    end

endmodule

// Fixed: Transaction-level token verification
module secure_bus_firewall (
    input wire clk,
    input wire reset_n,
    input wire [3:0] requester_id,
    input wire [31:0] transaction_addr,
    input wire [3:0] claimed_token,    // Token claimed by requester
    input wire transaction_valid,
    output reg transaction_allowed,
    output reg token_mismatch
);

    // FIXED: Hardware token table (read-only to requesters)
    reg [3:0] authentic_tokens [0:15];

    // FIXED: Compare claimed token with authentic token
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            transaction_allowed <= 1'b0;
            token_mismatch <= 1'b0;
        end
        else if (transaction_valid) begin
            // FIXED: Verify claimed token matches authentic token
            if (claimed_token != authentic_tokens[requester_id]) begin
                // Token spoofing detected!
                token_mismatch <= 1'b1;
                transaction_allowed <= 1'b0;
            end
            else begin
                token_mismatch <= 1'b0;
                // Check access based on authentic token
                transaction_allowed <= check_access(transaction_addr, authentic_tokens[requester_id]);
            end
        end
    end

endmodule
// Fixed: Secure token management

#include <stdint.h>

#define TOKEN_REGISTER_BASE 0x10000000
#define MAX_AGENTS 16

// FIXED: Token table is in secure memory, not directly accessible
typedef struct {
    uint32_t token;
    uint32_t permissions;
    uint32_t locked;  // Once set, token cannot change
    uint32_t checksum;
} secure_agent_token_t;

// FIXED: Hardware-managed token retrieval
static uint32_t get_authentic_token(int agent_id) {
    // This function runs in secure mode only
    // Token is retrieved from hardware, not memory
    return SECURE_TOKEN_HARDWARE->agent_token[agent_id];
}

// FIXED: Token assignment only during secure boot
int secure_set_token(int agent_id, uint32_t new_token) {
    // FIXED: Check if we're in secure programming mode
    if (!is_secure_boot_mode()) {
        log_security_violation("Token modification outside boot");
        return -EPERM;
    }

    // FIXED: Check if caller is secure master
    if (get_current_privilege() < PRIVILEGE_SECURE_MASTER) {
        log_security_violation("Unprivileged token modification");
        return -EPERM;
    }

    // FIXED: Check if token is already locked
    if (SECURE_TOKEN_HARDWARE->agent_locked[agent_id]) {
        log_security_violation("Attempt to modify locked token");
        return -EPERM;
    }

    // FIXED: Program token through secure hardware interface
    SECURE_TOKEN_HARDWARE->agent_token[agent_id] = new_token;

    // FIXED: Lock token to prevent future modification
    SECURE_TOKEN_HARDWARE->agent_locked[agent_id] = 1;

    // Verify programming
    if (SECURE_TOKEN_HARDWARE->agent_token[agent_id] != new_token) {
        return -EIO;
    }

    return 0;
}

// FIXED: Access check uses hardware token
int secure_check_access(int agent_id, uint32_t resource_id) {
    // FIXED: Get token from hardware, not from agent
    uint32_t authentic_token = get_authentic_token(agent_id);

    // FIXED: Also verify token integrity
    if (!verify_token_integrity(agent_id)) {
        log_security_violation("Token integrity failure");
        return ACCESS_DENIED;
    }

    if (authentic_token >= get_required_token(resource_id)) {
        return ACCESS_GRANTED;
    }

    return ACCESS_DENIED;
}

// FIXED: Verify token hasn't been tampered with
static bool verify_token_integrity(int agent_id) {
    uint32_t stored_checksum = SECURE_TOKEN_HARDWARE->agent_checksum[agent_id];
    uint32_t computed_checksum = compute_token_checksum(
        SECURE_TOKEN_HARDWARE->agent_token[agent_id],
        agent_id
    );

    return (stored_checksum == computed_checksum);
}

CVE Examples

Security token vulnerabilities have been found in various SoC designs where auxiliary controllers could modify their security identifiers to gain unauthorized access to protected resources like encryption keys.


  • CWE-284: Improper Access Control (parent)
  • CWE-1294: Insecure Security Identifier Mechanism (parent)
  • CWE-1255: Comparison Logic is Vulnerable to Power Side-Channel Attacks (peer)
  • CWE-1270: Generation of Incorrect Security Tokens (related)

References

  1. MITRE Corporation. "CWE-1259: Improper Restriction of Security Token Assignment." https://cwe.mitre.org/data/definitions/1259.html
  2. ARM. "TrustZone Security" - Security Identifiers
  3. AMBA. "AXI Protocol" - Transaction Security