Using CANoe CAPL program to test the repetition rate of random numbers

  Tip: after the article is written, the directory can be generated automatically. Please refer to the help document on the right for how to generate it

Article catalog


preface

Background: since the UDS service $27 security service requires the ECU to generate random numbers as seeds, and the MCU(RH850) used by the ECU does not have a random number generator, it is necessary to implement random numbers through algorithms.
Does the real random number generator exist- Knowhttps://www.zhihu.com/question/20145173 Requirement: the generated random number seed is 1000 times and cannot be repeated. The seed length is 3 Bytes.
Implementation: seed generation is realized by random algorithm, and the seed repetition rate is checked by CAPL program.
Note: This paper focuses on CAPL test program, not random number algorithm!


1, Random number generation algorithm

Since the rand function in the C standard library gets the same sequence every time, if you want to get different sequences, you need to call srand to set different seeds, as follows:

  • Before obtaining the random number, use the single chip microcomputer RTC / current voltage AD value / or global globaltime (time received from the vehicle CAN network) as the seed of srand to initialize the random number sequence;
  • Confirm the range of Rand random number (RAND_MAX in stdlib.h library used is 0x7FFF, unsigned number);

Sample code (with RTC as srand seed):

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;
}


2, CAPL program test


1. Correlation function

In order to quickly find and compare duplicate random numbers, you need to use a map container similar to that in C + +. The features of the map set are as follows:

  • The key value mapping method is used for storage, and the storage is unordered (hash);
  • The Key is unique in the Map, but the value can be repeated. A Key corresponds to a value;

CAPL has a special association type (associated fields), which is similar to Python dictionary and C++ Map container. The elements of its association type are also key value pairs.
View the usage from CANoe help document as follows:

  The format of association type definition is as follows. The Value type is on the left and the Key type is in [] on the right of the object:

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

Official example 1: associative floating point  

float m[float];    // Define associated objects
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]);
}

  Official example 2: association string

char[30] namen[char []];                    // Define associated objects
strncpy(namen["Max"], "Mustermann", 30);    // Equivalent to namen["Max"] = "Mustermann"
strncpy(namen["Vector"], "Informatik", 30); // Equivalent to namen["Vector"] = "Informatik"

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

Associated fields CAPL functions:  

This test code uses the unique feature of the key in the map, takes the random number as the key, and the corresponding value can be any type of data (because it doesn't care, it is uniformly set to integer data 1), and then finds it through the:: containsKey() method.
If:: containsKey(randomNum) returns 1, it indicates that the key (random number randomNum) already exists. Otherwise, it will be inserted into the association type.


2. Test procedure

Assumptions:

  • Diagnostic physical request ID & response ID are 0x705 & 0x745 respectively
  • Get seed via secure access service $27 01 request (random number, 3 bytes)

The code is as follows (example):

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
  }
}


reference resources

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

Tags: vector

Posted on Fri, 15 Oct 2021 00:47:23 -0400 by transfield