Practical Implementation of Secure Boot Mechanism in Embedded Systems: Signature Verification, Dual Partition Design, and Rollback Mechanism

With the widespread application of embedded devices in critical fields such as industrial control, automotive electronics, and the Internet of Things, system security has become an essential aspect of design. The Secure Boot mechanism serves as the first link in the firmware trust execution chain, effectively preventing the execution of unauthorized code and ensuring that the firmware running on the device is unaltered and from a trusted source.

This article combines a typical MCU platform (such as STM32) with practical engineering requirements, focusing on three aspects: signature verification, dual partition design, and rollback mechanism in case of upgrade failure, supplemented with key code snippets to help engineers establish a complete secure boot solution.

1. Signature Verification: Ensuring Firmware Integrity and Trusted Source

1. Overview of the Signature Process

Signature verification is based on asymmetric encryption principles. After the vendor compiles the firmware, they use a private key to generate a signature for the firmware; the Bootloader on the MCU side stores the public key and verifies whether the firmware matches the signature at startup.

  • Signature Process (Offline Tool):
https://lzltool.com/AES
  • Burning Content: Firmware file + Signature (usually appended at the end of the firmware).

2. MCU-side Verification Code (Pseudocode Example)

#include "crypto.h"

#define APP_BASE_ADDR   0x08010000
#define APP_SIZE        0x000F0000
#define SIG_SIZE        256  // RSA-2048

uint8_t app_data[APP_SIZE];
uint8_t signature[SIG_SIZE];
const uint8_t public_key[] = { /* PEM or DER format public key */ };

bool verify_firmware_signature() {
    memcpy(app_data, (void*)APP_BASE_ADDR, APP_SIZE);
    memcpy(signature, (void*)(APP_BASE_ADDR + APP_SIZE), SIG_SIZE);

    return rsa_verify_sha256(app_data, APP_SIZE, signature, public_key);
}

Before launching the APP, the Bootloader must first call verify_firmware_signature() to verify the signature before proceeding.

2. Dual Partition Design: Safeguarding Upgrades

In embedded devices, online firmware upgrades have become standard. However, if an error occurs during the upgrade process (such as a power failure), it may prevent the main program from starting. Therefore, adopting a dual partition (A/B) design is crucial.

1. Partition Structure Design

Region Name

Address Range

Purpose

Bootloader

0x08000000–0x0800FFFF

Fixed startup code

Partition A (Primary)

0x08010000–0x0805FFFF

Currently running program

Partition B (Backup)

0x08060000–0x080AFFFF

Upgrade target or backup

Parameter Area

0x080B0000–

Store metadata, status flags

2. Implementation of Startup Logic

typedef struct {
    uint32_t valid_flag;
    uint32_t version;
    uint32_t boot_target; // 0xA=Partition A, 0xB=Partition B
    uint32_t upgrade_pending;
} boot_info_t;

#define BOOT_INFO_ADDR  0x080B0000
#define VALID_FLAG      0xA5A5A5A5

boot_info_t* boot_info = (boot_info_t*)BOOT_INFO_ADDR;

void jump_to_app(uint32_t addr) {
    uint32_t sp = *(volatile uint32_t*)addr;
    uint32_t pc = *(volatile uint32_t*)(addr + 4);
    __set_MSP(sp);
    ((void (*)())pc)();
}

void boot_process() {
    if (boot_info->valid_flag != VALID_FLAG)
        fail_and_halt();

    uint32_t target = boot_info->boot_target == 0xA ? 0x08010000 : 0x08060000;

    if (verify_firmware_signature()) {
        jump_to_app(target);
    } else {
        rollback_and_jump();
    }
}

3. Rollback Mechanism for Upgrade Failure: The Key to System Self-Healing

1. Conditions for Triggering Rollback

  • Failure of signature verification for the startup partition;
  • The upgrade flag upgrade_pending remains 1;
  • Or the system has not reported a “normal operation” status within a certain period.

2. Rollback Process

void rollback_and_jump() {
    if (boot_info->upgrade_pending) {
        // Rollback to the other partition
        boot_info->boot_target = (boot_info->boot_target == 0xA) ? 0xB : 0xA;
        boot_info->upgrade_pending = 0;
        flash_write(BOOT_INFO_ADDR, (uint8_t*)boot_info, sizeof(boot_info_t));
        system_reset();
    } else {
        // Unable to rollback, halt with alarm
        fail_and_halt();
    }
}

3. Normal Operation Write Back Flag (Executed in APP)

void report_normal_boot() {
    boot_info_t info;
    flash_read(BOOT_INFO_ADDR, (uint8_t*)&info, sizeof(info));
    info.upgrade_pending = 0;
    flash_write(BOOT_INFO_ADDR, (uint8_t*)&info, sizeof(info));
}

After the APP starts successfully, it must actively clear upgrade_pending; otherwise, the next restart will be regarded as a failed rollback.

Conclusion

A reliable Secure Boot mechanism should possess the following characteristics:

  • Robust firmware verification mechanism: Prevents the execution of unauthorized or corrupted firmware;
  • Supports breakpoint recovery: Prevents bricking due to interrupted upgrades;
  • Rollback design: Achieves system self-repair;
  • Clear code execution: There is a clear logical layering from startup judgment, firmware selection, to execution jump.

For projects using common embedded platforms like STM32, developers are advised to fully utilize the MCU’s Flash dual bank structure or partitioning strategy, combined with security algorithms (such as AES, RSA, ECDSA), to establish a security defense line from the Bootloader stage.

Through the combination of signature verification + dual partition + rollback mechanism, embedded devices can maintain high system availability and security even in the face of unreliable networks, operational errors, or malicious attacks.

Leave a Comment