3. 实现AES-128加密与解密

实现AES-128加密与解密 学习卡片

任务说明

在MCU HSM(硬件安全模块)应用中,AES-128是最基础的对称加密原语,用于保护敏感数据(如密钥、固件更新包、通信载荷)。本案例要求在HSM环境中实现AES-128 ECB模式的加密与解密功能,并验证加解密结果的一致性。

HSM AES-128 硬件加速器接口定义

本案例基于典型的MCU HSM外设寄存器模型,HSM内部集成AES硬件引擎,支持128/192/256位密钥长度。CPU通过内存映射寄存器与HSM交互,数据通过DMA或直接寄存器写入/读取。以下为最小寄存器接口定义:

HSM AES-128 寄存器映射 (基地址 0x4002_5000) 0x00 CTRL bit[1:0]=模式(00:ECB,01:CBC) | bit[2]=方向(0:加密,1:解密) | bit[3]=启动 | bit[7:4]=密钥长度(0:128) 0x04 STATUS bit[0]=忙 | bit[1]=完成中断标志 | bit[2]=错误标志 0x10 KEY[3:0] 4个32位寄存器,按小端序写入128位密钥 (KEY0=K[31:0] ... KEY3=K[127:96]) 0x20 DIN[3:0] 4个32位数据输入寄存器,按小端序写入16字节明文/密文块 0x30 DOUT[3:0] 4个32位数据输出寄存器,按小端序读出16字节结果

HSM驱动实现

以下代码实现AES-128 ECB模式的完整加解密流程,包含密钥加载、单块数据处理、以及多块连续数据的处理函数。代码基于寄存器操作,不依赖第三方库,可直接在MCU裸机环境中编译运行。


/* hsm_aes.h */
#ifndef HSM_AES_H
#define HSM_AES_H

#include <stdint.h>
#include <stddef.h>

#define HSM_AES_BASE        0x40025000UL
#define HSM_AES_CTRL        (*(volatile uint32_t *)(HSM_AES_BASE + 0x00))
#define HSM_AES_STATUS      (*(volatile uint32_t *)(HSM_AES_BASE + 0x04))
#define HSM_AES_KEY0        (*(volatile uint32_t *)(HSM_AES_BASE + 0x10))
#define HSM_AES_KEY1        (*(volatile uint32_t *)(HSM_AES_BASE + 0x14))
#define HSM_AES_KEY2        (*(volatile uint32_t *)(HSM_AES_BASE + 0x18))
#define HSM_AES_KEY3        (*(volatile uint32_t *)(HSM_AES_BASE + 0x1C))
#define HSM_AES_DIN0        (*(volatile uint32_t *)(HSM_AES_BASE + 0x20))
#define HSM_AES_DIN1        (*(volatile uint32_t *)(HSM_AES_BASE + 0x24))
#define HSM_AES_DIN2        (*(volatile uint32_t *)(HSM_AES_BASE + 0x28))
#define HSM_AES_DIN3        (*(volatile uint32_t *)(HSM_AES_BASE + 0x2C))
#define HSM_AES_DOUT0       (*(volatile uint32_t *)(HSM_AES_BASE + 0x30))
#define HSM_AES_DOUT1       (*(volatile uint32_t *)(HSM_AES_BASE + 0x34))
#define HSM_AES_DOUT2       (*(volatile uint32_t *)(HSM_AES_BASE + 0x38))
#define HSM_AES_DOUT3       (*(volatile uint32_t *)(HSM_AES_BASE + 0x3C))

/* 模式定义 */
#define AES_MODE_ECB        0x00
#define AES_ENCRYPT         0x00
#define AES_DECRYPT         0x04
#define AES_KEY_128         0x00
#define AES_START           0x08

/* 状态位 */
#define AES_STATUS_BUSY     (1 << 0)
#define AES_STATUS_DONE     (1 << 1)
#define AES_STATUS_ERROR    (1 << 2)

/* 函数声明 */
void hsm_aes_set_key(const uint8_t key[16]);
void hsm_aes_process_block(const uint8_t in[16], uint8_t out[16], uint8_t decrypt);
void hsm_aes_ecb_crypt(const uint8_t *in, uint8_t *out, size_t len, const uint8_t key[16], uint8_t decrypt);

#endif /* HSM_AES_H */

/* hsm_aes.c */
#include "hsm_aes.h"

/* 将16字节数组按小端序写入4个32位寄存器 */
static void write_128bit(const uint8_t data[16], volatile uint32_t *reg0,
                         volatile uint32_t *reg1, volatile uint32_t *reg2,
                         volatile uint32_t *reg3)
{
    *reg0 = (uint32_t)data[0] | ((uint32_t)data[1] << 8) |
            ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24);
    *reg1 = (uint32_t)data[4] | ((uint32_t)data[5] << 8) |
            ((uint32_t)data[6] << 16) | ((uint32_t)data[7] << 24);
    *reg2 = (uint32_t)data[8] | ((uint32_t)data[9] << 8) |
            ((uint32_t)data[10] << 16) | ((uint32_t)data[11] << 24);
    *reg3 = (uint32_t)data[12] | ((uint32_t)data[13] << 8) |
            ((uint32_t)data[14] << 16) | ((uint32_t)data[15] << 24);
}

/* 从4个32位寄存器按小端序读出16字节数组 */
static void read_128bit(uint8_t data[16], volatile uint32_t *reg0,
                        volatile uint32_t *reg1, volatile uint32_t *reg2,
                        volatile uint32_t *reg3)
{
    uint32_t w0 = *reg0, w1 = *reg1, w2 = *reg2, w3 = *reg3;
    data[0]  = (uint8_t)(w0 & 0xFF);
    data[1]  = (uint8_t)((w0 >> 8) & 0xFF);
    data[2]  = (uint8_t)((w0 >> 16) & 0xFF);
    data[3]  = (uint8_t)((w0 >> 24) & 0xFF);
    data[4]  = (uint8_t)(w1 & 0xFF);
    data[5]  = (uint8_t)((w1 >> 8) & 0xFF);
    data[6]  = (uint8_t)((w1 >> 16) & 0xFF);
    data[7]  = (uint8_t)((w1 >> 24) & 0xFF);
    data[8]  = (uint8_t)(w2 & 0xFF);
    data[9]  = (uint8_t)((w2 >> 8) & 0xFF);
    data[10] = (uint8_t)((w2 >> 16) & 0xFF);
    data[11] = (uint8_t)((w2 >> 24) & 0xFF);
    data[12] = (uint8_t)(w3 & 0xFF);
    data[13] = (uint8_t)((w3 >> 8) & 0xFF);
    data[14] = (uint8_t)((w3 >> 16) & 0xFF);
    data[15] = (uint8_t)((w3 >> 24) & 0xFF);
}

/* 加载128位密钥到HSM */
void hsm_aes_set_key(const uint8_t key[16])
{
    write_128bit(key, &HSM_AES_KEY0, &HSM_AES_KEY1, &HSM_AES_KEY2, &HSM_AES_KEY3);
}

/* 等待HSM完成当前操作 */
static void hsm_aes_wait_done(void)
{
    while (HSM_AES_STATUS & AES_STATUS_BUSY) {
        /* 轮询等待硬件完成 */
    }
}

/* 处理单个16字节块 */
void hsm_aes_process_block(const uint8_t in[16], uint8_t out[16], uint8_t decrypt)
{
    /* 写入输入数据 */
    write_128bit(in, &HSM_AES_DIN0, &HSM_AES_DIN1, &HSM_AES_DIN2, &HSM_AES_DIN3);

    /* 配置CTRL: ECB模式 + 加/解密方向 + 128位密钥 + 启动 */
    HSM_AES_CTRL = AES_MODE_ECB | (decrypt ? AES_DECRYPT : AES_ENCRYPT) |
                   AES_KEY_128 | AES_START;

    /* 等待完成 */
    hsm_aes_wait_done();

    /* 读取输出数据 */
    read_128bit(out, &HSM_AES_DOUT0, &HSM_AES_DOUT1, &HSM_AES_DOUT2, &HSM_AES_DOUT3);
}

/* ECB模式多块加解密(len必须为16的倍数) */
void hsm_aes_ecb_crypt(const uint8_t *in, uint8_t *out, size_t len,
                       const uint8_t key[16], uint8_t decrypt)
{
    size_t i;

    /* 加载密钥 */
    hsm_aes_set_key(key);

    /* 逐块处理 */
    for (i = 0; i < len; i += 16) {
        hsm_aes_process_block(in + i, out + i, decrypt);
    }
}

测试与验证

使用NIST FIPS-197标准测试向量验证实现正确性。以下测试代码使用标准向量进行加解密一致性验证:


/* test_aes.c */
#include <stdio.h>
#include <string.h>
#include "hsm_aes.h"

/* FIPS-197 附录B 测试向量 */
static const uint8_t test_key[16] = {
    0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
    0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};

static const uint8_t test_plaintext[16] = {
    0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
};

static const uint8_t test_ciphertext[16] = {
    0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60,
    0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97
};

int main(void)
{
    uint8_t enc_out[16];
    uint8_t dec_out[16];
    int pass = 1;

    /* 加密测试 */
    hsm_aes_ecb_crypt(test_plaintext, enc_out, 16, test_key, 0);
    if (memcmp(enc_out, test_ciphertext, 16) != 0) {
        printf("FAIL: encryption mismatch\n");
        pass = 0;
    }

    /* 解密测试 */
    hsm_aes_ecb_crypt(test_ciphertext, dec_out, 16, test_key, 1);
    if (memcmp(dec_out, test_plaintext, 16) != 0) {
        printf("FAIL: decryption mismatch\n");
        pass = 0;
    }

    if (pass) {
        printf("PASS: AES-128 ECB encrypt/decrypt verified\n");
    }
    return pass ? 0 : 1;
}

编译与运行

在MCU工程中,将hsm_aes.c加入编译,并链接test_aes.c作为测试入口。若在PC上模拟寄存器行为,可先定义寄存器地址映射到模拟内存区域。实际MCU上电后,通过串口或调试器观察输出:

  • 若打印PASS: AES-128 ECB encrypt/decrypt verified,说明加解密功能正确;
  • 若打印FAIL,检查密钥加载顺序、寄存器位定义是否与硬件手册一致。

判定标准

本案例通过的标准为:加密输出与FIPS-197标准密文完全一致,且解密能恢复原始明文。该验证路径直接确认了HSM AES-128硬件引擎的寄存器配置、数据通路和字节序处理均正确无误。