[行业规范] 车载诊断之Security(安全解锁模式)汇总

[复制链接]
查看1663 | 回复0 | 2022-6-18 16:38:15 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册 |

x
车载诊断之Security(安全解锁模式)汇总

车载诊断技术 牌照.jpg
今天是2022年6月18日,魔都天气晴朗,蓝天白云,久违的好天气,早上做核酸的不悦一扫而空。2022年马上过去一半,自己在新的岗位已经逐步适应和上手,想象去年这个时候还在为跳槽与否忧愁,不由得感叹时间在时下的年纪真的不经过,如掌中沙,想抓住却总不能如愿。
分享一段喜欢的文字,避免自己成为高知识低文化的人:

等待是思维的一种状态,意味着自己需要未来,而自己不要现在。自己不要此时此刻,却把希望寄托于未来。丧失了对当下时刻的意识,会大大降低自己生命质量

Return to today's topic!
最近工作上需要对车载诊断安全访问(Security Access)中需求定义、功能实现、功能测试做一个梳理,鉴于此,在这里也用文字整理,便于自己后续查阅。
大体内容如下:
-> 诊断规范安全访问需求定义
-> 常用工具关于安全访问(诊断数据库)编辑
-> 安全访问功能实现
-> 安全访问测试
诊断规范安全访问需求定义
在进行诊断请求时,除了通过会话模式区分执行权限外,有些服务的执行Pre-condition需要控制器进行解锁动作(也就是这次话题安全访问),常见的服务有2E、2F、31等,目的是防止外界人员恶意破坏车辆功能。
a086bac8-85bc-44ad-950a-0eddbf927fba.png

DS协议定义了一些服务执行后会对控制器属性造成影响,执行这些服务需要满足前置条件——解锁,对应UDS中服务是Service 27。服务格式在UDS协议中定义如下(请求格式、响应格式都做了详细的定义):
1.png
2.png
3.png

对于Subfunction,协议也有详细定义:
4.png

在定义控制器的诊断需求规范时,根据需要可定义多个解锁安全等级,每一个安全等级可自由跳转切换(根据需求):
5.png

注:

1、定义了两个安全等级:Unlocked Level 1、Unlocked Level 2。在此例子中,Unlocked Level2只允许在解锁Unlocked Level 1条件下,才可以进行Level 2的解锁动作,可立理解为双保险。但实际经历过大多数项目中,一般定义两个安全等级,只会区分一个适用于Application,一个适用于Bootloader。


2、进行会话模式切换以及控制器Reset重启,对控制器解锁状态有影响:
(1)、若控制器当前处于解锁状态,Tester对其进行会话模式切换,控制器会从解锁状态跳转到锁住状态(尤其注意当前会话是扩展会话模式,Tester发送10 03控制器也会跳转到锁住状态);
(2)、当前控制器处于解锁状态,Tester发送了Service 11进行Reset操作,控制器在重启后同样会从解锁状态跳转到锁住状态;

这些需求都会在诊断需求规范中明确定义,对于供应商,会有诊断需求调查表释放,明确规定具体那些服务的执行权限(需要在解锁状态才可以进行数据交互)、定义该项目中有多少安全等级、定义该项目Seed&Key具体多少位数(多少Bytes)以及转换关系等等。
常用工具关于安全访问(诊断数据库)编辑
诊断数据库业界最常用的是CDD/ODX(PDX是其打包格式),关于CDD文件、ODX文件具体内容可以参看如下文字:
链接:《车载诊断技术》2021年CANdelaStudio操作指南集
诊断数据库ODX文章汇总
数据库现在优势大致分为如下:
1、贯穿车载开发全流程,保证诊断数据的一致性和有效性(避免整个过程中诸多工程师主管解读);
2、通过数据库可以加载代码配置工具中,可自动匹配代码框架中诊断描述内容;
3、将诊断数据库加载到相应的测试工具和售后诊断仪中,解析相应诊断内容。
CDD是Vector公司私有格式,鉴于业界使用较多,编辑起来又极其简单,通用性较强。ODX是ISO 22901协议定义的通用性诊断数据库格式,国内除了几个合资企业,能完全玩转的不是很多。这里暂且以CANdelaStudio工具编辑诊断数据库CDD文件为例,描述编辑过程,仅供参考:
首先对Service 27是成对存在:
奇数位请求Seed
偶数维发送Key(计算Key后发送验证)
在编辑诊断数据库CDD文件时,基于项目中所涉及ECU的诊断需求规范中定义Service 27安全等级,比如下面例子,定义了两个安全等级:
1、Unlocked 1(对应子服务01)
2、Unlocked 5(对应子服务05)
举例请求格式:
6.png

举例响应格式:
7.png

其中可知:Seed,Key都是4 bytes
8.png

其中需要名称(定义完善,且最好不要有中文)、Seed-key的长度
9.png
10.png

另外一个操作步骤类同,并按大小排列:

注:日常在编辑CDD数据库中发现如下一个问题,如果我新建的Service 27 subfunction 11,会有如下报错
11.png

其实是工具中定义Service 27 Subfunction data type时,做了设置,你只需要将自己所需要新添加的子服务在里面添加完善
12.png

添加后就没有错误咯!!!
14.png

因为安全访问是诊断范畴重要的两个状态机之一,也决定了诊断服务执行与否的判断条件。因此在编辑数据库CDD文件时另一个易错点是编辑安全访问服务执行状态。
15.png

在如图上位机进行属性编辑时,需要注意:
1、判定该服务该ECU当前状态下是否支持(是否可以执行)?
2、执行完该服务,对当前ECU状态是否会造成状态影响?
较为特殊的有两方面:
a.ECU当前出于解锁状态,执行完该服务对ECU解锁状态有影响的服务:
A:Service 10
B:Service 11
ECU处于解锁状态时,Tester发送会话模式切换或ECU重启,ECU都会从解锁状态跳转到锁住状态。
注:ECU当前处于扩展会话模式并且解锁状态,这个时候Tester发送10 03请求,这个时候ECU仍然要从解锁状态跳转到锁住状态。
16.png

b.ECU当前处于锁住状态,Tester发送Service 27+Key,这个时候从Locked跳转到Unlocked
17.png

安全访问功能实现
现在业界通用车载协议栈是AUTOSAR,其按照模块实现不同的功能。现阶段通过配置工具自动生成协议栈在行业内的比重逐步增加,手写代码框架比重几乎已经绝迹,这里简单以如下示意图,概述ECU解锁过程:
18.png

通过配置工具配置BSW模块诊断功能,具体模块是DCM(仅限于安全解锁,涉及到DTC相关也有DEM,后续会分享)。在该模块中配置Service 27以及对应项目中需要的子服务、Seed & Key长度(多少Bytes)以及对应转换关系。
concept-4903028.jpg
当Tester发送Service 27 01(实例化),获取Seed,生成Key发送ECU验证过程中有如下函数:
GetSeed:DcmDspSecurityGetSeedFnc从此函数获取Seed值;
Compare key:Xxx_CompareKey对比ECU内部生成Key和上位机生成的Key值;
AttemptConuter:GetSecurityAttemptCounter定义Tester进行解锁尝试的次数;
SetSecurityAttemptCounter:设置尝试次数;
相当于BSW与RTE进行交互,获取对应参数值。这里需要类似于系统设计工具,设计整个数据链路:
一般是C/S接口类型,定义P/R Port类型(P_Port是功能提供端,R_Port为服务请求端),将Port口、Runnable、Event链接关联关系在工具配置好,这样自动生成的代码就会直接调用。这样在RTE端自动生成的API接口,研发工程师只需要根据需求进行开发具体功能即可,有较强的代码稳健性。
安全访问测试
这里测试暂且以CANoe工具CAPL(CANoe专用测试脚本)为例,分享下测试实现过程:
首先新建CANoe工程,并新建Test Module(充当Tester)和仿真节点
19.png

如上图,Tester工程如下:
variables { char keyQual[30]; byte seedArray[4]; byte generatedKey[100]; dword actLen; }
void mainTest() { long waitKeyRes; diagSetTarget("VCU");
Sendrequest1(); testWaitForTimeout(1000);
Sendrequest2();
testWaitForTimeout(1000); waitKeyRes=TestWaitForGenerateKeyFromSeed( seedArray, elcount( seedArray), 1, generatedKey, elcount(generatedKey), actLen, 10000);
write("waitKeyRes=%d,Key is (hex) %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",waitKeyRes,generatedKey[0],generatedKey[1],generatedKey[2],generatedKey[3],generatedKey[4],generatedKey[5],generatedKey[6],generatedKey[7],generatedKey[8],generatedKey[9],generatedKey[10],generatedKey[11],generatedKey[12],generatedKey[13],generatedKey[14],generatedKey[15]);
}
void Sendrequest1() { DiagRequest VCU.ExtendedDiagnosticSession_Start request1;
DiagSendRequest(request1);
testWaitForTimeout(1000);
}
void Sendrequest2() { DiagRequest VCU.requestSeed_1_Request request2;
DiagSendRequest(request2);
testWaitForTimeout(1000); }
on diagResponse VCU.requestSeed_1_Request { long ret;
char buffer[100];
write("Go in this function"); if(DiagIsPositiveResponse(this)) { ret=DiagGetParameterRaw(this,"SecuritySeed",seedArray,elcount(seedArray));
if(ret>=0)
{
  write("Seed is (hex) %02X %02X %02X %02X",seedArray[0],seedArray[1],seedArray[2],seedArray[3]);
    snprintf(keyQual, elCount(keyQual), "KeyLevel_0x01_Send");
  
  
  
  ret=DiagStartGenerateKeyFromSeed("VCU",seedArray,elcount(seedArray),1,"Base Variant","");
  
  if(ret==0)
   
  {
    write("Key computation for security level 1 was started");
  }
  
  else
   
  {
    write("Error code %ld during key calculation",ret);
   
    if(ret==-84)
      
      write("invalid security level");
   
    if(ret==-86)
      
        write("buffer too small");
   
  }
}
else
  
  write("Could not retrieve seed-parameter");
} else { diagGetParameter(this, "RC", buffer, elCount(buffer));
write("Negative response received.\nNegative response code: 0x%02X - %s", (byte)DiagGetResponseCode(this), buffer);
}
}
仿真ECU工程如下:
on diagRequest VCU.requestSeed_1_Request { Diagresponse this resp; byte seedArray[4]={0x11,0x22,0x33,0x44};
DiagSetParameterRaw(resp,"SecuritySeed",seedArray,elcount(seedArray)); DiagSendResponse(resp); }
如下路径添加待测dll文件:
20.png

运行后结果如下图;
21.png

如上验证了Security基本功能,其他服务是基于此进行解锁后,才可以执行相应的诊断服务操作。
文末车牌照.png


-----------------------------------
   作者简介 | 穿拖鞋的汉子
    汽车电子工程师
微信公众号:车载诊断技术
    来,每天进步一点点!

"您的鼓励,是我前进的动力"
还没有人打赏,支持一下
车研会员,开心每一天!
您需要登录后才可以回帖 登录 | 立即注册 |

本版积分规则