1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /************* Include Files ****************/
8 #include "dx_rng.h"
9 #include "cc_pal_mem.h"
10 #include "cc_plat.h"
11 #include "dx_crys_kernel.h"
12 #include "cc_hal.h"
13 #include "cc_regs.h"
14 #include "dx_host.h"
15 #include "cc_rnd_error.h"
16 #include "llf_rnd_hwdefs.h"
17 #include "llf_rnd.h"
18 #include "llf_rnd_error.h"
19 #include "cc_sram_map.h"
20 #include "llf_rnd_trng.h"
21 #include "cc_config_trng90b.h"
22 #include "cc_int_general_defs.h"
23 
24 #ifndef CMPU_UTIL
25 #include "cc_pal_mutex.h"
26 #include "cc_pal_abort.h"
27 #include "cc_util_pm.h"
28 #endif
29 
30 #define ROSC_INIT_START_BIT   0x80000000
31 
32 #define LLF_RND_TRNG90B_MAX_BYTES ( LLF_RND_HW_DMA_EHR_SAMPLES_NUM_ON_TRNG90B_MODE * LLF_RND_HW_TRNG_EHR_WIDTH_IN_BYTES)
33 #define CC_CONFIG_TRNG90B_ADAPTIVE_PROPORTION_WINDOW_SIZE      1024     // binary noise source
34 
35 #if !defined(CMPU_UTIL) && !defined(SC_TEST_MODE)
36 extern CC_PalMutex *pCCRndCryptoMutex;
37 
38 #define MUTEX_LOCK_AND_RETURN_UPON_ERROR(pmutex) \
39         if (CC_PalMutexLock(pmutex, CC_INFINITE) != CC_SUCCESS) { \
40             CC_PalAbort("Fail to acquire mutex\n"); \
41         }
42 
43 #define MUTEX_UNLOCK(pmutex) \
44         if (CC_PalMutexUnlock(pmutex) != CC_SUCCESS) { \
45             CC_PalAbort("Fail to release mutex\n"); \
46         }
47 
48 #define DECREASE_CC_COUNTER \
49         if (CC_IS_IDLE != CC_SUCCESS) { \
50             CC_PalAbort("Fail to decrease PM counter\n"); \
51         }
52 
53 #define INCREASE_CC_COUNTER \
54         if (CC_IS_WAKE != CC_SUCCESS) { \
55             CC_PalAbort("Fail to increase PM counter\n"); \
56         }
57 
58 #else
59 #define MUTEX_LOCK_AND_RETURN_UPON_ERROR(mutex)
60 #define MUTEX_UNLOCK(mutex)
61 #define DECREASE_CC_COUNTER
62 #define INCREASE_CC_COUNTER
63 #endif
64 
65 /*********************************** Enums ******************************/
66 /*********************************Typedefs ******************************/
67 
68 /**************** Global Data to be read by RNG function ****************/
69 
70 /* test variables */
71 #ifdef RND_TEST_TRNG_WITH_ESTIMATOR
72 uint32_t  gEntrSize[4];
73 #endif
74 
75 
76 /******************************************************************************/
77 /***************   Prototypes and Private functions    ************************/
78 /******************************************************************************/
79 static CCError_t startTrngHW(
80         CCRndState_t  *rndState_ptr,
81         CCRndParams_t *trngParams_ptr,
82         CCBool_t           isRestart,
83         uint32_t          *roscsToStart_ptr,
84         CCBool_t           isStartup);
85 static CCError_t getTrngSource(CCRndState_t  *rndState_ptr,
86                  CCRndParams_t  *trngParams_ptr,
87                  CCBool_t            isContinued,
88                  uint32_t        **sourceOut_ptr_ptr,
89                  uint32_t         *sourceOutSize_ptr,
90                  uint32_t         *rndWorkBuff_ptr,
91                  CCBool_t          isStartup);
92 static CCError_t runContinuousTesting(uint32_t* pData, uint32_t sizeInBytes, CCRndParams_t  *trngParams_ptr);
93 CCError_t LLF_RND_RepetitionCounterTest(uint32_t* pData, uint32_t sizeInBytes, uint32_t C);
94 CCError_t LLF_RND_AdaptiveProportionTest(uint32_t* pData, uint32_t sizeInBytes, uint32_t C, uint32_t W);
95 static CCError_t LLF_RND_TRNG_ReadMultipleEHR(uint32_t inSize, uint8_t *ramAddr,
96                                     CCRndState_t  *rndState_ptr,
97                                     CCRndParams_t *trngParams_ptr,
98                                     uint32_t *roscsToStart_ptr);
99 static int32_t LLF_RND_TRNG_ReadEhrData(uint32_t *sample,
100                             CCRndState_t  *rndState_ptr,
101                             CCRndParams_t *trngParams_ptr,
102                             uint32_t *roscsToStart_ptr);
103 static uint32_t LLF_RND_TRNG_RoscMaskToNum(uint32_t mask);
104 static void LLF_RND_TRNG_EnableRngSourceAndWatchdog(CCRndParams_t *trngParams_ptr, CCBool_t isStartup);
105 
106 
107 /************************************************************************************/
108 /**
109  * The function checks that parameters, loaded in the TRNG HW
110  * are match to parameters, required by trngParams_ptr structures.
111  *
112  * @author reuvenl (6/25/2012)
113  *
114  * @param trngParams_ptr
115  *
116  * @return CCError_t
117  */
LLF_RND_TRNG_CheckHwParams(CCRndParams_t * trngParams_ptr)118 static CCError_t LLF_RND_TRNG_CheckHwParams(CCRndParams_t *trngParams_ptr)
119 {
120     uint32_t temp;
121     CCBool_t isTrue = CC_TRUE;
122 
123     /* check Debug control - masked TRNG tests according to mode */
124     temp = CC_HAL_READ_REGISTER(CC_REG_OFFSET(RNG, TRNG_DEBUG_CONTROL));
125     isTrue &= (temp == LLF_RND_HW_DEBUG_CONTROL_VALUE_ON_TRNG90B_MODE);
126     /* check samplesCount */
127     temp = CC_HAL_READ_REGISTER(CC_REG_OFFSET(RNG,SAMPLE_CNT1));
128     isTrue &= (temp == trngParams_ptr->SubSamplingRatio);
129 
130     /* if any parameters are not match return an Error */
131     if (isTrue == CC_FALSE)
132         return LLF_RND_TRNG_PREVIOUS_PARAMS_NOT_MATCH_ERROR;
133     else
134         return CC_OK;
135 }
136 
137 /****************************************************************************************/
138 /*****************************       Public Functions      ******************************/
139 /****************************************************************************************/
140 
LLF_RND_StartTrngHW(CCRndState_t * rndState_ptr,CCRndParams_t * trngParams_ptr,CCBool_t isRestart,uint32_t * roscsToStart_ptr)141 CCError_t LLF_RND_StartTrngHW(
142         CCRndState_t  *rndState_ptr,
143         CCRndParams_t *trngParams_ptr,
144         CCBool_t           isRestart,
145         uint32_t         *roscsToStart_ptr)
146 {
147         CCError_t error = CC_OK;
148         error = startTrngHW(rndState_ptr, trngParams_ptr, isRestart, roscsToStart_ptr, CC_FALSE/*isStartup*/);
149 
150         return error;
151 }
152 
153 
LLF_RND_GetTrngSource(CCRndState_t * rndState_ptr,CCRndParams_t * trngParams_ptr,CCBool_t isContinued,uint32_t * entropySize_ptr,uint32_t ** sourceOut_ptr_ptr,uint32_t * sourceOutSize_ptr,uint32_t * rndWorkBuff_ptr,bool isFipsSupported)154 CCError_t LLF_RND_GetTrngSource(
155                  CCRndState_t  *rndState_ptr,      /*in/out*/
156                  CCRndParams_t  *trngParams_ptr,   /*in/out*/
157                  CCBool_t            isContinued,    /*in*/
158                  uint32_t         *entropySize_ptr,  /*in/out*/
159                  uint32_t        **sourceOut_ptr_ptr,   /*out*/
160                  uint32_t         *sourceOutSize_ptr,/*in/out*/
161                  uint32_t         *rndWorkBuff_ptr,      /*in*/
162                  bool              isFipsSupported)      /*in*/
163 {
164     CCError_t error = CC_OK;
165 
166     CC_UNUSED_PARAM(entropySize_ptr);
167     CC_UNUSED_PARAM(isFipsSupported);
168 
169     /* Lock mutex, check fatal err, and increase cc counter*/
170     MUTEX_LOCK_AND_RETURN_UPON_ERROR(pCCRndCryptoMutex);
171 
172     CC_IS_FATAL_ERR_ON(error);
173     if (error == CC_TRUE) {
174             error = LLF_RND_TRNG_GENERATION_NOT_COMPLETED_ERROR;
175             goto EndUnlockMutex;
176     }
177 
178     INCREASE_CC_COUNTER
179 
180     /*Function Logic:*/
181     error = getTrngSource(rndState_ptr, trngParams_ptr, isContinued,
182                   sourceOut_ptr_ptr, sourceOutSize_ptr, rndWorkBuff_ptr, CC_FALSE/* isStartup*/);
183 
184     /* release mutex and decrease CC counter */
185     DECREASE_CC_COUNTER
186 
187 EndUnlockMutex:
188     MUTEX_UNLOCK(pCCRndCryptoMutex);
189     return error;
190 }
191 
LLF_RND_RunTrngStartupTest(CCRndState_t * rndState_ptr,CCRndParams_t * trngParams_ptr,uint32_t * rndWorkBuff_ptr)192 CCError_t LLF_RND_RunTrngStartupTest(
193         CCRndState_t        *rndState_ptr,
194         CCRndParams_t       *trngParams_ptr,
195         uint32_t                *rndWorkBuff_ptr)
196 {
197     CCError_t error = CC_OK;
198 
199     uint32_t        *pSourceOut;
200     uint32_t         sourceOutSize;
201 
202         error = getTrngSource(rndState_ptr, trngParams_ptr, CC_FALSE/*isContinued*/,
203                   &pSourceOut, &sourceOutSize, rndWorkBuff_ptr, CC_TRUE/* isStartup*/);
204 
205     return error;
206 }
207 
startTrngHW(CCRndState_t * rndState_ptr,CCRndParams_t * trngParams_ptr,CCBool_t isRestart,uint32_t * roscsToStart_ptr,CCBool_t isStartup)208 static CCError_t startTrngHW(
209         CCRndState_t  *rndState_ptr,
210         CCRndParams_t *trngParams_ptr,
211         CCBool_t          isRestart,
212         uint32_t         *roscsToStart_ptr,
213     CCBool_t      isStartup)
214 {
215         /* LOCAL DECLARATIONS */
216 
217         CCError_t error = CC_OK;
218         uint32_t tmpSamplCnt = 0;
219         uint32_t roscNum = 0;
220 #ifdef CC_IOT
221         uint32_t mask = 0;
222 #endif
223         /* FUNCTION LOGIC */
224 
225         /* Check pointers */
226         if ((rndState_ptr == NULL) || (trngParams_ptr == NULL) ||
227                 (roscsToStart_ptr == NULL))
228                 return LLF_RND_TRNG_ILLEGAL_PTR_ERROR;
229 
230 
231         /*--------------------------------------------------------------*/
232         /* 1. If full restart, get semaphore and set initial ROSCs      */
233         /*--------------------------------------------------------------*/
234         if (isRestart) {
235                 /* set ROSC to 1 (fastest)  */
236                 *roscsToStart_ptr = 1UL;
237 
238                 /* init rndState flags to zero */
239                 rndState_ptr->TrngProcesState = 0;
240         }
241 
242 
243         if (*roscsToStart_ptr == 0)
244                 return LLF_RND_TRNG_REQUIRED_ROSCS_NOT_ALLOWED_ERROR;
245 
246 
247         /* Get fastest allowed ROSC */
248         error = LLF_RND_GetFastestRosc(
249                 trngParams_ptr,
250                 roscsToStart_ptr     /*in/out*/);
251         if (error)
252                 return error;
253 
254         error = LLF_RND_GetRoscSampleCnt(*roscsToStart_ptr, trngParams_ptr);
255         if (error)
256                 return error;
257 
258         roscNum = LLF_RND_TRNG_RoscMaskToNum(*roscsToStart_ptr);
259 
260         /* 2. Restart the TRNG and set parameters and enable the HW RND clock   */
261         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_CLK_ENABLE), LLF_RND_HW_RND_CLK_ENABLE_VAL);
262 
263         /* do software reset */
264         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_SW_RESET), 0x1);
265         /* in order to verify that the reset has completed the sample count need to be verified */
266         do {
267                 /* enable the HW RND clock   */
268                 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_CLK_ENABLE), LLF_RND_HW_RND_CLK_ENABLE_VAL);
269 
270                 /* set sampling ratio (rng_clocks) between consecutive bits */
271                 CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, SAMPLE_CNT1), trngParams_ptr->SubSamplingRatio);
272 
273                 /* read the sampling ratio  */
274                 tmpSamplCnt = CC_HAL_READ_REGISTER(CC_REG_OFFSET(RNG, SAMPLE_CNT1));
275 
276         } while (tmpSamplCnt != trngParams_ptr->SubSamplingRatio);
277 
278 
279         /* disable the RND source for setting new parameters in HW */
280         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RND_SOURCE_ENABLE), LLF_RND_HW_RND_SRC_DISABLE_VAL);
281 
282         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_ICR), 0xFFFFFFFF);
283 
284         /* set interrupt mask */
285         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_IMR), LLF_RNG_INT_MASK_ON_TRNG90B_MODE);
286 
287         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, TRNG_CONFIG), roscNum);
288 
289 #ifdef CC_IOT
290         /* mask RNG_INT - this interrupt should be polled upon,
291          * and not handled by the operating system's interrupt handler. */
292         mask = CC_HAL_READ_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR));
293         CC_REG_FLD_SET(HOST_RGF, HOST_IMR, RNG_INT_MASK, mask, 1);
294         CC_HalMaskInterrupt(mask);
295 #endif
296 
297         /* Debug Control register: set to 0 - no bypasses */
298         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, TRNG_DEBUG_CONTROL), LLF_RND_HW_DEBUG_CONTROL_VALUE_ON_TRNG90B_MODE);
299 
300         LLF_RND_TRNG_EnableRngSourceAndWatchdog(trngParams_ptr, isStartup);
301 
302         /* set indication about current started ROSCs:  */
303         /*new started*/
304         rndState_ptr->TrngProcesState = (rndState_ptr->TrngProcesState & 0x00ffffff) | (*roscsToStart_ptr << 24);
305         /*total started*/
306         rndState_ptr->TrngProcesState |= (*roscsToStart_ptr << 8);
307 
308         return error;
309 }
310 
311 
312 
313 
LLF_RND_TRNG_RoscMaskToNum(uint32_t mask)314 static uint32_t LLF_RND_TRNG_RoscMaskToNum(uint32_t mask)
315 {
316         return (mask == LLF_RND_HW_TRNG_ROSC3_BIT) ? LLF_RND_HW_TRNG_ROSC3_NUM :
317                 (mask == LLF_RND_HW_TRNG_ROSC2_BIT) ? LLF_RND_HW_TRNG_ROSC2_NUM :
318                 (mask == LLF_RND_HW_TRNG_ROSC1_BIT) ? LLF_RND_HW_TRNG_ROSC1_NUM :
319                 LLF_RND_HW_TRNG_ROSC0_NUM;
320 }
321 
getTrngSource(CCRndState_t * rndState_ptr,CCRndParams_t * trngParams_ptr,CCBool_t isContinued,uint32_t ** sourceOut_ptr_ptr,uint32_t * sourceOutSize_ptr,uint32_t * rndWorkBuff_ptr,CCBool_t isStartup)322 static CCError_t getTrngSource(
323                 CCRndState_t  *rndState_ptr,      /*in/out*/
324                 CCRndParams_t  *trngParams_ptr,   /*in/out*/
325                 CCBool_t            isContinued,    /*in*/
326                 uint32_t        **sourceOut_ptr_ptr,   /*out*/
327                 uint32_t         *sourceOutSize_ptr,/*in/out*/
328                 uint32_t         *rndWorkBuff_ptr,     /*in*/
329                 CCBool_t          isStartup)           /*in*/
330 {
331     /* LOCAL DECLARATIONS */
332 
333     /* The return error identifier */
334     CCError_t error = 0;
335     int32_t  i;
336     uint32_t roscToStart;
337     uint32_t *ramAddr;
338     uint32_t trng90bRequiredBytes;
339 
340     /* FUNCTION LOGIC */
341     /* ............... local initializations .............................. */
342     /* -------------------------------------------------------------------- */
343 
344     /* initializing the Error to O.K */
345     error = CC_OK;
346 
347     if(isStartup == CC_FALSE) {
348         trng90bRequiredBytes = trngParams_ptr->userParams.trngModeParams.numOfBytes;
349     } else {
350         trng90bRequiredBytes = CC_CONFIG_TRNG90B_AMOUNT_OF_BYTES_STARTUP;
351     }
352 
353     /* Set source RAM address with offset 8 bytes from sourceOut address in
354       order to remain empty bytes for CC operations */
355     *sourceOut_ptr_ptr = rndWorkBuff_ptr + CC_RND_SRC_BUFF_OFFSET_WORDS;
356     ramAddr = *sourceOut_ptr_ptr + CC_RND_TRNG_SRC_INNER_OFFSET_WORDS;
357 
358     /* init to 0 for FE mode */
359     *sourceOutSize_ptr = 0;
360 #ifndef USE_MBEDTLS_CRYPTOCELL
361     /* Case of RND KAT or TRNG KAT testing  */
362     if (rndState_ptr->StateFlag & CC_RND_KAT_TRNG_Mode) {
363         return CC_RND_KAT_DATA_PARAMS_ERROR;
364     }
365 
366     if (rndState_ptr->StateFlag & CC_RND_KAT_DRBG_Mode) {
367 
368         /* set source sizes given by the user in KAT test and placed
369            in the rndWorkBuff with offset CC_RND_SRC_BUFF_OFFSET_WORDS */
370         *sourceOutSize_ptr = (*sourceOut_ptr_ptr)[0];
371         if (*sourceOutSize_ptr == 0) {
372             return CC_RND_KAT_DATA_PARAMS_ERROR;
373         }
374         goto End;
375     }
376 #endif
377     /* If not continued mode, set TRNG parameters and restart TRNG  */
378     /*--------------------------------------------------------------*/
379     if (isContinued == CC_FALSE) {
380 
381         /* Set instantiation, TRNG errors and time   *
382         * exceeding bits of State to 0           */
383 #ifndef USE_MBEDTLS_CRYPTOCELL
384         rndState_ptr->StateFlag &= ~(CC_RND_INSTANTIATED |
385                          CC_RND_INSTANTRESEED_AUTOCORR_ERRORS |
386                          CC_RND_INSTANTRESEED_TIME_EXCEED |
387                          CC_RND_INSTANTRESEED_LESS_ENTROPY);
388 #endif
389         /* Full restart TRNG */
390                 error = startTrngHW(
391                        rndState_ptr,
392                        trngParams_ptr,
393                        CC_TRUE/*isRestart*/,
394                        &roscToStart,
395                        isStartup);
396 
397         /*Note: in case of error the TRNG HW is still not started*/
398         if (error)
399             goto End;
400     }
401 
402     /* On continued mode check HW TRNG */
403     else {
404         /* check TRNG parameters */
405         error = LLF_RND_TRNG_CheckHwParams(trngParams_ptr);
406         if (error != CC_OK){
407                 goto End;
408         }
409 
410         /* previously started ROSCs */
411         roscToStart = (rndState_ptr->TrngProcesState & 0xff000000)>>24;
412     }
413 
414     /*====================================================*/
415     /*====================================================*/
416     /*         Processing after previous start            */
417     /*====================================================*/
418     /*====================================================*/
419 
420     /*====================================================*/
421     /* TRNG90b mode processing: start Roscs sequentionally - *
422     * from fast to slow Rosc                  */
423     /*====================================================*/
424 
425     for (i = 0; i < LLF_RND_NUM_OF_ROSCS; ++i) {
426         *sourceOutSize_ptr = trng90bRequiredBytes;
427 
428         error = LLF_RND_TRNG_ReadMultipleEHR(*sourceOutSize_ptr, (uint8_t *)ramAddr,
429                         rndState_ptr,
430                         trngParams_ptr,
431                         &roscToStart);
432 
433         if (error == CC_OK) {
434             error = runContinuousTesting(ramAddr, trng90bRequiredBytes, trngParams_ptr);
435             if (error == CC_OK) {
436                 break;
437             }
438             *sourceOutSize_ptr = 0;
439         }
440         if (error == LLF_RND_CRNGT_TEST_FAIL_ERROR) {
441             /* LLF_RND_CRNGT_TEST_FAIL_ERROR is set only in FIPS mode. do not continue to the next rosc. */
442             break;
443         }
444         if (error != CC_OK) {/* try next rosc */
445             /*  if no remain roscs to start, return error */
446             if (roscToStart == 0x8) {
447                 error = LLF_RND_TRNG_GENERATION_NOT_COMPLETED_ERROR;
448                 break;
449             }
450             else {
451                 /* Call StartTrng, with next ROSC */
452                 roscToStart <<= 1;
453                 error = LLF_RND_StartTrngHW(
454                     rndState_ptr,
455                     trngParams_ptr,
456                     CC_FALSE/*isRestart*/,
457                     &roscToStart);
458 
459                 /* if no remain valid roscs, return error */
460                 if (error == LLF_RND_TRNG_REQUIRED_ROSCS_NOT_ALLOWED_ERROR && (trngParams_ptr->RoscsAllowed != 0)) {
461 
462                     error = LLF_RND_TRNG_GENERATION_NOT_COMPLETED_ERROR;
463                 }
464 
465                 if (error != CC_OK) {
466                     goto End;
467                 }
468             }
469         }
470 
471 
472         /* update total processed ROSCs */
473         rndState_ptr->TrngProcesState |= ((rndState_ptr->TrngProcesState >> 8) & 0x00FF0000);
474         /*clean started & not processed*/
475         rndState_ptr->TrngProcesState &= 0x00FFFFFF;
476     }
477 
478     /* ................. end of function ..................................... */
479     /* ----------------------------------------------------------------------- */
480     End:
481 
482     CLEAR_TRNG_SRC();
483     /* turn the RNG off    */
484 #ifndef USE_MBEDTLS_CRYPTOCELL
485     if ((rndState_ptr->StateFlag & CC_RND_KAT_TRNG_Mode) == 0) {
486         LLF_RND_TurnOffTrng();
487     }
488 #else
489     LLF_RND_TurnOffTrng();
490 #endif
491 
492     return error;
493 }/* END of getTrngSource */
494 
495 
496 /*
497 implementation of Continuous Testing (NIST SP 800-90B 6.5.1.2)
498 */
499 
runContinuousTesting(uint32_t * pData,uint32_t sizeInBytes,CCRndParams_t * trngParams_ptr)500 static CCError_t runContinuousTesting(uint32_t* pData,
501                                       uint32_t sizeInBytes,
502                                       CCRndParams_t  *trngParams_ptr)
503 {
504     CCError_t error = CC_OK;
505     uint32_t repC = trngParams_ptr->userParams.trngModeParams.repetitionCounterCutoff;
506     uint32_t adpW = CC_CONFIG_TRNG90B_ADAPTIVE_PROPORTION_WINDOW_SIZE;
507     uint32_t adpC = trngParams_ptr->userParams.trngModeParams.adaptiveProportionCutOff;
508 
509 
510     error = LLF_RND_RepetitionCounterTest(pData, sizeInBytes, repC);
511     if (error != CC_OK) {
512         return error;
513     }
514         error = LLF_RND_AdaptiveProportionTest(pData, sizeInBytes, adpC, adpW);
515     if (error != CC_OK) {
516         return error;
517     }
518 
519         return CC_OK;
520 }
521 
522 #define UINT8_SIZE_IN_BITS  8
523 #define UINT32_SIZE_IN_BITS (sizeof(uint32_t) * UINT8_SIZE_IN_BITS)
getBitsFromUint32Array(uint32_t arrayBitsOffset,uint32_t numOfBits,uint32_t * arr)524 static uint32_t getBitsFromUint32Array(uint32_t arrayBitsOffset, uint32_t numOfBits, uint32_t* arr)
525 {
526     uint32_t res = 0;
527     uint32_t byteOffset = arrayBitsOffset / UINT32_SIZE_IN_BITS;
528     uint32_t bitOffset = arrayBitsOffset % UINT32_SIZE_IN_BITS;
529     if (numOfBits > UINT32_SIZE_IN_BITS) {
530         return 0;
531     }
532     res = arr[byteOffset] >> bitOffset;
533     // (UINT32_SIZE_IN_BITS - bitOffset) bits were taken from the first dword.
534 
535     if (UINT32_SIZE_IN_BITS - bitOffset > numOfBits)
536     // we copied more bits than required. zero the extra bits.
537     {
538         res &= (0xFFFFFFFF >> (UINT32_SIZE_IN_BITS - numOfBits));
539     } else if (UINT32_SIZE_IN_BITS - bitOffset < numOfBits)
540     // we copied less bits than required. copy the next bits from the next dword.
541     {
542         numOfBits -= UINT32_SIZE_IN_BITS - bitOffset;
543         res |= (arr[byteOffset + 1] & (0xFFFFFFFF >> (UINT32_SIZE_IN_BITS - numOfBits))) << (UINT32_SIZE_IN_BITS - bitOffset);
544     }
545 
546     return res;
547 }
548 
549 /*
550 implementation of Repetition Counter Test (NIST SP 800-90B (2nd Draft) 4.4.1)
551 C = the cutoff value at which the Repetition Count Test fails
552 */
LLF_RND_RepetitionCounterTest(uint32_t * pData,uint32_t sizeInBytes,uint32_t C)553 CCError_t LLF_RND_RepetitionCounterTest(uint32_t* pData, uint32_t sizeInBytes, uint32_t C)
554 {
555     uint32_t bitOffset=0;
556     uint32_t newSample = 0;
557     uint32_t A = 0;         /* the most recently seen sample value */
558     uint32_t B = 0;         /* the number of consecutive times that the value A has been seen */
559     uint32_t bitsPerSample = 1; /* always use single bit per sample for repetition counter test */
560 
561 
562         if (pData == NULL || sizeInBytes == 0 || LLF_RND_TRNG90B_MAX_BYTES < sizeInBytes) {
563         return LLF_RND_TRNG_REPETITION_COUNTER_ERROR;
564     }
565 
566         // the repetition count test is performed as follows:
567     for (bitOffset = 0; bitOffset <= (sizeInBytes * UINT8_SIZE_IN_BITS) - bitsPerSample; bitOffset += bitsPerSample) {
568         newSample = getBitsFromUint32Array(bitOffset, bitsPerSample, (uint32_t*)pData);
569 
570         // 1. Let A be the current sample value.
571         // 2. Initialize the counter B to 1.
572         if (bitOffset == 0) {
573             A = newSample;
574             B = 1;
575         }
576         // 3. If the next sample value is A, increment B by one.
577         else if (A == newSample) {
578             ++B;
579                         // If B is equal to C, return an error.
580             if (B == C) {
581                                 return LLF_RND_TRNG_REPETITION_COUNTER_ERROR;
582             }
583         } else {
584                         // Let A be the next sample value.
585             A = newSample;
586                         // Initialize the counter B to 1.
587             B = 1;
588                         // Repeat Step 3.
589         }
590     }
591     return CC_OK;
592 }
593 
594 /*
595 implementation of Adaptive Proportion Test (NIST SP 800-90B (2nd Draft) 4.4.2)
596 N = the total number of samples that must be observed in one run of the test, also known as the "window size" of the test
597 C = the cutoff value above which the test should fail
598 */
LLF_RND_AdaptiveProportionTest(uint32_t * pData,uint32_t sizeInBytes,uint32_t C,uint32_t W)599 CCError_t LLF_RND_AdaptiveProportionTest(uint32_t* pData, uint32_t sizeInBytes, uint32_t C, uint32_t W)
600 {
601     uint32_t bitOffset=0;
602     uint32_t currentSample = 0;
603     uint32_t A = 0;         /* the sample value currently being counted */
604         uint32_t B = 0;         /* the current number of times that A has been seen in the S samples examined so far */
605         uint32_t i = 0;         /* the counter for the number of samples examined in the current window */
606         uint32_t bitsPerSample = 1; /* binary source */
607 
608     if (pData == NULL || sizeInBytes == 0 || LLF_RND_TRNG90B_MAX_BYTES < sizeInBytes || W == 0 || C == 0) {
609         return LLF_RND_TRNG_ADAPTION_PROPORTION_ERROR;
610     }
611 
612     // The test is performed as follows:
613     for (bitOffset = 0; bitOffset <= (sizeInBytes * UINT8_SIZE_IN_BITS) - bitsPerSample; bitOffset += bitsPerSample) {
614         currentSample = getBitsFromUint32Array(bitOffset, bitsPerSample, (uint32_t*)pData);
615 
616                 // 1. Let A be the current sample value.
617                 // 2. Initialize the counter B to 1
618                 if ((bitOffset == 0) || (i == W)) {
619                         A = currentSample;
620                         B = 1;
621                         i = 0;
622                 }
623                 // 3. For i = 1 to W-1
624                 else {
625                         // If the next sample is equal to A, increment B by 1.
626                         if (A == currentSample) {
627                                 ++B;
628                         }
629                 }
630                 // 4. If B > C, return error.
631                 if (i == W - 1) {
632                         if (B > C) {
633                                 return LLF_RND_TRNG_ADAPTION_PROPORTION_ERROR;
634                         }
635                 }
636                 ++i;
637                 // 5. Go to Step 1.
638     }
639     return CC_OK;
640 }
641 
LLF_RND_TRNG_ReadEhrData(uint32_t * sample,CCRndState_t * rndState_ptr,CCRndParams_t * trngParams_ptr,uint32_t * roscsToStart_ptr)642 static int32_t LLF_RND_TRNG_ReadEhrData(uint32_t *sample,
643                             CCRndState_t  *rndState_ptr,
644                             CCRndParams_t *trngParams_ptr,
645                             uint32_t *roscsToStart_ptr)
646 {
647     uint32_t i;
648     CCError_t err = CC_OK;
649     uint32_t isr = 0;
650 
651     err = startTrngHW(rndState_ptr, trngParams_ptr, CC_FALSE, roscsToStart_ptr, CC_FALSE);
652     if (err) {
653         return err;
654     }
655 
656     /* wait RNG interrupt: isr signals error bits */
657     err = LLF_RND_WaitRngInterrupt(&isr);
658     if (err != CC_OK){
659             return err;
660     }
661 
662     err = LLF_RND_TRNG_REQUIRED_ROSCS_NOT_ALLOWED_ERROR;
663     if (CC_REG_FLD_GET(0, RNG_ISR, EHR_VALID, isr)) {
664             err = CC_OK;
665     }
666 
667     /* Read EHR into tmp buffer */
668     for (i = 0; i < LLF_RND_HW_TRNG_EHR_WIDTH_IN_WORDS; i++) {
669         uint32_t ehr = CC_HAL_READ_REGISTER(DX_EHR_DATA_0_REG_OFFSET + (i * sizeof(uint32_t)));
670         sample[i] = ehr;
671     }
672 
673     return CC_OK;
674 }
675 
LLF_RND_TRNG_ReadMultipleEHR(uint32_t inSize,uint8_t * ramAddr,CCRndState_t * rndState_ptr,CCRndParams_t * trngParams_ptr,uint32_t * roscsToStart_ptr)676 static CCError_t LLF_RND_TRNG_ReadMultipleEHR(uint32_t inSize, uint8_t *ramAddr,
677                                     CCRndState_t  *rndState_ptr,
678                                     CCRndParams_t *trngParams_ptr,
679                                     uint32_t *roscsToStart_ptr)
680 {
681     uint32_t noise_samples[LLF_RND_HW_TRNG_EHR_WIDTH_IN_WORDS];
682     CCError_t err = CC_OK;
683     uint32_t  final_chunk_size=0;
684     uint32_t counter = 0;
685     /* in case inSize is not divided by 6, copy partial last chunk */
686     if (inSize % LLF_RND_HW_TRNG_EHR_WIDTH_IN_WORDS){
687             final_chunk_size = inSize % LLF_RND_HW_TRNG_EHR_WIDTH_IN_WORDS;
688     }
689     while (inSize) {
690         LLF_RND_TurnOffTrng();
691         err = LLF_RND_TRNG_ReadEhrData(noise_samples, rndState_ptr, trngParams_ptr, roscsToStart_ptr);
692         if (err != CC_OK) {
693             return err;
694         }
695         if ((counter == inSize/LLF_RND_HW_TRNG_EHR_WIDTH_IN_WORDS) && (final_chunk_size != 0))
696     {
697             /* Copy the needed amount of bytes to the result buffer */
698             CC_PalMemCopy(ramAddr, (uint8_t *)noise_samples, final_chunk_size);
699                 inSize -= final_chunk_size;
700                 ramAddr += final_chunk_size;
701     }
702         else{
703             /* Copy the needed amount of bytes to the result buffer */
704             CC_PalMemCopy(ramAddr, (uint8_t *)noise_samples, LLF_RND_HW_TRNG_EHR_WIDTH_IN_BYTES);
705                 inSize -= LLF_RND_HW_TRNG_EHR_WIDTH_IN_BYTES;
706                 ramAddr += LLF_RND_HW_TRNG_EHR_WIDTH_IN_BYTES;
707         }
708         counter++;
709     }
710 
711     return CC_OK;
712 }
713 
LLF_RND_TRNG_EnableRngSourceAndWatchdog(CCRndParams_t * trngParams_ptr,CCBool_t isStartup)714 static void LLF_RND_TRNG_EnableRngSourceAndWatchdog(CCRndParams_t *trngParams_ptr, CCBool_t isStartup)
715 {
716         uint32_t maxCycles;
717         uint32_t ehrSamples;
718 
719     if (isStartup == CC_TRUE) {
720             ehrSamples = CC_CONFIG_TRNG90B_AMOUNT_OF_BYTES_STARTUP;
721         } else {
722             ehrSamples = trngParams_ptr->userParams.trngModeParams.numOfBytes;
723         }
724         ehrSamples/= LLF_RND_HW_TRNG_EHR_WIDTH_IN_BYTES;
725 
726         /* Set watchdog threshold to maximal allowed time (in CPU cycles) */
727         maxCycles = LLF_RND_CalcMaxTrngTime(ehrSamples, trngParams_ptr->SubSamplingRatio);
728         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_WATCHDOG_VAL), maxCycles);
729 
730         /* enable the RND source */
731         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RND_SOURCE_ENABLE), LLF_RND_HW_RND_SRC_ENABLE_VAL);
732 }
733 
734