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 
9 #include "dx_rng.h"
10 #include "cc_pal_mem.h"
11 #include "cc_pal_types.h"
12 #include "cc_rng_plat.h"
13 #include "dx_crys_kernel.h"
14 #include "cc_hal.h"
15 #include "cc_regs.h"
16 #include "dx_host.h"
17 #include "cc_rnd_local.h"
18 #include "cc_rnd_error.h"
19 #include "llf_rnd_hwdefs.h"
20 #include "llf_rnd.h"
21 #include "llf_rnd_error.h"
22 #include "cc_sram_map.h"
23 #include "cc_address_defs.h"
24 #include "llf_rnd_trng.h"
25 #include "cc_aes_defs.h"
26 
27 
28 /********************************* Defines ******************************/
29 #ifndef max
30 #define max(a,b) (a) > (b) ? (a) : (b)
31 #endif
32 
33 /* definitions used in the Entropy Estimator functions */
34 #define S(a,n) ((uint32_t)((a) * (1<<(n)))) /* a scaled by n: a \times 2^n */
35 #define U(a,n) ((uint32_t)(a) >> (n)) /* unscale unsigned: a / 2^n */
36 #define SQR(x) (((x)&0xffff)*((x)&0xffff))
37 
38 /* macros for updating histogram for any separate bit;
39    where x represents cw  or e1 */
40 #define   LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, x ) \
41     h_ptr[x & 0xff]++;  \
42     ec_ptr[x & 0x7f] = ((ec_ptr[x & 0x7f] & 1) == ((x & 0xff) >> 7)) ? ec_ptr[x & 0x7f] + 2 : ec_ptr[x & 0x7f] ^ 1; \
43     x >>= 1;
44 
45 /* Entropy estimation histogram width (prefix size + 1) */
46 #define LLF_RND_nb   CC_RND_nb
47 #define LLF_RND_NB   CC_RND_NB
48 #define halfNB   (LLF_RND_NB / 2)
49 #define ROSC_INIT_START_BIT   0x80000000
50 
51 
52 /*********************************** Enums ******************************/
53 /*********************************Typedefs ******************************/
54 
55 /**************** Global Data to be read by RNG function ****************/
56 
57 
58 /* test variables */
59 #ifdef RND_TEST_TRNG_WITH_ESTIMATOR
60 uint32_t  gEntrSize[4];
61 #endif
62 
63 
64 /******************************************************************************/
65 /***************   Prototypes and Private functions    ************************/
66 /******************************************************************************/
67 /****************************************************************************/
68 /***********         Functions used for Entropy estimation      *************/
69 /****************************************************************************/
70 /**
71  * The function calculates low half of 32*32 bits multiplication result
72  *
73  * @param a
74  * @param b
75  *
76  * @return uint64_t
77  */
Mult32x32(uint32_t a,uint32_t b)78 uint64_t Mult32x32(uint32_t a, uint32_t b)
79 {
80     uint64_t res=0;
81 
82     res = (((a>>16)*(b>>16)) + (((a>>16)*(b&0xffff))>>16) + (((b>>16)*(a&0xffff))>>16));
83     res <<= 32;
84     res += (uint64_t)((a&0xffff)*(b&0xffff)) + (((a>>16)*(b&0xffff))<<16) + (((b>>16)*(a&0xffff))<<16);
85 
86     return res;
87 }
88 
89 /* Calculate 48*16 bits multiple using 16*16 bit multiplier */
90 /* Code ASM takes 62 bytes */
Mult48x16(uint64_t a,uint32_t b)91 uint64_t Mult48x16(uint64_t a, uint32_t b)
92 {
93     uint32_t a3 = (a >> 32), a2 = (a >> 16) & 0xffff, a1 = a & 0xffff;
94     uint32_t b1 = (b & 0xffff);
95     uint32_t r31 = a3*b1, r21 = a2*b1, r11 = a1*b1;
96     return(((uint64_t)r31) << 32) +
97     (((uint64_t)r21) << 16) +
98     ((uint64_t)r11);
99 }
100 
101 
102 /* approximation of entropy  */
103 /**
104  * @brief The function approximates the entropy for separate prefix
105  *        ae = n * log2(n/m).
106  *
107  *    Implementation according A.Klimov algorithm uses approximation by
108  *    polynomial: ae = (n-m)*(A1 + A2*x + A3*x^2), where x = (n-m)/n <= 0.5 .
109  *    The coefficients are defined above in this file.
110  *
111  * @param[in] n - The summ of  0-bits and 1-bits in the test.
112  * @param[in] m - The maximal from the two above named counts.
113  *
114  * @return - result value of entropy ae.
115  */
ae(uint32_t n,uint32_t m)116 static uint32_t ae(uint32_t n, uint32_t m)
117 {
118     /* logarithm calculation constants */
119     #define A1 1.4471280
120     #define A2 0.6073851
121     #define A3 0.9790318
122 
123 
124     uint32_t d = n-m,
125     x = S(d,16) / n,         /* x; 16 */
126         a = S(A3,14) * x,            /* x*A3; 30 */
127         b = U(S(A2,30) + a, 16) * x,     /* x*(A2 + x*A3); 30 */
128             c = (S(A1,30) + b),          /* (A1 + x*(A2 + x*A3)); 30 */
129             r = d * U(c,14);         /* result: 16 bits scaled */
130 
131     return r;
132 
133 }
134 
135 /*****************************************************************************/
136 /**
137  * @brief The function calculates a histogram of 0-s and 1-s distribution
138  *        depending on forgouing bits combination - prefix.
139  *
140  *     Implementation according A.Klimov algorithm modified by A.Ziv
141  *
142  * @param[in]  h_ptr - The pointer to the histogramm h buffer.
143  * @param[in]  ec_ptr - The pointer to the histogramm equality counter (ec) buffer.
144  * @param[in]  r_ptr - The pointer to Entropy source.
145  * @param[in]  nr    - The size of Entropy source in words.
146  * @param[in/out] pref_ptr - The pointer to last saved prefix.
147  * @param[in]  snp_ptr   - The pointer to the flag defining whether the new prefix should be set.
148  *
149  * @return CCError_t - no return value
150  */
LLF_RND_HistogramUpdate(uint32_t * h_ptr,uint32_t * ec_ptr,uint32_t * r_ptr,uint32_t nr)151 static void LLF_RND_HistogramUpdate(
152                    uint32_t   *h_ptr,     /* in/out */
153                    uint32_t   *ec_ptr,  /* in/out */
154                    uint32_t   *r_ptr,     /* in - input sequence */
155                    uint32_t     nr)    /* in - input sequence size in words */
156 {
157     int32_t   i;
158     uint32_t j = 0;
159     uint32_t  cW;   /*current word of sequence*/
160     uint32_t  pref;
161 
162     /* FUNCTION  LOGIC  */
163 
164     /*------------------------------------------------------*/
165     /* update for first word of sequence: begin new prefix  */
166     /*------------------------------------------------------*/
167     cW = r_ptr[0];
168     /* 25 sequences are purely from new bits */
169     for (i = 0; i < 5; i++) {
170         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, cW );
171         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, cW );
172         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, cW );
173         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, cW );
174         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, cW );
175     }
176 
177     pref = cW;
178     j = 1;
179 
180     /*-----------------------------------------------------------------------*/
181     /* update for remaining words of sequence: continue with previous prefix */
182     /*-----------------------------------------------------------------------*/
183     for (; j < nr; j++) {
184         uint32_t e1;
185 
186         /*current word of random sequence*/
187         cW = r_ptr[j];
188         /* concatenation of previous saved prefix and new bits */
189         e1 = (cW << 7) | pref;
190 
191         /* first 7 sequences are combined from previous prefix and new bits  */
192         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, e1 );
193         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, e1 );
194         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, e1 );
195         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, e1 );
196         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, e1 );
197         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, e1 );
198         LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, e1 );
199 
200         /* next 25 sequences are purely from new bits */
201         for (i = 0; i < 5; i++) {
202             LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, cW );
203             LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, cW );
204             LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, cW );
205             LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, cW );
206             LLF_RND_UpdateHistOneBit( h_ptr, ec_ptr, cW );
207         }
208 
209         pref = cW;
210     }
211 
212 } /* End of LLF_RND_HistogramUpdate() */
213 
214 
215 /*****************************************************************************/
216 /**
217  * @brief The function calculates estimation of entropy, generated by TRNG and
218  *        used for control the TRNG work.
219  *
220  *   Implementation based on algorithm developed by A.Klimov.
221  *
222  * @param[in] h - The pointer to the h-buffer (counts of 0-s and 1-s for each prefix).
223  * @param[in] ec - The pointer to the ec-buffer (equality counters).
224  * @param[out] e_ptr - The pointer to count of accumulated Entropy (bits multiplied by 2^16).
225  *
226  * @return CCError_t - according to module definitions
227  */
LLF_RND_EntropyEstimate(uint32_t * h,uint32_t * ec,uint32_t * e_ptr)228 static CCError_t LLF_RND_EntropyEstimate(
229                       uint32_t *h, /*in/out*/
230                       uint32_t *ec,
231                       uint32_t *e_ptr ) /* out - result Entropy size */
232 {
233 
234     uint64_t t = 0;        /* total entropy */
235     uint32_t i, ac = 0;        /* number of active prefixes */
236 
237 
238     /*-------------  calculate entropy -----------------*/
239 
240     for (i = 0; i < halfNB; ++i) {
241 
242         uint32_t n = h[i] + h[i+halfNB], m = max(h[i], h[i+halfNB]);
243 
244         /* check that n < 2^16, else return overflow error */
245         if (n >= (1UL<<16))
246             return LLF_RND_TRNG_ENTR_ESTIM_SIZE_EXCEED_ERROR;
247 
248         if (n != m) { /* if active prefix */
249             uint32_t n2, pp, od;
250             uint64_t od2, od2n, var;
251 
252             /* increment count of active prefixes */
253             ++ac;
254 
255             pp = SQR(m) + SQR(n-m);       /* related to theoretical "autocorrelation" probability */
256             n2 = Mult16x16((ec[i]>>1),n); /* n2 used as temp */
257 
258             /* value, related to observed deviation of autocorrelation */
259             if (n2 > pp)
260                 od = n2 - pp;
261             else
262                 od = pp - n2;
263 
264             /* theoretical variance of B(n, pp): always > 0 */
265             n2 = SQR(n);
266             var = Mult32x32(pp,(n2-pp));
267 
268             /* if  n*od^2 < var then accumulate entropy, else return Error;
269                Note: that this condition is True only if od < 2^32 */
270             if (od != CC_MAX_UINT32_VAL) {
271                 od2 = Mult32x32(od, od);
272 
273                 /* scale variables */
274                 if (od2 > ((uint64_t)1ULL << 48)) {
275                     od2 /= (1UL<<16);
276                     var /= (1UL<<16);
277                 }
278 
279                 od2n = Mult48x16(od2, n);
280 
281                 if (od2n < var)
282                     t += ae(n, m);
283             }
284         }
285     }
286 
287     /* output entropy size value in bits (rescaled) */
288 
289     *e_ptr = ac > 3 ? (t / (1UL << 16)) : 0;
290 
291     return CC_OK;
292 
293 } /* End of LLF_RND_EntropyEstimate */
294 
295 /*****************************************************************************/
296 /**
297  * @brief The function calculates estimation of entropy, generated by 4 ROSCs
298  *
299  * @param[in] ramAddr - The pointer to random source.
300  * @param[in] blockSizeWords - The size of each block of random source in words.
301  * @param[in] countBlocks - The blocks count (according to given ROSCS).
302  * @param[in] h_ptr - The pointer to the h-buffer (counts of 0-s and 1-s for each prefix).
303  * @param[in] ec_ptr - The pointer to the ec-buffer (equality counters).
304  * @param[out] entrSize_ptr - The pointer to count of accumulated Entropy in bits.
305  * @param[in] rndContext_ptr - The pointer to random State.
306  *
307  * @return CCError_t - according to module definitions
308  */
LLF_RND_EntropyEstimateFull(uint32_t * ramAddr,uint32_t blockSizeWords,uint32_t countBlocks,uint32_t * entrSize_ptr,uint32_t * rndWorkBuff_ptr)309 CCError_t LLF_RND_EntropyEstimateFull(
310               uint32_t *ramAddr,      /*in*/
311               uint32_t  blockSizeWords, /*in*/
312               uint32_t  countBlocks,      /*in*/
313               uint32_t *entrSize_ptr,     /*out*/
314               uint32_t  *rndWorkBuff_ptr)   /*in*/
315 {
316 
317     CCError_t error = 0;
318     uint32_t i, totalEntr = 0, currEntr;
319     uint32_t *h_ptr, *ec_ptr;
320     uint32_t *eachRoscEntr_ptr = rndWorkBuff_ptr + CC_RND_WORK_BUFF_TMP2_OFFSET;
321 
322 
323     /* Initialization */
324 
325     h_ptr  = rndWorkBuff_ptr + CC_RND_H_BUFF_OFFSET;
326     ec_ptr = rndWorkBuff_ptr + CC_RND_EC_BUFF_OFFSET;
327 
328     /* estimate entropy for given blocks (ROSCs) */
329     for (i = 0; i < countBlocks; i++) {
330 
331         /* Zeroe working buffer for entr. estimator */
332         CC_PalMemSetZero(h_ptr, H_BUFF_SIZE_WORDS*4);
333         CC_PalMemSetZero(ec_ptr, EC_BUFF_SIZE_WORDS*4);
334 
335         LLF_RND_HistogramUpdate(
336                        h_ptr, ec_ptr,
337                        ramAddr + i*blockSizeWords,
338                        blockSizeWords);
339 
340         error = LLF_RND_EntropyEstimate(
341                            h_ptr, ec_ptr,
342                            &currEntr);   /* out - result Entropy size */
343 
344         if (error)
345             goto End;
346 
347         /*total entropy and separate ROSCs entropy*/
348         totalEntr += currEntr;
349         eachRoscEntr_ptr[i] = currEntr;
350     }
351 
352     /* entropy correction: down ~1.5% */
353     totalEntr  -= totalEntr >> 6;
354 
355     *entrSize_ptr = totalEntr;
356 
357     End:
358     return error;
359 }
360 
361 /****************************************************************************************/
362 /***********************      Auxiliary Functions              **************************/
363 /****************************************************************************************/
364 
365 
366 /************************************************************************************/
367 /*!
368  * Busy wait upon RNG Interrupt signals.
369  *
370  * This function waits RNG interrupt and then disables RNG source.
371  * It uses CC_HalWaitInterrupt function
372  * to receive common RNG interrupt and then reads and
373  * outputs the RNG ISR (status) register.
374  *
375  *
376  * \return uint32_t RNG Interrupt status.
377  */
LLF_RND_WaitRngInterrupt(uint32_t * isr_ptr)378 CCError_t LLF_RND_WaitRngInterrupt(uint32_t *isr_ptr)
379 {
380     uint32_t tmp = 0;
381     CCError_t error = CC_OK;
382     /* busy wait upon RNG IRR signals */
383     CC_REG_FLD_SET(HOST_RGF, HOST_IRR, RNG_INT, tmp, 1);
384     /* wait for watermark signal */
385     error = CC_HalWaitInterruptRND(tmp);
386     if (error != CC_OK){
387         /* stop DMA and the RNG source */
388         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG,RNG_DMA_ENABLE), 0);
389         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RND_SOURCE_ENABLE), 0);
390         return error;
391     }
392     /* stop DMA and the RNG source */
393     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG,RNG_DMA_ENABLE), 0);
394     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RND_SOURCE_ENABLE), 0);
395 
396     /* read specific RNG interrupt status */
397     *isr_ptr = CC_HAL_READ_REGISTER(CC_REG_OFFSET(RNG, RNG_ISR));
398 
399     /* clear RNG interrupt status besides HW errors */
400         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG, RNG_ICR), *isr_ptr);
401         /* clear again HOST_IRR, since it must be cleared after RNG_ISR */
402         CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_ICR), tmp);
403     return error;
404 }
405 
406 /*****************************************************************/
407 
LLF_RND_GetRoscSampleCnt(uint32_t rosc,CCRndParams_t * pTrngParams)408 CCError_t LLF_RND_GetRoscSampleCnt(uint32_t rosc, CCRndParams_t *pTrngParams)
409 {
410     switch (rosc) {
411     case 0x1:
412         pTrngParams->SubSamplingRatio = pTrngParams->userParams.SubSamplingRatio1;
413         break;
414     case 0x2:
415         pTrngParams->SubSamplingRatio = pTrngParams->userParams.SubSamplingRatio2;
416         break;
417     case 0x4:
418         pTrngParams->SubSamplingRatio = pTrngParams->userParams.SubSamplingRatio3;
419         break;
420     case 0x8:
421         pTrngParams->SubSamplingRatio = pTrngParams->userParams.SubSamplingRatio4;
422         break;
423     default:
424         return LLF_RND_TRNG_REQUIRED_ROSCS_NOT_ALLOWED_ERROR;
425     }
426 
427     return CC_OK;
428 }
429 
430 /**
431  * The function gets next allowed rosc
432  *
433  * @author reuvenl (9/12/2012)
434  *
435  * @param trngParams_ptr - a pointer to params structure.
436  * @param rosc_ptr - a pointer to previous rosc /in/, and
437  *          to next rosc /out/.
438  * @param isNext - defines is increment of rosc ID needed or not.
439  *             if isNext = TRUE - the function shifts rosc by one bit; Then
440  *             the function checks is this rosc allowed, if yes - updates
441  *             the rosc, else repeats previous steps. If no roscs allowed -
442  *             returns an error.
443  *
444  *
445  * @return CCError_t
446  */
LLF_RND_GetFastestRosc(CCRndParams_t * trngParams_ptr,uint32_t * rosc_ptr)447 CCError_t LLF_RND_GetFastestRosc(
448                   CCRndParams_t *trngParams_ptr,
449                   uint32_t *rosc_ptr     /*in/out*/)
450 {
451     /* setting rosc */
452     do {
453 
454         if (*rosc_ptr & trngParams_ptr->RoscsAllowed) {
455             return CC_OK;
456         } else {
457             *rosc_ptr <<= 1;
458         }
459 
460     }while (*rosc_ptr <= 0x08);
461 
462     return LLF_RND_TRNG_REQUIRED_ROSCS_NOT_ALLOWED_ERROR;
463 
464 }
465 
466 
467 /**
468  * The macros calculates count ROSCs to start, as count of bits "1" in allowed
469  * roscToStart parameter.
470  *
471  * @author reuvenl (9/20/2012)
472  *
473  * @param roscsAllowed
474  * @param roscToStart
475  *
476  * @return uint32_t
477  */
LLF_RND_GetCountRoscs(uint32_t roscsAllowed,uint32_t roscToStart)478 uint32_t LLF_RND_GetCountRoscs(
479                        uint32_t roscsAllowed,
480                        uint32_t roscToStart)
481 {
482     uint32_t countRoscs = 0;
483 
484     roscToStart &= roscsAllowed;
485     while (roscToStart) {
486         countRoscs += (roscToStart & 1UL);
487         roscToStart >>= 1;
488     }
489 
490     return countRoscs;
491 }
492 
493 /****************************************************************************************/
494 /*****************************       Public Functions      ******************************/
495 /****************************************************************************************/
496 
497 
498 /************************************************************************************/
499 /**
500  * @brief The LLF_RND_TurnOffTrng stops the hardware random bits collection
501  *        closes RND clocks and releases HW semaphore.
502  *
503  *
504  *
505  * @return CCError_t - On success CC_OK is returned, on failure a
506  *                        value MODULE_* as defined in ...
507  */
LLF_RND_TurnOffTrng(void)508 void LLF_RND_TurnOffTrng(void)
509 {
510     /* LOCAL DECLARATIONS */
511 
512     uint32_t temp = 0;
513 
514 
515     /* FUNCTION LOGIC */
516 
517     /* disable the RND source  */
518     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG,RND_SOURCE_ENABLE), LLF_RND_HW_RND_SRC_DISABLE_VAL);
519 
520     /* close the Hardware clock */
521     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG,RNG_CLK_ENABLE), LLF_RND_HW_RND_CLK_DISABLE_VAL);
522 
523     /* clear RNG interrupts */
524     CC_REG_FLD_SET(HOST_RGF, HOST_ICR, RNG_INT_CLEAR, temp, 1);                                               \
525     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_ICR), temp);
526     CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(RNG,RNG_ICR), 0xFFFFFFFF);
527 
528 
529     return;
530 
531 }/* END OF LLF_RND_TurnOffTrng*/
532 
533 
534 /**
535 * @brief: The function performs CPRNGT (Continued PRNG Test) according
536 *         to NIST 900-80 and FIPS (if defined) standards.
537 *
538 * @param[in] prev_ptr - The pointer to previous saved generated random
539 *                       value of size 16 bytes.
540 * @param[in] buff_ptr - The pointer to generated random buffer.
541 * @param[in] last_ptr - The pointer to last generated random block
542 *                       of size 16 bytes used for output last bytes.
543 * @param[in] countBlocks - The count of generated random blocks, including
544 *                          the last block. Assumed countBlocks > 0.
545 *
546 * @return CCError_t - On success CC_OK is returned, on failure a
547 *                        value MODULE_* as defined in cc_error.h
548 */
LLF_RND_RndCprngt(uint8_t * prev_ptr,uint8_t * buff_ptr,uint8_t * last_ptr,int32_t countBlocks)549 CCError_t LLF_RND_RndCprngt(uint8_t            *prev_ptr,        /*in*/
550                   uint8_t            *buff_ptr,        /*in*/
551                   uint8_t            *last_ptr,        /*in*/
552                   int32_t             countBlocks)   /*in*/
553 {
554         /* LOCAL DECLARATIONS */
555 
556         CCError_t error = CC_OK;
557         int32_t  i;
558 
559         /*  FUNCTION LOGIC */
560 
561     /* compare the previous Value and last block */
562     if (countBlocks == 1) {
563         if (CC_PalMemCmp(prev_ptr, /*prev*/
564                    last_ptr,/*last block*/
565                    CC_AES_BLOCK_SIZE_IN_BYTES) == 0) {
566             error =  CC_RND_CPRNG_TEST_FAIL_ERROR;
567             goto End;
568         }
569     } else { /* countBlocks > 1, compare first and last blocks */
570         if (CC_PalMemCmp(prev_ptr,  /*prev*/
571                    buff_ptr, /*first block*/
572                    CC_AES_BLOCK_SIZE_IN_BYTES) == 0) {
573             error =  CC_RND_CPRNG_TEST_FAIL_ERROR;
574             goto End;
575         }
576 
577         if (CC_PalMemCmp(buff_ptr + (countBlocks-2)*CC_AES_BLOCK_SIZE_IN_BYTES, /*prev*/
578                    last_ptr,/*last block*/
579                    CC_AES_BLOCK_SIZE_IN_BYTES) == 0) {
580             error =  CC_RND_CPRNG_TEST_FAIL_ERROR;
581             goto End;
582         }
583     }
584     /* compare intermediate blocks */
585     if (countBlocks > 2 && error == CC_OK) {
586         for (i = 0; i < countBlocks-2; i++) {
587             /* compare all current with previous blocks */
588             if (CC_PalMemCmp(buff_ptr + i*CC_AES_BLOCK_SIZE_IN_BYTES,
589                        buff_ptr + (i+1)*CC_AES_BLOCK_SIZE_IN_BYTES,
590                        CC_AES_BLOCK_SIZE_IN_BYTES) == 0) {
591                 error = CC_RND_CPRNG_TEST_FAIL_ERROR;
592                 goto End;
593             }
594         }
595     }
596 
597         End:
598 
599 
600         return error;
601 }
602 
603 
604