Security-Sensitive Hardware Controls with Missing Lock Bit Protection

Description

Security-Sensitive Hardware Controls with Missing Lock Bit Protection occurs when a product implements register lock bit protection but fails to ensure the lock bit prevents modification of all system registers that could alter important hardware configuration. Hardware devices often use trusted lock bits to disable writes to protected register sets after initial firmware configuration. This weakness occurs when the lock bit does not effectively write-protect all system registers or controls that could modify the protected system configuration, allowing adversaries to bypass protections through unprotected related registers.

Risk

Missing lock bit protection for sensitive controls has severe security implications. Related configuration registers may be modifiable. Calibration data may be altered to affect protected functions. Indirect control paths may bypass locks. Safety-critical controls may be disabled. Security features may be circumvented through unprotected registers. System behavior may be modified through peripheral settings. Debug or test modes may be enabled. Power management controls may affect locked resources.

Solution

Identify all registers that can affect security-sensitive configuration. Ensure lock bits protect all related registers and controls. Review indirect paths to protected functionality. Test that locked configuration cannot be modified through any means. Document which registers are protected by each lock. Implement comprehensive lock coverage analysis. Verify lock effectiveness during security reviews. Consider transitive dependencies when designing locks.

Common Consequences

ImpactDetails
Access ControlScope: Access Control

Modify Memory - System configuration protected by lock bit can be modified through unprotected related registers, violating access control.

Example Code

Vulnerable Code

// Vulnerable: Lock doesn't protect all related registers

module vulnerable_thermal_sensor (
    input wire clk,
    input wire reset_n,
    input wire [31:0] write_data,
    input wire write_enable,
    input wire [7:0] register_select,
    input wire set_lock,
    output reg [31:0] critical_temp_limit,    // Protected by lock
    output reg [31:0] calibration_offset,     // NOT protected by lock!
    output reg shutdown_enable,               // NOT protected by lock!
    output reg sensor_locked,
    output reg thermal_shutdown
);

    reg [31:0] current_temperature;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            critical_temp_limit <= 32'd100;  // 100 degrees
            calibration_offset <= 32'd0;
            shutdown_enable <= 1'b1;
            sensor_locked <= 1'b0;
        end
        else begin
            // Lock only protects critical_temp_limit
            if (set_lock) begin
                sensor_locked <= 1'b1;
            end

            if (write_enable) begin
                case (register_select)
                    8'h00: begin
                        // Critical temp - protected by lock
                        if (!sensor_locked) begin
                            critical_temp_limit <= write_data;
                        end
                    end
                    8'h01: begin
                        // VULNERABLE: Calibration not protected!
                        // Attacker can offset temperature reading
                        calibration_offset <= write_data;
                    end
                    8'h02: begin
                        // VULNERABLE: Shutdown enable not protected!
                        // Attacker can disable thermal shutdown
                        shutdown_enable <= write_data[0];
                    end
                endcase
            end
        end
    end

    // Thermal shutdown logic
    wire [31:0] calibrated_temp = current_temperature + calibration_offset;

    always @(posedge clk) begin
        // Shutdown if calibrated temp exceeds limit AND enabled
        thermal_shutdown <= (calibrated_temp > critical_temp_limit) && shutdown_enable;
    end

    // Attack: Even with critical_temp_limit locked at 100:
    // 1. Set calibration_offset to -100 (reading always shows 0)
    // 2. Or set shutdown_enable to 0 (never triggers shutdown)

endmodule

// Vulnerable: Memory protection with unprotected region config
module vulnerable_memory_protection (
    input wire clk,
    input wire reset_n,
    input wire [31:0] write_data,
    input wire write_enable,
    input wire [7:0] register_select,
    input wire set_lock,
    output reg [31:0] protected_region_start,  // Protected
    output reg [31:0] protected_region_end,    // Protected
    output reg [31:0] region_attributes,       // NOT protected!
    output reg protection_locked
);

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            protected_region_start <= 32'h0;
            protected_region_end <= 32'h0;
            region_attributes <= 32'h0;  // Read-only, no-execute, etc.
            protection_locked <= 1'b0;
        end
        else begin
            if (set_lock) begin
                protection_locked <= 1'b1;
            end

            if (write_enable) begin
                case (register_select)
                    8'h00: if (!protection_locked) protected_region_start <= write_data;
                    8'h01: if (!protection_locked) protected_region_end <= write_data;
                    8'h02: region_attributes <= write_data;  // VULNERABLE: Not locked!
                endcase
            end
        end
    end

    // Attack: Region boundaries are locked, but attributes aren't
    // Change attributes to make protected region writable or executable

endmodule
// Vulnerable: Software assumes complete lock protection

#define CRITICAL_TEMP_REG    0x40002000
#define CALIBRATION_REG      0x40002004
#define SHUTDOWN_ENABLE_REG  0x40002008
#define LOCK_REG             0x4000200C

void vulnerable_thermal_init(void) {
    // Set critical temperature
    *(volatile uint32_t*)CRITICAL_TEMP_REG = 100;

    // Set lock
    *(volatile uint32_t*)LOCK_REG = 1;

    // Assumes all thermal config is now protected
    // But calibration and shutdown_enable are not!
}

// Attacker exploit
void thermal_bypass_attack(void) {
    // Can't modify critical_temp - it's locked
    // But can modify calibration!
    *(volatile uint32_t*)CALIBRATION_REG = (uint32_t)-100;

    // Or disable shutdown entirely
    *(volatile uint32_t*)SHUTDOWN_ENABLE_REG = 0;

    // System will overheat without protection
}

Fixed Code

// Fixed: Lock protects all related security controls

module secure_thermal_sensor (
    input wire clk,
    input wire reset_n,
    input wire [31:0] write_data,
    input wire write_enable,
    input wire [7:0] register_select,
    input wire set_lock,
    output reg [31:0] critical_temp_limit,
    output reg [31:0] calibration_offset,
    output reg shutdown_enable,
    output reg sensor_locked,
    output reg thermal_shutdown
);

    reg [31:0] current_temperature;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            critical_temp_limit <= 32'd100;
            calibration_offset <= 32'd0;
            shutdown_enable <= 1'b1;  // Enabled by default
            sensor_locked <= 1'b0;
        end
        else begin
            if (set_lock) begin
                sensor_locked <= 1'b1;
            end

            if (write_enable) begin
                case (register_select)
                    8'h00: begin
                        // Critical temp - protected
                        if (!sensor_locked) begin
                            critical_temp_limit <= write_data;
                        end
                    end
                    8'h01: begin
                        // FIXED: Calibration protected by same lock
                        if (!sensor_locked) begin
                            calibration_offset <= write_data;
                        end
                    end
                    8'h02: begin
                        // FIXED: Shutdown enable protected by same lock
                        if (!sensor_locked) begin
                            shutdown_enable <= write_data[0];
                        end
                    end
                endcase
            end
        end
    end

    // All security-relevant registers now protected

endmodule

// Fixed: Comprehensive protection with multiple lock domains
module secure_comprehensive_lock (
    input wire clk,
    input wire reset_n,
    input wire [31:0] write_data,
    input wire write_enable,
    input wire [7:0] register_select,
    input wire set_security_lock,
    input wire set_config_lock,
    // Security-critical registers
    output reg [31:0] security_policy,
    output reg [31:0] access_control,
    output reg [31:0] debug_control,
    // Configuration registers
    output reg [31:0] peripheral_config,
    output reg [31:0] power_config,
    // Related controls that affect security
    output reg [31:0] calibration,
    output reg [31:0] timing_config,
    // Lock status
    output reg security_locked,
    output reg config_locked
);

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            // Secure defaults
            security_policy <= 32'hFFFFFFFF;  // Most restrictive
            access_control <= 32'h0;
            debug_control <= 32'h0;  // Debug disabled
            peripheral_config <= 32'h0;
            power_config <= 32'h0;
            calibration <= 32'h0;
            timing_config <= 32'h0;
            security_locked <= 1'b0;
            config_locked <= 1'b0;
        end
        else begin
            // Lock bits
            if (set_security_lock) security_locked <= 1'b1;
            if (set_config_lock) config_locked <= 1'b1;

            if (write_enable) begin
                case (register_select)
                    // Security domain - requires security lock
                    8'h00: if (!security_locked) security_policy <= write_data;
                    8'h01: if (!security_locked) access_control <= write_data;
                    8'h02: if (!security_locked) debug_control <= write_data;

                    // Config domain - requires config lock
                    8'h10: if (!config_locked) peripheral_config <= write_data;
                    8'h11: if (!config_locked) power_config <= write_data;

                    // Calibration affects security - requires BOTH locks
                    8'h20: if (!security_locked && !config_locked) calibration <= write_data;

                    // Timing can affect security - requires security lock
                    8'h21: if (!security_locked) timing_config <= write_data;
                endcase
            end
        end
    end

endmodule

// Fixed: Lock coverage verification module
module lock_coverage_checker (
    input wire clk,
    input wire reset_n,
    input wire security_locked,
    input wire [31:0] security_policy,
    input wire [31:0] calibration,
    input wire [31:0] shutdown_enable,
    output reg coverage_violation
);

    // Shadow copies of protected values
    reg [31:0] shadow_policy;
    reg [31:0] shadow_calibration;
    reg [31:0] shadow_shutdown;
    reg shadow_valid;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            shadow_valid <= 1'b0;
            coverage_violation <= 1'b0;
        end
        else if (security_locked && !shadow_valid) begin
            // Capture values when lock is set
            shadow_policy <= security_policy;
            shadow_calibration <= calibration;
            shadow_shutdown <= shutdown_enable;
            shadow_valid <= 1'b1;
        end
        else if (shadow_valid) begin
            // Verify all protected values remain unchanged
            if (security_policy != shadow_policy ||
                calibration != shadow_calibration ||
                shutdown_enable != shadow_shutdown) begin
                coverage_violation <= 1'b1;  // Something changed that shouldn't!
            end
        end
    end

endmodule
// Fixed: Verify complete lock coverage

#define CRITICAL_TEMP_REG    0x40002000
#define CALIBRATION_REG      0x40002004
#define SHUTDOWN_ENABLE_REG  0x40002008
#define LOCK_REG             0x4000200C

void secure_thermal_init(void) {
    // Set all thermal config
    *(volatile uint32_t*)CRITICAL_TEMP_REG = 100;
    *(volatile uint32_t*)CALIBRATION_REG = 0;
    *(volatile uint32_t*)SHUTDOWN_ENABLE_REG = 1;

    // Set lock
    *(volatile uint32_t*)LOCK_REG = 1;

    // Verify ALL related registers are protected
    verify_thermal_lock_coverage();
}

bool verify_thermal_lock_coverage(void) {
    // Save current values
    uint32_t saved_temp = *(volatile uint32_t*)CRITICAL_TEMP_REG;
    uint32_t saved_cal = *(volatile uint32_t*)CALIBRATION_REG;
    uint32_t saved_shutdown = *(volatile uint32_t*)SHUTDOWN_ENABLE_REG;

    bool all_protected = true;

    // Try to modify each register
    *(volatile uint32_t*)CRITICAL_TEMP_REG = ~saved_temp;
    if (*(volatile uint32_t*)CRITICAL_TEMP_REG != saved_temp) {
        log_error("CRITICAL_TEMP not protected by lock!");
        all_protected = false;
    }

    *(volatile uint32_t*)CALIBRATION_REG = ~saved_cal;
    if (*(volatile uint32_t*)CALIBRATION_REG != saved_cal) {
        log_error("CALIBRATION not protected by lock!");
        all_protected = false;
    }

    *(volatile uint32_t*)SHUTDOWN_ENABLE_REG = ~saved_shutdown;
    if (*(volatile uint32_t*)SHUTDOWN_ENABLE_REG != saved_shutdown) {
        log_error("SHUTDOWN_ENABLE not protected by lock!");
        all_protected = false;
    }

    if (!all_protected) {
        panic("Incomplete lock coverage detected!");
    }

    return all_protected;
}

CVE Examples

  • CVE-2018-9085: Write protection lock left unset after boot
  • CVE-2014-8273: Race condition between interrupt handler detection and lock bit reset

  • CWE-284: Improper Access Control (parent)
  • CWE-667: Improper Locking (related)
  • CWE-1231: Improper Prevention of Lock Bit Modification (related)

References

  1. MITRE Corporation. "CWE-1233: Security-Sensitive Hardware Controls with Missing Lock Bit Protection." https://cwe.mitre.org/data/definitions/1233.html
  2. Hardware Lock Coverage Analysis
  3. Security Register Protection Guidelines