Policy Privileges are not Assigned Consistently Between Control and Data Agents
Description
Policy Privileges are not Assigned Consistently Between Control and Data Agents occurs when hardware-enforced access control fails to properly account for privilege discrepancies between control and write policies affecting resource access. Hardware systems often implement multi-level access policies to control resource access including configuration and encryption keys. When control policies permit both direct resource access and policy modifications, resources included in control policies but excluded from write policies create vulnerabilities. An untrusted agent could exploit this gap to insert itself into write policy registers, potentially gaining unauthorized write access.
Risk
Inconsistent policy privileges have severe security implications. Untrusted agents may grant themselves access. Write policies can be modified through control access. Security configurations may be compromised. Encryption keys may be overwritten. Privilege escalation becomes possible. Protection mechanisms can be bypassed. System security may be undermined. Access control becomes ineffective.
Solution
Access control policies require comprehensive testing during both pre-silicon and post-silicon development phases to ensure consistent privilege assignment across all policy levels. Ensure that agents with control access to a resource also have consistent data access permissions. Implement privilege separation between policy modification and resource access. Audit policy consistency during security reviews.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality | Scope: Confidentiality Read Memory - Inconsistent policies may allow unauthorized data access. |
| Integrity | Scope: Integrity Modify Memory - Agents may gain write access through policy manipulation. |
| Access Control | Scope: Access Control Bypass Protection Mechanism - Policy inconsistencies enable privilege escalation. |
Example Code
Vulnerable Code
// Vulnerable: Inconsistent control and data policies
module vulnerable_aes_policy (
input wire clk,
input wire reset_n,
// Agent interface
input wire [3:0] agent_id,
input wire [7:0] reg_addr,
input wire [31:0] reg_write_data,
input wire reg_write,
input wire reg_read,
output reg [31:0] reg_read_data,
output reg access_denied
);
// AES key storage
reg [127:0] aes_key;
// Policy registers
reg [15:0] aes_key_control_policy; // Who can modify policies
reg [15:0] aes_key_read_policy; // Who can read key
reg [15:0] aes_key_write_policy; // Who can write key
// Register addresses
parameter AES_KEY_REG = 8'h00;
parameter CONTROL_POLICY_REG = 8'h10;
parameter READ_POLICY_REG = 8'h14;
parameter WRITE_POLICY_REG = 8'h18;
// VULNERABLE: Initial policy assignment
initial begin
// Agent 0: Secure Master - full access
// Agent 1: Crypto Engine - read/write key
// Agent 2: Boot ROM - read key only
// Agent 3: Untrusted Debug - SHOULD have no access
aes_key_control_policy = 16'b0000_0000_0000_1111;
// Agents 0,1,2,3 can modify policies
// VULNERABLE: Agent 3 (untrusted) has control access!
aes_key_read_policy = 16'b0000_0000_0000_0111;
// Agents 0,1,2 can read key
aes_key_write_policy = 16'b0000_0000_0000_0011;
// Agents 0,1 can write key
// Agent 3 cannot write key directly
end
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
access_denied <= 1'b0;
end
else if (reg_write) begin
access_denied <= 1'b0;
case (reg_addr)
AES_KEY_REG: begin
// Check write policy
if (aes_key_write_policy[agent_id]) begin
aes_key <= reg_write_data;
end
else begin
access_denied <= 1'b1;
end
end
WRITE_POLICY_REG: begin
// VULNERABLE: Check control policy for policy modification
if (aes_key_control_policy[agent_id]) begin
// Agent 3 can reach here!
// Agent 3 sets bit 3 to give itself write access
aes_key_write_policy <= reg_write_data;
end
else begin
access_denied <= 1'b1;
end
end
// Similar vulnerability for other policy registers
endcase
end
end
// Attack by Agent 3:
// 1. Agent 3 has control policy access (bit 3 set)
// 2. Agent 3 writes to WRITE_POLICY_REG
// 3. Agent 3 sets bit 3 in write policy
// 4. Now Agent 3 has write access to AES key!
endmodule
// Vulnerable: Software policy with inconsistent privileges
#include <stdint.h>
typedef struct {
uint32_t control_mask; // Who can modify policies
uint32_t read_mask; // Who can read resource
uint32_t write_mask; // Who can write resource
} resource_policy_t;
// VULNERABLE: Inconsistent policy assignment
resource_policy_t secret_key_policy = {
.control_mask = 0x0000000F, // Agents 0-3 can modify policies
.read_mask = 0x00000007, // Agents 0-2 can read
.write_mask = 0x00000003, // Agents 0-1 can write
// Agent 3 has control but not read/write
// This inconsistency is exploitable
};
int vulnerable_modify_policy(uint32_t agent_id, resource_policy_t* policy,
uint32_t policy_type, uint32_t new_value) {
// Check if agent has control access
if (!(policy->control_mask & (1 << agent_id))) {
return -EACCES;
}
// VULNERABLE: Agent with control can modify any policy
switch (policy_type) {
case POLICY_CONTROL:
policy->control_mask = new_value;
break;
case POLICY_READ:
policy->read_mask = new_value;
break;
case POLICY_WRITE:
// Agent 3 can set this to grant itself write access!
policy->write_mask = new_value;
break;
}
return 0;
}
// Attack:
// 1. Agent 3 calls vulnerable_modify_policy(..., POLICY_WRITE, 0x0000000F)
// 2. Now Agent 3 has write access to secret key
Fixed Code
// Fixed: Consistent policy privileges
module secure_aes_policy (
input wire clk,
input wire reset_n,
input wire [3:0] agent_id,
input wire [7:0] reg_addr,
input wire [31:0] reg_write_data,
input wire reg_write,
input wire reg_read,
output reg [31:0] reg_read_data,
output reg access_denied,
output reg policy_violation
);
// AES key storage
reg [127:0] aes_key;
// Policy registers
reg [15:0] aes_key_control_policy;
reg [15:0] aes_key_read_policy;
reg [15:0] aes_key_write_policy;
// FIXED: Master policy - only secure master can modify
parameter SECURE_MASTER = 4'd0;
// Register addresses
parameter AES_KEY_REG = 8'h00;
parameter CONTROL_POLICY_REG = 8'h10;
parameter READ_POLICY_REG = 8'h14;
parameter WRITE_POLICY_REG = 8'h18;
// FIXED: Consistent policy assignment
initial begin
// Only trusted agents have control access
aes_key_control_policy = 16'b0000_0000_0000_0001;
// Only Agent 0 (Secure Master) can modify policies
aes_key_read_policy = 16'b0000_0000_0000_0111;
// Agents 0,1,2 can read key
aes_key_write_policy = 16'b0000_0000_0000_0011;
// Agents 0,1 can write key
end
// FIXED: Validate policy consistency
function automatic is_policy_consistent;
input [15:0] new_control;
input [15:0] current_read;
input [15:0] current_write;
begin
// Control policy must be subset of read AND write
// Or: agents with control must also have data access
is_policy_consistent =
((new_control & ~current_read) == 16'h0) &&
((new_control & ~current_write) == 16'h0);
end
endfunction
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
access_denied <= 1'b0;
policy_violation <= 1'b0;
end
else if (reg_write) begin
access_denied <= 1'b0;
policy_violation <= 1'b0;
case (reg_addr)
AES_KEY_REG: begin
if (aes_key_write_policy[agent_id]) begin
aes_key <= reg_write_data;
end
else begin
access_denied <= 1'b1;
end
end
CONTROL_POLICY_REG: begin
// FIXED: Only secure master can modify control policy
if (agent_id == SECURE_MASTER) begin
// FIXED: Validate new policy is consistent
if (is_policy_consistent(reg_write_data,
aes_key_read_policy,
aes_key_write_policy)) begin
aes_key_control_policy <= reg_write_data;
end
else begin
policy_violation <= 1'b1;
end
end
else begin
access_denied <= 1'b1;
end
end
WRITE_POLICY_REG: begin
// FIXED: Only secure master can modify write policy
if (agent_id == SECURE_MASTER) begin
aes_key_write_policy <= reg_write_data;
end
else begin
access_denied <= 1'b1;
end
end
READ_POLICY_REG: begin
// FIXED: Only secure master can modify read policy
if (agent_id == SECURE_MASTER) begin
aes_key_read_policy <= reg_write_data;
end
else begin
access_denied <= 1'b1;
end
end
endcase
end
end
endmodule
// Alternative: Hierarchical policy with privilege levels
module secure_hierarchical_policy (
input wire clk,
input wire reset_n,
input wire [3:0] agent_id,
input wire [1:0] agent_privilege, // 0=user, 1=supervisor, 2=hypervisor, 3=secure
input wire [7:0] reg_addr,
input wire [31:0] reg_write_data,
input wire reg_write,
output reg access_denied
);
// FIXED: Privilege required for each operation
parameter CONTROL_PRIV = 2'd3; // Secure only
parameter WRITE_PRIV = 2'd2; // Hypervisor+
parameter READ_PRIV = 2'd1; // Supervisor+
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
access_denied <= 1'b0;
end
else if (reg_write) begin
case (reg_addr)
POLICY_REG: begin
// FIXED: Only highest privilege can modify policies
if (agent_privilege >= CONTROL_PRIV) begin
// Update policy
end
else begin
access_denied <= 1'b1;
end
end
DATA_REG: begin
// FIXED: Write requires appropriate privilege
if (agent_privilege >= WRITE_PRIV) begin
// Write data
end
else begin
access_denied <= 1'b1;
end
end
endcase
end
end
endmodule
// Fixed: Software policy with consistent privileges
#include <stdint.h>
#include <stdbool.h>
typedef struct {
uint32_t control_mask;
uint32_t read_mask;
uint32_t write_mask;
bool locked; // FIXED: Policy can be locked
} resource_policy_t;
// FIXED: Validate policy consistency
static bool is_policy_consistent(const resource_policy_t* policy,
uint32_t new_control) {
// Control agents must have corresponding data access
// to prevent privilege escalation
// Every agent with control must have read access
if ((new_control & ~policy->read_mask) != 0) {
return false;
}
// Every agent with control must have write access
// (or control must only be for reading policies)
if ((new_control & ~policy->write_mask) != 0) {
return false;
}
return true;
}
// FIXED: Secure policy modification
int secure_modify_policy(uint32_t agent_id, uint32_t agent_privilege,
resource_policy_t* policy,
uint32_t policy_type, uint32_t new_value) {
// FIXED: Policy modification requires highest privilege
if (agent_privilege < PRIVILEGE_SECURE) {
log_access_denied("Policy modification requires secure privilege");
return -EPERM;
}
// FIXED: Check if policy is locked
if (policy->locked) {
log_access_denied("Policy is locked");
return -EPERM;
}
switch (policy_type) {
case POLICY_CONTROL:
// FIXED: Validate consistency before applying
if (!is_policy_consistent(policy, new_value)) {
log_error("Inconsistent control policy rejected");
return -EINVAL;
}
policy->control_mask = new_value;
break;
case POLICY_READ:
// FIXED: Ensure control is subset of read
if ((policy->control_mask & ~new_value) != 0) {
log_error("Read policy would exclude control agents");
return -EINVAL;
}
policy->read_mask = new_value;
break;
case POLICY_WRITE:
// FIXED: Ensure control is subset of write
if ((policy->control_mask & ~new_value) != 0) {
log_error("Write policy would exclude control agents");
return -EINVAL;
}
policy->write_mask = new_value;
break;
case POLICY_LOCK:
// FIXED: Allow locking policy
policy->locked = true;
break;
default:
return -EINVAL;
}
log_policy_change(agent_id, policy_type, new_value);
return 0;
}
// FIXED: Factory function for consistent policies
resource_policy_t create_consistent_policy(uint32_t trusted_agents,
uint32_t read_agents,
uint32_t write_agents) {
resource_policy_t policy;
// Ensure consistency at creation time
// Trusted agents must be subset of both read and write
policy.read_mask = read_agents | trusted_agents;
policy.write_mask = write_agents | trusted_agents;
policy.control_mask = trusted_agents; // Only trusted can modify
policy.locked = false;
return policy;
}
CVE Examples
Inconsistent policy vulnerabilities have been found in SoC designs where untrusted agents could exploit control access to grant themselves data access permissions they should not have.
Related CWEs
- CWE-266: Incorrect Privilege Assignment (parent)
- CWE-1267: Policy Uses Obsolete Encoding (related)
- CWE-1259: Improper Restriction of Security Token Assignment (related)
- CAPEC-180: Exploiting Incorrectly Configured Access Control Levels (attack pattern)
References
- MITRE Corporation. "CWE-1268: Policy Privileges are not Assigned Consistently Between Control and Data Agents." https://cwe.mitre.org/data/definitions/1268.html
- ARM. "TrustZone Security Extensions"
- RISC-V. "Physical Memory Protection Specification"