3. 实现AES-128加密通信

实现AES-128加密通信 学习卡片

任务定义

在MCU与外部主机之间的串口通信链路上,使用HSM模块的硬件AES-128引擎对应用层数据进行加解密。MCU发送方向:将明文数据通过HSM加密后经UART发出;接收方向:将UART收到的密文通过HSM解密还原为明文。本案例聚焦HSM加解密API的正确调用与数据格式组织,不涉及密钥协商与安全存储(密钥以固定数组形式预置)。

硬件连接与数据流

测试拓扑:MCU (HSM集成) UART_TX/RX ←→ USB-TTL ←→ PC串口助手
验证观测点:PC发送16字节密文→MCU解密后回传明文;PC发送16字节明文→MCU加密后回传密文。
PC串口助手 明文/密文输入 显示回传结果 USB-TTL 电平转换 MCU HSM AES-128 硬件加密引擎 UART (115200-8-N-1) TX RX RX TX 测试流程 ① 发16B明文→收密文 ② 发16B密文→收明文 比对数据验证加解密

代码实现

以下代码基于STM32H5系列HSM驱动框架,使用固定测试密钥。核心函数hsm_aes_ecb_crypt完成单块加解密,主循环通过UART接收命令字节决定执行加密或解密操作。

/* hsm_aes_demo.c - HSM硬件AES-128 ECB加解密示例 */
#include "hsm_driver.h"      /* HSM底层驱动 */
#include "uart_driver.h"     /* UART收发驱动 */
#include <string.h>

/* 固定测试密钥(16字节 = AES-128) */
static const uint8_t test_key[16] = {
    0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
    0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
};

/* HSM加解密函数封装
 * mode: 0=加密, 1=解密
 * in/out: 各16字节数据块
 * 返回: 0成功, 非0失败
 */
static int hsm_aes_ecb_crypt(uint8_t mode, const uint8_t *in, uint8_t *out)
{
    hsm_handle_t hsm;
    hsm_status_t st;

    /* 打开HSM会话 */
    st = hsm_open(&hsm);
    if (st != HSM_OK) return -1;

    /* 加载密钥到HSM密钥槽 */
    st = hsm_load_key(hsm, 0, test_key, 16);
    if (st != HSM_OK) {
        hsm_close(hsm);
        return -2;
    }

    /* 执行硬件加解密 */
    st = hsm_aes_ecb(hsm, 0, mode, in, out);
    hsm_close(hsm);

    return (st == HSM_OK) ? 0 : -3;
}

/* 主函数 */
int main(void)
{
    uint8_t rx_buf[16];
    uint8_t result[16];
    uint8_t cmd;
    int ret;

    uart_init(115200);
    hsm_init();

    while (1) {
        /* 等待接收1字节命令: 0x01=加密, 0x02=解密 */
        if (uart_receive_byte(&cmd, 1000) != UART_OK) continue;

        /* 接收16字节数据块 */
        if (uart_receive_bytes(rx_buf, 16, 2000) != UART_OK) {
            uart_send_string("ERR:TIMEOUT\r\n");
            continue;
        }

        if (cmd == 0x01) {
            ret = hsm_aes_ecb_crypt(0, rx_buf, result);  /* 加密 */
        } else if (cmd == 0x02) {
            ret = hsm_aes_ecb_crypt(1, rx_buf, result);  /* 解密 */
        } else {
            uart_send_string("ERR:CMD\r\n");
            continue;
        }

        if (ret == 0) {
            uart_send_bytes(result, 16);   /* 回传处理结果 */
            uart_send_string("\r\nOK\r\n");
        } else {
            uart_send_string("ERR:HSM\r\n");
        }
    }
}

编译与烧录

# 使用STM32CubeIDE或arm-none-eabi-gcc编译
arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -O2 \
  -I./drivers -I./hsm \
  hsm_aes_demo.c ./drivers/uart_driver.c ./hsm/hsm_driver.c \
  -o hsm_aes_demo.elf

# 通过ST-Link烧录
st-flash write hsm_aes_demo.elf 0x08000000

验证方法与判定标准

测试准备:PC安装串口助手(如SSCOM),配置115200-8-N-1。MCU上电后,HSM初始化完成即可开始测试。

加密验证:发送十六进制数据 01 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF(首字节0x01为加密命令,后16字节为明文)。预期MCU回传16字节密文后跟\r\nOK\r\n。使用相同密钥的软件AES工具(如OpenSSL)计算同一明文的ECB加密结果,应与回传密文完全一致。

解密验证:发送 02 + 上述加密得到的16字节密文。预期MCU回传原始明文 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF,证明解密正确。

判定标准:

  • 加密回传密文与OpenSSL AES-128-ECB计算结果逐字节一致;
  • 解密回传明文与最初发送的明文完全一致;
  • 发送错误命令(如0x03)时,MCU回传ERR:CMD;
  • 发送长度不足时,MCU回传ERR:TIMEOUT。

预期输出示例(基于给定密钥与上述明文,由AES-128-ECB算法唯一确定):

加密命令发送:  01 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
MCU回传密文:   3A D7 7B B4 0D 7A 36 60 A8 9E CA F3 24 66 EF 97
解密命令发送:  02 3A D7 7B B4 0D 7A 36 60 A8 9E CA F3 24 66 EF 97
MCU回传明文:   00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF

注:以上密文为算法确定性输出,实际运行时若密钥或明文不同则结果不同。