UDS的安全访问服务(0x27)与CAPL实现自动处理

在实际的诊断中我们要经常和安全访问(Security Access)打交道,为了方便的处理这些问题,写CAPL脚本是一个很好的方案,所以我整理了Vector官方提供的与安全访问(Security Access)有关的函数,并对常用的进行简单说明。

本文CAPL函数有关几乎全部摘录自Vector的官方文档,只是做了整理与翻译。

一、 介绍安全访问(Security Access)

关于ISO 14229的安全访问(Security Access)一个比较好的介绍文档: 安全访问(ISO14229系列之27服务)

当客户端连接到服务端(即ECU)时,客户端有一个会话(session)和一个安全级别(security level)。

1.1 不同的会话(Session)模式

默认情况下,服务器通过为新客户端分配默认会话(Default Session) 来迎接新客户端,在该会话中,只有少数特定服务可以访问,如读取DTC。

但是还有些操作可能涉及到安全或者其他方面的原因,不允许在默认会话(Default Session)中使用,因此如果需要更高的权限,就必须切换到其他的会话中。

在ISO14229中规定了那些服务可以在默认会话中使用,那些不可以在默认会话中使用, 如下:
请添加图片描述

如果需要从默认会话(Default Session)切换到其他会话中使用UDS的10服务, 我们本文介绍的诊断会话(extendedDiagnosticSession) 是ISO 14229规定的必须要提供的会话模式,该会话模式代号通常是03。 也即是说如果要切换到该会话,使用命令为10 03.

1.2 安全访问(Security Access)的工作流程

因为诊断会话(extendedDiagnosticSession) 中包含高权限的操作,因此切换到这个会话后,必须要执行解锁(unlock) 操作才能进行后续的使用。所谓的解锁(unlock) 操作需要使用UDS提供的安全访问(Security Access)服务,也就是UDS的27服务。

0x27 安全访问(Security Access)服务的典型工作流程如下:

  1. Client先主动发送一个: 请求种子(Seed) 的消息
  2. ECU(也就是Server端)收到来自Client的请求后,ECU会发送种子(Seed)
  3. Client在收到ECU发送过来的种子(Seed) 后,客户端对种子(Seed)进行计算,并发送计算后的 密钥(Key)
  4. ECU在收到密钥(Key) 后对其进行校验,如果密钥(Key) 是有效的,那么ECU会将自己解锁,并向Client发送积极响应;否则返回否定响应
1.2.1 安全访问(Security Access)的步骤1:客户端发送请求种子(Seed)

Client端发送请求种子(Seed) 的消息格式如下:
请添加图片描述

虽然第二个参数可以是0x010x030x050x07等奇数,但是我们最常用的还是0x01, 另外securityAccessDataRecord通常为空,所以Client最常用的请求Seed的报文为:27 01

1.2.2 安全访问(Security Access)的步骤2:ECU发送种子(Seed)

ECU端在收到步骤1的请求消息后,如果请求格式正确,那么会发送积极响应,也就是发送种子(Seed) , 消息格式如下:
请添加图片描述

第2个参数一般和Client发送请求时的SubFunction是一致的,也就是最常用的0x01

第3个以及后面的参数securitySeed通常为2、4个字节。

所以ECU最常用的发送Seed的报文为:67 01 XX XX或者67 01 XX XX XX XX

1.2.3 安全访问(Security Access)的步骤3:客户端发送密钥(Key)

Client端发送密钥(Key) 的消息格式如下:
请添加图片描述

虽然第二个参数可以是0x020x040x060x08等偶数(必须为发送Seed时使用的SubFunction加1),但是我们最常用的还是0x02, 也就是最常用的请求报文为:27 02 + securityKey

1.2.4 安全访问(Security Access)的步骤4:ECU发送最终的响应

ECU在收到密钥(Key) 后对其进行校验,于是就分为两种情况:

  • 情况1: 如果密钥(Key) 是有效的,那么ECU会将自己解锁,并向Client发送积极响应。 这种情况下的报文格式比较简单,类似于上面的Table 44。 但是我们最常见的报文还是67 02
  • 情况2: 如果密钥(Key) 是无效的,返回否定响应,格式如下:

请添加图片描述
请添加图片描述

1.3 不同的安全等级(Security level)

安全等级(Security level) 是客户端通过提供安全密钥来解锁服务器内的功能而获得的状态。UDS被设计为允许多达64个安全级别,这些级别是在服务端中设置的布尔标志。

这些安全级别以及它们解锁的内容不是由UDS定义的,而是由ECU制造商定义的。安全级别可以解锁整个服务、子功能或对特定值的访问。例如,写入车辆识别码(VIN)可能需要特定的安全级别,该级别不同于写入最大速度或超越车辆IO所需的安全级别。

下图摘自ISO 14229-1, 描述了SecurityAccess处理的状态图(state chart):
请添加图片描述

上图中的1-10含义,可以参考ISO 14229-1 中的**“Table I.2 — State transitions – disjunctive normal form representation”**

默认会话(Default Session) 中不允许解锁安全等级(Security level) 。要获得一些权限,客户端必须首先切换到启用SecurityAccess服务的非默认会话。只有这样,客户端才能执行握手,从而解锁所需的功能。

在ISO 14229中对于安全等级有两个比较重要的描述:

  1. 在任何时刻,只有一个安全级别处于活动(active)状态
  2. 安全级别(security level)编号是随意的,不同级别之间不意味着有任何关系

二、 介绍常用函数

CAPL中与CRC有关的函数如下:

Functions Short Description
diagGenerateKeyFromSeed 生成一个密钥(Key)以在ECU内执行安全的诊断功能
diagStartGenerateKeyFromSeed 使用 Seed & Key DLL从种子(Seed)开始生成安全密钥(security key)
TestWaitForGenerateKeyFromSeed 使用配置的 Seed & Key DLL从种子(Seed)生成安全密钥(security key)
_Diag_GenerateKeyResult 显示使用DiagStartGenerateKeyFromSeed启动的安全密钥计算的结果

补充说明:

Windows和Linux支持这些CAPL功能。Linux下的功能尚未经过全面测试。

2.1 函数: diagGenerateKeyFromSeed()

函数功能描述

创建一个密钥(key) 以在设备内执行安全的诊断功能(secured diagnostic functions)
密钥(key) 将与设备的种子(Seed) 一起定义。
如果计算耗时超过1毫秒,则应使用:diagStartGenerateKeyFromSeed_Diag_GenerateKeyResult结合来完成。

函数语法
long diagGenerateKeyFromSeed(byte seedArray[], 
                             dword seedArraySize, 
                             dword securityLevel, 
                             char variant[], 
                             char ipOption[], 
                             byte keyArray[], 
                             dword maxKeyArraySize, 
                             dword& keyActualSizeOut); // form 1

long DiagGenerateKeyFromSeed(char ecuQualifier
在通用数据链路(GDL)协议的背景下,UDS (Unidirectional Serial Data) 22服务是指ISO-DAS(ISO on Demand Address Space)的一部分,它允许通过CAN总线发送或接收单向的数据请求。在Controller Area Network (CAN)系统中,CAN Application Programing Language (CAPL)是一种用于编写CAN应用软件的高级编程语言。 要创建一个简单的UDS 22服务自动回复的CAPL脚本,首先需要包含相关的库和定义。这里是一个基本的例子: ```capl // 导入必要的库 #include "uds.h" #include "can.h" // 定义服务ID const udsServiceId myServiceId = 0x22; // 定义服务响应结构体 typedef struct { serviceHeader header; // UDS服务头信息 uint8_t data[4]; // 示例数据,可根据实际需求更改 } MyResponse; void onReceiveData(CANMessage* msg) { // 检查消息是否针对我们的服务ID if (msg->serviceId == myServiceId) { // 创建响应 MyResponse response; response.header.serviceType = UdsServiceResponseType_Reply; response.header.length = sizeof(response.data); // 将接收到的数据复制到响应中,此处仅做示例 memcpy(response.data, msg->data, sizeof(msg->data)); // 发送回复 sendUdsResponse(msg->senderId, &response); } } int main() { initializeCAN(); CANFilter filter; filter.id = CANFilterType_Raw; filter.filterMask = CANFilterType_Raw; filter.serviceId = myServiceId; addCANFilter(&filter); // 注册监听特定的服务ID // 进入主循环,处理接收到的消息 while (true) { processCANEvents(onReceiveData); } return 0; } ``` 这个CAPL脚本的主要部分包括初始化CAN通信、设置过滤器监听特定服务ID、并定义一个回调函数`onReceiveData`来处理接收到的数据。当接收到请求时,它会创建一个响应并发送回去。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值