ZeroTierOne 中的 ARM NEON 汇编级 Salsa20/12 加速实现解析

ZeroTierOne 中的 ARM NEON 汇编级 Salsa20/12 加速实现解析 ZeroTierOne 中的 ARM NEON 汇编级 Salsa20/12 加速实现解析【免费下载链接】ZeroTierOneA Smart Ethernet Switch for Earth项目地址: https://gitcode.com/GitHub_Trending/ze/ZeroTierOne本篇指南围绕 ZeroTierOne 仓库中 ext/arm32-neon-salsa2012-asm/README.md 所描述的 ARM NEON32 位汇编版 Salsa20/12 实现展开说明它在项目中的定位、来源与许可、运行时接入方式以及构建门控机制。读完本文你将掌握该加速模块的完整调用链从汇编函数到 Packet.cpp 的快速路径宏、NEON 能力检测原理以及它在 32 位 Linux ARM 与 64 位 ARM 平台上的适用边界。一、模块定位一条地球级虚拟交换机的加密快车道ZeroTierOne 是一个去中心化的虚拟以太网交换方案所有节点间的数据包都需要经过加解密处理。包加密的主密钥流由 Salsa20 流密码派生而流密码的性能直接决定整条数据通路的吞吐上限。为了让 32 位 ARM 设备上的包处理跑得更快仓库引入了来自 supercop 项目、由 Daniel J. Bernstein 编写的 ARM NEON32 位汇编实现该实现相比朴素naive的 C 版本速度显著更快且与 Salsa20 系列算法一样属于公有领域public domain。从目录结构上该模块与 x86 侧的加速实现一一对应ARM 32 位 NEON 汇编ext/arm32-neon-salsa2012-asm/salsa2012.s 与配套头文件 salsa2012.hx86-64 SSE 汇编ext/x64-salsa2012-asm/salsa2012.s在 make-linux.mk 中由ZT_USE_X64_ASM_SALSA2012控制两者的作用相同在对应指令集上以单遍single-pass方式完成 Salsa20/12 的加解密。二、来源、作者与许可README 明确指出This is from supercop and was originally written by Daniel J. Bernstein. Code is in the public domain like the rest of Salsa20.该汇编代码源自 supercopeBACS基准测试项目原作者是 Daniel J. BernsteinSalsa20 算法作者本人。与 Salsa20 算法及其参考实现一样这段代码以公有领域授权可以自由使用、修改和再分发。仓库中对应的 C 参考实现 node/Salsa20.cpp 同样在文件头声明了公有领域属性Since the original was public domain, this is too.可见项目的加密原语层整体保持了公有领域代码的引入传统。三、对外接口zt_salsa2012_armneon3_xor汇编函数通过 salsa2012.h 暴露给 C/C 侧其声明如下// ciphertext buffer, message/NULL, length, nonce (8 bytes), key (32 bytes) extern int zt_salsa2012_armneon3_xor(unsigned char *c, const unsigned char *m, unsigned long long len, const unsigned char *n, const unsigned char *k);参数语义以头文件注释为准参数类型说明cunsigned char*密文输出缓冲区ciphertext buffermconst unsigned char*明文输入可传NULLZeroTier 的实际调用传0见下文lenunsigned long long待处理数据的字节长度nconst unsigned char*nonce8 字节64 位初始化向量kconst unsigned char*密钥32 字节256 位这个函数名中的armneon3表示它利用 NEON 的三路并行能力一次处理多个 64 字节块从而摊薄状态加载开销。它做的是异或加密XOR encryption将 Salsa20/12 生成的密钥流与输入异或因此加解密共用同一函数符合流密码的使用惯例。头文件的 NEON 能力检测宏salsa2012.h 还定义了一个运行时检测宏zt_arm_has_neon()其逻辑分三种情况#if defined(__linux__) || defined(linux) || defined(__LINUX__) || defined(__linux) #include sys/auxv.h #include asm/hwcap.h #define zt_arm_has_neon() ((getauxval(AT_HWCAP) HWCAP_NEON) ! 0) #elif defined(__ARM_NEON__) || defined(__ARM_NEON) #define zt_arm_has_neon() (true) #else #define zt_arm_has_neon() (false) #endif在 Linux 上通过getauxval(AT_HWCAP)读取内核暴露的硬件能力位与HWCAP_NEON做与运算运行期真实探测 CPU 是否支持 NEON在编译期已定义__ARM_NEON__/__ARM_NEON说明编译器按支持 NEON 的目标配置时直接返回真其他平台返回假保证该汇编模块不会被错误调用。这种编译期门控 运行期探测的双保险是模块被安全接入项目的关键。四、在 Packet 加解密路径中的实际接入真正让这段汇编发挥作用的是 node/Packet.cpp 中定义的快速单遍加密宏。其接入逻辑如下对应 Packet.cpp 第 19-67 行附近#ifdef ZT_USE_ARM32_NEON_ASM_SALSA2012 #include ../ext/arm32-neon-salsa2012-asm/salsa2012.h #endif // ARM (32-bit) NEON crypto (must be detected) #ifdef ZT_USE_ARM32_NEON_ASM_SALSA2012 class _FastCryptoChecker { public: _FastCryptoChecker() : canHas(zt_arm_has_neon()) {} bool canHas; }; static const _FastCryptoChecker _ZT_FAST_CRYPTO_CHECK; #define ZT_HAS_FAST_CRYPTO() (_ZT_FAST_CRYPTO_CHECK.canHas) #define ZT_FAST_SINGLE_PASS_SALSA2012(b, l, n, k) \ zt_salsa2012_armneon3_xor(reinterpret_castunsigned char*(b), \ (const unsigned char*)0, (l), \ reinterpret_castconst unsigned char*(n), \ reinterpret_castconst unsigned char*(k)) #endif这里有两个值得注意的工程细节静态对象做一次探测_FastCryptoChecker是static const全局对象构造时调用zt_arm_has_neon()把getauxval的系统调用成本摊到进程启动阶段之后ZT_HAS_FAST_CRYPTO()只是读一个 bool热路径上几乎零开销。原地异或in-place XOR调用时明文参数传(const unsigned char*)0说明实际场景是原地加解密——输出缓冲区b同时充当输入由汇编内部的 XOR 逻辑完成。这与Salsa20::crypt12的语义一致。ZT_HAS_FAST_CRYPTO()若为假则回退到通用路径若既无 x64 汇编也无 ARM32 NEON 汇编宏退化为空操作走 node/Salsa20.cpp 中的纯 C 实现crypt12/crypt20。x86 侧的对照宏使用zt_salsa2012_amd64_xmm6同样遵循宏 条件编译的接入模式。五、构建门控何时编译这段汇编该汇编不会在所有平台被编译而是由架构探测结果决定涉及两个层面。CMake 侧node/CMakeLists.txtif(ZT_USE_ARM32_NEON_ASM_CRYPTO) set(ASM_ARM32_DIR ${CMAKE_SOURCE_DIR}/ext/arm32-neon-salsa2012-asm) list(APPEND core_src_glob ${ASM_ARM32_DIR}/salsa2012.s) list(APPEND core_hdr_glob ${ASM_ARM32_DIR}/salsa2012.h) endif()当顶层启用ZT_USE_ARM32_NEON_ASM_CRYPTO时salsa2012.s被加入zerotier-core静态库的源文件集合同时 CMakeLists.txt 会执行add_definitions(-DZT_USE_ARM32_NEON_ASM_SALSA2012)从而触发 Packet.cpp 中的 include 与宏定义。此外只要任一汇编加密被启用含 x64 Salsa/Ed25519 或 ARM32 NEONCMake 还会为汇编源追加-x assembler-with-cpp -z noexecstack标志保证汇编可展开预处理宏且栈不可执行。Make 侧make-linux.mk传统 Makefile 构建体系里通过CC_MACH判断目标机器类型arm、armel、armhf、armv6*、armv7*等 32 位 ARM 机器类型会将ZT_USE_ARM32_NEON_ASM_CRYPTO置 1但 README 所称的ARM32 hell在 Makefile 中有更保守的处理例如armel软浮点走-marcharmv5t -mfloat-abisoft并强制ZT_USE_ARM32_NEON_ASM_CRYPTO0Raspberry Pi 一代的armv6zkarm1176jzf-s只有 VFP 而无 NEON同样被显式关闭 NEON 汇编当ZT_USE_ARM32_NEON_ASM_CRYPTO1时追加-DZT_USE_ARM32_NEON_ASM_SALSA2012定义并把ext/arm32-neon-salsa2012-asm/salsa2012.o加入CORE_OBJS。由此可见README 所说的自动包含在 32-bit Linux ARM 构建中并非无条件的它要求目标 CPU 实际具备 NEON 单元如 ARMv7-A 及以上的硬浮点环境软浮点老内核或仅带 VFP 的 ARMv6 会被构建系统主动排除。六、通用 C 实现作为回退基准当无法使用 NEON 汇编时node/Salsa20.cpp 提供等价的 C 实现二者共享同一算法结构init(key, iv)用常量串expand 32-byte k十六进制0x61707865 0x3320646e 0x79622d32 0x6b206574初始化 4×4 状态矩阵随后填入 32 字节密钥与 64 位 IV见Salsa20::initcrypt12执行 12 轮6 个 2X round后把状态与初始状态相加再与明文异或输出块计数器在j8溢出时进位到j9源码注释明确提示单 nonce 下 2^70 字节的上限由使用者负责——这一点同样适用于 NEON 汇编版本的使用约束。Salsa20/1212 轮是 ZeroTier 数据面选择的轮数配置相比标准 Salsa20/20 在保证安全性的前提下换取更高吞吐而 NEON 汇编正是为这条最高频路径服务的。若需查看算法回退实现的完整代码可阅读 node/Salsa20.cpp 与 node/Salsa20.hpp。七、平台适用性与已知限制README 末尾明确给出了该模块的边界Its included automatically in 32-bit Linux ARM builds. It likely will not work on 64-bit ARM, so itll need to be ported at least. That will unfortunately keep it out of mobile versions for now since those are all going 64-bit.概括为三点事实自动启用范围仅限 32 位 Linux ARM 构建且需 NEON 能力见第五节64 位 ARM 兼容性该汇编大概率无法在 64 位 ARMAArch64上直接工作至少需要移植。因为 32 位 NEON 汇编依赖 ARMv7 的寄存器布局与调用约定与 AArch64 不兼容移动端现状由于当时移动端已全面转向 64 位这段 32 位汇编暂时无法进入移动版本。从当前仓库的顶层 CMake 也可以印证AArch64 构建走的是另一条路——通过-DZT_ARCH_ARM_HAS_NEON -marcharmv8-acrypto启用 node/AES_armcrypto.cpp 中的 AES-NEON 与 PMULL 硬件加速对应ZT_AES_NEON而不是复用这段 32 位 Salsa 汇编。八、小结ext/arm32-neon-salsa2012-asm是 ZeroTierOne 密码学加速体系中的一块拼图它以公有领域的 supercop 汇编实现为基础通过编译期宏门控 静态对象运行期探测 NEON 单遍异或宏的方式被 Packet.cpp 的包加密路径调用并由 node/CMakeLists.txt 与 make-linux.mk 在 32 位 Linux ARM 构建中自动纳入。理解它的接口zt_salsa2012_armneon3_xor、zt_arm_has_neon()、构建门控ZT_USE_ARM32_NEON_ASM_CRYPTO/ZT_USE_ARM32_NEON_ASM_SALSA2012与平台边界不支持 AArch64可以帮助你在交叉编译嵌入式设备或分析数据面性能瓶颈时快速定位这条加密快车道的来龙去脉。【免费下载链接】ZeroTierOneA Smart Ethernet Switch for Earth项目地址: https://gitcode.com/GitHub_Trending/ze/ZeroTierOne创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考