利用CANoe CAPL程序测试随机数重复率问题

本文介绍了如何在UDS服务$27安全服务中,通过算法生成不重复的3字节随机数种子,以满足ECU的需求。当MCU无内置随机数生成器时,利用RTC时间作为种子初始化随机数序列。同时,文章详细展示了如何使用CAPL(CANalyzer或CANoe的编程语言)进行测试,利用关联类型( AssociativeFields )检查随机数种子的重复性,确保1000次生成的种子不重复。
摘要由CSDN通过智能技术生成

 文章目录



前言

背景:由于UDS服务$27安全服务中需要ECU生成随机数作为种子,且ECU使用的MCU(RH850)没有随机数生成器,因此需要通过算法实现随机数。
真正意义的随机数生成器存在吗? - 知乎https://www.zhihu.com/question/20145173要求:生成的随机数种子1000次不能重复,种子长度为3 Bytes。
实现:通过随机算法实现种子生成,并通过CAPL程序检查种子重复率问题。

注:本文重在CAPL测试程序,而非随机数算法!



一、随机数生成算法

由于C标准库中的rand函数每次得到的序列都是相同的,如果想得到不同序列需要调用srand设置不同的种子,做法如下:

  • 获取随机数之前,使用单片机RTC/当前电压AD值/或全局GlobalTime(从整车CAN网络接收的时间)等作为srand 的种子以初始化随机数序列;
  • 确认rand随机数范围(所使用stdlib.h库中RAND_MAX为0x7FFF,无符号数);

示例代码(以RTC作为srand种子):

FUNC(Std_ReturnType, DCM_APPL_CODE) SecurityAccess_Level1_GetSeed(
    Dcm_OpStatusType OpStatus,
    P2VAR(uint8, AUTOMATIC, DCM_VAR) Seed,
    P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, DCM_VAR) ErrorCode
    )
{
    static boolean isFirstRequest = TRUE;
    uint32 random = 0U;
    (void)OpStatus;

    /* Initialize random number generator with seed(RTC).*/
    if (isFirstRequest) {
        const uint32 currSysTime = SystemTime_Read_ticks_32bits();
        srand(currSysTime);
        isFirstRequest = FALSE;
    } else {
        ;
    }

    /* Generate the random number. the RAND_MAX is 0x7FFF in _gh stdlib.*/
    random  = (uint32)(rand());
    random += (uint32)(rand()<< 15U);

    Seed[0] = (uint8)(random);
    Seed[1] = (uint8)(random >> 8U);
    Seed[2] = (uint8)(random >> 16U);

    *ErrorCode = DCM_E_POSITIVERESPONSE;
    return E_OK;
}


二、CAPL程序测试


1.关联类型&用法

为了实现快速查找比对重复的随机数,需要使用到类似C++中的map容器进行查找,而map集合特点:

  • 采用了 Key-value键值对映射的方式进行存储,且存储是无序的(散列的);
  • Key在Map里面是唯一的但是value可以重复,一个Key对应一个Value;

而CAPL有一种特殊的关联类型(Associative Fields),类似Python字典和C++ Map容器,其关联类型的元素也是键值对(key value pairs)。
从CANoe帮助文档中查看用法,如下:

 关联类型定义格式如下对象左边是Value类型,右边[ ]内是Key类型

int      m[ float  ];  // maps floats to ints
float    x[ int64  ];  // maps int64s to floats
char[30] s[ char[] ];  // maps strings (of unspecified length) to strings of length < 30

官方示例1:关联浮点型 

float m[float];    // 定义关联对象
m[4.1] = 5.5;      // key is 4.1 (float)  and value is 5.5 (float)
m[5.3] = 6.6;
write ("4.1 is mapped to %2.2lf", m[4.1]);
write ("5.3 is mapped to %2.2lf", m[5.3]);
for (float mykey : m)
{
  write("%2.2lf is mapped to %2.2lf.", mykey, m[mykey]);
}

 官方示例2: 关联字符串

char[30] namen[char []];                    // 定义关联对象
strncpy(namen["Max"], "Mustermann", 30);    // 相当于 namen["Max"] = "Mustermann"
strncpy(namen["Vector"], "Informatik", 30); // 相当于 namen["Vector"] = "Informatik"

for (char[] mykey : namen)
{
  write("%s is mapped to %s", mykey, namen[mykey]);
}

关联对象方法(Associative Fields CAPL Functions): 

本测试代码则用到map中的key唯一的特性,将随机数作为key,对应的value可以是任意类型数据(由于不关心,统一设置为整型数据1),然后通过::containsKey()方法进行查找。
如果::containsKey(randomNum)返回1,则表示该key(随机数randomNum)已经存在,否则将其插入到关联类型中。


2.测试程序

假设:

  • 诊断物理请求ID & 响应ID分别为:0x705 & 0x745
  • 通过安全访问服务$27 01 请求获得种子(随机数,3个字节)

代码如下(示例):

on message 0x745       /* VCU_DiagResponse.*/
{
  int  seedMap[long];  /* Maps long to int */
  byte isDuplicateOccur = 0;
  long randomNum = 0;
  long index = 0;
  
  if ( (!isDuplicateOccur)
    && (this.byte(1) == 0x67) && (this.byte(2) == 0x01))
  {
    randomNum =  this.byte(3);
    randomNum <<= 8;
    randomNum += this.byte(4);
    randomNum <<= 8;
    randomNum += this.byte(5);
    
    /* Check if this random number is duplicated,
     * if not - insert this random number as key and the value is 1.*/
    if (seedMap.containskey(randomNum)) {
      write("Seed %6d: %06X =======> Duplicated seed is FOUND!!!", index++, randomNum);
      isDuplicateOccur = 1;
    } else {
      seedMap[randomNum] = 1;
      write("Seed %6d: %06X", index++, randomNum);
    }
    
#if (0) /* CAPL map test code.*/
    switch (index)
    {
    case 1: 
      seedMap[0x123456] = 1;
      write("Seed %6d: %06X", index++, 0x123456);
      break;
    case 1000:
      if (seedMap.containskey(0x123456)) {
        write("Seed %6d: %06X =======>  Duplicated seed is FOUND!!!", index++, 0x123456);
        isDuplicateOccur = 1;
      }
      break;
    default:
      break;
    }
#endif
  }
}


参考

rand - C++ Reference
map - C++ Reference

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值