CAN诊断 - SecurityAccess(安全访问)(0x27)服务

CAN诊断系列文章目录

CAN诊断 - DiagnosticSessionControl(诊断会话控制)(0x10)服务
CAN诊断 - ECUReset(ECU重置)(0x11)服务
CAN诊断 - SecurityAccess(安全访问)(0x27)服务


一、服务说明

本服务旨在提供一种访问因安全、排放或安全因素而被限制访问的数据和诊断服务的方式。用于下载 / 上传例程或数据到服务器及服务器及从服务器读取具体内存位置的诊断服务可能需要进行安全访问。下载至服务器的例程或数据若不当可能会损坏电子设备或其他车辆部件,或者可能使车辆不符合排放、安全或安全标准。安全理念采用的是种子与密钥式关系。

本服务的典型使用示例如下:
— 客户端要求“种子”,
— 服务器发送“种子”,
— 客户端发送“密钥”(适用于已接收到的种子),
— 服务器做出响应,确认“密钥”有效,并自行解锁。

“requestSeed(请求种子)”子功能参数值应始终为奇数,且同一安全级别的响应“sendKey(发送密钥)”子功能参数值应等于“requestSeed(请求种子)”子功能参数值加一。

任何时间都仅可有一个安全级别处于活动状态。例如,如果与 requestSeed(请求种子)0x03 相关的安全级别处于活动状态,且测试仪请求成功地解锁了与 requestSeed(请求种子)0x01 相关的安全级别,则此时仅应解锁与 requestSeed(请求种子)0x01 相关的安全级别所支持的受保护功能。此前已由与 requestSeed(请求种子)0x03 相关的安全级别解锁的任何其他受保护功能应不再处于活动状态。安全级别编号具有任意性,并不表明级别之间存在任何关系。

客户端应通过发送服务 SecurityAccess(安全访问)“requestSeed(请求种子)”消息来向服务器请求“解锁”。服务器应使用服务SecurityAccess(安全访问)“requestSeed(请求种子)”肯定响应消息以发送“种子”,通过这种方式做出响应。之后,客户端应使用适宜的服务 SecurityAccess(安全访问)“sendKey(发送密钥)”请求消息来将“密钥”数字返回给服务器,通过这种方式做出响应。服务器应将该“密钥”与内部存储 / 计算的密钥进行对比。如果两个编号相匹配,则服务器应启用(“解锁”)客户端对具体服务 / 数据的访问,并通过服务 SecurityAccess(安全访问)“sendKey(发送密钥)”肯定响应消息表明这一情况。如果两个编号不匹配,则这将被视作一次错误的访问尝试。无效密钥通过 SecurityAccess(安全访问)“requestSeed(请求种子)”消息要求客户端从最开始重新开始。

如果服务器支持安全性,但是接收 SecurityAccess(安全访问)“requestSeed(请求种子)”消息时所请求的安全级别已经解锁,则该服务器应通过种子值等于 0 的 SecurityAccess(安全访问)“requestSeed(请求种子)”肯定响应消息服务做出响应。无论何时,服务器均不得就当前已锁定的制定安全级别发送全为 0 的种子。客户端检查非零种子,通过这种方式确定服务器是否锁定为特定的安全级别。

服务器上电 / 重置及进行一定次数的错误访问尝试后,服务器能够对来自客户端的服务 SecurityAccess(安全访问)“requestSeed(请求种子)”消息做出肯定响应之前可能需要车辆制造商进行一定延时。
如果支持该延时计时器,则达到车辆制造商规定的错误访问次数后,或服务器上电 / 重置此前执行的 SecurityAccess(安全访问)服务应一次错误访问尝试而失败后,应激活该延时计时器。
如果服务器支持该延时计时器,则成功执行 SecurityAccess(安全访问)服务 “sendKey(发送密钥)” 后,服务器应清除关于上电 / 重置的延时计时器调用的服务器内部显示信息。
如果服务器支持该延时计时器,且无法确定上电 / 重置之前已执行 SecurityAccess(安全访问)服务是否失败,则上电 / 重置之后延时计时器应始终保持活动状态。仅当上电 / 重置时服务器被锁定的情况下要求延时。
车辆制造商应选择是否支持延时计时器。

尝试访问安全性时不得妨碍正常的车辆通信或其他诊断通信。

如果服务器被锁定时请求安全服务,则提供安全性的服务器应支持拒绝消息。

具体诊断会话期间请求的有些诊断功能 / 服务可能需要有效的安全访问序列。这种情况下,应要求以下服务序列:
— DiagnosticSessionControl(诊断会话控制)(0x10)服务
— SecurityAccess(安全访问)(0x27)服务
— 受保护的诊断服务
服务器中启用的 diagnosticSession(诊断会话)允许由多种AccessMode(访问模式)。

二、请求消息

1.请求消息定义

下表规定了请求消息定义 - sub-function = requestSeed

字节参数名称字节值
#1SecurityAccess(安全访问)请求SID0x27
#2sub-function = [
securityAccessType = requestSeed]
0x01,0x03,0x05,0x07 - 0x7D

#3
.
.
#n
securityAccessDataRecord[] = [
parameter#1
.
.
parameter#m ]

0x00 - 0xFF
.
.
0x00 - 0xFF

下表规定了请求消息定义 - sub-function = ==sendKey==。
字节参数名称字节值
#1SecurityAccess(安全访问)请求SID0x27
#2sub-function = [
securityAccessType = sendKey]
0x02,0x04,0x06,0x08 - 0x7E

#3
.
.
#n
securityKey[] = [
key#1(high byte)
.
.
key#m(low byte) ]

0x00 - 0xFF
.
.
0x00 - 0xFF

2.请求消息子功能参数定义

子功能参数 securityAccessType(安全访问类型)可通过服务器显示本服务正在进行的步骤、客户端想要访问的安全级别,以及种子和密钥的格式。如果服务器支持不同的安全级别,则应使用 requestSeed(请求种子)值来标识各个级别,这些值与 sendKey(发送密钥)值存在固定关系:

  • “requestSeed = 0x01” 标识了 “requestSeed = 0x01” 与 “sendKey = 0x02” 之前的固定关系
  • “requestSeed = 0x03” 标识了 “requestSeed = 0x03” 与 “sendKey = 0x04” 之前的固定关系

  • 下表定义了 requestSeed(请求种子)和 sendKey(发送密钥)的值。
    第 6 至 0 位说明
    0x00保留
    0x01requestSeed(请求种子)
    车辆制造商定义的安全级别的 RequestSeed(请求种子)。
    0x02sendKey(发送密钥)
    车辆制造商定义的安全级别的 SendKey(发送密钥)。
    0x03,0x05,0x07 - 0x41requestSeed(请求种子)
    车辆制造商定义的不同安全级别的 RequestSeed(请求种子)。
    0x04,0x06,0x08 - 0x42sendKey(发送密钥)
    车辆制造商定义的不同安全级别的 SendKey(发送密钥)。
    0x43 - 0x5E保留
    0x5FISO 26021 - 2 requestSeed(请求种子)值
    为车载点火装置寿命激活结束定义的不同安全级别的 RequestSeed(请求种子)符合 ISO 26021 - 2 中的定义。
    0x60ISO 26021 - 2 sendKey(发送密钥)值
    为车载点火装置寿命激活结束定义的不同安全级别的 sendKey(发送密钥)符合 ISO 26021 - 2 中的定义。
    0x61 - 0x7ESystemSupplierSpecific(由系统供应商规定)
    0x7F保留

    三、肯定响应消息

    1. 肯定响应消息定义

    字节参数名称字节值
    #1SecurityAccess(安全访问)请求SID0x67
    #2sub-function = [ securityAccessType ]0x00 - 0x7F

    #3
    .
    .
    #n
    securitySeed[] = [
    seed#1(high byte)
    .
    .
    seed#m(low byte) ]

    是否存在该参数取决于 securityAccessType(安全访问类型)参数。如果 securityAccessType(安全访问类型参数)表明客户端想要从服务器检索种子,则该参数必须存在。

    0x00 - 0xFF
    .
    .
    0x00 - 0xFF

    2. 肯定响应消息数据参数定义

    下表为响应消息数据参数定义

    定义
    securityAccessType(安全访问类型)
    该参数是对来自请求消息的子功能参数第 6 至 0 位的回显。
    securitySeed(安全种子)(高位和低位字节)
    种子参数是服务器发送的数据值,并在计算访问安全所需的密钥时供客户端使用。如果子功能设置为请求服务器种子的值的情况下发送请求消息,则 securitySeed(安全种子)数据字节仅出现在响应消息中。

    四、支持的NRC

    NRC说明
    0x12不受支持的子功能
    0x13消息长度不正确或格式无效
    0x22条件不正确
    0x24请求序列错误
    如果未先接收 “requestSeed(请求种子)” 请求消息就接收了 “sendKey(发送密钥)” 子功能,则发送该NRC。
    0x31请求超过限值
    如果用户可选的 securityAccessDataRecord(安全访问数据记录)包含无效数据,则应发送该NRC。
    0x35无效密钥
    如果接收到预期的 “sendKey(发送密钥)” 子功能值,且密钥值与服务器内部存储的 / 计出的密钥不匹配,则应发送该NRC。
    0x36超过尝试次数
    如果由于超过允许的错误访问尝试最大数次而导致延时计时器处于活动状态,,则应发送该NRC。
    0x37要求的延时未到时间
    如果延时计时器处于活动状态,且已传输请求,则应发送该NRC。

    五、示例

    1. 假设

    对于以下给出的消息流示例,如果服务器处于 “锁定” 状态,则须满足以下条件以成功地解锁服务器:
    — 请求种子的子功能:0x01(requestSeed(请求种子))
    — 发送密钥的子功能:0x02(sendKey(发送密钥))
    — 服务器的种子(2个字节):0x3657
    — 服务器的密钥(2个字节):0xC9A9

    设置抑制肯定响应消息指示位为 “0”。

    2. 示例1 - 服务器处于 “锁定” 状态

    step 1:请求种子

    req  27 01
    resp 67 01 36 57
    

    step 2:发送密钥

    req  27 02 C9 A9
    resp 67 02
    

    2. 示例2 - 服务器处于 “解锁” 状态

    step 1:请求种子

    req  27 01
    resp 67 01 00 00
    
  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Java的Socket和InputStream类来读取Socket中返回的ASCII数据,然后根据题目要求进行转义和生成图片。 下面是一个简单的示例代码,可以实现读取Socket中的数据并进行转义和生成图片: ```java import java.io.*; import java.net.Socket; import java.util.ArrayList; import java.util.List; public class SocketReader { public static void main(String[] args) throws IOException { String host = "localhost"; int port = 8080; Socket socket = new Socket(host, port); InputStream inputStream = socket.getInputStream(); List<Byte> bytes = new ArrayList<>(); int b; while ((b = inputStream.read()) != -1) { if (b == 0x7D) { bytes.add((byte) 0x7D); bytes.add((byte) 0x01); } else if (b == 0x5B) { bytes.add((byte) 0x7D); bytes.add((byte) 0x02); } else if (b == 0x5D) { bytes.add((byte) 0x7D); bytes.add((byte) 0x03); } else if (b == 0x2C) { bytes.add((byte) 0x7D); bytes.add((byte) 0x04); } else if (b == 0x2A) { bytes.add((byte) 0x7D); bytes.add((byte) 0x05); } else { bytes.add((byte) b); } } byte[] imageData = new byte[bytes.size()]; for (int i = 0; i < bytes.size(); i++) { imageData[i] = bytes.get(i); } FileOutputStream outputStream = new FileOutputStream("image.jpg"); outputStream.write(imageData); outputStream.close(); socket.close(); } } ``` 在上述代码中,我们首先建立了一个到指定主机和端口的Socket连接,并获取了该Socket连接的输入流。然后我们通过循环读取输入流中的数据,并根据题目要求对数据进行转义,最后将转义后的数据写入到一个字节数组中。 接着,我们将字节数组写入到一个文件中,生成图片。在这里,我们假设输入的ASCII数据就是一张JPEG图片,并将它写入到名为“image.jpg”的文件中。 需要注意的是,上述代码是一个简单的示例,实际的应用场景可能会更加复杂,需要根据具体的需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值