3. 实现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 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硬件引擎的寄存器配置、数据通路和字节序处理均正确无误。