4. 诊断会话与安全访问
在 UDS(ISO 14229)诊断中,0x10 诊断会话控制与 0x27 安全访问是几乎所有受保护操作的两道门槛。前者决定 ECU 当前“愿意提供哪些服务”,后者决定诊断仪是否“有资格执行这些服务”。在 Continental 的量产 ECU 上,这两者与刷写(0x34/0x36/0x37)之间存在严格的先后依赖:会话不对,安全访问会被拒绝;安全访问未通过,刷写请求会被 NRC 0x33(Security Access Denied)挡回。
一、0x10 诊断会话控制:权限的“档位”
0x10 服务通过子功能参数切换 ECU 的工作会话。常见会话如下:
| 子功能 | 会话名称 | 典型用途 |
|---|---|---|
| 0x01 | Default(默认会话) | 上电默认状态,仅开放读取类服务 |
| 0x02 | Programming(编程会话) | 刷写前置,允许 0x34/0x36/0x37 |
| 0x03 | Extended(扩展会话) | 执行例程、写数据、IO 控制 |
| 0x04 | Safety System(安全系统会话) | 安全气囊等特殊系统 |
请求格式为 10 02,肯定响应为 50 02 00 32 01 F4。其中 00 32 是 P2server(默认 50 ms),01 F4 是 P2*server(默认 5000 ms),单位均为毫秒。这两个参数决定了诊断仪等待响应的超时时间,在刷写场景中通常会被 ECU 主动延长。
会话切换的关键约束:ECU 在收到 0x10 请求后,会先检查当前会话是否允许切换到目标会话。例如从 Default 直接跳到 Programming 通常被允许,但从 Programming 回到 Default 后,之前的安全访问状态会被清除。此外,多数 ECU 设有 S3 定时器(默认 5000 ms),若在 S3 时间内没有收到任何诊断请求,ECU 会自动回落到 Default 会话,安全访问状态一并失效。
二、0x27 安全访问:种子与密钥的握手
0x27 服务采用“挑战—应答”机制,流程分为两步:
- 请求种子:诊断仪发送
27 01(奇数子功能),ECU 返回67 01加若干字节的种子(Seed),例如67 01 A3 5F 12 8C。 - 发送密钥:诊断仪用约定的安全算法对种子计算,得到密钥(Key),发送
27 02 <Key>(偶数子功能)。ECU 用相同算法验证,正确则返回67 02,安全访问解锁。
若密钥错误,ECU 返回 NRC 0x35(Invalid Key)。连续多次失败后,ECU 会启动 延时锁定(NRC 0x37 Required Time Delay Not Expired),通常每次失败延时递增,例如 10 s、20 s、40 s……直到达到上限。这个机制用于防止暴力破解。
三、Continental 安全算法变体
Continental 不同代际、不同客户项目的 ECU 使用不同的安全算法。常见变体包括:
- 固定密钥:种子被忽略,密钥为常量。仅用于早期或低安全等级 ECU,现已少见。
- 查表/异或类:密钥 = 种子与固定掩码逐字节异或,或经过简单字节置换。逆向难度低,常见于车身控制器。
- 基于 AES-128 的算法:以种子和 ECU 内部密钥为输入,经 AES 加密或 CMAC 计算得到密钥。这是当前 Continental 动力总成与域控制器的主流方案。
- 多级安全等级:同一 ECU 提供多组 0x27 子功能(如 0x01/0x02 对应 Level 1,0x11/0x12 对应 Level 2),不同等级对应不同算法和不同权限范围。
实际项目中,算法通常以 DLL 或 SO 库形式由 Continental 提供给整车厂和诊断仪供应商,诊断仪在运行时调用该库的 GenerateKey(seed, level) 接口。因此,诊断仪本身不“知道”算法,而是调用授权库。这也是为什么刷写工具必须使用与目标 ECU 匹配的算法库版本,版本错配会直接导致 0x27 失败。
四、权限等级与刷写前置条件
权限等级是会话与安全访问的组合结果。以典型 Continental 发动机 ECU 为例:
| 权限等级 | 所需会话 | 所需安全等级 | 可执行操作 |
|---|---|---|---|
| Level 0 | Default | 无 | 0x22 读数据、0x19 读 DTC |
| Level 1 | Extended | 0x27 01/02 | 0x2E 写数据、0x31 例程 |
| Level 2 | Programming | 0x27 11/12 | 0x34/0x36/0x37 刷写 |
刷写前置条件可归纳为一条链:进入扩展会话 → 安全访问 Level 1 → 执行刷写前置例程(如 0x31 01 FF00 检查编程条件)→ 切换到编程会话 → 安全访问 Level 2 → 开始 0x34 请求下载。任何一步失败,后续请求都会被拒绝。
五、实操中的关键判断
在诊断仪侧,一次完整的刷写前置流程通常如下(以示例参数说明):
发送: 10 03 → 响应: 50 03 00 32 01 F4
发送: 27 01 → 响应: 67 01 A3 5F 12 8C
计算: Key = Algo(Seed, Level1)
发送: 27 02 XX XX XX XX → 响应: 67 02
发送: 31 01 FF00 → 响应: 71 01 FF00 00 (条件满足)
发送: 10 02 → 响应: 50 02 00 32 01 F4
发送: 27 11 → 响应: 67 11 <Seed2>
计算: Key2 = Algo(Seed2, Level2)
发送: 27 12 XX XX XX XX → 响应: 67 12
发送: 34 ... → 响应: 74 ... (开始下载)
判断依据:每一步的肯定响应 SID 必须是请求 SID + 0x40。若收到 0x7F,需读取第三个字节的 NRC 定位原因。常见 NRC 包括:0x13(报文长度或格式错误)、0x22(条件不满足)、0x33(安全拒绝)、0x35(密钥无效)、0x37(延时未到)、0x78(响应挂起,需继续等待)。
最后需要强调:会话与安全访问不是孤立的两个服务,而是一条权限链。0x10 决定“门开在哪”,0x27 决定“钥匙对不对”,两者共同决定 ECU 是否接受刷写请求。理解这条链的顺序、超时和失败分支,是 Continental UDS 刷写工程中最基础也最关键的一环。