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