Files
STM32F4-Base/App/util/sha256.c
T
wandering1 d1e6bb4ba7 W5波+N-19收口:FTP鉴权落地、Trap25三连定案修复(N-30)、N-20/N-23/N-26
N-19 FTP 鉴权:
- lftpd_auth(USER/PASS 状态机 + 连续5次失败锁60s)+ SHA-256
  (user||pwd) 口令哈希;config.ini [ftp] 段 user/pwd_hash/write,
  出厂 admin/admin 在用有启动告警;lftpd_log.c 删除并入 lftpd_auth
- ftp_cfg 配置读写;台架 ftp_auth_bench.py 13/13

N-30 / Trap 25(CH395F_Trap_Records.md 四次定案全记录):
- 修复1 closed-with-data accept:客户端发完正常 FIN 后芯片按
  FUN_PARA(0x09) §5.52② 保留 Socket+RX 缓冲,旧代码把 CLOSED 一律
  relisten 自毁缓冲 → STOR 必挂 425;改为接受"已关但可读"连接排空
- 修复2 丢 CONNECT 中断探针 net_lost_connect_probe + last_peer_port
  幽灵甄别(拆链窗口握手完成但中断丢失,双信源去抖补 accept)
- 修复3 send_list/send_nlst 批量单发:背靠背 ~60B 小段毒化芯片 TX
  (芯片报 SEND_OK 但对端全丢),整份目录一次性写入
- 证伪存档:固定沉降/Socket 轮换冷却/listen 门控(台架 v7 矩阵)
- 台架工具 test/board/ch395f_reuse_bench.{c,h} + host 脚本存档
  (不注册编译;实验分支 n30-chip-bench 保留)

N-20:Error_Handler 死循环降级(记录+复位路径)
N-23:scripts/check_registration.py 双端注册反向校验(pre-commit)
N-26:GD5F NAND 直 DMA 调用方缓冲窗口断言

验证:BUILD_OK 0/0;ftp_regression 连跑 4 轮 11/11(修复前
LIST#4/#7 100% 挂、STOR#2 曾 100% 425);ftp_auth_bench 13/13;
@test 启动标记 PASS;ci_local L0+L0.5 全过;doc-links 通过。
登记簿 N-30 已销项。
2026-10-11 18:50:24 +08:00

254 lines
8.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:sha256
* 模块功能:SHA-256 安全散列(FIPS 180-4)实现——纯标准库、零堆分配
* 适用平台:STM32F407ZGTx / PC 主机侧单测(双端共用)
* 作者:王建锋
* 创建日期:2026-10-11
* 修改记录:
* v1.0 2026-10-11 王建锋 创建初始版本(N-19 FTP 鉴权;标准向量由
* test/host/sha256 主机单测钉死)
*/
/* 头文件包含区 */
#include <string.h>
#include "sha256.h"
/* 私有宏定义区 */
#define SHA256_ROTR32(x, n) (((x) >> (n)) | ((x) << (32u - (n))))
#define SHA256_CH(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
#define SHA256_MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define SHA256_EP0(x) (SHA256_ROTR32(x, 2u) ^ SHA256_ROTR32(x, 13u) ^ SHA256_ROTR32(x, 22u))
#define SHA256_EP1(x) (SHA256_ROTR32(x, 6u) ^ SHA256_ROTR32(x, 11u) ^ SHA256_ROTR32(x, 25u))
#define SHA256_SIG0(x) (SHA256_ROTR32(x, 7u) ^ SHA256_ROTR32(x, 18u) ^ ((x) >> 3u))
#define SHA256_SIG1(x) (SHA256_ROTR32(x, 17u) ^ SHA256_ROTR32(x, 19u) ^ ((x) >> 10u))
/* 私有变量定义区 */
/* 轮常量(FIPS 180-4 §4.2.2.2:前 64 个素数立方根小数部分前 32 位) */
static const uint32_t s_k[64] = {
0x428a2f98u, 0x71374491u, 0xb5c0fbcfu, 0xe9b5dba5u,
0x3956c25bu, 0x59f111f1u, 0x923f82a4u, 0xab1c5ed5u,
0xd807aa98u, 0x12835b01u, 0x243185beu, 0x550c7dc3u,
0x72be5d74u, 0x80deb1feu, 0x9bdc06a7u, 0xc19bf174u,
0xe49b69c1u, 0xefbe4786u, 0x0fc19dc6u, 0x240ca1ccu,
0x2de92c6fu, 0x4a7484aau, 0x5cb0a9dcu, 0x76f988dau,
0x983e5152u, 0xa831c66du, 0xb00327c8u, 0xbf597fc7u,
0xc6e00bf3u, 0xd5a79147u, 0x06ca6351u, 0x14292967u,
0x27b70a85u, 0x2e1b2138u, 0x4d2c6dfcu, 0x53380d13u,
0x650a7354u, 0x766a0abbu, 0x81c2c92eu, 0x92722c85u,
0xa2bfe8a1u, 0xa81a664bu, 0xc24b8b70u, 0xc76c51a3u,
0xd192e819u, 0xd6990624u, 0xf40e3585u, 0x106aa070u,
0x19a4c116u, 0x1e376c08u, 0x2748774cu, 0x34b0bcb5u,
0x391c0cb3u, 0x4ed8aa4au, 0x5b9cca4fu, 0x682e6ff3u,
0x748f82eeu, 0x78a5636fu, 0x84c87814u, 0x8cc70208u,
0x90befffau, 0xa4506cebu, 0xbef9a3f7u, 0xc67178f2u,
};
/* 函数定义区 */
/*
* 函数功能:处理一个 64 B 分组(消息扩展 + 64 轮压缩)
* 入口参数:p_ctx - 上下文 p_block - 64 B 分组(大端字序)
* 返回值:无
* 限定条件:p_block 恰为 64 B 有效数据
* 函数说明:w[64] 为栈上消息扩展数组(256 B,ftpTask 4 KB 栈可容纳)
*/
static void s_transform(sha256_ctx_t *p_ctx, const uint8_t *p_block) {
uint32_t w[64];
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
uint32_t e;
uint32_t f;
uint32_t g;
uint32_t h;
for (uint32_t i = 0u; i < 16u; i++) {
w[i] = ((uint32_t)p_block[4u * i] << 24) |
((uint32_t)p_block[4u * i + 1u] << 16) |
((uint32_t)p_block[4u * i + 2u] << 8) |
(uint32_t)p_block[4u * i + 3u];
}
for (uint32_t i = 16u; i < 64u; i++) {
w[i] = SHA256_SIG1(w[i - 2u]) + w[i - 7u] +
SHA256_SIG0(w[i - 15u]) + w[i - 16u];
}
a = p_ctx->state[0];
b = p_ctx->state[1];
c = p_ctx->state[2];
d = p_ctx->state[3];
e = p_ctx->state[4];
f = p_ctx->state[5];
g = p_ctx->state[6];
h = p_ctx->state[7];
for (uint32_t i = 0u; i < 64u; i++) {
uint32_t t1 = h + SHA256_EP1(e) + SHA256_CH(e, f, g) + s_k[i] + w[i];
uint32_t t2 = SHA256_EP0(a) + SHA256_MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
p_ctx->state[0] += a;
p_ctx->state[1] += b;
p_ctx->state[2] += c;
p_ctx->state[3] += d;
p_ctx->state[4] += e;
p_ctx->state[5] += f;
p_ctx->state[6] += g;
p_ctx->state[7] += h;
}
/*
* 函数功能:初始化上下文(清零 + 置初始链接变量,FIPS 180-4 §5.3.3)
* 入口参数:p_ctx - 上下文
* 返回值:无
* 限定条件:p_ctx 为 NULL 时静默返回(fail-safe)
*/
void sha256_init(sha256_ctx_t *p_ctx) {
if (p_ctx == NULL) {
return;
}
(void)memset(p_ctx, 0, sizeof(*p_ctx));
/* 初始链接变量(FIPS 180-4 §5.3.3:前 8 个素数平方根小数部分前 32 位) */
p_ctx->state[0] = 0x6a09e667u;
p_ctx->state[1] = 0xbb67ae85u;
p_ctx->state[2] = 0x3c6ef372u;
p_ctx->state[3] = 0xa54ff53au;
p_ctx->state[4] = 0x510e527fu;
p_ctx->state[5] = 0x9b05688cu;
p_ctx->state[6] = 0x1f83d9abu;
p_ctx->state[7] = 0x5be0cd19u;
}
/*
* 函数功能:流式喂入数据(任意长度,内部按 64 B 分组压缩)
* 入口参数:p_ctx - 上下文 p_data - 数据 len - 字节数
* 返回值:无
* 限定条件:p_ctx/p_data 为 NULL 时静默返回
*/
void sha256_update(sha256_ctx_t *p_ctx, const void *p_data, size_t len) {
const uint8_t *p = (const uint8_t *)p_data;
if ((p_ctx == NULL) || (p == NULL)) {
return;
}
for (size_t i = 0u; i < len; i++) {
p_ctx->buf[p_ctx->buf_len] = p[i];
p_ctx->buf_len++;
if (p_ctx->buf_len >= SHA256_BLOCK_SIZE) {
s_transform(p_ctx, p_ctx->buf);
p_ctx->bitlen += (uint64_t)SHA256_BLOCK_SIZE * 8u;
p_ctx->buf_len = 0u;
}
}
}
/*
* 函数功能:收尾输出 32 B 摘要(补位 + 长度字段 + 末次压缩)
* 入口参数:p_ctx - 上下文 p_out - 32 B 摘要输出
* 返回值:无
* 限定条件:p_ctx/p_out 为 NULL 时静默返回;收尾后上下文清零(防敏感残留)
*/
void sha256_final(sha256_ctx_t *p_ctx, uint8_t p_out[SHA256_DIGEST_SIZE]) {
uint64_t bitlen;
uint8_t pad = 0x80u;
uint8_t zero = 0x00u;
uint8_t len_be[8];
if ((p_ctx == NULL) || (p_out == NULL)) {
return;
}
/* 总长 = 完整分组累计 + 暂存区(必须在补位前定稿) */
bitlen = p_ctx->bitlen + (uint64_t)p_ctx->buf_len * 8u;
(void)sha256_update(p_ctx, &pad, 1u);
while (p_ctx->buf_len != 56u) {
(void)sha256_update(p_ctx, &zero, 1u);
}
for (uint32_t i = 0u; i < 8u; i++) {
len_be[i] = (uint8_t)((bitlen >> (56u - 8u * i)) & 0xFFu);
}
(void)sha256_update(p_ctx, len_be, 8u);
for (uint32_t i = 0u; i < 8u; i++) {
p_out[4u * i] = (uint8_t)(p_ctx->state[i] >> 24);
p_out[4u * i + 1u] = (uint8_t)(p_ctx->state[i] >> 16);
p_out[4u * i + 2u] = (uint8_t)(p_ctx->state[i] >> 8);
p_out[4u * i + 3u] = (uint8_t)(p_ctx->state[i]);
}
(void)memset(p_ctx, 0, sizeof(*p_ctx));
}
/*
* 函数功能:一次性计算 32 B 摘要(init+update+final 便捷封装)
* 入口参数:p_data - 数据 len - 字节数 p_out - 摘要输出
* 返回值:无
* 限定条件:栈上上下文 ≈108 B;NULL 参数由子函数兜底
*/
void sha256_calc(const void *p_data, size_t len, uint8_t p_out[SHA256_DIGEST_SIZE]) {
sha256_ctx_t ctx;
sha256_init(&ctx);
sha256_update(&ctx, p_data, len);
sha256_final(&ctx, p_out);
}
/*
* 函数功能:hex 字符 → 半字节值
* 入口参数:c - 字符 p_out - 输出 0~15
* 返回值:0 - 合法;-1 - 非法 int
* 限定条件:p_out 非空
*/
static int s_hex_nibble(char c, uint8_t *p_out) {
uint8_t v;
if ((c >= '0') && (c <= '9')) {
v = (uint8_t)(c - '0');
} else if ((c >= 'a') && (c <= 'f')) {
v = (uint8_t)(c - 'a') + 10u;
} else if ((c >= 'A') && (c <= 'F')) {
v = (uint8_t)(c - 'A') + 10u;
} else {
return -1;
}
*p_out = v;
return 0;
}
/*
* 函数功能:摘要与 64 位 hex 串恒定时间比较(大小写不敏感)
* 入口参数:p_digest - 32 B 摘要 p_hex - 64 字符 hex 串
* 返回值:1 - 相等;0 - 不等 / 长度非 64 / 非法 hex / NULL
* 限定条件:比较段不短路(XOR 累加器);hex 非法属配置错误,早退不构成口令侧信道
*/
int sha256_hex_eq(const uint8_t p_digest[SHA256_DIGEST_SIZE], const char *p_hex) {
uint8_t acc = 0u;
uint8_t hi;
uint8_t lo;
if ((p_digest == NULL) || (p_hex == NULL)) {
return 0;
}
if (strlen(p_hex) != (SHA256_DIGEST_SIZE * 2u)) {
return 0;
}
for (uint32_t i = 0u; i < SHA256_DIGEST_SIZE; i++) {
if ((s_hex_nibble(p_hex[2u * i], &hi) != 0) ||
(s_hex_nibble(p_hex[2u * i + 1u], &lo) != 0)) {
/* hex 非法 = 配置错误(可信来源),早退不构成口令侧信道 */
return 0;
}
acc |= (uint8_t)(p_digest[i] ^ (uint8_t)((hi << 4) | lo));
}
return (acc == 0u) ? 1 : 0;
}