/* * 模块名称:sha256 * 模块功能:SHA-256 安全散列(FIPS 180-4)实现——纯标准库、零堆分配 * 适用平台:STM32F407ZGTx / PC 主机侧单测(双端共用) * 作者:王建锋 * 创建日期:2026-10-11 * 修改记录: * v1.0 2026-10-11 王建锋 创建初始版本(N-19 FTP 鉴权;标准向量由 * test/host/sha256 主机单测钉死) */ /* 头文件包含区 */ #include #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; }