您的位置:首页 > 财经 > 金融 > 潍坊互联网推广_微信公众号的子菜单网页怎么制作_企业网络_什么是网络营销含义

潍坊互联网推广_微信公众号的子菜单网页怎么制作_企业网络_什么是网络营销含义

2024/12/22 23:37:43 来源:https://blog.csdn.net/Vista7Malone/article/details/142267763  浏览:    关键词:潍坊互联网推广_微信公众号的子菜单网页怎么制作_企业网络_什么是网络营销含义
潍坊互联网推广_微信公众号的子菜单网页怎么制作_企业网络_什么是网络营销含义

系列文章目录

使用CAPL脚本解析hex、S19、vbf文件
使用CAPL脚本对CAN报文的Counter、CRC、周期、错误帧进行实时监控
使用CAPL脚本模拟发送符合协议要求(Counter和CRC)的CAN报文
使用CAPL脚本控制继电器实现CAN线、电源线的通断
使用CAPL脚本实现安全访问解锁
使用CAPL脚本实现BUS OFF干扰测试
使用CAPL脚本进行DTC自动化测试
使用CAPL脚本进行UDS刷写及其自动化测试
使用CAPL脚本进行UDS协议测试
使用CAPL脚本进行网络管理测试
粉丝问题解答系列文章… …
其他持续更新中… …


文章目录

  • 系列文章目录
  • 前言
  • 一、利用安全算法.dll文件解锁
    • 1、函数介绍
    • 2、示例代码
  • 二、利用自定义安全算法解锁
    • 1、示例代码
  • 三、测试场景示例
    • 1、正常的安全访问解锁
    • 2、安全访问秘钥错误
    • 3、连续多次申请解锁,验证种子随机性
  • 总结


前言

在车载诊断中,我们经常会使用到安全访问解锁,常见的场景包括软件刷写前、通过2E服务写入某个DID前、通过31服务执行某个例程前等,都必须先通过27服务进行安全访问,解锁相应安全等级后才能执行上述操作。
在开发调试或测试时,有时候需要模拟正常的安全解锁、安全访问秘钥错误、连续多次请求安全访问等,手动操作极为不便。本文将介绍如何使用CAPL脚本实现安全访问解锁,并模拟各种测试场景。


一、利用安全算法.dll文件解锁

1、函数介绍

diagGenerateKeyFromSeed函数适用于利用CANoe工程中配置的安全算法动态链接库文件(.dll)生成秘钥的场景。详细说明如下:
在这里插入图片描述

2、示例代码

利用CANoe工程中配置的安全算法动态链接库文件(.dll)进行安全访问解锁。CAPL脚本示例如下:

variables
{byte glob_SeedArray[10];
}
//发送报文,并获取响应状态
long diagSendReqAndgetResp(diagRequest * req)
{long NRC;diagSendRequest(req);testWaitForDiagRequestSent(req, 200);if(1 == TestWaitForDiagResponse(req,5000)){NRC = diagGetLastResponseCode(req);if(NRC == -1)//积极响应{return 1;}else//消极响应 {TestReportWriteDiagResponse(req); return NRC;}}testStep("step","响应超时");return -1;//响应超时
}
//安全访问解锁函数:level——解锁的安全等级;errorMode——是否要模拟密钥错误;SeedArray_only——是否只申请种子,不进行解锁
long diagUnlockECU(byte level,byte errorMode,byte SeedArray_only)
{long Resp;byte  gSeedArray[20];int   gSeedArraySize,gSecurityLevel;                    char  gVariant[50]     = "Base_Variant";char  gOption[50]      = "option";byte gKeyArray[20];int  gMaxKeyArraySize = 255;dword gActualSizeOut;long errorcode,size;diagRequest  * req;diagResponse * resp;byte reqBuffer[20];req.Resize(2);diagSetPrimitiveByte(req,0,0x27);diagSetPrimitiveByte(req,1,level);gSecurityLevel = level;testStep("","安全访问申请Seed");/*请求Seed*/Resp = diagSendReqAndgetResp(req);if( Resp == 1 ){/*将响应Seed写入参数数组*/diagGetLastResponse(req, resp);/*获取Seed&Key的长度*/size = resp.GetPrimitiveSize();gSeedArraySize = size - 2;gActualSizeOut = size - 2;write("Seed&Key size:%d",size);resp.GetPrimitiveData(gSeedArray, elcount(gSeedArray));memcpy_off( gSeedArray,0,gSeedArray,2, gSeedArraySize);if( SeedArray_only == 1 ){memcpy( glob_SeedArray,gSeedArray, gSeedArraySize);//仅申请安全访问种子return 0xFF;}/*计算密钥(使用安全算法动态链接库文件(.dll)生成密钥)*/errorcode = diagGenerateKeyFromSeed(gSeedArray, gSeedArraySize, gSecurityLevel, gVariant, gOption, gKeyArray, gMaxKeyArraySize, gActualSizeOut);if( 0 == errorcode){/*写入请求参数*/req.Resize(gActualSizeOut + 2);reqBuffer[0] = 0x27;reqBuffer[1] = level+1;memcpy_off(reqBuffer,2,gKeyArray,0,gActualSizeOut);if(errorMode == 1){reqBuffer[4] += 1;//模拟制造密钥错误}req.SetPrimitiveData(reqBuffer,size);/*发送密钥*/testStep("","发送密钥进行解锁");Resp = diagSendReqAndgetResp(req);return Resp;}else{TestStepFail("","密钥计算出错,errorcode:%x",errorcode);return errorcode;}}else{return Resp;}
}

二、利用自定义安全算法解锁

前面说了diagGenerateKeyFromSeed函数是利用CANoe工程中配置的安全算法动态链接库文件(.dll)生成的秘钥,使用起来很方便,不需要再编写生成生成密钥的算法函数。但是有些测试场景可能不是很方便,比如利用自动化脚本分别进入扩展会话和编程会话进行解锁,一般来说扩展会话和编程会话模式下的密钥算法是不一样的,不能通过同一个动态链接库文件(.dll)生成秘钥。这个时候可以自定义一个密钥生成函数来替换diagGenerateKeyFromSeed函数即可。

1、示例代码

利用自定义的安全算法函数进行安全访问解锁。CAPL脚本示例如下:

variables
{byte glob_SeedArray[10];
}
//发送报文,并获取响应状态
long diagSendReqAndgetResp(diagRequest * req)
{long NRC;diagSendRequest(req);testWaitForDiagRequestSent(req, 200);if(1 == TestWaitForDiagResponse(req,5000)){NRC = diagGetLastResponseCode(req);if(NRC == -1)//积极响应{return 1;}else//消极响应 {TestReportWriteDiagResponse(req); return NRC;}}testStep("step","响应超时");return -1;//响应超时
}
//根据种子计算密钥(示例)
dword SeedToKey1(byte pData[],byte level)
{dword seed = 0;dword ret = 0;dword PositionA,PositionB,PositionC;dword B24 = 0;int i;qword ChallengeBitArray;ret = 0;PositionA = 0x123456;//示例PositionB = 0;PositionC = 0;B24 = 0;if(level == 9){ChallengeBitArray = 0x1122334455LL;//编程会话模式示例}else if(level == 1){ChallengeBitArray = 0x123456789ALL;//扩展会话模式示例}seed = (pData[2] << 16) | (pData[1] << 8) | (pData[0]);ChallengeBitArray = ((ChallengeBitArray << 24) | seed);for (i = 0; i < 64; i++){B24 = ((ChallengeBitArray >> i) ^ PositionA) & 0x01;PositionB = (B24 << 23) | (PositionA >> 1);PositionC = 0;PositionC = PositionC | (B24 << 3);PositionC = PositionC | (B24 << 5);PositionC = PositionC | (B24 << 12);PositionC = PositionC | (B24 << 15);PositionC = PositionC | (B24 << 20);PositionC = PositionC ^ PositionB;PositionA = PositionC;}ret = ret | ((PositionC & 0x000FF0) << 12);ret = ret | ((PositionC & 0x00F000));ret = ret | ((PositionC & 0xF00000) >> 12);ret = ret | ((PositionC & 0x00000F) << 4);ret = ret | ((PositionC & 0x0F0000) >> 16);return ret;
}
//自定义的密钥生成函数(示例)
byte GenerateKeyEx(byte iSeedArray[],dword iSeedArraySize,dword iSecurityLevel,char iVariant[],byte ioKeyArray[],dword iKeyArraySize,dword& oSize)
{dword nRet = 0;if (iSeedArraySize>iKeyArraySize)return 1;switch (iSecurityLevel){case 9://编程会话模式nRet = SeedToKey1(iSeedArray,9);break;case 1://扩展会话模式nRet = SeedToKey1(iSeedArray,1);break;default:break;}ioKeyArray[0] = nRet >> 16;ioKeyArray[1] = (nRet >> 8) & 0xFF;ioKeyArray[2] = nRet & 0xFF;oSize = 3;return 0;
}
//安全访问解锁函数:level——解锁的安全等级;errorMode——是否要模拟密钥错误;SeedArray_only——是否只申请种子,不进行解锁
long diagUnlockECU(byte level,byte errorMode,byte SeedArray_only)
{long Resp;byte  gSeedArray[20];int   gSeedArraySize,gSecurityLevel;                    char  gVariant[50]     = "Base_Variant";char  gOption[50]      = "option";byte gKeyArray[20];int  gMaxKeyArraySize = 255;dword gActualSizeOut;long errorcode,size;diagRequest  * req;diagResponse * resp;byte reqBuffer[20];req.Resize(2);diagSetPrimitiveByte(req,0,0x27);diagSetPrimitiveByte(req,1,level);gSecurityLevel = level;testStep("","安全访问申请Seed");/*请求Seed*/Resp = diagSendReqAndgetResp(req);if( Resp == 1 ){/*将响应Seed写入参数数组*/diagGetLastResponse(req, resp);/*获取Seed&Key的长度*/size = resp.GetPrimitiveSize();gSeedArraySize = size - 2;gActualSizeOut = size - 2;write("Seed&Key size:%d",size);resp.GetPrimitiveData(gSeedArray, elcount(gSeedArray));memcpy_off( gSeedArray,0,gSeedArray,2, gSeedArraySize);if( SeedArray_only == 1 ){memcpy( glob_SeedArray,gSeedArray, gSeedArraySize);//仅申请安全访问种子return 0xFF;}/*计算密钥(使用自定义的密钥生成函数)*/errorcode = GenerateKeyEx(gSeedArray, gSeedArraySize, gSecurityLevel, gVariant, gKeyArray, gMaxKeyArraySize, gActualSizeOut);if( 0 == errorcode){/*写入请求参数*/req.Resize(gActualSizeOut + 2);reqBuffer[0] = 0x27;reqBuffer[1] = level+1;memcpy_off(reqBuffer,2,gKeyArray,0,gActualSizeOut);if(errorMode == 1){reqBuffer[4] += 1;//模拟制造密钥错误}req.SetPrimitiveData(reqBuffer,size);/*发送密钥*/testStep("","发送密钥进行解锁");Resp = diagSendReqAndgetResp(req);return Resp;}else{TestStepFail("","密钥计算出错,errorcode:%x",errorcode);return errorcode;}}else{return Resp;}
}

三、测试场景示例

1、正常的安全访问解锁

	long Resp;/*正常解锁ECU:Level_1,正常解锁,申请种子+发送正确的密钥*/Resp = diagUnlockECU(0x01,0,0);if(Resp == 1){testStepPass("正确解锁ECU Level_1,测试成功!");}else{testStepFail("正确解锁ECU Level_1,测试失败!");}

2、安全访问秘钥错误

	long Resp;/*异常解锁ECU:Level_1,异常解锁,申请种子+发送错误的密钥*/Resp = diagUnlockECU(0x01,1,0);if(Resp == 0x35){testStepPass("第1次错误解锁ECU Level_1,测试成功!");}else{testStepFail("第1次错误解锁ECU Level_1,测试失败!");}

上述示例是密钥错误1次,返回NRC35。可以以此进行扩展,比如错误N-1次,返回NRC36,以及错误达到N次锁定后,返回NRC37。

3、连续多次申请解锁,验证种子随机性

	long Resp;byte tmp_SeedArray[6000];int i,j,k,cmp_cnt;/*Level_1,仅申请种子*/for(i = 0;i < 2000;i++){/*27 01申请安全访问种子,1~1000次*/Resp = diagUnlockECU(0x01,0,1);if(Resp == 0xFF){if((glob_SeedArray[0] == 0) && (glob_SeedArray[1] == 0) && (glob_SeedArray[2] == 0)){testStepFail("","27 01申请安全访问种子,第%d次:获取失败!种子全为0!",i+1);}else{memcpy_off(tmp_SeedArray,3*k,glob_SeedArray,0, 3);testStepPass("","27 01申请安全访问种子,第%d次:获取成功!",i+1);}}else{testStepFail("","27 01申请安全访问种子,第%d次:获取失败!",i+1);}}for(k = 0;k < 2000;k++){for(i = 0;i < 2000;i++){cmp_cnt = 0;if(i == k){continue;}for(j = 0;j < 3;j++){if(tmp_SeedArray[3*k+j] == tmp_SeedArray[3*i+j]){cmp_cnt +=1;}}if( cmp_cnt == 3 ){testStepFail("","27 01申请安全访问种子,第%d次与第%d次种子完全相同:测试失败!",k+1,i+1);break;}}if( cmp_cnt < 3 ){testStepPass("","27 01申请安全访问种子,第%d次与之前的种子不相同:测试成功!",k+1);}}

上述示例是连续申请2000次种子(此处示例的种子为3个字节),存放到tmp_SeedArray[]数组中,最后循环遍历对比,看这申请的这2000次是否有相同种子,以此来验证其随机性。


总结

以上就是如何使用CAPL脚本实现安全访问解锁的讲解,并结合了多个运用场景的实例进行介绍,希望对大家有所帮助。各位可根据本文的示例,结合自己的需求,进行完善和二次开发。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com