1. 初始化HSM模块并验证安全启动

初始化HSM模块并验证安全启动 学习卡片

任务说明

本案例面向集成硬件安全模块(HSM)的MCU平台,完成HSM外设的初始化,并验证基于HSM的安全启动流程。安全启动的核心目标是:在MCU上电后,由HSM对引导加载程序(Bootloader)镜像进行完整性校验与认证,仅当认证通过后才允许应用代码执行,从而防止未授权或篡改的固件运行。

硬件与依赖

本案例基于NXP S32K3系列MCU(集成CSEc HSM模块),开发环境为S32 Design Studio for S32 Platform,使用S32K3标准外设驱动库。需要准备:S32K3-EVB开发板、PE Micro调试器、S32 Design Studio IDE。HSM模块通过CSEc(Cryptographic Services Engine)IP核实现,支持AES-128、SHA-256及安全启动所需的密钥存储与签名验证功能。

实现方案

安全启动流程分为两个阶段:启动认证阶段——HSM对Bootloader镜像进行SHA-256哈希计算,并使用预置的公钥对镜像签名进行RSA-2048验证;应用跳转阶段——认证通过后,MCU将程序计数器跳转至Bootloader入口地址执行。本案例代码实现HSM模块的初始化配置、安全启动状态查询以及启动结果判定逻辑。

代码实现

/* main.c - HSM安全启动验证示例 */
#include "Cse.h"
#include "Cse_Crypto.h"
#include "Mcu.h"
#include "flash.h"

#define BOOT_IMAGE_START_ADDR   0x100000u  /* Bootloader存放起始地址 */
#define BOOT_IMAGE_SIZE         0x8000u    /* Bootloader镜像大小(32KB) */
#define SIGNATURE_ADDR          0x100000u + BOOT_IMAGE_SIZE  /* 签名存储位置 */

/* HSM密钥槽位:公钥索引 */
#define HSM_PUBLIC_KEY_SLOT     0x0u

/* 安全启动状态 */
typedef enum {
    SEC_BOOT_NOT_DONE = 0u,
    SEC_BOOT_SUCCESS,
    SEC_BOOT_FAIL
} SecBootStatus;

static SecBootStatus boot_status = SEC_BOOT_NOT_DONE;

/* 安全启动验证函数 */
static SecBootStatus SecureBoot_Verify(void)
{
    uint8_t hash[32];
    uint8_t signature[256];
    Cse_StatusType cse_ret;
    Cse_Crypto_VerifyStatusType verify_result;

    /* 1. 计算Bootloader镜像的SHA-256哈希 */
    cse_ret = Cse_Crypto_Sha256(BOOT_IMAGE_START_ADDR, BOOT_IMAGE_SIZE, hash);
    if (cse_ret != CSE_STATUS_SUCCESS) {
        return SEC_BOOT_FAIL;
    }

    /* 2. 从Flash读取预存的签名数据 */
    Flash_Read(SIGNATURE_ADDR, signature, sizeof(signature));

    /* 3. 使用HSM公钥验证签名 */
    cse_ret = Cse_Crypto_RsaVerify(HSM_PUBLIC_KEY_SLOT,
                                   hash,
                                   sizeof(hash),
                                   signature,
                                   sizeof(signature),
                                   &verify_result);
    if (cse_ret != CSE_STATUS_SUCCESS) {
        return SEC_BOOT_FAIL;
    }

    /* 4. 判定验证结果 */
    if (verify_result == CSE_CRYPTO_VERIFY_OK) {
        return SEC_BOOT_SUCCESS;
    } else {
        return SEC_BOOT_FAIL;
    }
}

/* HSM模块初始化 */
static void Hsm_Init(void)
{
    /* 初始化CSEc驱动 */
    Cse_Init(NULL);

    /* 配置HSM时钟与电源 */
    Mcu_InitClock();
    Mcu_InitCanonical();

    /* 等待HSM就绪 */
    while (Cse_GetStatus() != CSE_STATUS_IDLE) {
        /* 轮询等待 */
    }
}

int main(void)
{
    /* 系统级初始化 */
    Mcu_Init();
    Flash_Init();

    /* 初始化HSM模块 */
    Hsm_Init();

    /* 执行安全启动验证 */
    boot_status = SecureBoot_Verify();

    /* 根据验证结果决定是否跳转至Bootloader */
    if (boot_status == SEC_BOOT_SUCCESS) {
        /* 跳转至Bootloader入口 */
        void (*boot_entry)(void) = (void (*)(void))BOOT_IMAGE_START_ADDR;
        boot_entry();
    } else {
        /* 验证失败:停留在安全启动代码,禁止跳转 */
        while (1u) {
            /* 错误处理:可在此处点亮LED或记录错误码 */
        }
    }

    /* 正常流程不会到达此处 */
    return 0;
}

关键配置说明

上述代码中,BOOT_IMAGE_START_ADDR指向Bootloader在Flash中的物理地址,SIGNATURE_ADDR为签名数据存放位置。实际项目中,Bootloader镜像的SHA-256哈希值和RSA签名由上位机工具在固件构建时生成,并烧录至指定Flash区域。HSM公钥通过CSEc密钥注入流程在芯片出厂或首次配置时写入安全存储区,本案例使用密钥槽0。

验证方法

测试准备:使用S32K3 SDK提供的csec_key_tool生成RSA-2048密钥对,将公钥注入HSM密钥槽0,使用私钥对Bootloader镜像签名并烧录至SIGNATURE_ADDR地址。

执行步骤:

  1. 编译工程并烧录至S32K3-EVB开发板;
  2. 在IDE中设置断点于SecureBoot_Verify()函数返回处;
  3. 全速运行,观察程序是否停在断点位置;
  4. 检查boot_status变量值。

判定标准:

  • 当Bootloader镜像未被篡改时,boot_status应为SEC_BOOT_SUCCESS,程序跳转至Bootloader执行;
  • 人为修改Bootloader区域任意字节后重新烧录,boot_status应为SEC_BOOT_FAIL,程序停留在错误处理循环中;
  • 通过调试器观察HSM寄存器状态,确认CSEc模块无错误中断标志。

预期输出

在验证通过场景下,程序计数器跳转至0x100000地址处开始执行Bootloader代码;验证失败场景下,程序停留在while(1)错误循环中,可通过调试器观察boot_status变量值为2(SEC_BOOT_FAIL)。

HSM安全启动验证流程 MCU上电复位 HSM模块初始化 SHA-256哈希计算 (Bootloader镜像) RSA-2048签名验证 (HSM公钥槽0) 验证通过? 是 跳转至Bootloader (0x100000地址) 否 错误处理循环 (禁止执行Bootloader) 验证点:boot_status变量值 / 程序计数器位置 / HSM错误标志