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