Serial-Studio 中的 p256-m 深度解析:面向受限 32 位环境的极简 P-256 ECDH/ECDSA 实现
2026/9/18 8:55:03 网站建设 项目流程

Serial-Studio 中的 p256-m 深度解析:面向受限 32 位环境的极简 P-256 ECDH/ECDSA 实现

【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio

导读

p256-m 是一个在 NIST P-256 曲线上实现 ECDH(椭圆曲线 Diffie-Hellman 密钥协商)与 ECDSA(椭圆曲线数字签名算法)的极简开源实现,专为资源受限的 32 位嵌入式环境设计,以"正确性与安全优先于体积、体积优先于速度"为设计准则,最终以不足 3KiB 的代码和不足 768 字节的 RAM 提供了完整的两类密码学原语。本文以本仓库中随 Mbed TLS 一同分发的 p256-m 原始 README 为核心骨架,结合仓库内实际存在的源码、头文件与构建配置,系统讲解其正确性保障、恒定时间安全设计、体积/内存/性能指标、分层实现架构,以及它在 Mbed TLS PSA Crypto 驱动体系中的集成方式。读完本文,你将理解一个"以安全性换体积"的极简密码实现如何被设计、测试、度量和接入上层加密框架。

一、p256-m 是什么:一个以正确性与体积为先的 P-256 实现

p256-m 由 Manuel Pégourié-Gonnard 开发,是 NIST P-256 曲线上 ECDH 与 ECDSA 的极简实现,特别适合受限的 32 位环境。它使用标准 C 编写,并为 Arm Cortex-M 与 Cortex-A 系列 CPU 提供了可选的内联汇编优化。在本仓库中,它位于 lib/mbedtls/3rdparty/p256-m/p256-m/,作为 Mbed TLS 的第三方组件被分发,采用 Apache-2.0 OR GPL-2.0-or-later 双许可证。

与大多数"速度优先、体积其次"的密码实现不同,p256-m 的设计目标按如下优先级排序:

  1. 正确性与安全性(correctness & security);
  2. 低代码体积与低 RAM 占用(low code size & RAM usage);
  3. 运行时性能(runtime performance)。

作者在 README 中直言:"大多数密码实现更关心速度而非占用,p256-m 的诞生源于我想看看把通常的侧重点颠倒过来会发生什么。"结果是在不足 700 行 C 代码(含注释超过代码行数)内,交付了完整的 ECDH 与 ECDSA:代码体积小于 3KiB,RAM 占用小于 768 字节,而性能与主流实现相当(详见下文对比章节)。

注意:本仓库内分发的是 Mbed TLS 快照,Mbed TLS 侧说明 明确指出,这里只包含 p256-m 文件的一个子集,README 中提到的部分辅助脚本(如coverage.shsizes.shbench.shp256.py等)属于上游仓库,并不在本仓库中;且此快照不会随上游定期更新。

二、正确性:极简 API、全输入校验与多维测试

2.1 API 设计:极简接口 + 具体错误码

p256-m 的 API 设计遵循三个原则:公开函数数量极少、每个函数完整校验输入并返回具体错误码、所有输入输出均为字节数组。

README 声称 API 只有 4 个公开函数(密钥对生成、ECDH 共享密钥、ECDSA 签名、ECDSA 验证)。在 Mbed TLS 分发的 p256-m.h 中,除了这 4 个核心操作,还补充了p256_validate_pubkey()p256_validate_privkey()p256_public_from_private()三个辅助函数(用于在不执行操作的情况下单独校验密钥、或由私钥导出公钥)。完整的接口与错误码如下:

函数作用错误返回
p256_gen_keypair(priv[32], pub[64])生成密钥对(大端字节序)P256_RANDOM_FAILED
p256_ecdh_shared_secret(secret[32], priv[32], pub[64])计算 ECDH 共享密钥P256_INVALID_PRIVKEY/P256_INVALID_PUBKEY
p256_ecdsa_sign(sig[64], priv[32], hash, hlen)对给定哈希签名P256_RANDOM_FAILED/P256_INVALID_PRIVKEY
p256_ecdsa_verify(sig[64], pub[64], hash, hlen)验证签名P256_INVALID_PUBKEY/P256_INVALID_SIGNATURE
p256_validate_pubkey(pub[64])/p256_validate_privkey(priv[32])单独校验公/私钥P256_INVALID_PUBKEY/P256_INVALID_PRIVKEY
p256_public_from_private(pub[64], priv[32])由私钥计算公钥P256_INVALID_PRIVKEY

错误码定义见 p256-m.h:P256_SUCCESS = 0P256_RANDOM_FAILED = -1P256_INVALID_PUBKEY = -2P256_INVALID_PRIVKEY = -3P256_INVALID_SIGNATURE = -4。私钥/公钥分别以 32 字节与 64 字节大端整数表示。

2.2 测试策略:向量验证、双套测试与动态分析

p256-m 的正确性通过多层测试保障:

  • 标准测试向量:针对多个 RFC 与 NIST 测试向量进行了验证;
  • 构造性输入:使用精心构造的输入进行负向测试并触达边界情况;
  • 双测试套件:一是 closed-box(闭箱)测试,仅通过公开 API 驱动;二是 open-box(开箱)测试,直接对内部函数做单元测试,并利用对 RNG 使用方式的了解触达更多错误分支;
  • 分支覆盖:闭箱测试覆盖除 4 个分支外的所有分支;其中 3 个由开箱测试借助"作弊"的 RNG 触达,最后一个分支只能通过在 P-256 上计算离散对数才能到达(这意味着该分支在实践中几乎不可达);
  • 动态分析:valgrind、ASan(地址消毒器)、MemSan(内存消毒器)、UBSan(未定义行为消毒器)。

2.3 代码质量与 Short Weierstrass 陷阱

代码为纯标准 C99,可在clang -Weverythinggcc -Wall -Wextra -pedantic下无警告编译;代码小而文档完善,内部 API 也有注释,注释行数多于代码行数。作者也坦言,作为个人项目,它尚未经过独立审计

针对 safecurves 社区指出的 Short Weierstrass 曲线(NIST P-256 属于此类)两类经典陷阱,p256-m 做了针对性规避:

  • "对某些罕见曲线点产生错误结果":通过在全代码中仔细检查所用公式的有效性域来避免;
  • "当输入不是曲线点时泄漏秘密数据":通过每次反序列化点时都验证点确实在曲线上来避免。

三、安全设计:从底层恒定时间到明确的威胁模型

3.1 恒定时间属性

在正确性之外,p256-m 宣称具备两条硬性安全性质:

  • 不存在(哪怕间接)依赖秘密数据的分支
  • 不存在(哪怕间接)依赖秘密数据的内存访问

这两条性质通过 valgrind 与 MemSan 配合 ctgrind 的思路进行检查(README 中的consttime.sh)。源码中对应的机制是CT_POISON/CT_UNPOISON宏(见 p256-m.c):把秘密数据标记为"未初始化",任何依赖它的分支或指针解引用都会触发工具告警;公开数据则标记回"已初始化"。

此外,为避免执行时间依赖操作数取值的指令(或库函数),p256-m:

  • 从不使用整数除法
  • 默认只使用16x16→32 位无符号乘法
  • 在具有恒定时间 32x32→64 位无符号乘法指令的内核上,可通过在编译期定义宏MUL64_IS_CONSTANT_TIME启用该指令以改善性能与体积(在 Cortex-M / Cortex-A 上配 GCC 或 Clang 时无需此宏,因为直接使用了内联汇编)。

核心实现 中u32_muladd64()的四种实现正是这一策略的体现:两条内联汇编路径(有 DSP 扩展的UMAAL单周期指令、无 DSP 扩展时拆分为 16 位半字乘法),以及两条纯 C 路径(MUL64_IS_CONSTANT_TIME时直接用 32x32→64 乘法,否则用 16x16→32 乘法展开)。

3.2 威胁模型:能防什么、不防什么

由此 p256-m 声明可抵御以下三类攻击者:

  1. 只能操纵输入、观察输出的攻击者;
  2. 还能测量操作总耗时的攻击者(计时攻击);
  3. 还能以任意精度观察与操纵微架构特性(如缓存、分支预测器)的攻击者。

同时它明确抵御:

  1. 能记录 CPU 处理秘密时物理辐射(功耗、电磁、声音)轨迹的被动物理攻击者;
  2. 能向计算中注入故障的主动物理攻击者。

README 还补充:p256-m 由于整体恒定流量(constant-flow),实际上应能抵御 SPA(简单功耗分析),但预计无法抵御任何其他物理攻击。它也没有 TinyCrypt 那样的坐标随机化,因此不针对 DPA 类攻击设防。

3.3 关键前提:外部 RNG 与密钥擦除

p256-m 不自带加密安全随机数发生器(CSPRNG)。它要求外部提供p256_generate_random()函数(声明见 p256-m.h)。README 给出明确警告:如果该函数不是加密安全的,那么 p256-m 的密钥生成与 ECDSA 签名生成也不安全。在本仓库的 Mbed TLS 集成中,该函数包装了psa_generate_random()(见 p256-m.c),复用 PSA 层的 CSPRNG。

同时,p256-m 遵循"返回前安全擦除栈上秘密数据"的最佳实践。

四、代码体积:不足 3KiB 的秘密

README 给出的体积数据基于 ARM-GCC 9、-mthumb -Os编译:

内核代码体积
Cortex-M02988 字节
Cortex-M42900 字节
Cortex-A72924 字节

Clang 也被尝试过,但生成的代码通常大约大 10%(详见上游sizes.sh)。

体积中包含的部分:

  • 完整的输入校验与输入/输出字节序列化/反序列化;
  • 函数返回前从栈上清理秘密值;
  • 零依赖:代码不依赖任何 libc 函数或工具链运行时库(如长乘法辅助函数)——这一点可由上游deps.sh脚本对 Arm-GCC 工具链检查确认。

体积中不包含的部分:

  • 安全的 RNG 函数需外部提供(见上节p256_generate_random())。

五、RAM 使用:零堆分配,仅栈使用

p256-m 不使用任何动态内存(堆),只使用栈。README 给出 4 个公开函数在各内核上的栈占用:

函数Cortex-M0Cortex-M4Cortex-A7
p256_gen_keypair608564564
p256_ecdh_shared_secret640596596
p256_ecdsa_sign664604604
p256_ecdsa_verify752700700

(单位:字节;上述数据假设外部 RNG 函数最多使用 384 字节栈空间。)p256_ecdsa_verify因为需要处理双标量运算而成为栈消耗最大的操作。

六、运行时性能:与主流实现相当

README 的性能数据在三个平台测得:

  • Cortex-M0 @ 48 MHz:STM32F091 开发板,运行 Mbed OS 6;
  • Cortex-M4 @ 100 MHz:STM32F411 开发板,运行 Mbed OS 6;
  • Cortex-A7 @ 900 MHz:Raspberry Pi 2B,运行 Raspbian Buster。

各公开函数耗时(毫秒):

函数Cortex-M0Cortex-M4Cortex-A7
p256_gen_keypair92114511
p256_ecdh_shared_secret92214411
p256_ecdsa_sign99015512
p256_ecdsa_verify197630924
四项合计480975359

README 指出:这四项操作之和大致对应一次使用 ECDHE-ECDSA、基于裸公钥或直接信任证书做双向认证的 TLS 握手(否则,对端证书链中每增加一级就需要额外增加一次 verify)。此外,以上数据用 GCC 编译(能使用内联汇编);如果没有那 22 行(Cortex-M0)/1 行(Cortex-M4)内联汇编,这些平台上代码大约慢 2 倍(Cortex-A7 上影响小得多)。

七、与 TinyCrypt 的对比:体积换性能的代价与收益

README 选取 TinyCrypt 作为对比对象,因为它同样是仅面向 P-256、只做 ECDH 与 ECDSA 的独立实现、同样面向受限设备;而其他实现往往支持多曲线并基于共享的大数/MPI 模块(可能还支持 RSA),不利于公平比较。

代码体积(字节)

内核p256-mTinyCrypt
Cortex-M029886134
Cortex-M429005934
Cortex-A729245934

RAM 使用(Cortex-M0,栈字节)

操作p256-mTinyCrypt
密钥生成608824
ECDH 共享密钥640728
ECDSA 签名664880
ECDSA 验证752824

RAM 使用(Cortex-M4 或 Cortex-A7,数值相同)

操作p256-mTinyCrypt
密钥生成564796
ECDH 共享密钥596700
ECDSA 签名604844
ECDSA 验证700808

运行时性能(毫秒,Cortex-M0 @ 48 MHz)

操作p256-mTinyCrypt
密钥生成921979
ECDH 共享密钥922975
ECDSA 签名9901009
ECDSA 验证19761130
四项合计48094093

运行时性能(毫秒,Cortex-M4 @ 100 MHz)

操作p256-mTinyCrypt
密钥生成145178
ECDH 共享密钥144177
ECDSA 签名155188
ECDSA 验证309210
四项合计753753

运行时性能(毫秒,Cortex-A7 @ 900 MHz)

操作p256-mTinyCrypt
密钥生成1113
ECDH 共享密钥1113
ECDSA 签名1214
ECDSA 验证2415
四项合计5955

运行时性能(微秒,64 位 Intel i7-6500U @ 2.50 GHz,Ubuntu 20.04)

操作p256-mTinyCrypt
密钥生成10601627
ECDH 共享密钥10601611
ECDSA 签名11361712
ECDSA 验证22791888
四项合计55356838

其他关键差异(README 原文要点):

  • 输入校验:p256-m 全面校验所有输入;TinyCrypt 的 ECDH 共享密钥函数不校验对端公钥,静态 ECDH 场景下需用户另行校验(文献记载了用户忘记校验时存在攻击)。
  • 安全特性取向:p256-m 从底层起即完全恒定时间,对"强大本地攻击者"(如不受信 OS 攻击安全 enclave)更稳健;TinyCrypt 则包含坐标随机化,可抵御部分被动物理攻击(如 DPA),这是 p256-m 完全不考虑的。
  • 可扩展性:TinyCrypt 的代码看起来容易扩展支持更多曲线;p256-m 为压体积做了大量硬编码(详见下文"其他曲线")。
  • 归约算法:TinyCrypt 用专门例程利用曲线素数是 Solinas 素数这一结构做模归约,理论比 p256-m 的通用 Montgomery 归约快,但其他因素似乎抵消了这一点。
  • 点运算公式:TinyCrypt 用 Co-Z Jacobian 公式(更快但稍大);p256-m 用混合 affine-Jacobian 公式。
  • 汇编:p256-m 在基准平台上用少量内联汇编做 64 位乘法,TinyCrypt 只用 C(及编译器运行时库)。
  • 验证优化:TinyCrypt 用基于 Shamir 技巧的专门例程做 ECDSA 验证,性能远好于 p256-m 为压体积而采用的通用代码——这正是 p256-m 验证性能偏弱的原因。

总体结论:p256-m 在代码体积与 RAM 上全面领先约一倍,在密钥生成/ECDH/签名上与 TinyCrypt 相当甚至略快,但 ECDSA 验证(尤其小端 CPU 上)明显偏慢;这是它坚持"通用代码 + 最小体积"路线的必然取舍。

八、设计概览:单文件、五层架构

整个实现集中在单个文件(p256-m.c,共 1514 行)中,大部分函数保持static以利于优化。实现按职责分为五层:

8.1 固定宽度多精度算术层

大整数表示为uint32_t数组(limb,最低有效位在前,256 位即 8 个 limb,见 p256-m.c)。可能产生进位时使用向uint64_t的强制转换,引导编译器使用 CPU 的进位标志;可能溢出时函数返回进位标志。该层提供加、减、乘加、按 limb 移位(服务于 Montgomery 乘法)、条件赋值、相等比较、与零比较、大端字节序列化/反序列化。内部函数u32_muladd64()在此层有 4 种实现(两种 Cortex-M/A 汇编 + 两种纯 C),见前文第三节。

8.2 固定宽度模运算层

所有模运算都在Montgomery 域中进行,即 x 以x * 2^256 mod m表示;计算前需转入该域,计算后转回。曲线素数 p 与阶 n 对应的 Montgomery 常量预计算并存储在静态结构中。模逆使用费马小定理计算,以获得与所逆值无关的恒定时间行为。该层提供 p/n 常量及 Montgomery 常量、模加减乘逆、小值赋值、Montgomery 域转换、以及"带范围检查与 Montgomery 域转换的字节序列化/反序列化"。

8.3 曲线点运算层

曲线点使用仿射(affine)或 Jacobian 坐标表示;仿射坐标扩展用 (0,0) 表示零点。单个坐标始终处于 Montgomery 域。并非所有仿射/Jacobian 公式都是完备的,代码对每个函数的前置条件做了细致记录与满足。该层提供曲线常量 b、基点坐标、点有效性检查(在曲线上且非零)、Jacobian→仿射转换、Jacobian 坐标点倍(完备公式)、混合 affine-Jacobian 点加(P ∉ {0, Q, -Q})、仿射坐标"点加或点倍"(泄漏版,仅用于全部数据公开的 ECDSA 验证)、以及带有效性检查的字节序列化/反序列化。

8.4 标量运算层

核心是标量乘法,采用有符号二元阶梯(signed binary ladder)——经典 double-and-add 的变体,每一步都执行一次加/减。代码同样保证加法公式的前置条件始终满足。有符号二元阶梯要求标量为奇数;必要时通过同时对标量(模 n)和输入点取负来保证。该层提供标量乘法、带范围检查的字节反序列化、标量及其公钥的生成。

8.5 公共 API 层

该层构建于以上各层之上,与前几层不同,所有输入输出都是字节数组。密钥生成与 ECDH 共享密钥计算只是内部函数的薄封装,负责格式转换与错误处理;ECDSA 函数则有更多非平凡逻辑(如签名中的随机数处理、验证中的双标量运算)。

8.6 测试设计:Python 参考实现驱动

上游采用"先写一个自包含的纯 Python 参考实现p256.py作为热身并辅助核对中间值"的路线,内嵌多个来源的测试向量。第二个脚本gen-test-data.py基于该参考实现生成更多正/负测试数据,输出为 C 头文件,供闭箱与开箱测试程序使用。另外,p256-m 可编译带额外插桩的版本,把秘密数据标记出来,让 valgrind 或 MemSan 检查是否有分支/内存访问(哪怕间接)依赖它——相关宏定义在文件顶部(即前文第三节的CT_POISON/CT_UNPOISON)。

8.7 已测试平台

u32_muladd64()有 4 个版本(带/不带 DSP 扩展的两种汇编、MUL64_IS_CONSTANT_TIME开/关的两种纯 C),对应测试矩阵为:

  • x64 上make:测试不带MUL64_IS_CONSTANT_TIME的纯 C 版(Clang);
  • x64 上./consttime.sh:测试两种纯 C 版(Clang);
  • Arm v7-A(Raspberry Pi 2)上make:测试 Arm-DSP 汇编版(Clang);
  • Cortex-M0/M4 开发板上的on-target-*box:测试两种汇编版(GCC)。

此外sizes.sh用 GCC 与 Clang 为三个 Arm 内核构建以测体积,deps.sh用 GCC 检查外部依赖。

九、在当前仓库中的集成:作为 Mbed TLS 的 PSA 加速驱动

p256-m 在本仓库中的价值不仅在于算法本身,更在于它被接入了 Mbed TLS 的PSA Crypto 加速驱动体系,作为软件加速器(software accelerator)的示例实现。

9.1 目录与构建结构

  • 核心源码与头文件:p256-m/p256-m.c、p256-m/p256-m.h;
  • PSA 驱动入口:p256-m_driver_entrypoints.c 与 p256-m_driver_entrypoints.h;
  • 构建脚本:CMakeLists.txt 构建独立的p256m静态库目标,lib/mbedtls/3rdparty/CMakeLists.txt 中的add_subdirectory(p256-m)将其纳入整体构建;Makefile.inc 提供 Make 构建路径的源文件与头文件清单。

9.2 启用宏

启用驱动需要在配置头中定义MBEDTLS_PSA_P256M_DRIVER_ENABLED(见 mbedtls_config.h,默认注释关闭)。该宏在驱动入口头文件中还会自动定义PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT,告知 PSA 层存在加速驱动。

9.3 驱动入口与格式转换

驱动入口实现了 PSA 透明驱动规定的 6 个入口:p256_transparent_import_keyp256_transparent_export_public_keyp256_transparent_generate_keyp256_transparent_key_agreementp256_transparent_sign_hashp256_transparent_verify_hash。其核心工作之一是密钥格式转换

  • PSA 导出的 SECP256R1 公钥是 65 字节(前导0x04+ 64 字节公钥,即未压缩 ECPoint 格式),私钥是 32 字节;
  • p256-m 内部公钥格式只有 64 字节(与 PSA 相同但无前导字节),私钥格式与 PSA 一致;
  • 因此向 p256-m 传入公钥前需去掉前导字节(peer_key + 1/key_buffer + 1),导出公钥时则补回0x04(p256-m_driver_entrypoints.c);
  • 共享密钥与签名格式在 PSA 与 p256-m 之间完全一致,无需转换。

错误码转换由p256_to_psa_error()完成:P256_SUCCESS → PSA_SUCCESSP256_INVALID_PUBKEY/PRIVKEY → PSA_ERROR_INVALID_ARGUMENTP256_INVALID_SIGNATURE → PSA_ERROR_INVALID_SIGNATUREP256_RANDOM_FAILED → PSA_ERROR_GENERIC_ERROR(p256-m_driver_entrypoints.c)。verify_hash入口还通过psa_driver_wrapper_export_public_key()先统一把密钥规范为 65 字节公钥格式再交给 p256-m,全程避免动态分配。所有入口均坚持"无动态内存"原则,栈上分配固定缓冲。

9.4 快照性质与 RNG 复用

如 Mbed TLS 侧说明 所述:p256-m 刻意不提供自己的 CSPRNG,因此在 Mbed TLS 集成中p256_generate_random()包装了 PSA 的psa_generate_random()(p256-m.c),随机性安全边界完全由 PSA 层的 RNG 决定。同时要留意,本仓库内的 p256-m 文件不会随上游频繁更新,可能缺少上游项目的最新修复与改进。

十、可移植性与扩展:硬编码的边界

10.1 扩展其他曲线需要改什么

README 明确指出:最小代码体积只能通过对特定曲线做专门化实现来达到。要在分层结构上扩展其他曲线,各层需要做如下调整:

  • 多精度算术层:limb 数硬编码为 8。对同为 256 位的曲线无需改动;不同位宽的曲线改为硬编码其他值;若支持多种位宽,则需为每个函数增加 limb 数参数,数组声明统一用最大 limb 数。
  • 模运算层:p、n 及其 Montgomery 常量硬编码。换曲线只需替换常量;支持多曲线则定义全部常量,且只保留已接受mod参数的函数(删除m256_xxx_p()便捷函数);mod参数可同时携带 limb 数。
  • 曲线点运算层:曲线常量 b 与基点坐标 gx、gy 硬编码;常量 a 利用a == -3的标准优化(在point_double()第一步省一次乘法)隐式硬编码,对 a ≠ -3 的曲线需恢复常规计算;b != 0被间接利用——保证 (0,0) 不在曲线上从而可复用该值表示零点(目前已标准化的 Short Weierstrass 曲线均满足 b ≠ 0);曲线形状假设为 Short Weierstrass,对 Montgomery、(twisted) Edwards 等其他形状,本层实现与 API 都会大不相同。
  • 标量运算层:多曲线时所有函数需增加 curve id 参数;本层假设曲线阶 n 的位宽与模数 p 相同(绝大多数已标准化曲线如此,唯一例外是 secp224k1,需为 n 与标量表示增加一个 limb);scalar_mult()中阶的位宽硬编码;该函数还利用了阶 n 的次低有效位为 1 来避免特殊情形,不满足此条件的曲线阶需单独处理(乘 ±2 的情形单独计算再条件赋值)。
  • 公共 API 层:多曲线时需增加 curve id 参数并处理可变大小 I/O;ECDH API 在不同曲线形状下仍相似(仅公钥尺寸不同),但 ECDSA API 不适用于 Montgomery/Edwards 曲线,后者需要 EdDSA 风格的接口。

10.2 对其他平台的假设

p256-m 虽为标准 C99,但面向受限 32 位平台做了如下假设:

  • uint8_tuint16_tuint32_tuint64_t类型必须存在;
  • 32 位无符号加减(带进位)必须是恒定时间的;
  • 16x16→32 位无符号乘法必须可用且恒定时间。

即便平台上存在带进位的 64 位加减、甚至 64x64→128 位乘法,p256-m 也不使用它们(尽管它们能显著提升性能)。README 给出的改进方向是:把内部 API 中uint32_t数组替换为自定义类型,在 64 位平台上将该类型定义为uint64_t数组,并在多精度算术层做相应适配。

最后,可选的汇编代码(在被测 Cortex-M 上带来约 2 倍性能提升,同时略微减小代码体积与栈占用)目前仅适用于支持GCC 扩展 asm 语法的编译器(包括 GCC 与 Clang)。

结语

p256-m 是一份值得仔细研读的"极简密码实现"范本:它在不足 3KiB 的代码与不足 768 字节的 RAM 预算内,交付了恒定时间、全输入校验的 P-256 ECDH/ECDSA,并通过分层架构(多精度算术 → 模运算 → 曲线点 → 标量 → 公共 API)让安全与体积目标层层落地。它的取舍同样鲜明——E CDSA 验证用通用代码换体积而牺牲速度、不做物理侧信道防护、不支持多曲线——这些边界在 README 中被坦率记录。在本仓库中,它进一步以 Mbed TLS PSA 软件加速驱动的形态接入上层加密框架,成为理解"算法实现 ↔ PSA 驱动 ↔ 上层 API"三层关系的现成案例。相关一手材料均可在本仓库内查阅:原始 README、公共头文件、核心实现、PSA 驱动入口 与 Mbed TLS 集成说明。

【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询