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
| Impact | Details |
|---|---|
| Authorization | Scope: Authorization Privilege Escalation - Malicious agents can modify tokens to gain higher privileges. |
| Access Control | Scope: Access Control Bypass Protection Mechanism - Token spoofing allows bypassing access control checks. |
| Integrity | Scope: 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.
Related CWEs
- 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
- MITRE Corporation. "CWE-1259: Improper Restriction of Security Token Assignment." https://cwe.mitre.org/data/definitions/1259.html
- ARM. "TrustZone Security" - Security Identifiers
- AMBA. "AXI Protocol" - Transaction Security