UDS安全算法
注:如果仅仅是需要一个dll文件,可直接看DLL文件编写即可
一、安全算法介绍
1、UDS为什么需要安全算法:
汽车和我们当今的生活息息相关,并且在马路上行驶的时候,又与我们的生命财产密不可分,因此,针对于车辆上面修改的配置都需要专业的人士才能进行修改、配置,试想一下如果每个人都能够随意的配置车辆上面的各种数据,是否就如同将我们的生命财产系于钢丝之上呢?因此对于这部门的安全配置修改,必须要有一定的措施去防护,就像我们的银行卡密码一样,去保护我们的财产安全。
2、为什么使用dll文件来作为安全算法的载体
首先对于已有的安全算法来说,如果选择一种载体那必须的是需要能够动态修改且被调用的库文件,否则对于无序的安全种子来说,没有太多的手段去解决算法;同时它能够被代码调用、被Vector相关软件调用、Python调用等。而车辆在研发过程中,由于其体量的庞大,无法单独的一个部门或者公司能够完成,需要多方的合作,因此dll被选择使用作为安全算法的载体。
3、安全算法的目的:
对于当前我们常见的诊断协议来说,27H服务被用于修改设备的安全等级,通过执行27H服务来解锁更高级别的服务。例如:2EH服务,修改车辆配置;2FH服务,控制硬件IO接口;31服务,控制车辆软件代码逻辑。
通常,Tester作为请求方请求ECU发送种子,然后Tester在接收到种子(seed)后,通过相应的算法去计算种子对应的密钥(key),并将密钥(key)发送给ECU,ECU同样计算出一个密钥跟接收到Tester的密钥进行对比,一致的话即可解锁更高级别的服务。
4、27H服务的解锁流程:
二、制作dll准备工作
1、工程路径
当前制作的dll主要用于Vector相关产品的使用,所以我选择最简单的方式去制作工程,即vector提供的工程去制作,优点是制作简单、快捷、并且易上手。
路径:C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 14.2.43\CAN\Diagnostics\UDSSystem\SecurityAccess\Sources\KeyGenDll_GenerateKeyEx
通常选择第一种方案,即可满足我们大部分需求
2、函数介绍
iSeedArray, ECU返回的种子数组
iSeedArraySize, ECU返回的种子数组最大长度
iSecurityLevel, 要解锁的级别(01、03、05、11等)
iVariant, ECU变体限定符
ioKeyArray, Tester返回计算出的密钥
iKeyArraySize, Tester返回计算出的密钥最大长度
oSize 计算出密钥的字节数
iSeedArray, ECU返回的种子数组
iSeedArraySize, ECU返回的种子数组最大长度
iSecurityLevel, 要解锁的级别(01、03、05、11等)
iVariant, ECU变体限定符
ipOptions, 可选字符串(自由文本)
ioKeyArray, Tester返回计算出的密钥
iMaxKeyArraySize, Tester返回计算出的密钥最大长度
oActualKeyArraySize 计算出密钥的字节数
三、DLL文件编写
只需要将上面已有的删除,将下面代码复制过去修改ConstValue值即可
1、源码:
{
unsigned int key = 0U;
unsigned int seed = 0U;
unsigned int i = 0;
unsigned int ConstValue = 0U;
if (iSeedArraySize>iKeyArraySize)
return KGRE_BufferToSmall;
//将ECU返回的Seed整合起来(将seed从byte型转换为int型)
seed = iSeedArray[3];
seed = seed | (iSeedArray[2] << 8);
seed = seed | (iSeedArray[1] << 16);
seed = seed | (iSeedArray[0] << 24);
//解锁算法,确定不同的解锁等级选择不同的解锁算法
if (iSecurityLevel == 0x01)
{
ConstValue = 0xE8301AC3;//解锁的特殊值
}
if (iSecurityLevel == 0x03)
{
ConstValue = 0xD873ABEF;//解锁的特殊值
}
if (iSecurityLeve
}
if (iSecurityLevel == 0x11)
{
ConstValue = 0x9C827D3E;//解锁的特殊值
}
//解锁算法(通过seed计算出key)
key = (seed >> 9) | (seed << 22);
key *= 3;
key ^= ConstValue;
key = (key << 14) | (key >> 17);
//将计算处的key转换为成byte类型并返回到27 2N + data填充
ioKeyArray[3] = key & 0xff;
ioKeyArray[2] = (key >> 8) & 0xff;
ioKeyArray[1] = (key >> 16) & 0xff;
ioKeyArray[0] = (key >> 24) & 0xff;
oSize = 4;
return KGRE_Ok;
}