Generation of Incorrect Security Tokens

Description

Generation of Incorrect Security Tokens occurs when a system implements security tokens to differentiate allowed and disallowed actions but generates these tokens incorrectly. In System-on-Chip (SoC) designs, security tokens differentiate and identify actions from various agents representing actions like "read," "write," "program," "reset," "fetch," and "compute." Each agent receives a unique token based on trust level or privileges. When tokens are generated incorrectly, the same token may be assigned to different agents or different tokens assigned to the same agent, breaking the security model.

Risk

Incorrect security token generation has severe security implications. Privilege escalation becomes possible. Unauthorized access may be granted. Denial of service can occur. Multiple agents may receive identical tokens. Trusted and untrusted agents may be confused. Access control is completely bypassed. Protected resources become exposed. Entire security architecture can be compromised.

Solution

Review token generation logic for design inconsistencies and common weaknesses during security reviews. Test security-token definitions in both pre-silicon and post-silicon testing phases. Implement unique token assignment verification. Ensure token generation is deterministic and reproducible. Document all token assignments and validate consistency. Use formal verification for token generation logic.

Common Consequences

ImpactDetails
Access ControlScope: Access Control

Bypass Protection Mechanism - Incorrect tokens allow unauthorized actions.
ConfidentialityScope: Confidentiality

Read Memory - Unauthorized agents may gain read access.
IntegrityScope: Integrity

Modify Memory - Unauthorized agents may gain write access.
AvailabilityScope: Availability

DoS - Conflicting tokens may cause system failures.

Example Code

Vulnerable Code

// Vulnerable: Token generation with conflict

module vulnerable_token_generator (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire request_token,
    output reg [7:0] security_token,
    output reg token_valid
);

    // VULNERABLE: Flawed token generation logic
    // Multiple agents can receive the same token

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            security_token <= 8'h00;
            token_valid <= 1'b0;
        end
        else if (request_token) begin
            // VULNERABLE: Token based only on lower 2 bits of agent_id
            // Agents 0, 4, 8, 12 all get the same token
            // Agents 1, 5, 9, 13 all get the same token
            // etc.

            case (agent_id[1:0])
                2'b00: security_token <= 8'h01;  // Token 1
                2'b01: security_token <= 8'h02;  // Token 2
                2'b10: security_token <= 8'h03;  // Token 3
                2'b11: security_token <= 8'h04;  // Token 4
            endcase

            token_valid <= 1'b1;

            // Problem: Agent 0 (trusted CPU) gets token 1
            // Agent 4 (untrusted DMA) also gets token 1
            // Both can access same protected resources!
        end
    end

endmodule

// Vulnerable: AES key access with token collision
module vulnerable_aes_access (
    input wire clk,
    input wire reset_n,
    input wire [7:0] token,
    input wire [7:0] reg_addr,
    input wire read_request,
    output reg [31:0] read_data,
    output reg access_granted
);

    reg [127:0] aes_key;

    // Token assignments (vulnerable):
    // Token 1 = Crypto controller (trusted) - should access key
    // Token 1 = DMA controller (untrusted) - same token!

    parameter TRUSTED_CRYPTO = 8'h01;
    // VULNERABLE: Both agents have token 0x01

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_granted <= 1'b0;
        end
        else if (read_request) begin
            if (reg_addr == 8'h00) begin  // AES key register
                // VULNERABLE: Check only against token value
                if (token == TRUSTED_CRYPTO) begin
                    // Both trusted and untrusted get access!
                    read_data <= aes_key[31:0];
                    access_granted <= 1'b1;
                end
                else begin
                    access_granted <= 1'b0;
                end
            end
        end
    end

endmodule
// Vulnerable: Software token assignment with collision

#include <stdint.h>

#define MAX_AGENTS 16

typedef struct {
    uint8_t agent_id;
    uint8_t security_token;
    const char* name;
} agent_info_t;

// VULNERABLE: Token assignment function
uint8_t vulnerable_generate_token(uint8_t agent_id) {
    // VULNERABLE: Only uses lower 3 bits
    // Agents 0 and 8 get the same token
    // Agents 1 and 9 get the same token
    // etc.
    return (agent_id & 0x07) + 1;
}

// VULNERABLE: Token table with collisions
agent_info_t vulnerable_agent_table[] = {
    {0, 1, "Secure CPU"},        // Token 1
    {1, 2, "Crypto Engine"},     // Token 2
    {2, 3, "Boot ROM"},          // Token 3
    {3, 4, "User App"},          // Token 4
    // ... later additions
    {8, 1, "DMA Controller"},    // VULNERABLE: Same token as Secure CPU!
    {9, 2, "Debug Agent"},       // VULNERABLE: Same token as Crypto Engine!
};

bool vulnerable_check_access(uint8_t token, uint32_t resource) {
    // Only checks token value, not agent identity
    if (resource == RESOURCE_AES_KEY) {
        return (token == 1 || token == 2);  // Tokens 1 and 2 allowed
    }
    return false;

    // Problem: DMA (token 1) and Debug (token 2) can access AES key!
}

Fixed Code

// Fixed: Unique token generation

module secure_token_generator (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire request_token,
    output reg [7:0] security_token,
    output reg token_valid,
    output reg token_conflict
);

    // Token assignment table (verified unique)
    reg [7:0] token_table [0:15];

    // Track assigned tokens
    reg [255:0] token_assigned;

    // Initialize unique tokens
    initial begin
        // Each agent gets unique token
        token_table[0]  = 8'h01;  // Secure CPU
        token_table[1]  = 8'h02;  // Crypto Engine
        token_table[2]  = 8'h03;  // Boot ROM
        token_table[3]  = 8'h04;  // User Application
        token_table[4]  = 8'h10;  // DMA Controller (different!)
        token_table[5]  = 8'h20;  // Debug Agent (different!)
        token_table[6]  = 8'h30;  // Test Interface
        token_table[7]  = 8'h40;  // External Host
        token_table[8]  = 8'h50;  // GPU
        token_table[9]  = 8'h60;  // DSP
        token_table[10] = 8'h70;  // Network Controller
        token_table[11] = 8'h80;  // Storage Controller
        token_table[12] = 8'h90;  // USB Controller
        token_table[13] = 8'hA0;  // Audio Controller
        token_table[14] = 8'hB0;  // Video Controller
        token_table[15] = 8'hC0;  // Reserved

        token_assigned = 256'h0;
    end

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            security_token <= 8'h00;
            token_valid <= 1'b0;
            token_conflict <= 1'b0;
        end
        else if (request_token) begin
            token_conflict <= 1'b0;

            // FIXED: Use full agent_id for lookup
            security_token <= token_table[agent_id];

            // FIXED: Verify no token collision
            if (token_assigned[token_table[agent_id]]) begin
                // Token already assigned to another agent!
                token_conflict <= 1'b1;
                token_valid <= 1'b0;
            end
            else begin
                token_assigned[token_table[agent_id]] <= 1'b1;
                token_valid <= 1'b1;
            end
        end
    end

endmodule

// Fixed: AES access with verified tokens
module secure_aes_access (
    input wire clk,
    input wire reset_n,
    input wire [3:0] agent_id,
    input wire [7:0] token,
    input wire [7:0] reg_addr,
    input wire read_request,
    output reg [31:0] read_data,
    output reg access_granted,
    output reg token_mismatch
);

    reg [127:0] aes_key;

    // Expected token table
    reg [7:0] expected_token [0:15];

    // Access policy for AES key
    reg [15:0] aes_access_policy;

    initial begin
        // Set expected tokens (must match token generator)
        expected_token[0]  = 8'h01;  // Secure CPU
        expected_token[1]  = 8'h02;  // Crypto Engine
        expected_token[4]  = 8'h10;  // DMA Controller
        expected_token[5]  = 8'h20;  // Debug Agent

        // Only agents 0 and 1 can access AES key
        aes_access_policy = 16'b0000_0000_0000_0011;
    end

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            access_granted <= 1'b0;
            token_mismatch <= 1'b0;
        end
        else if (read_request) begin
            token_mismatch <= 1'b0;
            access_granted <= 1'b0;

            // FIXED: Verify token matches expected for agent
            if (token != expected_token[agent_id]) begin
                // Token doesn't match agent - possible spoofing
                token_mismatch <= 1'b1;
            end
            else if (reg_addr == 8'h00) begin  // AES key register
                // FIXED: Check agent permission, not just token
                if (aes_access_policy[agent_id]) begin
                    read_data <= aes_key[31:0];
                    access_granted <= 1'b1;
                end
            end
        end
    end

endmodule

// Fixed: Token verification module
module token_verification (
    input wire clk,
    input wire reset_n,
    input wire verify_enable,
    output reg verification_passed,
    output reg [3:0] conflict_agent_a,
    output reg [3:0] conflict_agent_b
);

    reg [7:0] token_table [0:15];
    integer i, j;
    reg conflict_found;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            verification_passed <= 1'b0;
            conflict_found <= 1'b0;
        end
        else if (verify_enable) begin
            conflict_found <= 1'b0;

            // FIXED: Check all token pairs for uniqueness
            for (i = 0; i < 15; i = i + 1) begin
                for (j = i + 1; j < 16; j = j + 1) begin
                    if (token_table[i] == token_table[j]) begin
                        conflict_found <= 1'b1;
                        conflict_agent_a <= i[3:0];
                        conflict_agent_b <= j[3:0];
                    end
                end
            end

            verification_passed <= !conflict_found;
        end
    end

endmodule
// Fixed: Software token generation with uniqueness verification

#include <stdint.h>
#include <stdbool.h>

#define MAX_AGENTS 16
#define INVALID_TOKEN 0x00

typedef struct {
    uint8_t agent_id;
    uint8_t security_token;
    const char* name;
    bool is_trusted;
} secure_agent_info_t;

// FIXED: Verified unique token table
static const secure_agent_info_t secure_agent_table[] = {
    {0,  0x01, "Secure CPU",       true},
    {1,  0x02, "Crypto Engine",    true},
    {2,  0x03, "Boot ROM",         true},
    {3,  0x04, "User Application", false},
    {4,  0x10, "DMA Controller",   false},  // FIXED: Unique token
    {5,  0x20, "Debug Agent",      false},  // FIXED: Unique token
    {6,  0x30, "Test Interface",   false},
    {7,  0x40, "External Host",    false},
    {8,  0x50, "GPU",              false},  // FIXED: Unique token
    {9,  0x60, "DSP",              false},  // FIXED: Unique token
    {10, 0x70, "Network",          false},
    {11, 0x80, "Storage",          false},
    {12, 0x90, "USB",              false},
    {13, 0xA0, "Audio",            false},
    {14, 0xB0, "Video",            false},
    {15, 0xC0, "Reserved",         false},
};

// FIXED: Verify token uniqueness at startup
bool verify_token_uniqueness(void) {
    uint8_t token_count[256] = {0};

    for (int i = 0; i < MAX_AGENTS; i++) {
        uint8_t token = secure_agent_table[i].security_token;

        if (token == INVALID_TOKEN) {
            log_error("Agent %d has invalid token", i);
            return false;
        }

        if (token_count[token] > 0) {
            log_error("Token collision: token 0x%02X assigned multiple times", token);
            return false;
        }

        token_count[token]++;
    }

    log_info("Token uniqueness verified for all %d agents", MAX_AGENTS);
    return true;
}

// FIXED: Get token for agent with validation
uint8_t secure_get_token(uint8_t agent_id) {
    if (agent_id >= MAX_AGENTS) {
        return INVALID_TOKEN;
    }

    return secure_agent_table[agent_id].security_token;
}

// FIXED: Verify token belongs to claimed agent
bool verify_token_ownership(uint8_t agent_id, uint8_t presented_token) {
    if (agent_id >= MAX_AGENTS) {
        return false;
    }

    return (secure_agent_table[agent_id].security_token == presented_token);
}

// FIXED: Access check with agent and token verification
bool secure_check_access(uint8_t agent_id, uint8_t token, uint32_t resource) {
    // Verify token matches agent
    if (!verify_token_ownership(agent_id, token)) {
        log_security_event("Token mismatch for agent %d", agent_id);
        return false;
    }

    // Check resource access based on agent identity (not just token)
    if (resource == RESOURCE_AES_KEY) {
        // Only trusted agents can access AES key
        return secure_agent_table[agent_id].is_trusted;
    }

    return false;
}

CVE Examples

Token generation vulnerabilities have been found in various SoC designs where multiple agents were incorrectly assigned the same security token, allowing untrusted components to access protected resources.


  • CWE-284: Improper Access Control (parent)
  • CWE-1294: Insecure Security Identifier Mechanism (parent)
  • CWE-1259: Improper Restriction of Security Token Assignment (related)
  • CAPEC-121: Exploit Non-Production Interfaces (attack pattern)
  • CAPEC-633: Token Impersonation (attack pattern)
  • CAPEC-681: Exploitation of Improperly Controlled Hardware Security Identifiers (attack pattern)

References

  1. MITRE Corporation. "CWE-1270: Generation of Incorrect Security Tokens." https://cwe.mitre.org/data/definitions/1270.html
  2. ARM. "AMBA AXI Security Extensions"
  3. RISC-V. "World-Guard Security Specification"