
汽车电子领域这几年最明显的变化就是功能安全与信息安全从加分项变成了准入门槛。以前做ECU开发大家聊的是CAN通信稳不稳、标定好不好调现在但凡涉及整车控制器、域控制器、BMS、EPS这类部件客户审核清单里必然有一项——安全启动。而安全启动绕不开两个关键词HSM和CMAC。前者是硬件安全模块是芯片里那块独立王国后者是基于AES的认证算法负责给固件盖章验章。这篇文章就围绕这两个东西把汽车电子MCU安全启动从原理到落地讲透包括HSM到底怎么工作、CMAC为什么比CRC和哈希更适合做启动校验、密钥怎么管、启动流程怎么设计、实测中会遇到哪些坑。不管你是刚接触信息安全的MCU驱动工程师还是正在做功能安全认证的架构师都能从里面找到能直接抄作业的部分。1. 安全启动到底在防什么从一次真实的篡改场景说起1.1 没有安全启动的MCU攻击者能做什么先讲一个我实际遇到过的场景。某项目做的是车身域控制器MCU用的是带HSM的英飞凌TC3xx系列。项目早期为了赶进度安全启动没做固件直接放在Flash里跑。后来做渗透测试测试人员用调试器接上JTAG口把Flash里的应用固件读出来改了几个字节——把某个限速判断的阈值从120改成200再写回去。整个过程不到十分钟MCU上电后照常运行没有任何异常提示。这就是没有安全启动的典型风险。攻击面其实比很多人想的要宽物理接触攻击通过调试接口JTAG/SWD读写Flash这是最直接的方式。很多量产件如果没做调试口保护一个几十块的调试器就能搞定。通信链路注入通过CAN、以太网、OTA通道下发被篡改的固件包如果Bootloader不做签名校验恶意固件就会被刷进去。供应链环节代工厂、维修点等环节的固件替换这类风险在售后市场尤其突出。回滚攻击把新版本固件替换成存在已知漏洞的旧版本利用旧漏洞进一步攻击。安全启动要解决的核心问题就一句话MCU上电后在把控制权交给应用代码之前必须确认这段代码是自己人写的、没被改过、且是允许运行的版本。三个条件缺一不可——完整性、真实性、版本合法性。1.2 为什么CRC校验远远不够很多工程师第一反应是我在固件末尾加个CRC不就行了上电算一遍CRC对得上就运行。这个思路在功能安全层面没问题但在信息安全层面基本等于没做。原因很简单CRC是公开算法没有密钥。攻击者改完固件重新算一遍CRC填进去校验照样通过。CRC只能防意外损坏比如Flash位翻转防不了蓄意篡改。这两者的威胁模型完全不同。那用SHA-256哈希呢比CRC强但单独用哈希也不够。因为哈希值如果和固件存在同一块Flash里攻击者改固件的同时把哈希值也改了一样能过。哈希要发挥作用必须配合密钥或者可信存储——要么用带密钥的算法HMAC/CMAC要么把哈希值存到攻击者改不了的地方比如HSM的OTP区域。这就引出了CMAC的价值它是带密钥的认证算法攻击者没有密钥就算改了固件也算不出正确的认证码。1.3 HSM在安全启动里扮演的角色HSMHardware Security Module不是软件模块是芯片内部一个独立的硬件子系统。以常见的汽车MCU为例HSM通常包含独立的CPU核常见是ARM Cortex-M0或类似精简核独立的Flash/RAM与主核物理隔离硬件加密加速器AES、SHA、ECC、TRNG等独立的调试接口和访问控制逻辑安全密钥存储区OTP或受保护的Flash区它和主核的关系可以类比成保险柜和办公室主核在办公室里干活密钥和敏感操作都锁在保险柜里主核只能通过一个受控的窗口通常是共享内存加中断请求HSM帮忙做加密运算但拿不到密钥本身。安全启动的信任根Root of Trust就建立在HSM里。主核上电后第一段执行的代码通常是BootROM里的固化代码会先让HSM去校验下一级固件校验通过才跳转。这样形成一条信任链BootROM → Bootloader → 应用固件每一级都校验下一级。2. CMAC算法拆解为什么它是安全启动的合适选择2.1 CMAC的数学原理用大白话讲清楚CMAC全称Cipher-based Message Authentication Code基于分组密码的消息认证码。它的底层用的是AES这类分组密码输出一个固定长度的认证标签AES-128对应128位实际常用截断到64位或128位。它的工作逻辑可以这样理解把固件按16字节一块切开用密钥K对每一块做AES加密但加密前要和上一块的输出做异或形成链式结构。最后一块特殊处理用两个子密钥K1、K2中的一个再加密一次得到最终标签。用生活化的类比假设你要给一叠文件盖章防伪。CMAC的做法是每盖一页章就把这一页的章印和上一页的章印叠在一起再盖最后一页用特制的印泥收尾。这样任何一页被换掉后面所有章印都会变最终章印必然对不上。而攻击者没有那枚特制印章密钥伪造不出来。CMAC的两个子密钥K1、K2是通过对密钥K做一次AES加密再左移、条件异或得到的这是标准算法NIST SP 800-38B规定的不需要额外存储。2.2 CMAC、HMAC、CRC、哈希的横向对比选算法不能只看哪个强要看场景。安全启动的场景特点是数据量大固件动辄几百KB到几MB、有硬件加速器可用、对启动时间敏感、需要密钥保护。算法是否带密钥硬件加速支持计算速度适用场景CRC32否通常无专用加速极快仅防意外损坏SHA-256否HSM通常支持中等配合可信存储做完整性HMAC-SHA256是依赖SHA加速中等偏慢通用认证软件实现多CMAC-AES128是AES加速器普遍支持快嵌入式安全启动首选CMAC的优势在于AES加速器在汽车MCU里几乎是标配HSM里基本都有。而SHA-256的硬件加速器虽然也有但很多中低端MCU的HSM只带AES。用CMAC可以直接复用AES硬件计算速度快代码量小。HMAC-SHA256在纯软件实现时开销明显更大对启动时间敏感的ECU不太友好。另一个关键点是认证标签长度可控。CMAC可以截断到64位甚至32位在安全强度和存储开销之间做权衡。对于安全启动这种一次性校验场景64位标签2^-64的伪造概率已经足够。2.3 密钥长度和标签长度的取舍实际项目里经常被问到AES-128够不够要不要上AES-256我的经验是对于安全启动AES-128在可预见的未来是足够的。原因在于安全启动的威胁模型里攻击者通常不具备大规模算力去暴力破解128位密钥。真正的风险点往往在密钥管理环节——密钥泄露、密钥硬编码、密钥传输不加密这些比算法强度问题严重得多。标签长度方面建议至少64位。我见过有项目为了省Flash把标签截断到32位理论上2^32分之一的伪造概率在量产百万级的场景下就不太稳妥了。64位是性价比比较平衡的选择。密钥本身必须是随机生成的不能用固定值。生成方式建议用HSM内置的TRNG真随机数发生器生成后写入HSM的密钥槽主核永远读不到明文密钥。3. 基于HSM的启动流程设计从复位向量到应用跳转3.1 信任链的建立BootROM是第一环安全启动的信任根必须不可篡改。这个不可篡改的起点就是芯片出厂时固化的BootROM。BootROM里包含一段只读代码上电后最先执行它负责初始化HSM让HSM进入工作状态从Flash的固定位置读取Bootloader固件和它的CMAC标签请求HSM用预置密钥计算Bootloader的CMAC与存储的标签比对比对通过跳转到Bootloader不通过进入安全失败处理这里有个关键设计点BootROM校验用的密钥必须存在HSM的OTP区域或者受保护的密钥槽里且在生产阶段一次性烧录之后不可读不可改。有些芯片支持密钥派生即用一个主密钥派生出多个子密钥分别用于不同固件这样主密钥只需烧录一次。BootROM的代码是芯片厂商提供的开发者改不了但可以通过配置字比如OTP里的启动模式位控制它的行为。这部分配置一定要在量产前确认清楚我见过有项目因为OTP配置错误导致BootROM跳过了校验直接启动安全启动形同虚设。3.2 Bootloader如何校验应用固件Bootloader拿到控制权后要做的事情和BootROM类似但对象换成了应用固件。流程大致如下/* 伪代码展示Bootloader校验应用固件的逻辑 */ typedef struct { uint32_t fw_start_addr; uint32_t fw_length; uint8_t cmac_tag[16]; /* 实际可能截断到8字节 */ uint32_t fw_version; uint32_t reserved; } fw_header_t; int verify_application(void) { fw_header_t *hdr (fw_header_t *)APP_HEADER_ADDR; /* 1. 版本合法性检查防回滚 */ if (hdr-fw_version get_min_allowed_version()) { return VERIFY_FAIL_ROLLBACK; } /* 2. 请求HSM计算CMAC */ hsm_cmac_request_t req; req.key_slot APP_VERIFY_KEY_SLOT; req.data_addr hdr-fw_start_addr; req.data_len hdr-fw_length; req.out_tag computed_tag; if (hsm_compute_cmac(req) ! HSM_OK) { return VERIFY_FAIL_HSM; } /* 3. 比对标签注意用恒定时间比较防时序攻击 */ if (constant_time_memcmp(computed_tag, hdr-cmac_tag, TAG_LEN) ! 0) { return VERIFY_FAIL_MISMATCH; } return VERIFY_OK; }这段逻辑里有几个容易踩坑的地方后面章节会展开。这里先强调一点CMAC计算的范围必须覆盖固件头和固件体但标签字段本身要排除在外。否则就成了用标签算标签的死循环。通常做法是把标签字段置零后再计算或者把标签放在计算范围之外。3.3 校验失败后的处理策略校验失败后怎么办直接复位进Bootloader等待重新刷写还是进安全模式这取决于产品形态。我的建议是分场景量产件校验失败后进入一个受限的恢复模式只允许通过经过认证的OTA通道重新刷写固件不允许通过调试口刷写。同时记录失败事件到HSM的防篡改计数器里。开发件可以配置成校验失败后仍允许启动但打上标记方便调试。这个配置必须在量产前关闭。安全关键件如刹车、转向校验失败后应进入安全状态比如限制输出、点亮故障灯而不是简单复位了事。有个细节要注意失败处理代码本身不能被篡改。如果攻击者能改掉失败处理逻辑让它假装校验通过那前面所有工作都白费。所以失败处理代码通常放在BootROM或HSM控制的区域里。4. 密钥管理安全启动里最容易翻车的一环4.1 密钥从哪来、存哪里、怎么用密钥管理是安全启动的命门。算法再强密钥泄露了全盘皆输。实际项目里密钥的生命周期大致是生成在安全环境里用TRNG生成或者由密钥管理系统KMS下发。绝不能用12345678这种固定值也不能用时间戳、芯片ID这类可预测的值。注入产线烧录阶段通过安全通道把密钥写入HSM的OTP或密钥槽。注入过程要防窃听、防重放。存储密钥存在HSM内部主核不可读。有些芯片支持密钥加密存储用芯片唯一密钥加密后存Flash启动时解密加载。使用主核通过HSM的API请求CMAC计算密钥始终不出HSM边界。更新密钥需要轮换时通过安全OTA通道更新。要支持新旧密钥并存一段时间避免更新过程中变砖。销毁产品退役或密钥泄露时触发密钥销毁流程让HSM里的密钥不可恢复。4.2 密钥槽的设计与分配HSM通常提供多个密钥槽Key Slot每个槽可以配置用途加密、认证、派生和访问权限。一个合理的分配方案密钥槽用途访问权限备注Slot 0BootROM校验Bootloader仅BootROM可读OTP烧录不可改Slot 1Bootloader校验应用Bootloader可请求支持OTA更新Slot 2OTA包认证Bootloader可请求与Slot 1分离Slot 3安全通信应用可请求运行时使用Slot 4密钥派生主密钥仅HSM内部用于派生其他密钥这样分配的好处是权限最小化每个密钥只用于一个目的一个密钥泄露不会影响其他环节。我见过有项目图省事所有校验共用一个密钥结果OTA密钥泄露后连BootROM的信任根都被波及。4.3 密钥更新与回滚保护的配合密钥更新和固件回滚保护要一起设计。常见做法是维护一个单调递增的版本号Monotonic Counter存在HSM的防篡改区域里。每次固件或密钥更新版本号加一。校验时不仅要比对CMAC还要检查版本号不低于当前记录值。这个计数器必须是只增不减的且不能被复位。HSM通常提供这类硬件计数器或者用OTP区域模拟。如果用普通Flash存版本号攻击者可以擦掉重写回滚保护就失效了。有个实际踩过的坑某项目用Flash存版本号结果产线返修时整片擦除版本号归零导致新固件因为版本号低于记录值而拒绝启动。后来改成用HSM的OTP区域存每次更新烧录一个bit虽然消耗OTP空间但确实可靠。5. 实测中的坑从启动失败到性能瓶颈5.1 启动时间超标CMAC计算到底要多久安全启动最直接的代价就是启动时间。CMAC计算本身不慢但加上Flash读取、HSM通信开销累积起来可能超出预期。实测数据以某TC3xx芯片、AES-128 CMAC、1MB固件为例环节耗时说明Flash读取1MB约15ms取决于Flash时钟和预取配置HSM通信分块传输约8ms每块16字节中断开销累积CMAC计算约5msAES硬件加速标签比对与跳转1ms可忽略合计约28ms未优化28ms对于大多数ECU可以接受但如果你的启动时间预算只有50ms那就很紧张了。优化方向增大HSM通信块大小不要16字节一传用DMA批量传输能省掉大量中断开销。并行处理Flash读取和CMAC计算可以流水线化读一块算一块。只校验关键区域如果固件很大但关键代码只占一部分可以只校验关键区域但这样会降低安全性要权衡。缓存校验结果对于支持快速启动的场景可以在第一次校验通过后把结果存到HSM的受保护区域下次启动直接读取。但这会引入校验结果被篡改的风险需要额外保护。5.2 标签比对用memcmp的时序攻击隐患这是个容易被忽略的细节。如果标签比对用标准的memcmp它会逐字节比较遇到第一个不匹配就返回。攻击者可以通过测量比对耗时逐字节猜出正确标签。虽然在实际攻击中难度较高但在安全认证里这是明确的扣分项。正确做法是用恒定时间比较int constant_time_memcmp(const uint8_t *a, const uint8_t *b, uint32_t len) { uint8_t diff 0; for (uint32_t i 0; i len; i) { diff | a[i] ^ b[i]; } return diff; /* 0表示相等 */ }这个函数无论哪里不匹配都会遍历完所有字节耗时恒定。编译器优化可能会把它改回短路比较所以要用volatile或者编译屏障保护。5.3 OTA升级与安全启动的衔接问题OTA升级时新固件先写到备份区校验通过后再切换。这里有个经典问题切换过程中断电怎么办如果切换是擦除旧固件→写入新固件→更新启动指针三步在第二步断电系统就变砖了。解决方案是双区A/B设计A区运行当前固件B区接收新固件新固件在B区校验通过后更新启动指针指向B区下次启动从B区运行同时把A区标记为可擦除如果B区启动失败回退到A区启动指针本身也要保护通常存在HSM控制的区域或者用CMAC保护。我见过有项目启动指针存在普通Flash里结果被篡改后指向了未校验的区域安全启动被绕过。5.4 调试口保护与量产配置开发阶段调试口是开着的量产必须关闭。但关闭方式有讲究完全禁用JTAG/SWD最安全但售后无法调试。适合安全关键件。密码保护需要密码才能连接调试口密码存在HSM里。适合需要售后诊断的件。生命周期状态机芯片通常有开发→量产→返修等状态不同状态下调试口权限不同。这是推荐做法。关键点是调试口保护配置必须和HSM的密钥烧录一起做且在OTP里锁定。我见过有项目量产时忘了锁OTP结果调试口一直开着安全启动等于没做。6. 从合规到落地功能安全与信息安全的交叉点6.1 ISO 21434对安全启动的要求ISO 21434是汽车网络安全的标准它对安全启动的要求可以归纳为几点信任根必须不可篡改BootROM和HSM的密钥存储要满足这个要求。启动链每一级都要校验不能只校验应用固件Bootloader本身也要校验。失败处理要安全校验失败不能静默通过要有明确的失败响应。密钥管理要有流程从生成到销毁的全生命周期管理。要有审计能力记录校验失败、密钥更新等事件。实际做认证时审核员会重点看你的威胁分析与风险评估TARA文档里面要说明你识别了哪些威胁、采取了哪些措施、残余风险是否可接受。安全启动通常是TARA里的一个关键缓解措施。6.2 与功能安全的配合ASIL等级的影响功能安全ISO 26262和信息安全ISO 21434在安全启动上有交叉。ASIL等级越高对安全启动的要求越严ASIL D通常要求HSM独立校验且校验逻辑本身要达到ASIL D。这意味着HSM的固件也要经过安全认证或者用双核锁步等方式保证。ASIL B可以用HSM校验但校验逻辑的失效模式要分析。QM信息安全措施可以相对宽松但基本的安全启动还是要做。有个实际问题是HSM本身的固件如果出bug可能导致校验误判。比如HSM固件有缺陷把正确的固件判成错误的导致车辆无法启动。这类风险在功能安全里叫误报需要通过冗余或自检来缓解。6.3 量产阶段的密钥注入与产线配合量产阶段的密钥注入是最容易出问题的环节。产线环境嘈杂操作人员流动性大密钥泄露风险高。建议的做法密钥不落地密钥由KMS生成后通过加密通道直接下发到烧录设备烧录设备直接写入芯片中间不经过任何可存储的介质。一机一密每颗芯片用不同的密钥或者至少每批次不同。这样一颗芯片的密钥泄露不会影响其他芯片。烧录后验证烧录完成后让HSM做一次自校验确认密钥可用。OTP锁定密钥写入后立即锁定OTP区域防止二次写入。产线日志审计记录每颗芯片的烧录时间、操作员、密钥版本便于追溯。我参与过一个项目产线为了图快把密钥写在U盘里插到烧录机上。后来U盘丢失整个批次的密钥都要作废重烧损失惨重。这个教训值得所有做量产的团队记住。7. 写在最后几个我踩过的坑和实用建议安全启动这个事原理不难难在落地细节。分享几个我实际踩过的坑希望能帮你少走弯路。第一个坑以为HSM配好了就万事大吉。实际上HSM的配置字、OTP烧录、生命周期状态任何一个环节出错都可能导致安全启动失效。建议在项目早期就做一次完整的攻击测试用调试器尝试篡改固件看能不能绕过校验。这个测试比看文档有用得多。第二个坑忽略启动时间的累积效应。单看CMAC计算只要几毫秒但加上Flash读取、HSM通信、多级校验累积起来可能超标。建议在架构设计阶段就把启动时间预算分配好每一级校验留多少时间心里有数。第三个坑密钥更新流程没设计好。很多项目只考虑了首次烧录没考虑后续密钥轮换。等到需要更新密钥时发现没有安全通道只能返厂。建议在项目初期就把密钥更新的OTA流程设计进去。第四个坑调试口保护忘了锁。这个前面提过但真的太常见了。量产前一定要有一份检查清单逐项确认OTP锁定、调试口关闭、生命周期状态切换。最后说个实用技巧在Bootloader里加一个校验日志功能把每次启动的校验结果、耗时、失败原因记录到HSM的受保护区域。出问题时这个日志是排查的第一手资料。我靠这个日志定位过好几次现场问题比猜快多了。安全启动不是一次性工作是贯穿芯片选型、架构设计、软件开发、量产烧录、售后维护的全生命周期工程。HSM和CMAC只是工具真正决定安全水平的是你对威胁模型的理解和对细节的把控。