4. 诊断会话与安全访问

在 UDS(ISO 14229)诊断中,0x10 诊断会话控制与 0x27 安全访问是几乎所有受保护操作的两道门槛。前者决定 ECU 当前“愿意提供哪些服务”,后者决定诊断仪是否“有资格执行这些服务”。在 Continental 的量产 ECU 上,这两者与刷写(0x34/0x36/0x37)之间存在严格的先后依赖:会话不对,安全访问会被拒绝;安全访问未通过,刷写请求会被 NRC 0x33(Security Access Denied)挡回。

一、0x10 诊断会话控制:权限的“档位”

0x10 服务通过子功能参数切换 ECU 的工作会话。常见会话如下:

子功能会话名称典型用途
0x01Default(默认会话)上电默认状态,仅开放读取类服务
0x02Programming(编程会话)刷写前置,允许 0x34/0x36/0x37
0x03Extended(扩展会话)执行例程、写数据、IO 控制
0x04Safety 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 服务采用“挑战—应答”机制,流程分为两步:

  1. 请求种子:诊断仪发送 27 01(奇数子功能),ECU 返回 67 01 加若干字节的种子(Seed),例如 67 01 A3 5F 12 8C。
  2. 发送密钥:诊断仪用约定的安全算法对种子计算,得到密钥(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……直到达到上限。这个机制用于防止暴力破解。

注意:种子每次请求都会变化,密钥必须基于当次种子实时计算,不能缓存上一次的密钥。若在 S3 超时后重发密钥,会因会话回落而收到 NRC 0x7F 或 0x33。

三、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 0Default无0x22 读数据、0x19 读 DTC
Level 1Extended0x27 01/020x2E 写数据、0x31 例程
Level 2Programming0x27 11/120x34/0x36/0x37 刷写

刷写前置条件可归纳为一条链:进入扩展会话 → 安全访问 Level 1 → 执行刷写前置例程(如 0x31 01 FF00 检查编程条件)→ 切换到编程会话 → 安全访问 Level 2 → 开始 0x34 请求下载。任何一步失败,后续请求都会被拒绝。

0x10 会话 + 0x27 安全访问 → 刷写权限链 会话状态(0x10) Default (0x01) Extended (0x03) Programming (0x02) 安全访问(0x27) 27 01 → 67 01 Seed 算法计算 Key 27 02 Key → 67 02 权限等级 Level 0:只读 Level 1:写数据/例程 Level 2:刷写 会话允许 解锁 刷写前置条件链(顺序不可颠倒) 10 03 扩展会话 27 01/02 安全 Level 1 31 01 FF00 编程条件检查 10 02 编程会话 27 11/12 安全 Level 2 任一步失败 → NRC 0x33 / 0x35 / 0x37 / 0x7F 刷写请求被拒绝,需重新从会话切换开始 S3 超时(默认 5000 ms)会导致会话回落,安全状态清除

五、实操中的关键判断

在诊断仪侧,一次完整的刷写前置流程通常如下(以示例参数说明):

发送: 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(响应挂起,需继续等待)。

在 Continental 项目中,0x27 的种子长度和算法等级由 ECU 的诊断描述文件(CDD/ODX)定义。刷写工具应优先从 ODX 中读取安全等级和算法库引用,而不是硬编码子功能号,否则换项目时极易出错。

最后需要强调:会话与安全访问不是孤立的两个服务,而是一条权限链。0x10 决定“门开在哪”,0x27 决定“钥匙对不对”,两者共同决定 ECU 是否接受刷写请求。理解这条链的顺序、超时和失败分支,是 Continental UDS 刷写工程中最基础也最关键的一环。