EMS 知识库
首页 / knowledge/代码解析/common

md5.h

源文件路径:common/md5.h 所属模块:common(通用工具库) 代码行数:60

1. 文件职责

本文件是 RSA Data Security 原始 MD5 参考实现的配套头文件(保留 1990 年版权声明),声明 MD5 消息摘要算法所需的上下文结构体 MD5_CTX 与 4 个函数原型。它在 EMS 里承担两类用途:一是网络层生成「动态登录密码 / 特服指令校验值」(net/ems.c、net/server.c),二是固件升级前后对 Boot、EMS 固件镜像做完整性校验(net/ems_boot_handle.c、net/ems_download.c、net/upd_download.c)。本文件不含实现、不参与数据流计算,只把摘要上下文的内存布局(位计数、输入缓冲、摘要缓冲)固定下来,供调用方在栈上分配 MD5_CTX 局部变量。全部代码行中有 38 行是版权注释,实际内容仅 15 行。

2. 关键数据结构与宏

名称类型说明
UINT4类型别名typedef unsigned long int UINT4;(第 41 行)。GD32F407 为 32 位 ARM,unsigned long 恰好 4 字节,与算法要求一致;移植到 64 位平台会失效
MD5_CTX结构体MD5 计算上下文(第 44-49 行):i[2](已处理位数 mod 2^64 的低/高 32 位)、buf[4](A/B/C/D 中间状态与暂存)、in[64](待处理分组缓冲)、digest[16](MD5Final 后的最终摘要,小端按字展开)

本文件不定义枚举、联合体、位域,也没有除 include guard 外的宏常量——实际上连 include guard 都没有(见第 7 节风险 1)。MASK 之类的辅助宏定义在 md5.c 内部而非本头文件。

3. 函数清单

函数名作用域说明
MD5Init全局(原型声明)初始化上下文,写入 4 个魔数初值,定义于 md5.c:82
MD5Update全局(原型声明)追加数据(支持任意次分段调用),定义于 md5.c:93
MD5Final全局(原型声明)填充分组 + 追加位长度 + 输出 16 字节摘要,定义于 md5.c:122
Transform全局(原型声明)单分组压缩函数(64 步 FF/GG/HH/II),定义于 md5.c:155(但实际为 static,见第 7 节风险 2)

共 4 个原型声明,全部对应 md5.c 中的定义;本头文件没有 static 函数、没有宏函数、没有函数指针。

4. 核心逻辑解析

本文件是纯声明文件,无可执行逻辑、无状态机、无定时器、不涉及 uCOS-II。要点在接口契约:

4.1 调用契约(三段式)

标准用法为 MD5Init → MD5Update(可多次) → MD5Final,MD5_CTX 由调用方在栈上分配并传入指针。工程内 5 处调用点全部遵循该顺序:

4.2 摘要呈现格式

调用方约定把 md5.digest[0..15] 按存储顺序逐字节 sprintf("%02X") 拼成 32 字符大写 HEX(ems_download.c:159-161、server.c:2060-2061、upd_download.c:404-406)。这与 RFC 1321 的摘要文本表示一致(MD5Final 已把 buf[] 按小端拆字节存入 digest,见 md5.c:145-150)。net/ems.c 只截取后 4 字节是业务约定,不是算法约定。

4.3 结构体字段的读写分工

因为 MD5_CTX 完全由调用方管理且各调用点使用局部变量,不同任务间不共享上下文,不存在跨任务的竞态。

5. 对外接口

本文件导出(供谁调用)

本文件调用的外部函数/变量

6. 依赖关系

7. 备注与风险点

  1. 没有 include guard:第 40-54 行直接是 typedef 与函数声明,文件开头(第 1-38 行)全是注释,没有 #ifndef __MD5_H__。当前工程无文件重复 include 它,所以未暴露问题;但一旦某个 .c 经两条路径引入 md5.h,typedef unsigned long int UINT4; 会重复定义(C99 起允许重复 typedef 且定义相同,MD5_CTX 结构体重复定义则会直接编译报错)。属明显遗留隐患。
  2. Transform 声明与定义的作用域冲突:md5.h:54 声明为全局 void Transform(UINT4 *buf, UINT4 *in);,而 md5.c:155 定义为 static void Transform(...)。由于全工程除 md5.c 自身外无任何地方引用 Transform(grep -rn "\bTransform\b" 零命中),链接期未报冲突,但头文件里的原型是死声明,且给调用者提供了「可以外部调用单分组压缩」的错误暗示。
  3. #include 风格不统一:UINT4 用内建类型而非 chip.h 的 u32,导致 common 目录出现两套整数类型体系(u8/u16/u32 与 UINT4/unsigned char),阅读时需要心算等价关系。
  4. 无 const 限定:MD5Update(MD5_CTX *, char *inBuf, unsigned int inLen) 的输入缓冲是非 const 的 char *,迫使调用方对只读固件缓冲做强制转型(如 (char *)MCU_START_ADDRESS、(char *)g_u8_fw_sdram),削弱了类型安全。
  5. 版权声明的义务:第 16-38 行的 RSA 许可要求任何提及本算法的材料标注 "RSA Data Security, Inc. MD5 Message Digest Algorithm"。本项目文档与产品说明中若未标注,属许可合规问题(非技术缺陷)。
  6. MD5 已不具抗碰撞性:用于动态密码与服务器配置校验时,MD5 只能防误改、不能防篡改;对固件完整性校验(ems_boot_handle.c)而言这是安全强度上的已知弱点。