UDS诊断详解(二)27服务安全访问流程
一、安全访问流程概述
1、请求种子
上位机向ECU发送请求(27+SF),ECU返回Seed。
Note:种子字节数需要注意,通常是4个字节,也可能是其他字节数,具体需要关注需求
2、发送密钥
上位机收到Seed后,计算出一个密钥发送给ECU,ECU根据同样的算法计算一个密钥,两数值匹配通过

上位机向ECU发送请求(27+SF),ECU计算出一个种子,可能是一个随机表,ECU将种子返回给上位机Tester,上位机收到种子,通过一个特定的算法,种子作为参数,来计算出一个密钥(Key1),然后将密钥发送给ECU,27+(SF+1)+Key,规定了请求种子的子功能是奇数,发送密钥的子功能是请求种子的子功能+1,也就是一个偶数。这时候ECU也不闲着,ECU也通过相同的算法计算一个Key2,如果Key1和Key2比较,相同的话,就返回67 +(SF+1),表示肯定响应,表示安全访问通过,把lock解开,达到安全等级,解锁一些相应的服务,以及允许访问一些参数。如果不相同,则否定相应7F+27+NRC。
二、安全访问流程中的安全等级、种子、密钥
任意时刻,仅有一个安全级别可以被激活;安全级别的数字是任意分配的,没有优先级之分;比如说有三个安全等级:LV1\LV2\LV3 LV1允许你做操作A,LV2允许你做操作B,LV3允许你做操作C,假如你解锁了LV1,那么LV2和LV3的操作是无法执行的,三个等级是平等的,任一安全级别被激活,则其他两个安全级别无法被激活或操作
种子的值为ECU随机产生(一般4个字节,也可以是其他字节数),应避开0和最大值F——全0的种子常用来检测当前是否已经解锁,已解锁状态下请求种子时将会返回全0的种子;
上图请求种子及发送密钥的动作流程是强制性(01、02)的,当ECU返回否定响应、或者因为其他原因导致诊断会话模式回到默认会话模式,种子将重新生成。
27服务(SecurityAccess)请求种子通常需要在非默认会话下进行,具体会话要求如下:
扩展会话(0x10 03):大多数ECU要求首先通过10服务进入扩展会话后才能执行27服务的种子请求,这是最常见的应用场景,例如在写入Flash数据或执行重要诊断操作前需先通过扩展会话解锁安全访问
编程会话(0x10 02):部分ECU(如刷写场景)可能要求在编程会话中请求种子,此时安全等级与扩展会话不同,需单独解锁,编程会话通常用于软件更新等高权限操作
会话切换影响:若从扩展会话切换到相同非默认会话(如再次发送10 03),已解锁的安全等级可能保持有效,此时请求种子可能返回全0响应,但切换到不同会话(如从扩展会话到编程会话)需重新请求种子
默认会话限制:ECU上电后默认处于默认会话(0x10 01),此时直接请求27服务通常会被拒绝,需先切换至非默认会话
三、请求格式
请求种子:27 + SF(01)
肯定响应:67 + SF(01) + Seed
否定响应:7F + SF(01)+ NRC1
发送密钥:27 + (SF + 1) + Key
肯定响应:67 +(SF + 1)
否定响应:7F + (SF + 1) + NRC2
注意:
请求种子的子功能SF是奇数(0x01、0x03、0x11等),对应的发送密钥的子功能是请求种子的子功能+1(0x02、0x04、0x12等);
NRC1处:12子功能不支持、13报文长度错误、22条件未满足、37延迟时间未到
12:子功能不支持
例如:
假如扩展会话下支持01 03
请求种子:27 + 05 (不支持的子功能)
否定响应:7F + 05 +12
NRC2处:12、13、22、24请求序列错误、35密钥错误、36超出访问次数限制
24:请求序列错误
比如在没有请求种子的情况下,直接发送27 02(发送密钥),会出现请求序列错误
35:密钥错误
Key1和Key2不相等
36:超出访问次数限制
比如允许你错3次,你正好错误达到三次,就会返回NRC 36
四、延迟机制(NRC=36、37)——防止多次请求,暴力遍历
在x次请求安全访问失败后,返回NRC=36,需要等待y秒后再能接受下一次安全访问请求,请求种子,在ECU被成功进行一次解锁后,错误计数器归零。
错误计数器:初始值为0,每当“出错”就+1,达到某个阈值后不允许安全访问请求,请求种子返回否定响应,NRC=37;
错误计数器计数的场景:
1)错误计数器从0开始,出现一次NRC=35,错误计数器就会加1(Att_Cnt+1),假如最大值是3,则会出现此种情况:35 35 36
2)返回NRC=24(请求序列错误)
错误延时时间
达到错误计数器最大值,即NRC=36后。再次请求seed,返回NRC=37,指的是错误延时时间未到(比如说错误延时时间是10秒,在请求次数达到错误计数器最大值时,即NRC=36,此时要在10秒之后继续请求Seed,ECU才能发送一个Seed,如果在10秒之内请求Seed,ECU发出否定响应NRC=37)
掉电前,错误计数器达到最大值,则上电后错误计数器仍为最大值,需要等待延时,比如等待10秒,才能继续请求种子
假如延时10秒,错误计数器最大值为3次,若一直请求错误密钥,返回NRC=35,错误密钥请求第一次,NRC=35,错误密钥请求第二次,NRC=35,错误密钥请求第三次,NRC=36,若在延时时间10秒之内请求密钥,则返回NRC=37,这个时候重新刷新延时,再等10秒,等了10秒结束,情况1,如果错误计数器减1,再次请求,返回NRC=36,情况2,如果错误计数器清零,则返回NRC=35

初始状态下,错误计数器是0,没有开启延时,ECU状态是锁住的状态,没有任何安全等级解锁,第一次请求错误密钥,返回NRC=35,错误计数器加1,再次请求错误密钥,返回NRC=35,错误计数器再次加1,若是请求了正确了密钥,通过了安全访问,错误计数器清零,假如下一次回到默认会话,或者再请求其他的安全等级,比如之前进的是27 01、27 02,现在请求27 03、27 04,请求了一个错误的27 04的密钥,错误计数器加1,连续请求三次,错误计数器达到3,到3以后,开启延时,在延时还未关闭之前(未达到10秒),请求了一次Seed,返回NRC=37,错误计数器依然是3,并继续延时10秒,延时到,错误计数器减1,下次再次请求一次错误密钥,返回NRC=36,延时再次开启,若在10s内请求Seed,返回NRC=37

状态A:所有的安全等级都没解锁,未请求Seed
状态B:所有的安全等级都没解锁,Seed已请求到,ECU在等待上位机发送密钥
状态C:收到密钥了,安全等级已解锁,但是没有发送新的种子(无论是当前安全等级的种子或者其他安全等级的种子)
状态D:解锁了,发送种子了(有可能是本身,比如等级1,后面又收到一个等级1的种子请求,则回一个全0,再比如等级1,后面又收到一个进等级3的种子请求,给了它一个种子),在等一个新的密钥
(1) Reset→A
当启动/重启ECU,进行初始化,初始化进入的一个默认状态就是A状态,执行:
①初始化错误计数器(根据需求)
②启动延时(如果上一次错误计数器等于3的话,就是达到最大值了,需求让启动延时就启动延时,如果不需要,那就不启动)
(2) A→B
当上位机收到Seed或者ECU发送Seed。
且:DLC格式(要4个字节的Seed,就返回4个字节的Seed)
先决条件(例如满足车速条件等)
延时已过(连续请求三次密钥,要等10s,10s过了)
将种子存在一个存储器里,并且存储子功能,方便下一次上位机发送密钥的时候,进行对比,看是否是同一个子功能
(3) B→C
ECU收到密钥,且子功能为请求种子的子功能+1,例如27 01 →27 02,DTC格式无问题,Key正确
执行:
① 错误计数器清零,并存非易失性存储器中(不同的安全等级有不同的错误计数器)
② 解锁对应安全等级,并清除存储的Seed
③ 返回肯定响应
(4)B→B
Static-Seed:布尔值,1表示连续请求种子相同,0表示不同
① 种子不同,ECU收到请求种子报文,生成新种子,保存子功能(安全等级类型)
② 种子相同,返回上次存储的种子
③ 种子相同,生成种子并存储
(5)D→A C→A
当诊断会话超时,回默认会话,锁定所有安全等级