尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

国产安全芯片国密算法性能适配策略与优化实践

国产安全芯片国密算法性能适配策略与优化实践 拿到一颗国产安全芯片的样片第一件事往往不是烧录官方demo而是先算一笔性能账SM2签名一次要多久SM3处理1KB数据要多久SM4连续加密一段会话流量能到多少MbpsZUC密钥流生成能不能扛住目标业务。我在实际项目里踩过的坑反复证明一个朴素的道理所有“国产安全芯片在密码算法国密体系下的性能适配策略”问题本质上都不是算法本身跑不动而是没有在方案设计阶段把四种国密算法的计算特征搞明白等到板子回来才拿一个裸CPU硬跑然后被性能指标卡得进退两难。这篇就把我在安全芯片上适配SM2、SM3、SM4、SM9、ZUC的完整思路和排障经验拆开讲适合正在做嵌入式安全产品、选型密码芯片、或者打算自己优化国密算法软实现的工程师参考。1. 国密算法全家桶的性能账本四种算法的计算特征差异很多人一提“国密算法性能优化”第一反应就是“把所有算法都用硬件实现”。这个思路方向没错但落到芯片上就会发现面积、功耗、开发周期都撑不住。正确做法是先搞清楚国密体系里几个核心算法各自“吃”什么资源再决定用软件硬啃、指令扩展、还是专用密码引擎。1.1 SM2的“重引擎”与SM4的“轻流水”SM2是椭圆曲线公钥密码算法标准文档是GB/T 32918。它最重的计算是大数模乘和椭圆曲线点乘。一次SM2签名核心运算是一个256位标量乘 kP验签时通常要算双标量乘 sG tPA。我在几百MHz以下是敢直接拿CPU硬跑的但到了40MHz~120MHz的SE芯片上没有硬件模乘器的话单次点乘要累加几百次点加和倍点每次点加又涉及大数乘法、模约减、坐标转换整体耗时能到几十毫秒到数百毫秒这在安全认证场景里经常是没法接受的。所以SM2类公钥运算必须靠MALU这类大数模乘加速单元配合蒙哥马利约减和雅可比坐标才能把一次签名压到几十毫秒以内。SM4是分组密码算法128位密钥、128位分组32轮轮函数迭代。它的特点是结构非常规整每轮就是异或、查S盒、线性变换L。虽然轮数多但硬件实现很友好可以做成单轮迭代引擎面积不大还能保持较高吞吐软件实现时查表法是最常用的手段把S盒做成256×4字节的查找表单轮的T变换可以用4张表压缩成4次查表加异或。SM4在低位MCU上的主要瓶颈不是运算本身而是查表时的内存访问模式和代码体积这一点后面章节再详细讲。1.2 SM3和ZUC的软件不友好性SM3是杂凑算法输出256位摘要内部结构类似SHA-256但细节差很多。它的核心轮函数里有大量32位模加、循环左移、条件逻辑函数FF/GG和两个置换P0/P1。最麻烦的是SM3压函数每轮都有一条较长的数据依赖链从A、E两个寄存器出发经过模加、循环左移、置换再到下一轮软件上很难像SM4那样用简单的查表就加速。如果目标MCU没有单指令循环移位即funnel shift或rotate指令一次X 9就要拆成左移、右移、OR三条指令64轮下来指令数很可观。ZUC祖冲之算法是国密序列密码128位安全强度同时提供加密和完整性保护。它的内部结构比SM4复杂得多涉及16个31比特寄存器组成的线性反馈移位寄存器、比特重组和带S盒的非线性函数F。ZUC的软件实现最头疼的是LFSR的模2^31-1约减以及位拼接带来的大量掩码和位移操作。后面专门有章节拆解它。这四种算法的差异决定了适配策略不能“一碗水端平”。我的习惯是先算一版理论账列出目标芯片主频、内存、总线位宽再估算每种算法在纯软件下的吞吐量找出最短时间的木板然后才决定哪些算法上硬件引擎。下表是我在方案阶段常用的一张对比表算法类型典型计算粒度主要性能瓶颈硬件加速价值SM2公钥密码256位点乘/模幂大数模乘、双标量乘极高软件很难达到可用时延SM3杂凑512位分组32位模加依赖链、循环移位高尤其对连续大块数据SM4分组密码128位分组S盒查表、32轮迭代中高引擎面积收益明显ZUC序列密码32比特密钥字/拍LFSR约减、S盒与加法串联高软件位操作过于密集2. 从算法特性反推芯片架构为什么通用CPU硬跑国密会死得很难看做安全芯片性能适配本质上是在做“算法特征”到“硬件结构”的映射。这一章我从端侧安全芯片的实际约束出发说说为什么直接拿一颗ARM Cortex-M或RISC-V内核硬跑国密算法往往达不到产品指标。2.1 安全芯片的“穷困”现实面积、功耗、频率约束端侧安全芯片和应用处理器完全是两个物种。它的主频可能只有几十到两百多MHz片上SRAM往往只有几十KB到一两百KB没有独立的二级缓存总线位宽通常是32位甚至16位还要兼顾极低功耗。同时安全芯片内部还要放真随机数发生器、密钥存储、防侧信道与主动屏蔽层等安全机制这些都会占面积和功耗预算。留给密码算法的逻辑门其实非常有限。在这种条件下如果让CPU软跑SM3假设主频100MHz按每个字节几百个周期估算处理1KB数据的耗时可能达到毫秒级连续做HUK升级或者大块固件校验时非常吃力。更重要的是软件跑国密算法时CPU被占满无法响应实时中断这在安全通信握手、证书校验等交互流程里会放大延迟。硬跑SM2就更不用说了256位模乘没有硬件帮助在低端核上接近灾难。所以性能适配的第一步往往不是狂优化软件而是承认通用CPU的路走不通必须把高频、规则、面积可控的运算下沉到专用硬件。2.2 三类密码引擎形态的取舍根据算法粒度我习惯把硬件加速器分成三类第一类是面向SM4、ZUC这类轮函数规则的对称密码引擎常见形态是小型状态机加数据通路。SM4引擎可以做到每个时钟周期处理一到两轮ZUC引擎则重点加速LFSR反馈和F函数的S盒与线性变换。这种引擎的面积在几万到十几万门级别对一颗安全芯片来说可控。第二类是面向SM2、SM9这类公钥算法的大数运算单元核心是256位或512位模乘器、模加器以及支持蒙哥马利约减的状态机。公钥密码的光谱很宽SM9还涉及双线性对单独把点乘优化到位已经能解决大部分性能问题。第三类是CPU指令扩展。对SM3这种“大量循环移位模加”的算法如果芯片核支持在ALU里插入旋转指令比如RISC-V的rol扩展软件性能能提升好几倍。这种方式适合面积预算极紧、不想放独立引擎的型号但得和编译器工具链配合好。选择哪类引擎要同时考虑算法是否会更新、产品系列是否复用、以及驱动代码的维护成本。我的建议是优先保证SM2和SM3的硬件化SM4和ZUC视目标场景决定如果产品主打TLS类协议SM4的引擎也非常值得做因为对称加密的数据量大。3. 祖冲之算法的性能解构LFSR、比特重组与S盒的协同设计ZUC在国密体系里的地位比较特殊。它不是分组密码也能当流密码用标准是GM/T 0008。很多工程师刚接触ZUC时会被它的结构劝退16个31比特寄存器、比特重组、非线性函数F有点当年学A5/1的感觉。这一章我从性能角度把它拆开搞清楚每个模块为什么慢、硬件怎么加。3.1 ZUC的三个模块与两阶段工作模式ZUC整体分为线性反馈移位寄存器、比特重组和非线性函数F三块。LFSR的16个状态单元都是31比特宽度工作在素域GF(2^31-1)上这意味着LFSR的反馈不是简单的异或而是要做模约减。标准里反馈值 v 由若干状态变量左移后相加再模2^31-1得到处理不好就容易出0状态所以规范还有若u0则把它置为2^31-1的特殊规则。比特重组负责从不同LFSR寄存器中抽取指定位拼接成X0、X1、X2、X3四个32位字分别送入非线性函数F和产生最终密钥流。这步操作从算法角度看就是取位、拼接非常零碎在硬件里只是一根根物理连线但在软件里就是大量的右移、掩码、OR操作。非线性函数F包含两个32位寄存器R1、R2和S盒。F模块一方面参与LFSR初始化时的反馈另一方面在生成阶段每拍输出一个32比特密钥字。ZUC的S盒是8比特进8比特出的基础盒实际使用时按字节方式展开到32位再配合线性变换L1、L2和循环左移完成高扩散。硬件设计时这堆S盒通常做成组合逻辑或小RAML1/L2就是异或树加固定的循环移位连接反而没有什么悬念。ZUC有两个阶段初始化阶段和生成阶段。初始化时要装载128位密钥和128位初始向量执行32拍运算后进入生成阶段。软件实现中一次会话若频繁更换密钥和IV光初始化32拍的开销就会占到明显比例。因此在适配策略里我特别看重“会话复用”尽量让同一个ZUC上下文连续生成较长密钥流而不是隔几字节就重建一次。3.2 软件实现慢在哪硬件加速快在哪先算软件侧的账。ZUC每生成一个32比特密钥字LFSR要先做一次带模约减的反馈F要做S盒查表和32位加法。如果芯片的指令集不擅长位域拼接BR这一步还要再消耗几条指令。整体下来一个密钥字的纯计算周期数往往上百折算到吞吐上远低于SM4。硬件侧的做法是把LFSR反馈路径做成专用加法器和比较器判断加法结果是否大于等于2^31-1是则减去一个周期内完成。F的S盒用组合逻辑实现后BR和L1/L2都是固定连线整条数据通路可以流水化最终做到每拍输出32比特。以100MHz主频算密钥流理论吞吐约400MB/s实际受总线宽度和数据搬运影响会打折扣但已经足够覆盖多数安全通信需求。实际调优时还有一个容易被忽略的点ZUC引擎与CPU之间交换数据如果用轮询FIFOCPU会被占死。更好的方案是引擎直接写一个小的密钥流缓冲区由DMA搬到目的地址满了再触发中断。这样密钥流的批量生产与业务数据包的处理是并行的CPU只负责组包和协议解析。4. SM3的P置换与差分扩散从1比特到3比特的性能与验证价值SM3的优化里有个很有意思的细节和热词里“sm3密码杂凑算法的p置换中有1比特输入差分输出差分有多少比特”直接相关。这个问题表面上是差分密码分析的题目但在工程上它直接影响到我们对P置换数据通路的理解和测试向量设计。4.1 P0/P1置换到底是什么SM3里有两个置换函数P0出现在压缩函数内部定义为 P0(X) X ^ (X 9) ^ (X 17)P1出现在消息扩展中定义为 P1(X) X ^ (X 15) ^ (X 23)。从性能角度这两个函数都是纯位运算没有S盒、没有模加看起来毫不起眼。但堆到64轮里每次都要做两次循环移位和两次异或在不支持rotate指令的CPU上一次循环左移等于三条指令P0就要消耗约六条指令。硬件实现中循环移位倒不贵但位宽是32位数据通路的走线长度会拉长某些工艺下关键路径上也能看到P置换的影子。所以SM3硬件加速不只是加S盒还要把模加、循环移位、FF/GG函数综合优化。4.2 一比特输入差分经P置换后为什么是3比特回答开头那个问题前先明确“输入差分”是什么。假设某一位输入产生了一个1比特的差分用一个只在第i位为1的32位向量 e_i 表示。经过P0后输出差分是 e_i ^ (e_i 9) ^ (e_i 17)。关键点在于三个循环移位后的活动位位置分别是 i、i9模32、i17模32。9、17、0两两之间在模32意义下都不相同所以这三个置位位置不会重叠异或结果中也就没有互相抵消的情况。结论是P0处理一个1比特输入差分输出差分恰好有3个比特为1。P1同理移位量是15和23也是三个不同位置输出差分同样为3比特。这背后其实体现了P置换的设计目标让单个输入差异尽快扩散到输出多个位。用密码学行话说P置换的线性分支数很高可以把轮与轮之间的扩散速度拉上去。虽然是“1变3”看着数目不大但压缩函数每轮里还有其他模加和逻辑函数参与经过多轮迭代这种差异会迅速覆盖过半状态位。4.3 这个性质对安全芯片调试和验证有什么用我在验证一颗SM3硬件加速器时还真用它抓过一次bug。当时P0数据通路的测试向量是按标准文档给的大样例做的全流程功能是对的但一致性测试偶尔出现位错误。后来我构造了“把所有移位量设置为固定值但给单个输入位翻转1比特”的定向测试同时观察输出差分。预期的3比特输出在部分向量上变成了2比特一查原因是硬件实现里把X 9和X 17两条路径中的一条接到了错误的位移量上导致两个活动位重叠。从性能适配策略的角度看这个性质还有另一个价值它提醒我们SM3软件优化时不要试图用查表去替代循环移位——那反而会破坏P置换的线性规则还会增加内存访问。正确做法是让编译器识别到固定移位量或者直接用内建rotate函数。如果芯片支持RISC-V的位操作扩展SM3的加速效果会非常明显。5. 一套实际可落地的性能适配流程基线、优化、避坑前面几章讲的是算法特征和硬件架构的“道”这一章说说我实际跑项目时的“术”。以一颗中等性能的国产安全芯片为例主频128MHz片上有SM2模乘器和SM4引擎SM3与ZUC主要靠软件加部分指令优化目标是把TLS握手、本地数据加密、ZUC密钥流三条主路径都调到可用状态。5.1 先测基线算清每种操作的时间占比拿到开发板后我不会急着改代码而是先写一个简单的性能测量程序用定时器对每个算法操作打点。测量对象包括SM2签名、SM2验签、SM3处理1KB、SM4加密1KB、ZUC生成1KB密钥流。每个操作执行多次取均值避免缓存和中断干扰。测试时最好关掉调试打印和日志否则结果会非常难看。这步的意义是把优化优先级量化。以我碰到的项目为例初始结果是SM2验签耗时约120msSM3是6ms/KBSM4引擎约2ms/KBZUC软跑约4ms/KB。显然SM2是绝对大头。那么优化的重心就放在SM2点乘的实现检查是否有现成的模乘器驱动、坐标是否用了雅可比、固定基点G能否预计算查表。做完这些验签降到45ms。然后我再回头调整SM3和ZUC的软实现。5.2 按成本收益排序的优化手段清单针对对称算法我的常用优化手法如下查表法加速S盒尤其SM4和ZUC。把S盒放到常量区访问模式要连续避免频繁Cache miss。8位MCU上查表未必比位运算快需要实测。循环展开减少跳转开销。SM4按8轮或16轮展开SM3把消息扩展和压缩循环分开让编译器更好调度寄存器。利用位操作扩展指令。如果编译器支持__ror、__rol或RISC-V的B扩展循环移位从三条指令变一条SM3提升很大。大块数据用DMA搬运密码引擎和CPU并行。例如SM4加密一段1MB日志CPU配置好引擎后立刻去做协议解析完成中断再回来取结果。会话上下文缓存。SM2私钥装载、SM4密钥扩展、ZUC初始化都避免重复计算能合并的会话尽量合并。每个优化做完都要重新跑基线并且用标准测试向量回归一遍功能正确性。5.3 必须记住的避坑清单最后整理几个我踩过且反复出现的坑硬件引擎的启动等待用轮询比中断快但会占CPU大数据场景用DMA加中断小数据包用轮询反而省心。SM2的软件实现不能出现依赖密钥值的分支。点加、倍点选择必须恒定时间否则侧信道分析可能被利用。SM3的填充逻辑在处理“长度刚好等长”和“跨两个512位分组”时容易出错测试向量必须覆盖边界。ZUC引擎在上下文切换时要完整保存LFSR的全部16个31比特值、R1/R2以及已输出字数缺少一个都会导致密钥流错位。硬件S盒和软件S盒的字节序在不同芯片上可能不一样联调前先跑一遍单轮中间值对照。密钥、IV等敏感数据在软件栈中用完要主动清零不能依赖编译器优化掉。我把这些经验沉淀成了一张内部检查表后新项目的性能适配周期几乎缩短了一半。说白了国产安全芯片的国密性能问题没有玄学就是把算法特征、芯片约束和工程验证连成一条线从最重的瓶颈下手反复用数据说话。如果你手里的项目刚开始建议先把基线测试建好再按本文的顺序逐项排查。
返回列表