1 /*
2  * Copyright (c) 2001-2020, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /************* Include Files ****************/
8 
9 #include "cc_pal_types.h"
10 #include "cc_pal_mem.h"
11 #include "cc_pal_log.h"
12 #include "cc_rng_plat.h"
13 #include "cc_common.h"
14 #include "cc_common_math.h"
15 #include "cc_rnd_common.h"
16 #include "cc_rnd_error.h"
17 #include "cc_rnd_local.h"
18 #include "llf_rnd.h"
19 #include "llf_rnd_trng.h"
20 #include "llf_rnd_error.h"
21 #include "cc_pal_abort.h"
22 #include "cc_pal_mutex.h"
23 #include "cc_fips_defs.h"
24 #include "cc_util_pm.h"
25 #ifdef CC_IOT
26 #include "mbedtls/ctr_drbg.h"
27 #include "mbedtls/entropy.h"
28 #endif
29 
30 /* CC RND module version compliant to NIST 800-90 standard. Based on CTR DRBG Block Cipher (AES) */
31 
32 /************************ Defines ******************************/
33 
34 /*********************************** Enums ******************************/
35 
36 /*********************************Typedefs ******************************/
37 /* rotate 32-bits word by 16 bits */
38 #define RND_ROT32(x) ( (x) >> 16 | (x) << 16 )
39 
40 /* inverse the bytes order in a word */
41 #define RND_REVERSE32(x)  ( ((RND_ROT32((x)) & 0xff00ff00UL) >> 8) | ((RND_ROT32((x)) & 0x00ff00ffUL) << 8) )
42 
43 /**************** Global Data to be read by RNG function ****************/
44 
45 /************************************************************************************/
46 /***********************           Private functions            *********************/
47 /************************************************************************************/
48 
49 /********************************************************************************
50   @brief This function subtracts a value from a large vector presented in the buffer.
51          The LSB of the counter is stored in the left most cell.
52 
53   @return signed value of carry (borrow)
54  */
55 
AddInt8ValueToUin8Vector(uint8_t * vect,int8_t val,uint32_t vectSizeInBytes)56 static uint8_t AddInt8ValueToUin8Vector(uint8_t  *vect, /*! [in]  vect - the buffer containing the vector. */
57                     int8_t    val,  /*! [in]  val  - the value to add/subtract (according to its sign). */
58                     uint32_t  vectSizeInBytes) /*! [in]  vectSizeInBytes - the vector size in bytes. */
59 {
60         /* DECLARATIONS */
61 
62         /* loop index */
63     uint32_t i;
64     int32_t temp;
65 
66     /* FUNCTION LOGIC */
67 
68     temp = val;
69 
70         for (i = 0; i < vectSizeInBytes; i++) {
71                 temp = vect[i] + val;
72                 vect[i] = (uint32_t)temp & 0xFF;
73                 val = (temp >> 8) & 0xFF;
74     }
75 
76     return val;
77 
78 }/* End of AddInt8ValueToUin8Vector() */
79 
80 
81 
82 
83 
84 /****************************************************************************************/
85 /*****************************       Public Functions      ******************************/
86 /****************************************************************************************/
87 
88 
89 /****************************************************************************************/
90 /**
91 
92   @brief The function set the RND Generate vector function, provided by the User.
93 
94   @param [in/out] rndContext_ptr  - Pointer to the RND context buffer.
95   @param [in] rndGenerateVectFunc - The pointer to RND Generate vector function.
96 
97   @return CCError_t - no return value
98  */
CC_RndSetGenerateVectorFunc(CCRndContext_t * rndContext_ptr,CCRndGenerateVectWorkFunc_t rndGenerateVectFunc)99 CCError_t CC_RndSetGenerateVectorFunc(CCRndContext_t *rndContext_ptr,
100                        CCRndGenerateVectWorkFunc_t rndGenerateVectFunc)
101 {
102 
103     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
104 
105         /* check parameters */
106         if (rndContext_ptr == NULL)
107                 return CC_RND_CONTEXT_PTR_INVALID_ERROR;
108         if (rndGenerateVectFunc == NULL)
109                 return CC_RND_GEN_VECTOR_FUNC_ERROR;
110 
111 
112         rndContext_ptr->rndGenerateVectFunc = rndGenerateVectFunc;
113 
114         return 0;
115 }
116 
117 
118 
119 
120 
121 
122 #ifndef _INTERNAL_CC_ONE_SEED
123 
124 
125 /**********************************************************************************************************/
126 /**
127   @brief The function generates a random vector Rand in range  1 < RandVect < MaxVect
128               by testing candidates (described and used in FIPS 186-4: B.1.2, B.4.2 etc.):
129          The function performs the following:
130          1.  Check input parameters, in partial, check that value of max. vector > 3 (our requirement).
131          2.  If maxVect != 0 (maxVect is provided), then calculate required size of random
132              equaled to actual bit size of MaxVector, else set it = rndSizeInBits.
133          3.  Calls the CC_RndGenerateVector() function for generating random vector
134              RndVect of required size.
135          4.  If maxVect is provided, then:
136               4.0. Subtract maxVect  -= 2;
137               4.1. Sets all high bits of RndVect, greatest than MSBit of MaxVector, to 0.
138               4.2. If size of random vector > 16 bytes, then:
139                       4.2.1. Compares high 16 bytes of randVect to maxVect.
140                       4.2.2. If condition is not satisfied, then generate new high 16 bytes
141                              of rndVect and go to step 4.2.1.
142               4.3. Compare the full RndVect with MaxVector. If condition is not satisfied,
143                    then generate new random RndVect and go to step 4.1, else go to 6.
144          5. Else if maxVect is not provided, then set MSBit of rndVect to 1.
145          6. Output the result and Exit.
146 
147           Note: Random and Max vectors are given as sequence of bytes, where LSB is most left byte
148                 and MSB = most right one.
149 
150   @param rndContext_ptr [in/out] - Pointer to the RND context buffer.
151   @param rndSizeInBits [in]   - If maxVect_ptr is not given, then rndSizeInBits defining the exact size (in bits)
152                          of generated random vector. If maxVect is given, then it defines the
153                       size (rounded up to bytes) of the maxVect_ptr buffer.
154   @param maxVect_ptr [in]     - The pointer to vector defining a high limit
155                          of random vector.
156   @param rndVect_ptr [in,out] - The output buffer for the random vector.
157 
158   @return CCError_t  - On success CC_OK is returned, on failure - a value,
159               defined in cc_rnd_error.h.
160  */
CC_RndGenerateVectorInRange(CCRndContext_t * rndContext_ptr,size_t rndSizeInBits,uint8_t * maxVect_ptr,uint8_t * rndVect_ptr)161 CEXPORT_C CCError_t CC_RndGenerateVectorInRange(
162                                                     CCRndContext_t *rndContext_ptr,
163                                                     size_t   rndSizeInBits,
164                                                     uint8_t  *maxVect_ptr,
165                                                     uint8_t  *rndVect_ptr )
166 {
167         /* FUNCTION DECLARATIONS */
168 
169         CCError_t Error = CC_OK;
170         int32_t   k, extraBytes;
171         int8_t    shift;
172         uint8_t   mask;
173         uint32_t   rndSizeInBytes, checkingSizeBytes = 0;
174         uint32_t   maxVectSizeBits;
175         uint32_t   maxVectSizeBytes = 0;
176         CCCommonCmpCounter_t CompRes;
177         /* RND state and function pointers */
178         CCRndState_t   *rndState_ptr;
179         CCRndGenerateVectWorkFunc_t RndGenerateVectFunc;
180 
181         /* FUNCTION LOGIC */
182     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
183 
184         /*  Check input parameters */
185         if (rndVect_ptr == NULL)
186                 return CC_RND_VECTOR_OUT_PTR_ERROR;
187 
188     /* verify that rndSizeInBits is not greater than 2^19 -1 */
189     if (rndSizeInBits > 0x7FFFF)
190         return CC_RND_VECTOR_OUT_SIZE_ERROR;
191 
192     /* given size of random vector in bytes */
193     rndSizeInBytes = CALC_FULL_BYTES(rndSizeInBits);
194 
195     if (rndSizeInBits <= 1 || (uint32_t)rndSizeInBytes > CC_RND_MAX_GEN_VECTOR_SIZE_BYTES)
196             return CC_RND_VECTOR_OUT_SIZE_ERROR;
197 
198     /* check parameters */
199     if (rndContext_ptr == NULL)
200             return CC_RND_CONTEXT_PTR_INVALID_ERROR;
201 
202     rndState_ptr = (CCRndState_t *)(rndContext_ptr->rndState);
203     RndGenerateVectFunc = rndContext_ptr->rndGenerateVectFunc;
204 
205     if (RndGenerateVectFunc == NULL)
206             return CC_RND_GEN_VECTOR_FUNC_ERROR;
207 
208 
209     /*--------------------------------------*/
210     /* generation in case of exact bit size */
211     /*--------------------------------------*/
212 
213     if (maxVect_ptr == NULL) {
214 
215             Error = RndGenerateVectFunc((void *)rndState_ptr, (unsigned char *)rndVect_ptr, (size_t)rndSizeInBytes);
216 
217             if (Error != CC_OK)
218                     goto End;
219 
220             /* swap from big endian to little*/
221             CC_CommonReverseMemcpy(rndVect_ptr, rndVect_ptr, rndSizeInBytes);
222 
223             /* correction of bit size */
224             rndVect_ptr[rndSizeInBytes-1] |= 0x80;
225             if (rndSizeInBits%8 != 0) {
226                     rndVect_ptr[rndSizeInBytes-1] >>= (8 - (rndSizeInBits&0x7))&0x7;
227             }
228 
229             goto End;
230         }
231 
232         /*------------------------------------------*/
233         /* generation in case of given max. vector  */
234         /*------------------------------------------*/
235 
236         /* calculate actual size of MaxVector in bits*/
237         maxVectSizeBits = CC_CommonGetBytesCounterEffectiveSizeInBits(
238                                                                         maxVect_ptr, (uint16_t)rndSizeInBytes);
239         /* if maxVect < 4 then return an error */
240         if (maxVectSizeBits < 3 || (maxVectSizeBits == 3 && maxVect_ptr[0] < 4)) {
241                 Error = CC_RND_MAX_VECTOR_IS_TOO_SMALL_ERROR;
242         goto End;
243     }
244 
245         /* temporary subtract 2 from maxVect */
246         AddInt8ValueToUin8Vector(maxVect_ptr, -2/*val*/, maxVectSizeBytes);
247 
248         maxVectSizeBytes = CALC_FULL_BYTES(maxVectSizeBits);
249 
250         /* calculate count of extra 0-bytes in maxVector */
251         extraBytes = rndSizeInBytes - maxVectSizeBytes;
252 
253         /* zeroing 0-bytes in rndVect_ptr buffer */
254         CC_PalMemSetZero(rndVect_ptr + maxVectSizeBytes, extraBytes);
255 
256         /* calc. intermediate checking size */
257         if ((uint32_t)maxVectSizeBytes > CC_AES_BLOCK_SIZE_IN_BYTES) {
258                 checkingSizeBytes = CC_AES_BLOCK_SIZE_IN_BYTES;
259         } else {
260                 checkingSizeBytes = maxVectSizeBytes;
261         }
262 
263         /* calculate count of extra 0-bits for mask shifting */
264         shift = (int8_t)(8 - (maxVectSizeBits & 7))&7;
265         mask = 0xFF >> shift;
266 
267         /* main loop for generating random number    */
268         /*-------------------------------------------*/
269         k = 0;
270 
271         while (k < 0xFFFF) {
272                 /* generate full size random vector */
273                 Error = RndGenerateVectFunc((void *)rndState_ptr, (unsigned char *)rndVect_ptr, (size_t)maxVectSizeBytes);
274 
275                 if (Error != CC_OK)
276                         goto End;
277 
278                 /* swap from big endian to little*/
279                 CC_CommonReverseMemcpy(rndVect_ptr, rndVect_ptr, maxVectSizeBytes);
280 
281                 /* mask the non significant high bits */
282                 rndVect_ptr[maxVectSizeBytes - 1] &= mask;
283 
284                 /* step1 check high part of random */
285                 if (checkingSizeBytes == CC_AES_BLOCK_SIZE_IN_BYTES) {
286                         while (1) {
287                                 CompRes = CC_CommonCmpLsbUnsignedCounters(
288                                                                             rndVect_ptr + maxVectSizeBytes - CC_AES_BLOCK_SIZE_IN_BYTES,
289                                                                             CC_AES_BLOCK_SIZE_IN_BYTES,
290                                                                             maxVect_ptr + maxVectSizeBytes - CC_AES_BLOCK_SIZE_IN_BYTES,
291                                                                             CC_AES_BLOCK_SIZE_IN_BYTES);
292 
293                                 if (CompRes == CC_COMMON_CmpCounter2GreaterThenCounter1) {
294                                         goto End;  /* random is found */
295                                 } else if (CompRes == CC_COMMON_CmpCounter1AndCounter2AreIdentical)
296                                         break; /* go to check full size */
297 
298                                 /* generate new 16 random high bytes - without*
299                                 *  repeat the same Additional Data            */
300                                 Error = RndGenerateVectFunc((void *)rndState_ptr,
301                                                             (unsigned char *)rndVect_ptr + maxVectSizeBytes - CC_AES_BLOCK_SIZE_IN_BYTES,
302                                                             CC_AES_BLOCK_SIZE_IN_BYTES);
303                                 if (Error != CC_OK)
304                                         goto End;
305 
306                                 /* mask the non significant high bits */
307                                 rndVect_ptr[maxVectSizeBytes - 1] &= mask;
308                         }
309                 }
310 
311                 /* check full size relating to max vector */
312                 CompRes = CC_CommonCmpLsbUnsignedCounters(rndVect_ptr, (uint16_t)maxVectSizeBytes,
313                                                              maxVect_ptr, (uint16_t)maxVectSizeBytes);
314 
315                 if (CompRes == CC_COMMON_CmpCounter2GreaterThenCounter1) {
316                         goto End;
317                 }
318 
319                 /* increment counter and continue the loop */
320                 k++;
321         }
322 
323         /* if all tries are Fail, then return the Error */
324         Error = CC_RND_CAN_NOT_GENERATE_RAND_IN_RANGE;
325 
326 End:
327 
328     if (Error != CC_OK) {
329         CC_PalMemSetZero(rndVect_ptr, rndSizeInBytes);
330                 return Error;
331     }
332 
333 
334         if (maxVect_ptr != NULL) {
335             /* reset the maxVect to (original value -1) */
336             AddInt8ValueToUin8Vector(maxVect_ptr, 1/*val*/, maxVectSizeBytes);
337 
338             if (CC_CommonGetBytesCounterEffectiveSizeInBits(rndVect_ptr, maxVectSizeBytes) < 2) { /* vect == 1*/
339                 /* replace 1 with(maxVect -1) */
340                     CC_PalMemCopy(rndVect_ptr, maxVect_ptr, maxVectSizeBytes);
341             }
342             /* reset the maxVect to original value */
343             AddInt8ValueToUin8Vector(maxVect_ptr, 1/*val*/, maxVectSizeBytes);
344 
345         }
346 
347         return Error;
348 
349 } /* End of CC_RndGenerateVectorInRange function */
350 
351 #endif /*_INTERNAL_CC_ONE_SEED*/
352 
353 
354 /**********************************************************************************************************/
355 /**
356  * @brief The RndGenerateWordsArrayInRange function generates a random words vector in range:
357  *            1 < RndVect < MaxVect,   using the FIPS-PUB 186-2 standard appendix 3 :
358  *
359  *        The function generates random array  using CC_RndGenerateVectorInRange function and
360  *        conversion of bytes to words.
361  *
362  *         Note: RndVect and MaxVect arrayss are given as sequence of words, where LSWord is most left byte
363  *               and MSWord - most right.
364  *
365  * @param rndContext_ptr [in/out]  - Pointer to the RND context buffer.
366  * @param rndSizeInBits [in]   - If maxVect_ptr is not given, then rndSizeInBits defining the exact size (in bits)
367  *                        of generated random vector. If maxVect is given, then it defines the
368  *                    size (rounded up to words) of the maxVect_ptr buffer. The size must be not greate
369  *                than CC_RND_MAX_SIZE_OF_OUTPUT_BYTES/4
370  * @param maxVect_ptr [in]     - The pointer to vector defining a high limit of random vector.
371  * @param rndVect_ptr [out]    - The output buffer for the random vector.
372  * @param tmp_ptr [int]        - The temp buffer for the random generation. The size must be not
373  *                less, than rndSizeInBits converted to words (rounded up).
374  *
375  * @return CCError_t  - On success CC_OK is returned, on failure - a value,
376  *                defined in cc_rnd_error.h.
377  */
RndGenerateWordsArrayInRange(CCRndContext_t * rndContext_ptr,uint32_t rndSizeInBits,uint32_t * maxVect_ptr,uint32_t * rndVect_ptr,uint32_t * tmp_ptr)378 CCError_t RndGenerateWordsArrayInRange(CCRndContext_t *rndContext_ptr,
379                                        uint32_t   rndSizeInBits,
380                                        uint32_t  *maxVect_ptr,
381                                        uint32_t  *rndVect_ptr,
382                                        uint32_t  *tmp_ptr)
383 {
384         /* FUNCTION DECLARATIONS */
385 
386         CCError_t err;
387         uint32_t rndSizeInWords = CALC_FULL_32BIT_WORDS(rndSizeInBits);
388 
389 
390         /* check parameters */
391         if (rndVect_ptr == NULL)
392                 return CC_RND_DATA_OUT_POINTER_INVALID_ERROR;
393 
394         /* given size of random vector in bytes */
395         if (rndSizeInBits == 0 || rndSizeInWords*4 > CC_RND_MAX_GEN_VECTOR_SIZE_BYTES)
396                 return CC_RND_VECTOR_SIZE_ERROR;
397 
398         /* copy the maxVector into temp buffer and set endiannes as LE bytes  *
399         *  array                                  */
400         CC_PalMemMove((uint8_t*)tmp_ptr, (uint8_t*)maxVect_ptr, rndSizeInWords*sizeof(uint32_t));
401 
402 #ifdef BIG__ENDIAN
403         CC_COMMON_INVERSE_UINT32_IN_ARRAY(tmp_ptr, rndSizeInWords);
404 #endif
405         /* generate vector in range [1...MaxVect] as LE bytes array */
406         rndVect_ptr[rndSizeInWords-1] = 0;
407         err = CC_RndGenerateVectorInRange(rndContext_ptr, rndSizeInBits, (uint8_t*)tmp_ptr, (uint8_t*)rndVect_ptr);
408 
409         if (err)
410                 return err;
411 
412         /* set endianness in output words according to LE words array */
413 #ifdef BIG__ENDIAN
414         CC_COMMON_INVERSE_UINT32_IN_ARRAY(rndVect_ptr, rndSizeInWords);
415 #endif
416 
417         return err;
418 }
419 
420 
421 
422