Product Released in Non-Release Configuration

Description

Product Released in Non-Release Configuration occurs when a product reaches market in a pre-production or manufacturing configuration rather than a finalized release state. Pre-production and manufacturing stages include extensive debug capabilities that create security vulnerabilities including ability to bypass cryptographic checks (authentication, authorization, integrity), access to read/write/modify internal state (registers, memory), system configuration alteration capabilities, and hidden commands exposing intellectual property. When the "Manufacturing Complete" marker is not activated before release, the system remains vulnerable.

Risk

Non-release configuration has severe security implications. Debug interfaces remain accessible. Authentication can be bypassed. Memory can be freely read and written. Internal state can be modified. Cryptographic checks can be disabled. Intellectual property may be exposed. System configuration can be altered. Unauthorized code can be executed. Complete system compromise is possible.

Solution

Establish a Manufacturing Complete marker. Ensure the marker updates at manufacturing completion through mechanisms like fuse activation. Verify release configuration before shipping. Implement checks that enforce production mode. Test that debug features are properly disabled in release. Document and follow secure manufacturing procedures.

Common Consequences

ImpactDetails
ConfidentialityScope: Confidentiality

Read Memory - Manufacturing mode allows unrestricted memory access including secrets.
IntegrityScope: Integrity

Modify Memory - Debug capabilities allow arbitrary memory modification.
Access ControlScope: Access Control

Bypass Protection Mechanism - Security checks can be bypassed in manufacturing mode.
AuthenticationScope: Authentication

Bypass Authentication - Authentication may be disabled in manufacturing mode.

Example Code

Vulnerable Code

// Vulnerable: Device without manufacturing complete check

module vulnerable_security_controller (
    input wire clk,
    input wire reset_n,
    // Debug interface
    input wire debug_request,
    input wire [31:0] debug_addr,
    input wire [31:0] debug_data,
    input wire debug_write,
    output reg [31:0] debug_read_data,
    output reg debug_granted,
    // Manufacturing fuse
    input wire manufacturing_complete_fuse,
    // Secure boot
    input wire boot_request,
    output reg boot_allowed
);

    // VULNERABLE: Manufacturing complete fuse is NOT checked
    // Product ships with fuse unblown (manufacturing_complete_fuse = 0)

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            debug_granted <= 1'b0;
            boot_allowed <= 1'b0;
        end
        else begin
            // VULNERABLE: Debug always granted - no fuse check
            // In production, this should require manufacturing_complete_fuse = 0
            if (debug_request) begin
                // Should check: !manufacturing_complete_fuse
                debug_granted <= 1'b1;

                // Unrestricted memory access
                if (debug_write) begin
                    memory[debug_addr] <= debug_data;
                end
                else begin
                    debug_read_data <= memory[debug_addr];
                end
            end

            // VULNERABLE: Secure boot can be bypassed
            if (boot_request) begin
                // Should enforce signature check in production
                // But manufacturing mode allows bypass
                boot_allowed <= 1'b1;  // Always allowed!
            end
        end
    end

endmodule

// Vulnerable: UART debug enabled in production
module vulnerable_uart_debug (
    input wire clk,
    input wire reset_n,
    input wire uart_rx,
    output wire uart_tx,
    // Manufacturing mode
    input wire mfg_mode_fuse
);

    // VULNERABLE: Manufacturing mode fuse not blown
    // mfg_mode_fuse = 0 means manufacturing mode active

    // Debug commands available
    parameter CMD_READ_MEM = 8'h01;
    parameter CMD_WRITE_MEM = 8'h02;
    parameter CMD_DUMP_SECRETS = 8'h03;
    parameter CMD_BYPASS_AUTH = 8'h04;

    reg [7:0] command;
    reg [31:0] address;
    reg [31:0] data;

    always @(posedge clk) begin
        // VULNERABLE: No check for production mode
        // These commands work even after product ships

        case (command)
            CMD_READ_MEM: begin
                // Read any memory location
                uart_send(memory[address]);
            end

            CMD_WRITE_MEM: begin
                // Write any memory location
                memory[address] <= data;
            end

            CMD_DUMP_SECRETS: begin
                // VULNERABLE: Dump all secrets
                uart_send(encryption_key);
                uart_send(private_key);
            end

            CMD_BYPASS_AUTH: begin
                // VULNERABLE: Skip authentication
                authenticated <= 1'b1;
            end
        endcase
    end

endmodule
// Vulnerable: Software without manufacturing check

#include <stdint.h>

#define FUSE_REG_ADDR 0x40000000
#define MFG_COMPLETE_BIT 0

// VULNERABLE: Manufacturing complete fuse not checked
bool is_manufacturing_mode(void) {
    uint32_t fuse_value = *(volatile uint32_t*)FUSE_REG_ADDR;
    // Fuse not blown = manufacturing mode (bit 0 = 0)
    return (fuse_value & (1 << MFG_COMPLETE_BIT)) == 0;
}

void vulnerable_boot(void) {
    // VULNERABLE: Debug enabled regardless of manufacturing status
    enable_debug_uart();
    enable_jtag();

    // VULNERABLE: Skip signature check in manufacturing mode
    if (is_manufacturing_mode()) {
        // This code path should not exist in shipping product!
        execute_unsigned_firmware();
    }
    else {
        if (verify_signature()) {
            execute_firmware();
        }
        else {
            halt();
        }
    }

    // Problem: Product shipped with fuse not blown
    // is_manufacturing_mode() returns true
    // Attacker can execute unsigned firmware!
}

void vulnerable_handle_debug_command(uint8_t cmd, uint32_t* args) {
    // VULNERABLE: No manufacturing mode check
    // These commands work on shipped products

    switch (cmd) {
        case DEBUG_CMD_READ_MEM:
            // Read any memory
            uart_send(*(volatile uint32_t*)args[0]);
            break;

        case DEBUG_CMD_WRITE_MEM:
            // Write any memory
            *(volatile uint32_t*)args[0] = args[1];
            break;

        case DEBUG_CMD_EXTRACT_KEY:
            // VULNERABLE: Extract cryptographic key
            uart_send_buffer(crypto_key, 32);
            break;

        case DEBUG_CMD_DISABLE_SECURITY:
            // VULNERABLE: Disable all security
            security_enabled = false;
            break;
    }
}

Fixed Code

// Fixed: Device with proper manufacturing complete enforcement

module secure_security_controller (
    input wire clk,
    input wire reset_n,
    // Debug interface
    input wire debug_request,
    input wire [31:0] debug_addr,
    input wire [31:0] debug_data,
    input wire debug_write,
    output reg [31:0] debug_read_data,
    output reg debug_granted,
    output reg debug_denied,
    // Manufacturing fuse (1 = manufacturing complete, 0 = manufacturing)
    input wire manufacturing_complete_fuse,
    // Secure boot
    input wire boot_request,
    input wire signature_valid,
    output reg boot_allowed,
    output reg boot_denied
);

    // FIXED: Determine production vs manufacturing mode
    wire is_production = manufacturing_complete_fuse;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            debug_granted <= 1'b0;
            debug_denied <= 1'b0;
            boot_allowed <= 1'b0;
            boot_denied <= 1'b0;
        end
        else begin
            debug_granted <= 1'b0;
            debug_denied <= 1'b0;
            boot_denied <= 1'b0;

            // FIXED: Debug only available in manufacturing mode
            if (debug_request) begin
                if (!is_production) begin
                    // Manufacturing mode - debug allowed
                    debug_granted <= 1'b1;
                    // ... debug operations
                end
                else begin
                    // FIXED: Production mode - debug denied
                    debug_denied <= 1'b1;
                    debug_read_data <= 32'hDEADBEEF;
                end
            end

            // FIXED: Secure boot enforced in production
            if (boot_request) begin
                if (is_production) begin
                    // Production mode - require valid signature
                    if (signature_valid) begin
                        boot_allowed <= 1'b1;
                    end
                    else begin
                        boot_denied <= 1'b1;
                    end
                end
                else begin
                    // Manufacturing mode - may allow unsigned boot
                    // with appropriate warnings
                    boot_allowed <= 1'b1;
                end
            end
        end
    end

endmodule

// Fixed: UART with manufacturing mode enforcement
module secure_uart_debug (
    input wire clk,
    input wire reset_n,
    input wire uart_rx,
    output wire uart_tx,
    input wire mfg_mode_fuse,  // 1 = production, 0 = manufacturing
    output reg mfg_mode_violation
);

    wire is_production = mfg_mode_fuse;

    reg [7:0] command;
    reg command_valid;

    // FIXED: Debug command handling with mode check
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            mfg_mode_violation <= 1'b0;
        end
        else if (command_valid) begin
            mfg_mode_violation <= 1'b0;

            // FIXED: Block all debug commands in production
            if (is_production) begin
                // Log violation attempt
                mfg_mode_violation <= 1'b1;
                // Return error to UART
                uart_send_error();
            end
            else begin
                // Manufacturing mode - commands allowed
                case (command)
                    CMD_READ_MEM: uart_send(memory[address]);
                    CMD_WRITE_MEM: memory[address] <= data;
                    // Note: Sensitive commands may still be restricted
                    CMD_DUMP_SECRETS: begin
                        // Even in mfg mode, require additional auth
                        if (mfg_authenticated) begin
                            // Allowed
                        end
                        else begin
                            uart_send_error();
                        end
                    end
                endcase
            end
        end
    end

endmodule

// Fixed: Manufacturing complete verification
module mfg_complete_checker (
    input wire clk,
    input wire reset_n,
    input wire mfg_fuse,
    input wire check_enable,
    output reg mfg_complete,
    output reg check_failed
);

    // FIXED: Verify fuse is properly blown
    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            mfg_complete <= 1'b0;
            check_failed <= 1'b0;
        end
        else if (check_enable) begin
            // Read fuse multiple times to ensure reliability
            if (mfg_fuse && mfg_fuse && mfg_fuse) begin
                mfg_complete <= 1'b1;
                check_failed <= 1'b0;
            end
            else if (!mfg_fuse && !mfg_fuse && !mfg_fuse) begin
                mfg_complete <= 1'b0;
                check_failed <= 1'b0;
            end
            else begin
                // Inconsistent reads - potential tampering
                check_failed <= 1'b1;
            end
        end
    end

endmodule
// Fixed: Software with proper manufacturing mode handling

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

#define FUSE_REG_ADDR 0x40000000
#define MFG_COMPLETE_BIT 0

// FIXED: Comprehensive manufacturing mode check
static bool is_manufacturing_mode(void) {
    volatile uint32_t* fuse_reg = (volatile uint32_t*)FUSE_REG_ADDR;

    // FIXED: Read multiple times to prevent glitching
    uint32_t read1 = *fuse_reg;
    uint32_t read2 = *fuse_reg;
    uint32_t read3 = *fuse_reg;

    // All reads must match
    if (read1 != read2 || read2 != read3) {
        // Inconsistent - assume production (secure default)
        log_security_event("Fuse read inconsistency - assuming production");
        return false;
    }

    // Fuse blown (bit = 1) = production mode
    return (read1 & (1 << MFG_COMPLETE_BIT)) == 0;
}

void secure_boot(void) {
    bool mfg_mode = is_manufacturing_mode();

    if (mfg_mode) {
        // Manufacturing mode
        log_info("Manufacturing mode active");
        enable_debug_uart();
        enable_jtag();
    }
    else {
        // FIXED: Production mode - disable debug
        disable_debug_uart();
        disable_jtag();
        lock_debug_interface();  // Prevent re-enabling
    }

    // FIXED: Secure boot always required in production
    if (!mfg_mode) {
        if (!verify_signature()) {
            log_error("Signature verification failed");
            enter_secure_halt();  // Don't boot!
            return;
        }
    }

    execute_firmware();
}

// FIXED: Debug commands only in manufacturing mode
int secure_handle_debug_command(uint8_t cmd, uint32_t* args) {
    // FIXED: Check manufacturing mode for every command
    if (!is_manufacturing_mode()) {
        log_security_event("Debug command blocked in production mode");
        return -EPERM;
    }

    // Additional authentication even in manufacturing
    if (!is_debug_authenticated()) {
        log_security_event("Debug authentication required");
        return -EAUTH;
    }

    switch (cmd) {
        case DEBUG_CMD_READ_MEM:
            // Limited read in manufacturing
            if (!is_address_debug_readable(args[0])) {
                return -EACCES;
            }
            uart_send(*(volatile uint32_t*)args[0]);
            break;

        case DEBUG_CMD_WRITE_MEM:
            if (!is_address_debug_writable(args[0])) {
                return -EACCES;
            }
            *(volatile uint32_t*)args[0] = args[1];
            break;

        case DEBUG_CMD_EXTRACT_KEY:
            // FIXED: Never allow key extraction, even in manufacturing
            log_security_event("Key extraction attempted");
            return -EPERM;

        default:
            return -EINVAL;
    }

    return 0;
}

// FIXED: Manufacturing finalization procedure
int finalize_manufacturing(void) {
    // Verify device is ready for production
    if (!run_self_tests()) {
        return -EFAULT;
    }

    // FIXED: Blow manufacturing complete fuse
    if (blow_mfg_complete_fuse() != 0) {
        log_error("Failed to blow manufacturing complete fuse");
        return -EIO;
    }

    // FIXED: Verify fuse is blown
    if (is_manufacturing_mode()) {
        log_error("Manufacturing mode still active after fuse blow");
        return -EFAULT;
    }

    // FIXED: Verify debug is disabled
    if (is_debug_accessible()) {
        log_error("Debug still accessible after finalization");
        return -EFAULT;
    }

    log_info("Manufacturing finalization complete");
    return 0;
}

CVE Examples

  • CVE-2019-13945: SIMATIC S7-1200/S7-200 manufacturing access mode enabled diagnostics via UART
  • CVE-2018-4251: Intel chipset laptops discovered operating in Manufacturing Mode with debug capabilities enabled

  • CWE-693: Protection Mechanism Failure (parent)
  • CWE-1191: On-Chip Debug/Test Interface With Improper Access Control (related)
  • CWE-489: Active Debug Code (related)
  • CAPEC-439: Manipulation During Distribution (attack pattern)

References

  1. MITRE Corporation. "CWE-1269: Product Released in Non-Release Configuration." https://cwe.mitre.org/data/definitions/1269.html
  2. Intel. "Manufacturing Mode Documentation"
  3. Siemens. "Industrial Control System Security Advisories"