4、安全访问(0x27):种子与密钥机制、安全等级划分、常见的刷写安全解锁流程

好,咱们接着聊。前面几章我们把刷写的基础流程和诊断会话管理讲透了。这一章,我要重点聊聊安全访问——也就是 0x27 服务。

说实话,在 OTA 刷写里,安全访问是真正的一道「鬼门关」。很多刷写失败,不是协议没走对,而是安全解锁这一步卡住了。我自己就踩过不少坑,今天把这些经验都抖出来。

4.1 为什么需要安全访问?

你想想看,一辆车的 ECU 要是谁都能随便刷写,那还得了?

安全访问的目的很简单:防止未经授权的刷写操作。说白了,就是给 ECU 加一把锁。只有拿着正确钥匙的人,才能打开这扇门。

我记得有一次,客户反馈说刷写过程中突然中断,ECU 变砖了。查了半天,发现是安全访问的种子和密钥对不上,导致 ECU 进入了锁定状态。嗯,从那以后,我对安全访问的流程就格外小心。

4.2 种子与密钥机制

安全访问的核心机制,就是「种子与密钥」的挑战-应答模式。流程大概是这样的:

  1. 客户端请求种子:Tester 发送 0x27 服务,请求种子。
  2. ECU 返回种子:ECU 生成一个随机数(种子),返回给 Tester。
  3. 客户端计算密钥:Tester 用种子和约定的算法,计算出密钥。
  4. 客户端发送密钥:Tester 把密钥发回给 ECU。
  5. ECU 验证密钥:ECU 用同样的算法计算,比对密钥是否一致。
  6. 解锁成功/失败:一致则解锁,不一致则锁定一段时间。

这里有个细节:种子是随机生成的,每次都不一样。这就防止了重放攻击。你截获了一次密钥,下次用同样的密钥是没用的。

核心要点:种子和密钥的算法,是 OEM 自己定义的。有的用 AES,有的用自定义的异或算法。我见过最奇葩的,是把种子倒序再取反,然后加上一个固定偏移。嗯,安全强度嘛……只能说聊胜于无。

4.3 安全等级划分

ECU 的安全访问,通常不是一把锁,而是好几把锁。不同的操作,需要不同的安全等级。

常见的等级划分是这样的:

安全等级 典型用途 解锁方式
Level 1 读取诊断数据、清除故障码 简单种子-密钥(甚至不需要)
Level 2 写入配置、标定数据 标准种子-密钥
Level 3 刷写应用程序、Bootloader 高强度种子-密钥(可能结合硬件加密)
Level 4 刷写 Bootloader 本身 需要物理授权或特殊工具

我个人习惯,在项目初期就确认好每个 ECU 的安全等级划分。因为不同等级对应的刷写流程完全不同。有一次,我遇到一个 ECU,刷写应用程序需要 Level 3,但刷写 Bootloader 需要 Level 4。结果测试团队一直用 Level 3 去刷 Bootloader,卡了好几天。后来我一看,安全等级没对上。

我的建议:在刷写流程设计阶段,就把每个 ECU 的安全等级矩阵画出来。哪个操作对应哪个等级,一目了然。别等到测试了才发现问题。

4.4 常见的刷写安全解锁流程

好了,咱们进入实战环节。一个典型的刷写安全解锁流程,大概是这样的:

4.4.1 第一步:进入扩展会话

刷写前,必须先进入扩展会话(0x10 03)。这是前提条件。有些 ECU 在默认会话下,连安全访问的请求都不接受。

4.4.2 第二步:请求种子

发送 0x27 服务,子功能通常是 0x01(请求种子)。ECU 返回的种子,长度可能是 4 字节、8 字节,甚至更长。

// 请求种子示例
// 发送:02 27 01
// 响应:06 67 01 12 34 56 78
// 种子为:12 34 56 78

4.4.3 第三步:计算密钥

拿到种子后,Tester 端用约定的算法计算密钥。这个算法,OEM 通常会提供 DLL 或者文档。我建议你写一个独立的密钥计算模块,方便测试和调试。

// 伪代码示例:简单的异或算法
uint32_t calculateKey(uint32_t seed) {
    // 这是我见过的一种简单算法
    // 种子取反,然后加上固定偏移 0xA5A5A5A5
    return (~seed) + 0xA5A5A5A5;
}

注意:实际项目中,算法往往复杂得多。我曾经遇到一个 ECU,密钥计算需要用到硬件加密芯片。Tester 端必须模拟同样的加密流程,否则密钥永远对不上。嗯,那一次排查了整整两天。

4.4.4 第四步:发送密钥

计算好密钥后,发送 0x27 服务,子功能 0x02(发送密钥)。

// 发送密钥示例
// 发送:06 27 02 5A 5B 5C 5D
// 响应:02 67 02

如果响应是 0x67 02,说明解锁成功。如果响应是 0x7F 27 35(无效密钥),说明密钥不对,需要重新请求种子。

4.4.5 第五步:执行刷写操作

解锁成功后,就可以进行刷写了。但要注意:安全解锁是有时效的。有些 ECU 解锁后,如果一段时间内没有操作,会自动锁定。所以,解锁后要尽快开始刷写。

4.5 避坑指南

最后,我分享几个实战中遇到的坑:

  • 种子过期:有些 ECU 的种子有有效期,比如 5 秒内必须发送密钥。超时了,种子就失效了。我曾经遇到一个 ECU,种子有效期只有 2 秒,网络稍微一延迟就超时。后来我们优化了网络延迟,才解决。
  • 锁定时间:连续多次密钥错误,ECU 会进入锁定状态,比如锁定 30 秒甚至 5 分钟。刷写流程中,一定要处理这种异常情况。
  • 多 ECU 解锁:在 OTA 刷写中,可能需要同时解锁多个 ECU。这时候要注意,每个 ECU 的种子和密钥是独立的,不能混用。
  • 安全等级混淆:同一个 ECU,刷写应用程序和刷写配置数据,可能对应不同的安全等级。搞混了,解锁失败是小事,把 ECU 刷成砖就麻烦了。

总结一下:安全访问是 OTA 刷写的「守门员」。种子与密钥机制、安全等级划分、解锁流程,这三个环节环环相扣。任何一个环节出问题,刷写都进行不下去。我个人建议,在项目初期就建立一套安全访问的测试用例,覆盖各种异常场景。这样,到了实车测试阶段,才能少踩坑。

好,这一章就到这里。下一章,咱们聊聊刷写过程中的数据传输和完整性校验。那又是另一个有意思的话题了。