公司动态
UDS 0x27 安全访问:ECU 秘钥握手到底怎么握
做 ECU 的都知道读个版本号、读个故障码无所谓但刷写程序、写 VIN/序列号、改关键标定这种危险操作绝不能谁拿个诊断仪都能干。UDS 里管这道门的就是0x27 安全访问Security Access。很多项目里 0x27 只是摆设seed 写死成固定值、key 算法等于没加密、错了也不锁。本文把它从协议流程到 ECU 落地讲透让你能设计出真正扛得住的握手。一、为什么需要它分级管控0x27 不是开/关一个总闸而是按安全等级分级。比如默认会话只允许读一级解锁01/02允许写普通参数二级解锁03/04允许进编程会话、刷写三级05/06更高权限如产线终检子功能成对出现奇数请求 seed偶数提交 key。低等级解锁后高等级服务仍要再解权限粒度才可控。二、握手流程真实报文诊断仪 → ECU 27 01 // 请求一级 seedECU → 诊断仪 67 01 [seed] // 返回随机数 seed常 4 字节诊断仪算 key key Algo(seed, Secret)诊断仪 → ECU 27 02 [key] // 提交 keyECU 校验 67 02 // 通过或 7F 27 35 // key 无效NRC0x35seed 和 key 的长度、算法两端必须预先约定一致——算法烧在 ECU 里等价实现常是 DLL发给授权诊断仪。三、Seed真随机 防重放最经典的漏洞就是 seed 写死或顺序递增。攻击者抓几次包就能反推 key 算法甚至直接重放旧 seed/key 登录。正确做法用硬件随机数 TRNG生成没有 TRNG 也要用带时间戳/计数器的 PRNG。连续两次请求不能返回相同 seed规范没强制但工程必防重放。解锁成功后该 seed 立即作废下次必须重新请求。四、Key 算法四档别停在摆设级最弱key seed 常数、key ~seed。一眼被逆纯走过场。常见key f(seed, 整车厂 Secret)如多轮移位异或、查表、自定义混淆。OEM 把算法烧进 ECU把 DLL 发给授权工具。较安全基于 AES-128 等分组密码seed 作明文/IV、Secret 作密钥输出作 key或 HMAC。抗逆向能力强。前沿非对称 PKIECU 持私钥对 challenge 签名诊断仪用公钥验——适合 EV/ADAS 高安全。五、必须上防暴破失败计数连错 N 次常 3 次锁死回 NRC0x36exceeded attempts需下电或特殊流程解。时间延迟连续失败回 NRC0x37required time delay not expired强制诊断仪等待拖慢暴力。解锁即废 seed再次访问要重新走一遍握手。六、ECU 端最小实现骨架uint8_t seed[4], last[4];void gen_seed(void){do {trng_read(seed, 4);} while (!memcmp(seed, last, 4)); // 防重复memcpy(last, seed, 4);}bool verify_key(uint8_t *key){uint8_t expect[4];key_algo(seed, SECRET, expect); // 与诊断仪同一套if (fail_cnt 3){locked true; // 防暴破}return !locked !memcmp(key, expect, 4);}七、工程坑Secret 别裸奔算法和密钥放 Bootloader 受保护区别和 App 一起躺在可读 Flash。刷完要重新上锁或复位回默认会话别留高权限。诊断仪 DLL 也要管OEM 给第三方的算法 DLL 要授权泄露等于门户大开。长度取舍4 字节够日常高安全用 8 字节以上增大暴力成本。结语0x27 看着就两个子功能真要做稳随机性、算法强度、防暴破、密钥保护每一处都是工程活。设计好了它是 ECU 的安全闸门设计烂了它就是个安慰自己的摆设。