Missing Write Protection for Parametric Data Values
Description
Missing Write Protection for Parametric Data Values occurs when the device does not write-protect the parametric data values for sensors that scale the sensor value, allowing untrusted software to manipulate the apparent result and potentially damage hardware or cause operational failure. Hardware devices employ sensors to monitor operational parameters like thermal, power, voltage, current, and frequency levels. While threshold limits are typically protected via hardware fuses or trusted BIOS, the sensor calibration data used for unit conversion may remain unprotected. Untrusted software can modify these parametric scaling values to bypass safety limits and falsify sensor readings.
Risk
Unprotected sensor parameters have severe implications. Physical hardware damage possible. Thermal limits bypassed causing overheating. Power limits bypassed causing component damage. False sensor readings mask dangerous conditions. Denial of service through induced failures. Safety mechanisms rendered ineffective. Hardware lifetime reduced. High availability impact.
Solution
Implement access controls restricting modification of threshold limits and sensor parametric data to trusted software only during architecture and design phase. Store calibration data in protected memory regions. Require privileged access for parameter modification. Consider hardware fuses for critical calibration values. Validate parameter changes against safe ranges even for trusted software.
Common Consequences
| Impact | Details |
|---|---|
| Availability | Scope: Availability Denial of service through hardware damage, false shutdowns, or induced instability. |
Example Code
Vulnerable Code
// Vulnerable: Sensor with unprotected calibration parameters
module vulnerable_temperature_sensor (
input wire clk,
input wire rst_n,
// Raw sensor input (oscillator frequency)
input wire [15:0] oscillator_freq,
// Calibration parameters (VULNERABLE: writable by anyone)
input wire param_write_enable,
input wire [31:0] param_write_data,
input wire [3:0] param_write_addr,
// Temperature output
output reg [15:0] temperature_celsius,
output reg over_temp_alarm,
output reg shutdown_required
);
// Calibration parameters for temperature calculation
// Temperature = a * freq + b (linear approximation)
reg signed [15:0] param_a; // Slope coefficient
reg signed [15:0] param_b; // Offset coefficient
// Threshold (typically protected by fuse)
localparam SHUTDOWN_THRESHOLD = 16'd100; // 100°C
// VULNERABLE: Calibration parameters writable without restriction
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// Default calibration values
param_a <= 16'h0010; // Default slope
param_b <= 16'hFF00; // Default offset
end else if (param_write_enable) begin
// VULNERABLE: Any software can modify parameters
case (param_write_addr)
4'h0: param_a <= param_write_data[15:0];
4'h1: param_b <= param_write_data[15:0];
endcase
end
end
// Calculate temperature from oscillator frequency
reg signed [31:0] temp_calc;
always @(posedge clk) begin
// Temperature = a * freq + b
temp_calc <= param_a * $signed({1'b0, oscillator_freq}) + param_b;
temperature_celsius <= temp_calc[15:0];
// Check against threshold
if (temperature_celsius >= SHUTDOWN_THRESHOLD) begin
over_temp_alarm <= 1'b1;
shutdown_required <= 1'b1;
end else begin
over_temp_alarm <= 1'b0;
shutdown_required <= 1'b0;
end
end
// Attack:
// 1. Attacker sets param_a = 0, param_b = 0
// 2. Temperature always reads as 0°C
// 3. Hardware overheats to dangerous levels
// 4. Shutdown threshold never triggered
// 5. Physical damage to hardware
endmodule
// Vulnerable: Power sensor with unprotected scaling
module vulnerable_power_sensor (
input wire clk,
input wire rst_n,
// Raw ADC reading
input wire [11:0] adc_reading,
// Scaling parameters (VULNERABLE: unprotected)
input wire scale_write_en,
input wire [15:0] scale_multiplier,
input wire [15:0] scale_divisor,
// Power output
output reg [15:0] power_watts,
output reg power_limit_exceeded
);
// VULNERABLE: Scaling factors writable without authentication
reg [15:0] multiplier;
reg [15:0] divisor;
localparam POWER_LIMIT = 16'd150; // 150W limit
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
multiplier <= 16'd100; // Default calibration
divisor <= 16'd1024;
end else if (scale_write_en) begin
// VULNERABLE: No access control
multiplier <= scale_multiplier;
divisor <= scale_divisor;
end
end
// Calculate power
always @(posedge clk) begin
if (divisor != 0) begin
power_watts <= (adc_reading * multiplier) / divisor;
end else begin
// VULNERABLE: Division by zero if attacker sets divisor=0
power_watts <= 16'hFFFF; // Overflow!
end
power_limit_exceeded <= (power_watts > POWER_LIMIT);
end
// Attack:
// Set multiplier=0 -> power always reads 0W
// Or set divisor=0 -> causes undefined behavior
// Power limits never triggered, component damage possible
endmodule
// Vulnerable: Software sensor driver without parameter protection
#include <stdint.h>
#include <stdbool.h>
// VULNERABLE: Calibration structure accessible to all software
typedef struct {
int16_t slope;
int16_t offset;
uint16_t threshold;
} sensor_calibration_t;
// VULNERABLE: Global, unprotected calibration data
static sensor_calibration_t thermal_calibration = {
.slope = 16,
.offset = -256,
.threshold = 100
};
// VULNERABLE: Any code can modify calibration
void vulnerable_set_calibration(int16_t slope, int16_t offset) {
// No privilege check!
thermal_calibration.slope = slope;
thermal_calibration.offset = offset;
}
int16_t vulnerable_read_temperature(uint16_t raw_reading) {
// Uses potentially compromised calibration
int32_t temp = (thermal_calibration.slope * raw_reading) +
thermal_calibration.offset;
return (int16_t)temp;
}
bool vulnerable_check_thermal_limit(uint16_t raw_reading) {
int16_t temp = vulnerable_read_temperature(raw_reading);
// VULNERABLE: Returns false if calibration corrupted to show low temp
return temp >= thermal_calibration.threshold;
}
// Attack:
// malicious_code() {
// vulnerable_set_calibration(0, 0); // Set slope=0, offset=0
// // Now all temperature readings return 0
// // System won't trigger thermal protection
// }
Fixed Code
// Fixed: Sensor with protected calibration parameters
module secure_temperature_sensor (
input wire clk,
input wire rst_n,
// Raw sensor input
input wire [15:0] oscillator_freq,
// Calibration write interface (restricted)
input wire param_write_enable,
input wire [31:0] param_write_data,
input wire [3:0] param_write_addr,
input wire privileged_access, // FIXED: Privilege signal
input wire boot_complete, // FIXED: Lifecycle signal
// Temperature output
output reg [15:0] temperature_celsius,
output reg over_temp_alarm,
output reg shutdown_required,
output reg param_write_denied
);
// Calibration parameters
reg signed [15:0] param_a;
reg signed [15:0] param_b;
// FIXED: Write lock after boot
reg calibration_locked;
// FIXED: Valid parameter ranges
localparam MIN_SLOPE = 16'sh0001;
localparam MAX_SLOPE = 16'sh00FF;
localparam MIN_OFFSET = 16'shFC00;
localparam MAX_OFFSET = 16'sh0400;
localparam SHUTDOWN_THRESHOLD = 16'd100;
// FIXED: Lock calibration after boot
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
calibration_locked <= 1'b0;
end else if (boot_complete) begin
// FIXED: Once boot completes, lock calibration
calibration_locked <= 1'b1;
end
end
// FIXED: Protected calibration parameter writes
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// Load default calibration from OTP/fuse
param_a <= 16'h0010;
param_b <= 16'hFF00;
param_write_denied <= 1'b0;
end else if (param_write_enable) begin
param_write_denied <= 1'b0;
// FIXED: Check privileges and lifecycle
if (!privileged_access || calibration_locked) begin
// FIXED: Deny write from unprivileged or after lock
param_write_denied <= 1'b1;
end else begin
// FIXED: Validate parameter ranges
case (param_write_addr)
4'h0: begin
if ($signed(param_write_data[15:0]) >= MIN_SLOPE &&
$signed(param_write_data[15:0]) <= MAX_SLOPE) begin
param_a <= param_write_data[15:0];
end else begin
param_write_denied <= 1'b1; // Out of range
end
end
4'h1: begin
if ($signed(param_write_data[15:0]) >= MIN_OFFSET &&
$signed(param_write_data[15:0]) <= MAX_OFFSET) begin
param_b <= param_write_data[15:0];
end else begin
param_write_denied <= 1'b1; // Out of range
end
end
default: begin
param_write_denied <= 1'b1;
end
endcase
end
end
end
// Calculate temperature
reg signed [31:0] temp_calc;
always @(posedge clk) begin
temp_calc <= param_a * $signed({1'b0, oscillator_freq}) + param_b;
temperature_celsius <= temp_calc[15:0];
if (temperature_celsius >= SHUTDOWN_THRESHOLD) begin
over_temp_alarm <= 1'b1;
shutdown_required <= 1'b1;
end else begin
over_temp_alarm <= 1'b0;
shutdown_required <= 1'b0;
end
end
endmodule
// Fixed: Power sensor with protected and validated parameters
module secure_power_sensor (
input wire clk,
input wire rst_n,
// Raw ADC reading
input wire [11:0] adc_reading,
// Protected scaling parameter interface
input wire scale_write_en,
input wire [15:0] scale_multiplier,
input wire [15:0] scale_divisor,
input wire privileged_access,
input wire boot_complete,
// Power output
output reg [15:0] power_watts,
output reg power_limit_exceeded,
output reg param_error
);
reg [15:0] multiplier;
reg [15:0] divisor;
reg params_locked;
// FIXED: Safe parameter ranges
localparam MIN_DIVISOR = 16'd100; // Prevent division issues
localparam MAX_MULTIPLIER = 16'd1000;
localparam POWER_LIMIT = 16'd150;
// FIXED: Lock after boot
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
params_locked <= 1'b0;
end else if (boot_complete) begin
params_locked <= 1'b1;
end
end
// FIXED: Protected parameter writes
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
multiplier <= 16'd100;
divisor <= 16'd1024;
param_error <= 1'b0;
end else if (scale_write_en) begin
param_error <= 1'b0;
if (!privileged_access || params_locked) begin
// FIXED: Deny unprivileged or locked writes
param_error <= 1'b1;
end else begin
// FIXED: Validate divisor to prevent divide-by-zero
if (scale_divisor >= MIN_DIVISOR &&
scale_multiplier <= MAX_MULTIPLIER) begin
multiplier <= scale_multiplier;
divisor <= scale_divisor;
end else begin
param_error <= 1'b1;
end
end
end
end
// Calculate power (safe with validated divisor)
always @(posedge clk) begin
power_watts <= (adc_reading * multiplier) / divisor;
power_limit_exceeded <= (power_watts > POWER_LIMIT);
end
endmodule
// Fixed: Software sensor driver with protected parameters
#include <stdint.h>
#include <stdbool.h>
typedef struct {
int16_t slope;
int16_t offset;
uint16_t threshold;
bool locked; // FIXED: Lock flag
} sensor_calibration_t;
// FIXED: Static calibration, not directly accessible
static sensor_calibration_t thermal_calibration = {
.slope = 16,
.offset = -256,
.threshold = 100,
.locked = false
};
// FIXED: Valid parameter ranges
#define MIN_SLOPE 1
#define MAX_SLOPE 255
#define MIN_OFFSET -1024
#define MAX_OFFSET 1024
// FIXED: Privileged-only calibration setting
bool secure_set_calibration(int16_t slope, int16_t offset, bool privileged) {
// FIXED: Require privilege
if (!privileged) {
return false;
}
// FIXED: Prevent modification after lock
if (thermal_calibration.locked) {
return false;
}
// FIXED: Validate parameter ranges
if (slope < MIN_SLOPE || slope > MAX_SLOPE) {
return false;
}
if (offset < MIN_OFFSET || offset > MAX_OFFSET) {
return false;
}
thermal_calibration.slope = slope;
thermal_calibration.offset = offset;
return true;
}
// FIXED: Lock calibration after initialization
void secure_lock_calibration(void) {
thermal_calibration.locked = true;
}
int16_t secure_read_temperature(uint16_t raw_reading) {
int32_t temp = (thermal_calibration.slope * raw_reading) +
thermal_calibration.offset;
return (int16_t)temp;
}
bool secure_check_thermal_limit(uint16_t raw_reading) {
int16_t temp = secure_read_temperature(raw_reading);
return temp >= thermal_calibration.threshold;
}
// FIXED: Initialization sequence
void secure_sensor_init(int16_t cal_slope, int16_t cal_offset) {
// Only during boot, from trusted code
if (secure_set_calibration(cal_slope, cal_offset, true)) {
secure_lock_calibration();
} else {
// Use safe defaults if calibration fails
// Don't lock - allows recovery with valid params
}
}
CVE Examples
- CVE-2020-8703: Improper input validation in thermal subsystem allowed manipulation of temperature readings.
- CVE-2019-0151: Insufficient access control on power sensor parameters in certain Intel processors.
Related CWEs
- CWE-862: Missing Authorization (parent)
- CWE-1299: Missing Protection Mechanism for Alternate Hardware Interface (peer)
- CWE-1198: Privilege Separation and Access Control Issues (category)
- CWE-1206: Power, Clock, Thermal, and Reset Concerns (category)
References
- MITRE Corporation. "CWE-1314: Missing Write Protection for Parametric Data Values." https://cwe.mitre.org/data/definitions/1314.html
- Intel. "Thermal Management Specifications"
- JEDEC. "Power Management Standards"