详解:从 ECB 到 GCM/CCM 的硬件加解密实战)
操作系统嵌入式物联网嵌入式OSRTOS【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址https://gitcode.com/gh_mirrors/rt/rt-thread点击查看免费下载本篇技术指南以 RT-Thread 仓库中 Microchip SAME54 BSP 自带的 HAL 层 AES 同步驱动文档aes_sync.rst为核心结合其完整源码实现系统讲解该驱动支持的工作模式、API 用法、初始化流程与底层寄存器操作。读者读完将能够基于 SAME54 硬件 AES 外设在 RT-Thread 工程中完成密钥装载、ECB/CBC/CFB/OFB/CTR 加解密以及 GCM/CCM 认证加密并理解驱动内部的分层架构与已知限制。驱动概述硬件 AES 与同步调用模型Advanced Encryption StandardAES是美国国家标准与技术研究院NIST于 2001 年确立的电子数据加密规范。它作用于 128 位的输入数据块密钥长度决定了将明文转换为密文所需的变换轮数且属于对称密钥算法——加密与解密使用同一个密钥。在 Microchip SAME54 系列如 ATSAME54P20A上芯片集成了硬件 AES 外设。根据该 BSP 的 README_zh.md 中的加密功能描述SAME54 的 AES 支持 256 位密钥长度、最高约 2 MB/s 数据率提供 ECB、CBC、CFB、OFB、CTR 五种机密模式并支持 GCMGalois Counter Mode与 CCMCounter with CBC-MAC认证加密模式芯片同时集成了 TRNG、PUKCC 等配套加密资源。本驱动属于 HALHardware Abstraction Layer层的同步Sync驱动所有加解密调用均为阻塞式执行调用返回时数据已处理完毕无需中断与回调机制因此文档中将并发性Concurrency标注为 N/A。从源码结构看驱动采用两层设计HAL 层hal_aes_sync.h 与 hal_aes_sync.c 提供面向应用的aes_sync_*API负责参数断言、数据对齐处理如 CFB/CTR 非整块数据的头尾处理以及 GCM/CCM 标签比对校验。HPL 层hpl_aes_sync.h 与 hpl_aes.c 提供_aes_sync_*底层函数通过 HRIHeader Register Interface宏直接读写 AES 外设寄存器如CTRLA、CTRLB、INDATA、GHASH、HASHKEY等。功能特性清单依据驱动文档 aes_sync.rst 的 Features 章节该驱动完整提供初始化与去初始化aes_sync_init/aes_sync_deinit使能与禁用aes_sync_enable/aes_sync_disable128 / 192 / 256 位密钥装载aes_sync_set_encrypt_key/aes_sync_set_decrypt_key电子密码本模式 ECBElectronic Code Book密码分组链接模式 CBCCipher Block Chaining8、16、32、64、128 位分组长度的 CFBCipher Feedback输出反馈模式 OFBOutput Feedback计数器模式 CTRCounterCCMCounter with CBC-MAC认证加密GCMGalois Counter Mode加密与认证典型应用场景是使用同一认证密钥将明文数据加密为密文或将密文解密回明文没有认证密钥时无法恢复密文数据。架构与依赖三层结构与硬件依赖驱动的依赖项非常明确AES 能力硬件AES capable hardware。除 SAME54 之外这一套 Microchip HAL 层 AES 同步驱动同样适用于同一软件框架下的其他 Microchip 器件因此在 RT-Thread 仓库的其他 Microchip BSP 中也可能复用同构代码。驱动内部的数据结构揭示了其工作状态模型。在 hpl_aes_sync.h 中设备描述符struct _aes_sync_device保存了struct _aes_sync_device { void * hw; /*! Hardware module instance handler */ uint8_t key[32]; /*! Key value 128/192/256 bits */ uint8_t iv[16]; /*! Initialization Vector */ uint32_t aad_len; /*! length of additional data(GCM) */ enum aes_keysize keysize; /*! bit length of key */ };HAL 层在此基础上包装为struct aes_sync_descriptor { struct _aes_sync_device dev; }。关键枚举定义于 hpl_aes.henum aes_action { AES_DECRYPT, AES_ENCRYPT }; enum aes_keysize { AES_KEY_128, AES_KEY_192, AES_KEY_256 };值得注意的实现细节_aes_sync_set_keyhpl_aes.c将密钥复制进设备描述符的key[32]缓冲字节数为(size 2) 3即 128 位→16 字节、192 位→24 字节、256 位→32 字节随后在真正执行加解密时__aes_sync_set_key通过hri_aes_write_KEYWORD_reg将密钥字写入硬件 KEYWORD 寄存器。在 RT-Thread 工程中的初始化流程在 SAME54 BSP 中AES 驱动的实例化与时钟使能由 Atmel Start 生成的初始化代码完成。查看 driver_init.c全局描述符CRYPTOGRAPHY_0的初始化函数如下void CRYPTOGRAPHY_0_init(void) { hri_mclk_set_APBCMASK_AES_bit(MCLK); aes_sync_init(CRYPTOGRAPHY_0, AES); }流程分两步使能外设时钟通过 HRI 宏hri_mclk_set_APBCMASK_AES_bit(MCLK)打开 AES 外设所在的 APB 时钟门控调用aes_sync_init传入全局描述符地址与硬件实例指针AES。aes_sync_inithal_aes_sync.c先断言参数非空再转发给 HPL 层_aes_sync_init。HPL 实现hpl_aes.c会对CTRLA寄存器执行软件复位AES_CTRLA_SWRST并把hw句柄存入描述符随后写入调试控制寄存器DBGCTRL。system_init()会在上电阶段统一调用CRYPTOGRAPHY_0_init()。这里需要说明一个容易引起误解的细节HAL 层的aes_sync_enable/aes_sync_disable在 SAME54 的 HPL 实现中为空操作直接返回ERR_NONE。这是因为 AES 外设的使能/禁用实际上在每次加解密调用内部由寄存器操作完成——例如_aes_sync_ecb_crypt会先清除CTRLA.ENABLE、配置好CTRLA/CTRLB后重新置位ENABLE操作结束后再清除。因此应用层可以照常调用aes_sync_enable保持代码一致但真正的硬件使能时机由底层函数控制。密钥管理先设密钥、用后清零驱动文档特别强调了两条密钥使用规范任何加密模式使用前必须先设置密钥——底层每个加解密函数都会调用__aes_sync_set_key(dev)将描述符中保存的密钥写入硬件 KEYWORD 寄存器对于隐私敏感场景加解密完成后应用层应主动清除密钥常见做法是将密钥清零set the key to zero。从代码可以印证密钥的写入时机ECB 实现中注释为Key must be set for each ECB encrypt每次调用_aes_sync_ecb_crypt都会重新装载密钥CBC 实现注释为The Key must be write before CBC crypt。换言之驱动以每次操作装载密钥为安全模型应用侧只要在流程结束将密钥缓冲清零如memset(key, 0, sizeof(key))即可降低密钥长期驻留内存被泄露的风险。分组模式 API 详解ECB / CBC / CFB / OFB / CTRECB单块加解密ECB 每次处理一个 16 字节块输入输出均为 16 字节是最基础的用法int32_t aes_sync_ecb_crypt(struct aes_sync_descriptor *descr, const enum aes_action enc, const uint8_t *input, /* 16-byte input data */ uint8_t *output); /* 16-byte output data */HPL 实现hpl_aes.c的寄存器流程为清除ENABLE→ 复位CTRLA/CTRLB→ 配置CTRLA的KEYSIZE与CIPHER位enc AES_CTRLA_CIPHER_Pos→ 置位ENABLE→ 写密钥 → 写 4 个字16 字节输入数据INDATA→ 置位CTRLB.START→ 轮询ENCCMP中断标志 → 读取 4 字输出。整个过程为同步阻塞while (hri_aes_get_interrupt_ENCCMP_bit(dev-hw) 0);即忙等加密完成。CBC分组链接需要 IVCBC 模式下数据长度必须是 16 字节的整数倍IV 参数在调用后会被更新为最后一个密文块iv同时是入参和出参int32_t aes_sync_cbc_crypt(struct aes_sync_descriptor *descr, const enum aes_action enc, const uint8_t *input, uint8_t *output, uint32_t length, /* multiple of 16 bytes */ uint8_t iv[16]); /* updated after use */HPL 实现hpl_aes.c中AESMODE被设为 1CBC通过CTRLB.NEWMSG指示新消息、__aes_sync_set_iv写入初始向量INTVECTV寄存器随后逐块每块 16 字节装载数据、启动、轮询、读取。完成后以memcpy(iv, ...)将最后一块密文写回 IV供多段连续加解密衔接使用。CFB8/16/32/64/128 位反馈粒度CFB 模式提供五种反馈长度变体覆盖流式加密场景数据长度无需对齐到 16 字节int32_t aes_sync_cfb128_crypt(struct aes_sync_descriptor *descr, const enum aes_action enc, const uint8_t *input, uint8_t *output, uint32_t length, uint8_t *iv, uint32_t *iv_ofst); int32_t aes_sync_cfb64_crypt(...); /* 8-byte feedback */ int32_t aes_sync_cfb32_crypt(...); /* 4-byte feedback */ int32_t aes_sync_cfb16_crypt(...); /* 2-byte feedback */ int32_t aes_sync_cfb8_crypt(...); /* 1-byte feedback, 无 iv_ofst 参数 */iv_ofst表示 IV 内的当前偏移用于在非块对齐位置继续数据流如连续加密多个不同长度的数据段其值必须小于对应反馈粒度128→16、64→8、32→4、16→2这由 HAL 层的ASSERT检查保证。HAL 层通过两个静态辅助函数处理首尾非对齐数据aes_sync_cfb_crypt_first_unaligned_data若*iv_ofst非零先按 CFB 的异或规则output input ^ iv[iv_ofst]并同步更新 IV逐字节消费掉偏移aes_sync_cfb_crypt_last_unaligned_data对剩余不足一块的数据先做一次 ECB 加密刷新密钥流再逐字节异或。中间整块部分则交给 HPL 的_aes_sync_cfb*_crypt。HPL 实现通过CTRLA.AESMODE3选择 CFB 家族并以CTRLA.CFBS位域区分反馈粒度CFB128→0、CFB64→1、CFB32→2、CFB16→3、CFB8→4逐块循环处理。块结束后__aes_sync_update_cfb_iv依据加解密方向把输出加密或输入解密的最后一块复制为新的 IV。OFB输出反馈OFB 将加密器输出作为反馈送入下一轮加密与解密对称不要求数据长度对齐到块int32_t aes_sync_ofb_crypt(struct aes_sync_descriptor *descr, const uint8_t *input, uint8_t *output, uint32_t length, uint8_t *iv, uint32_t *iv_ofst);HAL 层同样先处理偏移处的非整块数据再调用 HPL_aes_sync_ofb_cryptAESMODE2处理整块部分最后对不足一块的数据做一次 ECB 加密刷新密钥流并逐字节异或。HPL 实现与 CFB 类似地循环装载、启动、轮询ENCCMP、读取输出并在每块后对 IV 做一次加密更新。CTR计数器模式支持断点续传CTR 模式同样无需数据长度对齐且提供了buffer当前密钥流块与nc_ofst密钥流偏移用于在流中间恢复处理int32_t aes_sync_ctr_crypt(struct aes_sync_descriptor *descr, const uint8_t *input, uint8_t *output, uint32_t length, uint8_t buffer[16], /* stream block for resuming */ uint8_t nc[16], /* 128-bit nonce and counter */ uint32_t *nc_ofst); /* offset in current stream block, 0 at stream start */HAL 层hal_aes_sync.c在整块处理前用buffer中的密钥流先消费掉*nc_ofst处的未对齐字节剩余整块交给 HPL_aes_sync_ctr_cryptAESMODE4Counter 模式尾块处理时先对nc做一次 ECB 加密生成密钥流存入buffer随后对计数器nc执行大端式自增从最低字节起nc[i-1]进位即继续再逐字节异或。HPL 循环中每完成一块也对nc做一次自增hpl_aes.c保证连续块的计数器正确递增。模式选择速查模式数据对齐要求IV/Nonce说明ECB每次 16 字节无最简单相同明文块产生相同密文块CBC16 字节整数倍16 字节 IV调用后更新分组链接需处理填充CFB8/16/32/64/128无IV iv_ofst流式反馈粒度可变OFB无IV iv_ofst输出反馈流式CTR无nc[16] buffer nc_ofst计数器流式可断点续传认证加密GCM 与 CCMGCM已知长度限制GCMGalois Counter Mode同时提供加密与认证消息认证码/标签。驱动提供了两种调用风格一站式 API——单次调用完成全部处理int32_t aes_sync_gcm_crypt_and_tag(struct aes_sync_descriptor *const descr, const enum aes_action enc, const uint8_t *input, uint8_t *output, uint32_t length, const uint8_t *iv, uint32_t iv_len, const uint8_t *aad, uint32_t aad_len, uint8_t *tag, uint32_t tag_len);以及认证解密aes_sync_gcm_auth_decrypt内部解密并重新计算标签逐字节与传入标签比对不一致返回ERR_INVALID_DATA。分段式 API——aes_sync_gcm_start设置方向、IV、AAD→aes_sync_gcm_update处理数据→aes_sync_gcm_finish生成标签。文档明确标注的限制LimitationsGCM 仅支持已知长度数据的处理aes_sync_gcm_update不能被多次调用应用应把所有数据先组装进一个缓冲区然后一次性调用aes_sync_gcm_update完成加解密。这一点与底层实现直接相关——__aes_sync_gcm_updatehpl_aes.c会把单次调用传入的length直接写入CIPLEN寄存器并以该长度生成最终的 GHASH 长度块AAD 与密文长度的 64 位表示多次调用无法正确累计长度信息。GCM 底层实现遵循标准三步流程可见于__aes_sync_gcm_start生成 HASHKEY以 ECB 模式加密全零输入得到认证子密钥 H由 IV 生成预计数器块 j0当iv_len 1296 位推荐值时直接拼接IV || 0x00000001其他长度时按标准通过 GHASH(H, {}, IV) 计算 j0GHASH 处理 AAD将附加认证数据 AAD 分块做 GHASH 运算。随后__aes_sync_gcm_update以 CTR 模式计数器从 j01 起处理密文数据设置EOM结束标志并在末尾用 AAD 长度与密文长度生成最终 GHASH 块__aes_sync_gcm_generate_tag则切回 Counter 模式用 j0 加密最终 GHASH 值并截取前tag_len字节作为标签最后清理GHASH、HASHKEY、INDATA、CIPLEN等寄存器避免影响下一次 GCM 运算。HAL 层参数断言还限定了标签长度tag_len 16。CCMSP800-38C 约束CCMCounter with CBC-MAC同样提供一站式加密aes_sync_ccm_crypt_and_tag与认证解密aes_sync_ccm_auth_decrypt。HAL 层断言按 NIST SP800-38C 的 A.1 节要求强制执行ASSERT(tag (tag_len 4) (tag_len 16) !(tag_len % 2)); ASSERT((iv_len 7) (iv_len 13));即标签长度必须为 416 字节的偶数IV此处实为 nonce长度必须在 713 字节之间。HPL 层依据enc值分别进入__aes_sync_ccm_crypt_and_tag或__aes_sync_ccm_decrypt_and_tag按 SP800-38C 第 6.1 节的生成-加密过程执行。驱动使用示例来自 BSP 的 ECB 参考实现BSP 自带的 driver_examples.c 提供了一个完整的 ECB 加解密参考可直接用于验证驱动链路。它使用了 FIPS-197 附录 B 的标准测试向量static uint8_t aes_plain_text[16] {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}; static uint8_t aes_key[16] {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; static uint8_t aes_cipher_text[16] {0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97}; uint8_t aes_output[16] {0x00}; void CRYPTOGRAPHY_0_example(void) { int32_t i; aes_sync_enable(CRYPTOGRAPHY_0); aes_sync_set_encrypt_key(CRYPTOGRAPHY_0, aes_key, AES_KEY_128); aes_sync_ecb_crypt(CRYPTOGRAPHY_0, AES_ENCRYPT, aes_plain_text, aes_output); for (i 0; i 16; i) { while (aes_output[i] ! aes_cipher_text[i]) ; } }该示例演示了标准三步流程使能 → 装载 128 位加密密钥 → ECB 加密。若加密结果与已知密文不一致程序会陷入忙等循环可作为硬件/驱动自检手段。若要验证解密方向将AES_ENCRYPT换成AES_DECRYPT、输入换成aes_cipher_text并比对aes_plain_text即可。已知问题与注意事项总结根据文档 aes_sync.rst 与源码分析使用本驱动需要特别注意GCM 数据长度必须预先已知aes_sync_gcm_update只能调用一次需先将全部数据组装到单一缓冲区再处理否则 GHASH 长度信息错误、认证失败密钥生命周期管理使用前必须先aes_sync_set_encrypt_key/aes_sync_set_decrypt_key装载密钥隐私敏感场景下加解密完成后应主动将密钥缓冲区清零CBC 长度对齐CBC 要求数据长度是 16 字节的整数倍应用需自行实现填充padding方案CFB/CTR 偏移参数iv_ofst/nc_ofst有严格取值范围限制分别小于反馈粒度和 16流式续传场景需正确维护这些状态参数HAL 层通过 ASSERT 做了运行时检查同步阻塞特性所有 API 均为阻塞式、忙等ENCCMP/GFMCMP完成标志调用期间 CPU 不能做其他事情并发场景需考虑任务调度影响文档标注 Concurrency: N/ACCM 参数约束标签长度须为 416 字节偶数IV 长度须为 713 字节SP800-38C。当前仓库中该驱动无已知问题Known issues and workarounds: N/A上述限制均属于设计约束而非缺陷。开发者可在 bsp/microchip/same54/bsp/hal/include/hal_aes_sync.h 中查阅全部 API 原型在 bsp/microchip/same54/bsp/hpl/aes/hpl_aes.c 中研读底层寄存器实现并结合 bsp/microchip/same54/bsp/driver_init.c 理解外设初始化从而在 RT-Thread 上安全、高效地构建数据加密与认证能力。赞分享操作系统嵌入式物联网嵌入式OSRTOS【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址https://gitcode.com/gh_mirrors/rt/rt-thread点击查看免费下载相关推荐RT-Thread 下 Microchip SAME54 CAN 异步驱动HAL CAN Async架构、API 与实战指南RT Thread 下 Microchip SAME54 CAN 异步驱动HAL CAN Async架构、API 与实战指南 RT Thread 在 bsp操作系统嵌入式物联网嵌入式OSRTOSRT-Thread 中 Microchip SAM E70 ADC 同步驱动adc_sync详解工作原理、HAL API 与实战采样RT Thread 中 Microchip SAM E70 ADC 同步驱动adc_sync详解工作原理、HAL API 与实战采样 本文以 RT Thr操作系统嵌入式物联网嵌入式OSRTOSBokeh NotebookHandler 深度解析用 Jupyter Notebook 直接驱动 Bokeh Server 应用Bokeh NotebookHandler 深度解析用 Jupyter Notebook 直接驱动 Bokeh Server 应用 NotebookHandl操作系统嵌入式物联网嵌入式OSRTOS上一篇Visual C运行库修复指南告别软件无法启动的烦恼下一篇深入解析 graphile/lruGraphile 内部极简高性能 LRU 缓存的设计与版本演进创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考