1 /* random.c
2  *
3  * Copyright (C) 2006-2021 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL.
6  *
7  * wolfSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * wolfSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20  */
21 
22 /*
23 
24 DESCRIPTION
25 This library contains implementation for the random number generator.
26 
27 */
28 #ifdef HAVE_CONFIG_H
29     #include <config.h>
30 #endif
31 
32 #include <wolfssl/wolfcrypt/settings.h>
33 #include <wolfssl/wolfcrypt/error-crypt.h>
34 
35 /* on HPUX 11 you may need to install /dev/random see
36    http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
37 
38 */
39 
40 #if defined(HAVE_FIPS) && \
41     defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
42 
43     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
44     #define FIPS_NO_WRAPPERS
45 
46     #ifdef USE_WINDOWS_API
47         #pragma code_seg(".fipsA$c")
48         #pragma const_seg(".fipsB$c")
49     #endif
50 #endif
51 
52 
53 #include <wolfssl/wolfcrypt/random.h>
54 #include <wolfssl/wolfcrypt/cpuid.h>
55 
56 
57 /* If building for old FIPS. */
58 #if defined(HAVE_FIPS) && \
59     (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
60 
wc_GenerateSeed(OS_Seed * os,byte * seed,word32 sz)61 int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz)
62 {
63     return GenerateSeed(os, seed, sz);
64 }
65 
wc_InitRng_ex(WC_RNG * rng,void * heap,int devId)66 int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
67 {
68     (void)heap;
69     (void)devId;
70     return InitRng_fips(rng);
71 }
72 
wc_InitRng(WC_RNG * rng)73 int wc_InitRng(WC_RNG* rng)
74 {
75     return InitRng_fips(rng);
76 }
77 
78 
wc_RNG_GenerateBlock(WC_RNG * rng,byte * b,word32 sz)79 int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz)
80 {
81     return RNG_GenerateBlock_fips(rng, b, sz);
82 }
83 
84 
wc_RNG_GenerateByte(WC_RNG * rng,byte * b)85 int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
86 {
87     return RNG_GenerateByte(rng, b);
88 }
89 
90 #ifdef HAVE_HASHDRBG
91 
wc_FreeRng(WC_RNG * rng)92     int wc_FreeRng(WC_RNG* rng)
93     {
94         return FreeRng_fips(rng);
95     }
96 
wc_RNG_HealthTest(int reseed,const byte * seedA,word32 seedASz,const byte * seedB,word32 seedBSz,byte * output,word32 outputSz)97     int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz,
98                                       const byte* seedB, word32 seedBSz,
99                                       byte* output, word32 outputSz)
100     {
101         return RNG_HealthTest_fips(reseed, seedA, seedASz,
102                               seedB, seedBSz, output, outputSz);
103    }
104 #endif /* HAVE_HASHDRBG */
105 
106 #else /* else build without fips, or for new fips */
107 
108 #ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
109 
110 #include <wolfssl/wolfcrypt/sha256.h>
111 
112 #ifdef WOLF_CRYPTO_CB
113     #include <wolfssl/wolfcrypt/cryptocb.h>
114 #endif
115 
116 #ifdef NO_INLINE
117     #include <wolfssl/wolfcrypt/misc.h>
118 #else
119     #define WOLFSSL_MISC_INCLUDED
120     #include <wolfcrypt/src/misc.c>
121 #endif
122 
123 #if defined(WOLFSSL_SGX)
124     #include <sgx_trts.h>
125 #elif defined(USE_WINDOWS_API)
126     #ifndef _WIN32_WINNT
127         #define _WIN32_WINNT 0x0400
128     #endif
129     #include <windows.h>
130     #include <wincrypt.h>
131 #elif defined(HAVE_WNR)
132     #include <wnr.h>
133     #include <wolfssl/wolfcrypt/logging.h>
134     wolfSSL_Mutex wnr_mutex;    /* global netRandom mutex */
135     int wnr_timeout     = 0;    /* entropy timeout, milliseconds */
136     int wnr_mutex_init  = 0;    /* flag for mutex init */
137     wnr_context*  wnr_ctx;      /* global netRandom context */
138 #elif defined(FREESCALE_KSDK_2_0_TRNG)
139     #include "fsl_trng.h"
140 #elif defined(FREESCALE_KSDK_2_0_RNGA)
141     #include "fsl_rnga.h"
142 #elif defined(WOLFSSL_WICED)
143     #include "wiced_crypto.h"
144 #elif defined(WOLFSSL_NETBURNER)
145     #include <predef.h>
146     #include <basictypes.h>
147     #include <random.h>
148 #elif defined(NO_DEV_RANDOM)
149 #elif defined(CUSTOM_RAND_GENERATE)
150 #elif defined(CUSTOM_RAND_GENERATE_BLOCK)
151 #elif defined(CUSTOM_RAND_GENERATE_SEED)
152 #elif defined(WOLFSSL_GENSEED_FORTEST)
153 #elif defined(WOLFSSL_MDK_ARM)
154 #elif defined(WOLFSSL_IAR_ARM)
155 #elif defined(WOLFSSL_ROWLEY_ARM)
156 #elif defined(WOLFSSL_EMBOS)
157 #elif defined(WOLFSSL_DEOS)
158 #elif defined(MICRIUM)
159 #elif defined(WOLFSSL_NUCLEUS)
160 #elif defined(WOLFSSL_PB)
161 #elif defined(WOLFSSL_ZEPHYR)
162 #elif defined(WOLFSSL_TELIT_M2MB)
163 #elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG)
164 #else
165     /* include headers that may be needed to get good seed */
166     #include <fcntl.h>
167     #ifndef EBSNET
168         #include <unistd.h>
169     #endif
170 #endif
171 
172 #if defined(WOLFSSL_SILABS_SE_ACCEL)
173 #include <wolfssl/wolfcrypt/port/silabs/silabs_random.h>
174 #endif
175 
176 #if defined(WOLFSSL_IOTSAFE) && defined(HAVE_IOTSAFE_HWRNG)
177 #include <wolfssl/wolfcrypt/port/iotsafe/iotsafe.h>
178 #endif
179 
180 #if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
181     static word32 intel_flags = 0;
wc_InitRng_IntelRD(void)182     static void wc_InitRng_IntelRD(void)
183     {
184         intel_flags = cpuid_get_flags();
185     }
186     #if defined(HAVE_INTEL_RDSEED) && !defined(WOLFSSL_LINUXKM)
187     static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz);
188     #endif
189     #ifdef HAVE_INTEL_RDRAND
190     static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz);
191     #endif
192 
193 #ifdef USE_WINDOWS_API
194     #define USE_INTEL_INTRINSICS
195 #elif !defined __GNUC__ || defined __clang__ || __GNUC__ > 4
196     #define USE_INTEL_INTRINSICS
197 #else
198     #undef USE_INTEL_INTRINSICS
199 #endif
200 
201 #ifdef USE_INTEL_INTRINSICS
202     #include <immintrin.h>
203     /* Before clang 7 or GCC 9, immintrin.h did not define _rdseed64_step() */
204     #ifndef HAVE_INTEL_RDSEED
205     #elif defined __clang__ && __clang_major__ > 6
206     #elif !defined __GNUC__
207     #elif __GNUC__ > 8
208     #else
209         #ifndef __clang__
210             #pragma GCC push_options
211             #pragma GCC target("rdseed")
212         #else
213             #define __RDSEED__
214         #endif
215         #include <x86intrin.h>
216         #ifndef __clang__
217             #pragma GCC pop_options
218         #endif
219     #endif
220 #endif /* USE_WINDOWS_API */
221 #endif
222 
223 /* Start NIST DRBG code */
224 #ifdef HAVE_HASHDRBG
225 
226 #define OUTPUT_BLOCK_LEN  (WC_SHA256_DIGEST_SIZE)
227 #define MAX_REQUEST_LEN   (0x10000)
228 #define RESEED_INTERVAL   WC_RESEED_INTERVAL
229 
230 
231 /* For FIPS builds, the user should not be adjusting the values. */
232 #if defined(HAVE_FIPS) && \
233     defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
234     #if defined(RNG_SECURITY_STRENGTH) \
235             || defined(ENTROPY_SCALE_FACTOR) \
236             || defined(SEED_BLOCK_SZ)
237 
238         #error "Do not change the RNG parameters for FIPS builds."
239     #endif
240 #endif
241 
242 
243 /* The security strength for the RNG is the target number of bits of
244  * entropy you are looking for in a seed. */
245 #ifndef RNG_SECURITY_STRENGTH
246     #if defined(HAVE_FIPS) && \
247         defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
248         /* SHA-256 requires a minimum of 256-bits of entropy. The goal
249          * of 1024 will provide 4 times that. */
250         #define RNG_SECURITY_STRENGTH (1024)
251     #else
252         /* If not using FIPS or using old FIPS, set the number down a bit.
253          * More is better, but more is also slower. */
254         #define RNG_SECURITY_STRENGTH (256)
255     #endif
256 #endif
257 
258 #ifndef ENTROPY_SCALE_FACTOR
259     /* The entropy scale factor should be the whole number inverse of the
260      * minimum bits of entropy per bit of NDRNG output. */
261     #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
262         /* The value of 2 applies to Intel's RDSEED which provides about
263          * 0.5 bits minimum of entropy per bit. */
264         #define ENTROPY_SCALE_FACTOR 2
265     #else
266         /* Setting the default to 1. */
267         #define ENTROPY_SCALE_FACTOR 1
268     #endif
269 #endif
270 
271 #ifndef SEED_BLOCK_SZ
272     /* The seed block size, is the size of the output of the underlying NDRNG.
273      * This value is used for testing the output of the NDRNG. */
274     #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
275         /* RDSEED outputs in blocks of 64-bits. */
276         #define SEED_BLOCK_SZ sizeof(word64)
277     #else
278         /* Setting the default to 4. */
279         #define SEED_BLOCK_SZ 4
280     #endif
281 #endif
282 
283 #define SEED_SZ        (RNG_SECURITY_STRENGTH*ENTROPY_SCALE_FACTOR/8)
284 
285 /* The maximum seed size will be the seed size plus a seed block for the
286  * test, and an additional half of the seed size. This additional half
287  * is in case the user does not supply a nonce. A nonce will be obtained
288  * from the NDRNG. */
289 #define MAX_SEED_SZ    (SEED_SZ + SEED_SZ/2 + SEED_BLOCK_SZ)
290 
291 
292 #ifdef WC_RNG_SEED_CB
293 
294 static wc_RngSeed_Cb seedCb = NULL;
295 
wc_SetSeed_Cb(wc_RngSeed_Cb cb)296 int wc_SetSeed_Cb(wc_RngSeed_Cb cb)
297 {
298     seedCb = cb;
299     return 0;
300 }
301 
302 #endif
303 
304 
305 /* Internal return codes */
306 #define DRBG_SUCCESS      0
307 #define DRBG_FAILURE      1
308 #define DRBG_NEED_RESEED  2
309 #define DRBG_CONT_FAILURE 3
310 #define DRBG_NO_SEED_CB   4
311 
312 /* RNG health states */
313 #define DRBG_NOT_INIT     0
314 #define DRBG_OK           1
315 #define DRBG_FAILED       2
316 #define DRBG_CONT_FAILED  3
317 
318 #define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4)
319 
320 /* Verify max gen block len */
321 #if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN
322     #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length
323 #endif
324 
325 enum {
326     drbgInitC     = 0,
327     drbgReseed    = 1,
328     drbgGenerateW = 2,
329     drbgGenerateH = 3,
330     drbgInitV     = 4
331 };
332 
333 typedef struct DRBG_internal DRBG_internal;
334 
335 static int wc_RNG_HealthTestLocal(int reseed);
336 
337 /* Hash Derivation Function */
338 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
Hash_df(DRBG_internal * drbg,byte * out,word32 outSz,byte type,const byte * inA,word32 inASz,const byte * inB,word32 inBSz)339 static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type,
340                                                   const byte* inA, word32 inASz,
341                                                   const byte* inB, word32 inBSz)
342 {
343     int ret = DRBG_FAILURE;
344     byte ctr;
345     int i;
346     int len;
347     word32 bits = (outSz * 8); /* reverse byte order */
348 #ifdef WOLFSSL_SMALL_STACK_CACHE
349     wc_Sha256* sha = &drbg->sha256;
350 #else
351     wc_Sha256 sha[1];
352 #endif
353 #ifdef WC_ASYNC_ENABLE_SHA256
354     WC_DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
355     if (digest == NULL)
356         return MEMORY_E;
357 #else
358     byte digest[WC_SHA256_DIGEST_SIZE];
359 #endif
360 
361     (void)drbg;
362 #ifdef WC_ASYNC_ENABLE_SHA256
363     if (digest == NULL)
364         return DRBG_FAILURE;
365 #endif
366 
367 #ifdef LITTLE_ENDIAN_ORDER
368     bits = ByteReverseWord32(bits);
369 #endif
370     len = (outSz / OUTPUT_BLOCK_LEN)
371         + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
372 
373     ctr = 1;
374     for (i = 0; i < len; i++) {
375 #ifndef WOLFSSL_SMALL_STACK_CACHE
376     #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
377         ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
378     #else
379         ret = wc_InitSha256(sha);
380     #endif
381         if (ret != 0)
382             break;
383 #endif
384         ret = wc_Sha256Update(sha, &ctr, sizeof(ctr));
385         if (ret == 0) {
386             ctr++;
387             ret = wc_Sha256Update(sha, (byte*)&bits, sizeof(bits));
388         }
389 
390         if (ret == 0) {
391             /* churning V is the only string that doesn't have the type added */
392             if (type != drbgInitV)
393                 ret = wc_Sha256Update(sha, &type, sizeof(type));
394         }
395         if (ret == 0)
396             ret = wc_Sha256Update(sha, inA, inASz);
397         if (ret == 0) {
398             if (inB != NULL && inBSz > 0)
399                 ret = wc_Sha256Update(sha, inB, inBSz);
400         }
401         if (ret == 0)
402             ret = wc_Sha256Final(sha, digest);
403 
404 #ifndef WOLFSSL_SMALL_STACK_CACHE
405         wc_Sha256Free(sha);
406 #endif
407         if (ret == 0) {
408             if (outSz > OUTPUT_BLOCK_LEN) {
409                 XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
410                 outSz -= OUTPUT_BLOCK_LEN;
411                 out += OUTPUT_BLOCK_LEN;
412             }
413             else {
414                 XMEMCPY(out, digest, outSz);
415             }
416         }
417     }
418 
419     ForceZero(digest, WC_SHA256_DIGEST_SIZE);
420 
421 #ifdef WC_ASYNC_ENABLE_SHA256
422     WC_FREE_VAR(digest, drbg->heap);
423 #endif
424 
425     return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
426 }
427 
428 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
Hash_DRBG_Reseed(DRBG_internal * drbg,const byte * seed,word32 seedSz)429 static int Hash_DRBG_Reseed(DRBG_internal* drbg, const byte* seed, word32 seedSz)
430 {
431     byte newV[DRBG_SEED_LEN];
432 
433     XMEMSET(newV, 0, DRBG_SEED_LEN);
434 
435     if (Hash_df(drbg, newV, sizeof(newV), drbgReseed,
436                 drbg->V, sizeof(drbg->V), seed, seedSz) != DRBG_SUCCESS) {
437         return DRBG_FAILURE;
438     }
439 
440     XMEMCPY(drbg->V, newV, sizeof(drbg->V));
441     ForceZero(newV, sizeof(newV));
442 
443     if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
444                                     sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) {
445         return DRBG_FAILURE;
446     }
447 
448     drbg->reseedCtr = 1;
449     drbg->lastBlock = 0;
450     drbg->matchCount = 0;
451     return DRBG_SUCCESS;
452 }
453 
454 /* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */
wc_RNG_DRBG_Reseed(WC_RNG * rng,const byte * seed,word32 seedSz)455 int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz)
456 {
457     if (rng == NULL || seed == NULL) {
458         return BAD_FUNC_ARG;
459     }
460 
461     return Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, seed, seedSz);
462 }
463 
array_add_one(byte * data,word32 dataSz)464 static WC_INLINE void array_add_one(byte* data, word32 dataSz)
465 {
466     int i;
467 
468     for (i = dataSz - 1; i >= 0; i--)
469     {
470         data[i]++;
471         if (data[i] != 0) break;
472     }
473 }
474 
475 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
Hash_gen(DRBG_internal * drbg,byte * out,word32 outSz,const byte * V)476 static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V)
477 {
478     int ret = DRBG_FAILURE;
479     byte data[DRBG_SEED_LEN];
480     int i;
481     int len;
482     word32 checkBlock;
483 #ifdef WOLFSSL_SMALL_STACK_CACHE
484     wc_Sha256* sha = &drbg->sha256;
485 #else
486     wc_Sha256 sha[1];
487 #endif
488 #ifdef WC_ASYNC_ENABLE_SHA256
489     WC_DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
490     if (digest == NULL)
491         return MEMORY_E;
492 #else
493     byte digest[WC_SHA256_DIGEST_SIZE];
494 #endif
495 
496     /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for
497      * the continuous test. */
498 
499     if (outSz == 0) outSz = 1;
500 
501     len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
502 
503     XMEMCPY(data, V, sizeof(data));
504     for (i = 0; i < len; i++) {
505 #ifndef WOLFSSL_SMALL_STACK_CACHE
506     #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
507         ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
508     #else
509         ret = wc_InitSha256(sha);
510     #endif
511         if (ret == 0)
512 #endif
513             ret = wc_Sha256Update(sha, data, sizeof(data));
514         if (ret == 0)
515             ret = wc_Sha256Final(sha, digest);
516 #ifndef WOLFSSL_SMALL_STACK_CACHE
517         wc_Sha256Free(sha);
518 #endif
519 
520         if (ret == 0) {
521             XMEMCPY(&checkBlock, digest, sizeof(word32));
522             if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) {
523                 if (drbg->matchCount == 1) {
524                     return DRBG_CONT_FAILURE;
525                 }
526                 else {
527                     if (i == (len-1)) {
528                         len++;
529                     }
530                     drbg->matchCount = 1;
531                 }
532             }
533             else {
534                 drbg->matchCount = 0;
535                 drbg->lastBlock = checkBlock;
536             }
537 
538             if (out != NULL && outSz != 0) {
539                 if (outSz >= OUTPUT_BLOCK_LEN) {
540                     XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
541                     outSz -= OUTPUT_BLOCK_LEN;
542                     out += OUTPUT_BLOCK_LEN;
543                     array_add_one(data, DRBG_SEED_LEN);
544                 }
545                 else {
546                     XMEMCPY(out, digest, outSz);
547                     outSz = 0;
548                 }
549             }
550         }
551         else {
552             /* wc_Sha256Update or wc_Sha256Final returned error */
553             break;
554         }
555     }
556     ForceZero(data, sizeof(data));
557 
558 #ifdef WC_ASYNC_ENABLE_SHA256
559     WC_FREE_VAR(digest, drbg->heap);
560 #endif
561 
562     return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
563 }
564 
array_add(byte * d,word32 dLen,const byte * s,word32 sLen)565 static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
566 {
567     word16 carry = 0;
568 
569     if (dLen > 0 && sLen > 0 && dLen >= sLen) {
570         int sIdx, dIdx;
571 
572         dIdx = dLen - 1;
573         for (sIdx = sLen - 1; sIdx >= 0; sIdx--) {
574             carry += (word16)d[dIdx] + (word16)s[sIdx];
575             d[dIdx] = (byte)carry;
576             carry >>= 8;
577             dIdx--;
578         }
579 
580         for (; carry != 0 && dIdx >= 0; dIdx--) {
581             carry += (word16)d[dIdx];
582             d[dIdx] = (byte)carry;
583             carry >>= 8;
584         }
585     }
586 }
587 
588 /* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */
Hash_DRBG_Generate(DRBG_internal * drbg,byte * out,word32 outSz)589 static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz)
590 {
591     int ret;
592 #ifdef WOLFSSL_SMALL_STACK_CACHE
593     wc_Sha256* sha = &drbg->sha256;
594 #else
595     wc_Sha256 sha[1];
596 #endif
597     byte type;
598     word32 reseedCtr;
599 
600     if (drbg->reseedCtr == RESEED_INTERVAL) {
601         return DRBG_NEED_RESEED;
602     } else {
603     #ifdef WC_ASYNC_ENABLE_SHA256
604         WC_DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
605         if (digest == NULL)
606             return MEMORY_E;
607     #else
608         byte digest[WC_SHA256_DIGEST_SIZE];
609     #endif
610         type = drbgGenerateH;
611         reseedCtr = drbg->reseedCtr;
612 
613         ret = Hash_gen(drbg, out, outSz, drbg->V);
614         if (ret == DRBG_SUCCESS) {
615 #ifndef WOLFSSL_SMALL_STACK_CACHE
616         #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
617             ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
618         #else
619             ret = wc_InitSha256(sha);
620         #endif
621             if (ret == 0)
622 #endif
623                 ret = wc_Sha256Update(sha, &type, sizeof(type));
624             if (ret == 0)
625                 ret = wc_Sha256Update(sha, drbg->V, sizeof(drbg->V));
626             if (ret == 0)
627                 ret = wc_Sha256Final(sha, digest);
628 
629 #ifndef WOLFSSL_SMALL_STACK_CACHE
630             wc_Sha256Free(sha);
631 #endif
632 
633             if (ret == 0) {
634                 array_add(drbg->V, sizeof(drbg->V), digest, WC_SHA256_DIGEST_SIZE);
635                 array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
636             #ifdef LITTLE_ENDIAN_ORDER
637                 reseedCtr = ByteReverseWord32(reseedCtr);
638             #endif
639                 array_add(drbg->V, sizeof(drbg->V),
640                                           (byte*)&reseedCtr, sizeof(reseedCtr));
641                 ret = DRBG_SUCCESS;
642             }
643             drbg->reseedCtr++;
644         }
645         ForceZero(digest, WC_SHA256_DIGEST_SIZE);
646     #ifdef WC_ASYNC_ENABLE_SHA256
647         WC_FREE_VAR(digest, drbg->heap);
648     #endif
649     }
650 
651     return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
652 }
653 
654 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
Hash_DRBG_Instantiate(DRBG_internal * drbg,const byte * seed,word32 seedSz,const byte * nonce,word32 nonceSz,void * heap,int devId)655 static int Hash_DRBG_Instantiate(DRBG_internal* drbg, const byte* seed, word32 seedSz,
656                                              const byte* nonce, word32 nonceSz,
657                                              void* heap, int devId)
658 {
659     int ret = DRBG_FAILURE;
660 
661     XMEMSET(drbg, 0, sizeof(DRBG_internal));
662 #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
663     drbg->heap = heap;
664     drbg->devId = devId;
665 #else
666     (void)heap;
667     (void)devId;
668 #endif
669 
670 #ifdef WOLFSSL_SMALL_STACK_CACHE
671     #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
672         ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId);
673     #else
674         ret = wc_InitSha256(&drbg->sha256);
675     #endif
676     if (ret != 0)
677         return ret;
678 #endif
679 
680     if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
681                                               nonce, nonceSz) == DRBG_SUCCESS &&
682         Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
683                                     sizeof(drbg->V), NULL, 0) == DRBG_SUCCESS) {
684 
685         drbg->reseedCtr = 1;
686         drbg->lastBlock = 0;
687         drbg->matchCount = 0;
688         ret = DRBG_SUCCESS;
689     }
690 
691     return ret;
692 }
693 
694 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
Hash_DRBG_Uninstantiate(DRBG_internal * drbg)695 static int Hash_DRBG_Uninstantiate(DRBG_internal* drbg)
696 {
697     word32 i;
698     int    compareSum = 0;
699     byte*  compareDrbg = (byte*)drbg;
700 
701 #ifdef WOLFSSL_SMALL_STACK_CACHE
702     wc_Sha256Free(&drbg->sha256);
703 #endif
704 
705     ForceZero(drbg, sizeof(DRBG_internal));
706 
707     for (i = 0; i < sizeof(DRBG_internal); i++)
708         compareSum |= compareDrbg[i] ^ 0;
709 
710     return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
711 }
712 
713 
wc_RNG_TestSeed(const byte * seed,word32 seedSz)714 int wc_RNG_TestSeed(const byte* seed, word32 seedSz)
715 {
716     int ret = 0;
717 
718     /* Check the seed for duplicate words. */
719     word32 seedIdx = 0;
720     word32 scratchSz = min(SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ);
721 
722     while (seedIdx < seedSz - SEED_BLOCK_SZ) {
723         if (ConstantCompare(seed + seedIdx,
724                             seed + seedIdx + scratchSz,
725                             scratchSz) == 0) {
726 
727             ret = DRBG_CONT_FAILURE;
728         }
729         seedIdx += SEED_BLOCK_SZ;
730         scratchSz = min(SEED_BLOCK_SZ, (seedSz - seedIdx));
731     }
732 
733     return ret;
734 }
735 #endif /* HAVE_HASHDRBG */
736 /* End NIST DRBG Code */
737 
738 
_InitRng(WC_RNG * rng,byte * nonce,word32 nonceSz,void * heap,int devId)739 static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
740                     void* heap, int devId)
741 {
742     int ret = 0;
743 #ifdef HAVE_HASHDRBG
744     word32 seedSz = SEED_SZ + SEED_BLOCK_SZ;
745 #endif
746 
747     (void)nonce;
748     (void)nonceSz;
749 
750     if (rng == NULL)
751         return BAD_FUNC_ARG;
752     if (nonce == NULL && nonceSz != 0)
753         return BAD_FUNC_ARG;
754 
755 #ifdef WOLFSSL_HEAP_TEST
756     rng->heap = (void*)WOLFSSL_HEAP_TEST;
757     (void)heap;
758 #else
759     rng->heap = heap;
760 #endif
761 #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
762     rng->devId = devId;
763     #if defined(WOLF_CRYPTO_CB)
764         rng->seed.devId = devId;
765     #endif
766 #else
767     (void)devId;
768 #endif
769 
770 #ifdef HAVE_HASHDRBG
771     /* init the DBRG to known values */
772     rng->drbg = NULL;
773     rng->status = DRBG_NOT_INIT;
774 #endif
775 
776 #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
777     /* init the intel RD seed and/or rand */
778     wc_InitRng_IntelRD();
779 #endif
780 
781     /* configure async RNG source if available */
782 #ifdef WOLFSSL_ASYNC_CRYPT
783     ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG,
784                                                         rng->heap, rng->devId);
785     if (ret != 0)
786         return ret;
787 #endif
788 
789 #ifdef HAVE_INTEL_RDRAND
790     /* if CPU supports RDRAND, use it directly and by-pass DRBG init */
791     if (IS_INTEL_RDRAND(intel_flags))
792         return 0;
793 #endif
794 
795 #ifdef CUSTOM_RAND_GENERATE_BLOCK
796     ret = 0; /* success */
797 #else
798 #ifdef HAVE_HASHDRBG
799     if (nonceSz == 0)
800         seedSz = MAX_SEED_SZ;
801 
802     if (wc_RNG_HealthTestLocal(0) == 0) {
803     #ifdef WC_ASYNC_ENABLE_SHA256
804         WC_DECLARE_VAR(seed, byte, MAX_SEED_SZ, rng->heap);
805         if (seed == NULL)
806             return MEMORY_E;
807     #else
808         byte seed[MAX_SEED_SZ];
809     #endif
810 
811 #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
812         rng->drbg =
813                 (struct DRBG*)XMALLOC(sizeof(DRBG_internal), rng->heap,
814                                                           DYNAMIC_TYPE_RNG);
815         if (rng->drbg == NULL) {
816             ret = MEMORY_E;
817             rng->status = DRBG_FAILED;
818         }
819 #else
820         rng->drbg = (struct DRBG*)&rng->drbg_data;
821 #endif
822         if (ret == 0) {
823 #ifdef WC_RNG_SEED_CB
824             if (seedCb == NULL) {
825                 ret = DRBG_NO_SEED_CB;
826             }
827             else {
828                 ret = seedCb(&rng->seed, seed, seedSz);
829                 if (ret != 0) {
830                     ret = DRBG_FAILURE;
831                 }
832             }
833 #else
834             ret = wc_GenerateSeed(&rng->seed, seed, seedSz);
835 #endif
836             if (ret == 0)
837                 ret = wc_RNG_TestSeed(seed, seedSz);
838             else {
839                 ret = DRBG_FAILURE;
840                 rng->status = DRBG_FAILED;
841             }
842 
843             if (ret == DRBG_SUCCESS)
844                 ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg,
845                             seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ,
846                             nonce, nonceSz, rng->heap, devId);
847 
848             if (ret != DRBG_SUCCESS) {
849             #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
850                 XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
851             #endif
852                 rng->drbg = NULL;
853             }
854         }
855 
856         ForceZero(seed, seedSz);
857     #ifdef WC_ASYNC_ENABLE_SHA256
858         WC_FREE_VAR(seed, rng->heap);
859     #endif
860     }
861     else
862         ret = DRBG_CONT_FAILURE;
863 
864     if (ret == DRBG_SUCCESS) {
865         rng->status = DRBG_OK;
866         ret = 0;
867     }
868     else if (ret == DRBG_CONT_FAILURE) {
869         rng->status = DRBG_CONT_FAILED;
870         ret = DRBG_CONT_FIPS_E;
871     }
872     else if (ret == DRBG_FAILURE) {
873         rng->status = DRBG_FAILED;
874         ret = RNG_FAILURE_E;
875     }
876     else {
877         rng->status = DRBG_FAILED;
878     }
879 #endif /* HAVE_HASHDRBG */
880 #endif /* CUSTOM_RAND_GENERATE_BLOCK */
881 
882     return ret;
883 }
884 
885 
886 WOLFSSL_ABI
wc_rng_new(byte * nonce,word32 nonceSz,void * heap)887 WC_RNG* wc_rng_new(byte* nonce, word32 nonceSz, void* heap)
888 {
889     WC_RNG* rng;
890 
891     rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), heap, DYNAMIC_TYPE_RNG);
892     if (rng) {
893         int error = _InitRng(rng, nonce, nonceSz, heap, INVALID_DEVID) != 0;
894         if (error) {
895             XFREE(rng, heap, DYNAMIC_TYPE_RNG);
896             rng = NULL;
897         }
898     }
899 
900     return rng;
901 }
902 
903 
904 WOLFSSL_ABI
wc_rng_free(WC_RNG * rng)905 void wc_rng_free(WC_RNG* rng)
906 {
907     if (rng) {
908         void* heap = rng->heap;
909 
910         wc_FreeRng(rng);
911         ForceZero(rng, sizeof(WC_RNG));
912         XFREE(rng, heap, DYNAMIC_TYPE_RNG);
913         (void)heap;
914     }
915 }
916 
917 
wc_InitRng(WC_RNG * rng)918 int wc_InitRng(WC_RNG* rng)
919 {
920     return _InitRng(rng, NULL, 0, NULL, INVALID_DEVID);
921 }
922 
923 
wc_InitRng_ex(WC_RNG * rng,void * heap,int devId)924 int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
925 {
926     return _InitRng(rng, NULL, 0, heap, devId);
927 }
928 
929 
wc_InitRngNonce(WC_RNG * rng,byte * nonce,word32 nonceSz)930 int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz)
931 {
932     return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID);
933 }
934 
935 
wc_InitRngNonce_ex(WC_RNG * rng,byte * nonce,word32 nonceSz,void * heap,int devId)936 int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
937                        void* heap, int devId)
938 {
939     return _InitRng(rng, nonce, nonceSz, heap, devId);
940 }
941 
942 
943 /* place a generated block in output */
944 WOLFSSL_ABI
wc_RNG_GenerateBlock(WC_RNG * rng,byte * output,word32 sz)945 int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
946 {
947     int ret;
948 
949     if (rng == NULL || output == NULL)
950         return BAD_FUNC_ARG;
951 
952     if (sz == 0)
953         return 0;
954 
955 #ifdef WOLF_CRYPTO_CB
956     if (rng->devId != INVALID_DEVID) {
957         ret = wc_CryptoCb_RandomBlock(rng, output, sz);
958         if (ret != CRYPTOCB_UNAVAILABLE)
959             return ret;
960         /* fall-through when unavailable */
961     }
962 #endif
963 
964 #ifdef HAVE_INTEL_RDRAND
965     if (IS_INTEL_RDRAND(intel_flags))
966         return wc_GenerateRand_IntelRD(NULL, output, sz);
967 #endif
968 
969 #if defined(WOLFSSL_SILABS_SE_ACCEL) && defined(WOLFSSL_SILABS_TRNG)
970     return silabs_GenerateRand(output, sz);
971 #endif
972 
973 #if defined(WOLFSSL_ASYNC_CRYPT)
974     if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) {
975         /* these are blocking */
976     #ifdef HAVE_CAVIUM
977         return NitroxRngGenerateBlock(rng, output, sz);
978     #elif defined(HAVE_INTEL_QA) && defined(QAT_ENABLE_RNG)
979         return IntelQaDrbg(&rng->asyncDev, output, sz);
980     #else
981         /* simulator not supported */
982     #endif
983     }
984 #endif
985 
986 #ifdef CUSTOM_RAND_GENERATE_BLOCK
987     XMEMSET(output, 0, sz);
988     ret = CUSTOM_RAND_GENERATE_BLOCK(output, sz);
989 #else
990 
991 #ifdef HAVE_HASHDRBG
992     if (sz > RNG_MAX_BLOCK_LEN)
993         return BAD_FUNC_ARG;
994 
995     if (rng->status != DRBG_OK)
996         return RNG_FAILURE_E;
997 
998     ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz);
999     if (ret == DRBG_NEED_RESEED) {
1000         if (wc_RNG_HealthTestLocal(1) == 0) {
1001             byte newSeed[SEED_SZ + SEED_BLOCK_SZ];
1002 
1003             ret = wc_GenerateSeed(&rng->seed, newSeed,
1004                                   SEED_SZ + SEED_BLOCK_SZ);
1005             if (ret != 0)
1006                 ret = DRBG_FAILURE;
1007             else
1008                 ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
1009 
1010             if (ret == DRBG_SUCCESS)
1011                 ret = Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, newSeed + SEED_BLOCK_SZ,
1012                                        SEED_SZ);
1013             if (ret == DRBG_SUCCESS)
1014                 ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz);
1015 
1016             ForceZero(newSeed, sizeof(newSeed));
1017         }
1018         else
1019             ret = DRBG_CONT_FAILURE;
1020     }
1021 
1022     if (ret == DRBG_SUCCESS) {
1023         ret = 0;
1024     }
1025     else if (ret == DRBG_CONT_FAILURE) {
1026         ret = DRBG_CONT_FIPS_E;
1027         rng->status = DRBG_CONT_FAILED;
1028     }
1029     else {
1030         ret = RNG_FAILURE_E;
1031         rng->status = DRBG_FAILED;
1032     }
1033 #else
1034 
1035     /* if we get here then there is an RNG configuration error */
1036     ret = RNG_FAILURE_E;
1037 
1038 #endif /* HAVE_HASHDRBG */
1039 #endif /* CUSTOM_RAND_GENERATE_BLOCK */
1040 
1041     return ret;
1042 }
1043 
1044 
wc_RNG_GenerateByte(WC_RNG * rng,byte * b)1045 int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
1046 {
1047     return wc_RNG_GenerateBlock(rng, b, 1);
1048 }
1049 
1050 
wc_FreeRng(WC_RNG * rng)1051 int wc_FreeRng(WC_RNG* rng)
1052 {
1053     int ret = 0;
1054 
1055     if (rng == NULL)
1056         return BAD_FUNC_ARG;
1057 
1058 #if defined(WOLFSSL_ASYNC_CRYPT)
1059     wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG);
1060 #endif
1061 
1062 #ifdef HAVE_HASHDRBG
1063     if (rng->drbg != NULL) {
1064       if (Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg) != DRBG_SUCCESS)
1065             ret = RNG_FAILURE_E;
1066 
1067     #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
1068         XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
1069     #endif
1070         rng->drbg = NULL;
1071     }
1072 
1073     rng->status = DRBG_NOT_INIT;
1074 #endif /* HAVE_HASHDRBG */
1075 
1076     return ret;
1077 }
1078 
1079 #ifdef HAVE_HASHDRBG
wc_RNG_HealthTest(int reseed,const byte * seedA,word32 seedASz,const byte * seedB,word32 seedBSz,byte * output,word32 outputSz)1080 int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz,
1081                                   const byte* seedB, word32 seedBSz,
1082                                   byte* output, word32 outputSz)
1083 {
1084     return wc_RNG_HealthTest_ex(reseed, NULL, 0,
1085                                 seedA, seedASz, seedB, seedBSz,
1086                                 output, outputSz,
1087                                 NULL, INVALID_DEVID);
1088 }
1089 
1090 
wc_RNG_HealthTest_ex(int reseed,const byte * nonce,word32 nonceSz,const byte * seedA,word32 seedASz,const byte * seedB,word32 seedBSz,byte * output,word32 outputSz,void * heap,int devId)1091 int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz,
1092                                   const byte* seedA, word32 seedASz,
1093                                   const byte* seedB, word32 seedBSz,
1094                                   byte* output, word32 outputSz,
1095                                   void* heap, int devId)
1096 {
1097     int ret = -1;
1098     DRBG_internal* drbg;
1099 #ifndef WOLFSSL_SMALL_STACK
1100     DRBG_internal  drbg_var;
1101 #endif
1102 
1103     if (seedA == NULL || output == NULL) {
1104         return BAD_FUNC_ARG;
1105     }
1106 
1107     if (reseed != 0 && seedB == NULL) {
1108         return BAD_FUNC_ARG;
1109     }
1110 
1111     if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) {
1112         return ret;
1113     }
1114 
1115 #ifdef WOLFSSL_SMALL_STACK
1116     drbg = (DRBG_internal*)XMALLOC(sizeof(DRBG_internal), NULL, DYNAMIC_TYPE_RNG);
1117     if (drbg == NULL) {
1118         return MEMORY_E;
1119     }
1120 #else
1121     drbg = &drbg_var;
1122 #endif
1123 
1124     if (Hash_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
1125                               heap, devId) != 0) {
1126         goto exit_rng_ht;
1127     }
1128 
1129     if (reseed) {
1130         if (Hash_DRBG_Reseed(drbg, seedB, seedBSz) != 0) {
1131             goto exit_rng_ht;
1132         }
1133     }
1134 
1135     /* This call to generate is prescribed by the NIST DRBGVS
1136      * procedure. The results are thrown away. The known
1137      * answer test checks the second block of DRBG out of
1138      * the generator to ensure the internal state is updated
1139      * as expected. */
1140     if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
1141         goto exit_rng_ht;
1142     }
1143 
1144     if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
1145         goto exit_rng_ht;
1146     }
1147 
1148     /* Mark success */
1149     ret = 0;
1150 
1151 exit_rng_ht:
1152 
1153     /* This is safe to call even if Hash_DRBG_Instantiate fails */
1154     if (Hash_DRBG_Uninstantiate(drbg) != 0) {
1155         ret = -1;
1156     }
1157 
1158 #ifdef WOLFSSL_SMALL_STACK
1159     XFREE(drbg, NULL, DYNAMIC_TYPE_RNG);
1160 #endif
1161 
1162     return ret;
1163 }
1164 
1165 
1166 const FLASH_QUALIFIER byte seedA_data[] = {
1167     0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4,
1168     0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00,
1169     0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f,
1170     0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68
1171 };
1172 
1173 const FLASH_QUALIFIER byte reseedSeedA_data[] = {
1174     0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3,
1175     0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22,
1176     0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3
1177 };
1178 
1179 const FLASH_QUALIFIER byte outputA_data[] = {
1180     0x04, 0xee, 0xc6, 0x3b, 0xb2, 0x31, 0xdf, 0x2c, 0x63, 0x0a, 0x1a, 0xfb,
1181     0xe7, 0x24, 0x94, 0x9d, 0x00, 0x5a, 0x58, 0x78, 0x51, 0xe1, 0xaa, 0x79,
1182     0x5e, 0x47, 0x73, 0x47, 0xc8, 0xb0, 0x56, 0x62, 0x1c, 0x18, 0xbd, 0xdc,
1183     0xdd, 0x8d, 0x99, 0xfc, 0x5f, 0xc2, 0xb9, 0x20, 0x53, 0xd8, 0xcf, 0xac,
1184     0xfb, 0x0b, 0xb8, 0x83, 0x12, 0x05, 0xfa, 0xd1, 0xdd, 0xd6, 0xc0, 0x71,
1185     0x31, 0x8a, 0x60, 0x18, 0xf0, 0x3b, 0x73, 0xf5, 0xed, 0xe4, 0xd4, 0xd0,
1186     0x71, 0xf9, 0xde, 0x03, 0xfd, 0x7a, 0xea, 0x10, 0x5d, 0x92, 0x99, 0xb8,
1187     0xaf, 0x99, 0xaa, 0x07, 0x5b, 0xdb, 0x4d, 0xb9, 0xaa, 0x28, 0xc1, 0x8d,
1188     0x17, 0x4b, 0x56, 0xee, 0x2a, 0x01, 0x4d, 0x09, 0x88, 0x96, 0xff, 0x22,
1189     0x82, 0xc9, 0x55, 0xa8, 0x19, 0x69, 0xe0, 0x69, 0xfa, 0x8c, 0xe0, 0x07,
1190     0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17
1191 };
1192 
1193 const FLASH_QUALIFIER byte seedB_data[] = {
1194     0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3,
1195     0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19,
1196     0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */
1197     0x85, 0x81, 0xf9, 0x31, 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d,
1198     0xdb, 0xcb, 0xcc, 0x2e
1199 };
1200 
1201 const FLASH_QUALIFIER byte outputB_data[] = {
1202     0xd3, 0xe1, 0x60, 0xc3, 0x5b, 0x99, 0xf3, 0x40, 0xb2, 0x62, 0x82, 0x64,
1203     0xd1, 0x75, 0x10, 0x60, 0xe0, 0x04, 0x5d, 0xa3, 0x83, 0xff, 0x57, 0xa5,
1204     0x7d, 0x73, 0xa6, 0x73, 0xd2, 0xb8, 0xd8, 0x0d, 0xaa, 0xf6, 0xa6, 0xc3,
1205     0x5a, 0x91, 0xbb, 0x45, 0x79, 0xd7, 0x3f, 0xd0, 0xc8, 0xfe, 0xd1, 0x11,
1206     0xb0, 0x39, 0x13, 0x06, 0x82, 0x8a, 0xdf, 0xed, 0x52, 0x8f, 0x01, 0x81,
1207     0x21, 0xb3, 0xfe, 0xbd, 0xc3, 0x43, 0xe7, 0x97, 0xb8, 0x7d, 0xbb, 0x63,
1208     0xdb, 0x13, 0x33, 0xde, 0xd9, 0xd1, 0xec, 0xe1, 0x77, 0xcf, 0xa6, 0xb7,
1209     0x1f, 0xe8, 0xab, 0x1d, 0xa4, 0x66, 0x24, 0xed, 0x64, 0x15, 0xe5, 0x1c,
1210     0xcd, 0xe2, 0xc7, 0xca, 0x86, 0xe2, 0x83, 0x99, 0x0e, 0xea, 0xeb, 0x91,
1211     0x12, 0x04, 0x15, 0x52, 0x8b, 0x22, 0x95, 0x91, 0x02, 0x81, 0xb0, 0x2d,
1212     0xd4, 0x31, 0xf4, 0xc9, 0xf7, 0x04, 0x27, 0xdf
1213 };
1214 
1215 
wc_RNG_HealthTestLocal(int reseed)1216 static int wc_RNG_HealthTestLocal(int reseed)
1217 {
1218     int ret = 0;
1219 #ifdef WOLFSSL_SMALL_STACK
1220     byte* check;
1221 #else
1222     byte  check[RNG_HEALTH_TEST_CHECK_SIZE];
1223 #endif
1224 
1225 #ifdef WOLFSSL_SMALL_STACK
1226     check = (byte*)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, NULL,
1227                            DYNAMIC_TYPE_TMP_BUFFER);
1228     if (check == NULL) {
1229         return MEMORY_E;
1230     }
1231 #endif
1232 
1233     if (reseed) {
1234 #ifdef WOLFSSL_USE_FLASHMEM
1235         byte* seedA = (byte*)XMALLOC(sizeof(seedA_data), NULL,
1236                              DYNAMIC_TYPE_TMP_BUFFER);
1237         byte* reseedSeedA = (byte*)XMALLOC(sizeof(reseedSeedA_data), NULL,
1238                              DYNAMIC_TYPE_TMP_BUFFER);
1239         byte* outputA = (byte*)XMALLOC(sizeof(outputA_data), NULL,
1240                              DYNAMIC_TYPE_TMP_BUFFER);
1241 
1242         if (!seedA || !reseedSeedA || !outputA) {
1243             XFREE(seedA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1244             XFREE(reseedSeedA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1245             XFREE(outputA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1246             ret = MEMORY_E;
1247         }
1248         else {
1249             XMEMCPY_P(seedA, seedA_data, sizeof(seedA_data));
1250             XMEMCPY_P(reseedSeedA, reseedSeedA_data, sizeof(reseedSeedA_data));
1251             XMEMCPY_P(outputA, outputA_data, sizeof(outputA_data));
1252 #else
1253         const byte* seedA = seedA_data;
1254         const byte* reseedSeedA = reseedSeedA_data;
1255         const byte* outputA = outputA_data;
1256 #endif
1257         ret = wc_RNG_HealthTest(1, seedA, sizeof(seedA_data),
1258                                 reseedSeedA, sizeof(reseedSeedA_data),
1259                                 check, RNG_HEALTH_TEST_CHECK_SIZE);
1260         if (ret == 0) {
1261             if (ConstantCompare(check, outputA,
1262                                 RNG_HEALTH_TEST_CHECK_SIZE) != 0)
1263                 ret = -1;
1264         }
1265 
1266 #ifdef WOLFSSL_USE_FLASHMEM
1267             XFREE(seedA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1268             XFREE(reseedSeedA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1269             XFREE(outputA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1270         }
1271 #endif
1272     }
1273     else {
1274 #ifdef WOLFSSL_USE_FLASHMEM
1275         byte* seedB = (byte*)XMALLOC(sizeof(seedB_data), NULL,
1276                              DYNAMIC_TYPE_TMP_BUFFER);
1277         byte* outputB = (byte*)XMALLOC(sizeof(outputB_data), NULL,
1278                                DYNAMIC_TYPE_TMP_BUFFER);
1279 
1280         if (!seedB || !outputB) {
1281             XFREE(seedB, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1282             XFREE(outputB, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1283             ret = MEMORY_E;
1284         }
1285         else {
1286             XMEMCPY_P(seedB, seedB_data, sizeof(seedB_data));
1287             XMEMCPY_P(outputB, outputB_data, sizeof(outputB_data));
1288 #else
1289         const byte* seedB = seedB_data;
1290         const byte* outputB = outputB_data;
1291 #endif
1292         ret = wc_RNG_HealthTest(0, seedB, sizeof(seedB_data),
1293                                 NULL, 0,
1294                                 check, RNG_HEALTH_TEST_CHECK_SIZE);
1295         if (ret == 0) {
1296             if (ConstantCompare(check, outputB,
1297                                 RNG_HEALTH_TEST_CHECK_SIZE) != 0)
1298                 ret = -1;
1299         }
1300 
1301         /* The previous test cases use a large seed instead of a seed and nonce.
1302          * seedB is actually from a test case with a seed and nonce, and
1303          * just concatenates them. The pivot point between seed and nonce is
1304          * byte 32, feed them into the health test separately. */
1305         if (ret == 0) {
1306             ret = wc_RNG_HealthTest_ex(0,
1307                                     seedB + 32, sizeof(seedB_data) - 32,
1308                                     seedB, 32,
1309                                     NULL, 0,
1310                                     check, RNG_HEALTH_TEST_CHECK_SIZE,
1311                                     NULL, INVALID_DEVID);
1312             if (ret == 0) {
1313                 if (ConstantCompare(check, outputB, sizeof(outputB_data)) != 0)
1314                     ret = -1;
1315             }
1316         }
1317 
1318 #ifdef WOLFSSL_USE_FLASHMEM
1319             XFREE(seedB, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1320             XFREE(outputB, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1321         }
1322 #endif
1323     }
1324 
1325 #ifdef WOLFSSL_SMALL_STACK
1326     XFREE(check, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1327 #endif
1328 
1329     return ret;
1330 }
1331 
1332 #endif /* HAVE_HASHDRBG */
1333 
1334 
1335 #ifdef HAVE_WNR
1336 
1337 /*
1338  * Init global Whitewood netRandom context
1339  * Returns 0 on success, negative on error
1340  */
wc_InitNetRandom(const char * configFile,wnr_hmac_key hmac_cb,int timeout)1341 int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout)
1342 {
1343     if (configFile == NULL || timeout < 0)
1344         return BAD_FUNC_ARG;
1345 
1346     if (wnr_mutex_init > 0) {
1347         WOLFSSL_MSG("netRandom context already created, skipping");
1348         return 0;
1349     }
1350 
1351     if (wc_InitMutex(&wnr_mutex) != 0) {
1352         WOLFSSL_MSG("Bad Init Mutex wnr_mutex");
1353         return BAD_MUTEX_E;
1354     }
1355     wnr_mutex_init = 1;
1356 
1357     if (wc_LockMutex(&wnr_mutex) != 0) {
1358         WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
1359         return BAD_MUTEX_E;
1360     }
1361 
1362     /* store entropy timeout */
1363     wnr_timeout = timeout;
1364 
1365     /* create global wnr_context struct */
1366     if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) {
1367         WOLFSSL_MSG("Error creating global netRandom context");
1368         return RNG_FAILURE_E;
1369     }
1370 
1371     /* load config file */
1372     if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) {
1373         WOLFSSL_MSG("Error loading config file into netRandom context");
1374         wnr_destroy(wnr_ctx);
1375         wnr_ctx = NULL;
1376         return RNG_FAILURE_E;
1377     }
1378 
1379     /* create/init polling mechanism */
1380     if (wnr_poll_create() != WNR_ERROR_NONE) {
1381         printf("ERROR: wnr_poll_create() failed\n");
1382         WOLFSSL_MSG("Error initializing netRandom polling mechanism");
1383         wnr_destroy(wnr_ctx);
1384         wnr_ctx = NULL;
1385         return RNG_FAILURE_E;
1386     }
1387 
1388     /* validate config, set HMAC callback (optional) */
1389     if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) {
1390         WOLFSSL_MSG("Error setting up netRandom context");
1391         wnr_destroy(wnr_ctx);
1392         wnr_ctx = NULL;
1393         wnr_poll_destroy();
1394         return RNG_FAILURE_E;
1395     }
1396 
1397     wc_UnLockMutex(&wnr_mutex);
1398 
1399     return 0;
1400 }
1401 
1402 /*
1403  * Free global Whitewood netRandom context
1404  * Returns 0 on success, negative on error
1405  */
wc_FreeNetRandom(void)1406 int wc_FreeNetRandom(void)
1407 {
1408     if (wnr_mutex_init > 0) {
1409 
1410         if (wc_LockMutex(&wnr_mutex) != 0) {
1411             WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
1412             return BAD_MUTEX_E;
1413         }
1414 
1415         if (wnr_ctx != NULL) {
1416             wnr_destroy(wnr_ctx);
1417             wnr_ctx = NULL;
1418         }
1419         wnr_poll_destroy();
1420 
1421         wc_UnLockMutex(&wnr_mutex);
1422 
1423         wc_FreeMutex(&wnr_mutex);
1424         wnr_mutex_init = 0;
1425     }
1426 
1427     return 0;
1428 }
1429 
1430 #endif /* HAVE_WNR */
1431 
1432 
1433 #if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
1434 
1435 #ifdef WOLFSSL_ASYNC_CRYPT
1436     /* need more retries if multiple cores */
1437     #define INTELRD_RETRY (32 * 8)
1438 #else
1439     #define INTELRD_RETRY 32
1440 #endif
1441 
1442 #ifdef HAVE_INTEL_RDSEED
1443 
1444 #ifndef USE_INTEL_INTRINSICS
1445 
1446     /* return 0 on success */
IntelRDseed64(word64 * seed)1447     static WC_INLINE int IntelRDseed64(word64* seed)
1448     {
1449         unsigned char ok;
1450 
1451         __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok));
1452         return (ok) ? 0 : -1;
1453     }
1454 
1455 #else /* USE_INTEL_INTRINSICS */
1456     /* The compiler Visual Studio uses does not allow inline assembly.
1457      * It does allow for Intel intrinsic functions. */
1458 
1459     /* return 0 on success */
1460 # ifdef __GNUC__
1461     __attribute__((target("rdseed")))
1462 # endif
IntelRDseed64(word64 * seed)1463     static WC_INLINE int IntelRDseed64(word64* seed)
1464     {
1465         int ok;
1466 
1467         ok = _rdseed64_step((unsigned long long*) seed);
1468         return (ok) ? 0 : -1;
1469     }
1470 
1471 #endif /* USE_INTEL_INTRINSICS */
1472 
1473 /* return 0 on success */
IntelRDseed64_r(word64 * rnd)1474 static WC_INLINE int IntelRDseed64_r(word64* rnd)
1475 {
1476     int i;
1477     for (i = 0; i < INTELRD_RETRY; i++) {
1478         if (IntelRDseed64(rnd) == 0)
1479             return 0;
1480     }
1481     return -1;
1482 }
1483 
1484 #ifndef WOLFSSL_LINUXKM
1485 /* return 0 on success */
wc_GenerateSeed_IntelRD(OS_Seed * os,byte * output,word32 sz)1486 static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz)
1487 {
1488     int ret;
1489     word64 rndTmp;
1490 
1491     (void)os;
1492 
1493     if (!IS_INTEL_RDSEED(intel_flags))
1494         return -1;
1495 
1496     for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
1497                                                     output += sizeof(word64)) {
1498         ret = IntelRDseed64_r((word64*)output);
1499         if (ret != 0)
1500             return ret;
1501     }
1502     if (sz == 0)
1503         return 0;
1504 
1505     /* handle unaligned remainder */
1506     ret = IntelRDseed64_r(&rndTmp);
1507     if (ret != 0)
1508         return ret;
1509 
1510     XMEMCPY(output, &rndTmp, sz);
1511     ForceZero(&rndTmp, sizeof(rndTmp));
1512 
1513     return 0;
1514 }
1515 #endif
1516 
1517 #endif /* HAVE_INTEL_RDSEED */
1518 
1519 #ifdef HAVE_INTEL_RDRAND
1520 
1521 #ifndef USE_INTEL_INTRINSICS
1522 
1523 /* return 0 on success */
IntelRDrand64(word64 * rnd)1524 static WC_INLINE int IntelRDrand64(word64 *rnd)
1525 {
1526     unsigned char ok;
1527 
1528     __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok));
1529 
1530     return (ok) ? 0 : -1;
1531 }
1532 
1533 #else /* USE_INTEL_INTRINSICS */
1534     /* The compiler Visual Studio uses does not allow inline assembly.
1535      * It does allow for Intel intrinsic functions. */
1536 
1537 /* return 0 on success */
1538 # ifdef __GNUC__
1539 __attribute__((target("rdrnd")))
1540 # endif
IntelRDrand64(word64 * rnd)1541 static WC_INLINE int IntelRDrand64(word64 *rnd)
1542 {
1543     int ok;
1544 
1545     ok = _rdrand64_step((unsigned long long*) rnd);
1546 
1547     return (ok) ? 0 : -1;
1548 }
1549 
1550 #endif /* USE_INTEL_INTRINSICS */
1551 
1552 /* return 0 on success */
IntelRDrand64_r(word64 * rnd)1553 static WC_INLINE int IntelRDrand64_r(word64 *rnd)
1554 {
1555     int i;
1556     for (i = 0; i < INTELRD_RETRY; i++) {
1557         if (IntelRDrand64(rnd) == 0)
1558             return 0;
1559     }
1560     return -1;
1561 }
1562 
1563 /* return 0 on success */
wc_GenerateRand_IntelRD(OS_Seed * os,byte * output,word32 sz)1564 static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz)
1565 {
1566     int ret;
1567     word64 rndTmp;
1568 
1569     (void)os;
1570 
1571     if (!IS_INTEL_RDRAND(intel_flags))
1572         return -1;
1573 
1574     for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
1575                                                     output += sizeof(word64)) {
1576         ret = IntelRDrand64_r((word64 *)output);
1577         if (ret != 0)
1578             return ret;
1579     }
1580     if (sz == 0)
1581         return 0;
1582 
1583     /* handle unaligned remainder */
1584     ret = IntelRDrand64_r(&rndTmp);
1585     if (ret != 0)
1586         return ret;
1587 
1588     XMEMCPY(output, &rndTmp, sz);
1589 
1590     return 0;
1591 }
1592 
1593 #endif /* HAVE_INTEL_RDRAND */
1594 #endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED */
1595 
1596 
1597 /* Begin wc_GenerateSeed Implementations */
1598 #if defined(CUSTOM_RAND_GENERATE_SEED)
1599 
1600     /* Implement your own random generation function
1601      * Return 0 to indicate success
1602      * int rand_gen_seed(byte* output, word32 sz);
1603      * #define CUSTOM_RAND_GENERATE_SEED  rand_gen_seed */
1604 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1605     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1606     {
1607         (void)os; /* Suppress unused arg warning */
1608         return CUSTOM_RAND_GENERATE_SEED(output, sz);
1609     }
1610 
1611 #elif defined(CUSTOM_RAND_GENERATE_SEED_OS)
1612 
1613     /* Implement your own random generation function,
1614      *  which includes OS_Seed.
1615      * Return 0 to indicate success
1616      * int rand_gen_seed(OS_Seed* os, byte* output, word32 sz);
1617      * #define CUSTOM_RAND_GENERATE_SEED_OS  rand_gen_seed */
1618 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1619     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1620     {
1621         return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz);
1622     }
1623 
1624 #elif defined(CUSTOM_RAND_GENERATE)
1625 
1626    /* Implement your own random generation function
1627     * word32 rand_gen(void);
1628     * #define CUSTOM_RAND_GENERATE  rand_gen  */
1629 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1630     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1631     {
1632         word32 i = 0;
1633 
1634         (void)os;
1635 
1636         while (i < sz)
1637         {
1638             /* If not aligned or there is odd/remainder */
1639             if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz ||
1640                 ((wc_ptr_t)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0
1641             ) {
1642                 /* Single byte at a time */
1643                 output[i++] = (byte)CUSTOM_RAND_GENERATE();
1644             }
1645             else {
1646                 /* Use native 8, 16, 32 or 64 copy instruction */
1647                 *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE();
1648                 i += sizeof(CUSTOM_RAND_TYPE);
1649             }
1650         }
1651 
1652         return 0;
1653     }
1654 
1655 #elif defined(WOLFSSL_SGX)
1656 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1657 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1658 {
1659     int ret = !SGX_SUCCESS;
1660     int i, read_max = 10;
1661 
1662     for (i = 0; i < read_max && ret != SGX_SUCCESS; i++) {
1663         ret = sgx_read_rand(output, sz);
1664     }
1665 
1666     (void)os;
1667     return (ret == SGX_SUCCESS) ? 0 : 1;
1668 }
1669 
1670 #elif defined(USE_WINDOWS_API)
1671 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1672 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1673 {
1674 #ifdef WOLF_CRYPTO_CB
1675     int ret;
1676 
1677     if (os != NULL && os->devId != INVALID_DEVID) {
1678         ret = wc_CryptoCb_RandomSeed(os, output, sz);
1679         if (ret != CRYPTOCB_UNAVAILABLE)
1680             return ret;
1681         /* fall-through when unavailable */
1682     }
1683 #endif
1684 
1685     #ifdef HAVE_INTEL_RDSEED
1686         if (IS_INTEL_RDSEED(intel_flags)) {
1687              if (!wc_GenerateSeed_IntelRD(NULL, output, sz)) {
1688                  /* success, we're done */
1689                  return 0;
1690              }
1691         #ifdef FORCE_FAILURE_RDSEED
1692              /* don't fall back to CryptoAPI */
1693              return READ_RAN_E;
1694         #endif
1695         }
1696     #endif /* HAVE_INTEL_RDSEED */
1697 
1698     if(!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
1699                             CRYPT_VERIFYCONTEXT))
1700         return WINCRYPT_E;
1701 
1702     if (!CryptGenRandom(os->handle, sz, output))
1703         return CRYPTGEN_E;
1704 
1705     CryptReleaseContext(os->handle, 0);
1706 
1707     return 0;
1708 }
1709 
1710 
1711 #elif defined(HAVE_RTP_SYS) || defined(EBSNET)
1712 
1713 #include "rtprand.h"   /* rtp_rand () */
1714 #include "rtptime.h"   /* rtp_get_system_msec() */
1715 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1716 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1717 {
1718     word32 i;
1719 
1720     rtp_srand(rtp_get_system_msec());
1721     for (i = 0; i < sz; i++ ) {
1722         output[i] = rtp_rand() % 256;
1723     }
1724 
1725     return 0;
1726 }
1727 
1728 #elif (defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC_RNG)) && \
1729       !defined(WOLFSSL_PIC32MZ_RNG)
1730     /* enable ATECC RNG unless using PIC32MZ one instead */
1731     #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
1732 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1733     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1734     {
1735         int ret = 0;
1736 
1737         (void)os;
1738         if (output == NULL) {
1739             return BUFFER_E;
1740         }
1741 
1742         ret = atmel_get_random_number(sz, output);
1743 
1744         return ret;
1745     }
1746 
1747 #elif defined(MICROCHIP_PIC32)
1748 
1749     #ifdef MICROCHIP_MPLAB_HARMONY
1750         #ifdef MICROCHIP_MPLAB_HARMONY_3
1751             #include "system/time/sys_time.h"
1752             #define PIC32_SEED_COUNT SYS_TIME_CounterGet
1753         #else
1754             #define PIC32_SEED_COUNT _CP0_GET_COUNT
1755         #endif
1756     #else
1757         #if !defined(WOLFSSL_MICROCHIP_PIC32MZ)
1758             #include <peripheral/timer.h>
1759         #endif
1760         extern word32 ReadCoreTimer(void);
1761         #define PIC32_SEED_COUNT ReadCoreTimer
1762     #endif
1763 
1764     #ifdef WOLFSSL_PIC32MZ_RNG
1765         #include "xc.h"
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1766         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1767         {
1768             int i;
1769             byte rnd[8];
1770             word32 *rnd32 = (word32 *)rnd;
1771             word32 size = sz;
1772             byte* op = output;
1773 
1774 #if ((__PIC32_FEATURE_SET0 == 'E') && (__PIC32_FEATURE_SET1 == 'C'))
1775             RNGNUMGEN1 = _CP0_GET_COUNT();
1776             RNGPOLY1 = _CP0_GET_COUNT();
1777             RNGPOLY2 = _CP0_GET_COUNT();
1778             RNGNUMGEN2 = _CP0_GET_COUNT();
1779 #else
1780             /* All others can be seeded from the TRNG */
1781             RNGCONbits.TRNGMODE = 1;
1782             RNGCONbits.TRNGEN = 1;
1783             while (RNGCNT < 64);
1784             RNGCONbits.LOAD = 1;
1785             while (RNGCONbits.LOAD == 1);
1786             while (RNGCNT < 64);
1787             RNGPOLY2 = RNGSEED2;
1788             RNGPOLY1 = RNGSEED1;
1789 #endif
1790 
1791             RNGCONbits.PLEN = 0x40;
1792             RNGCONbits.PRNGEN = 1;
1793             for (i=0; i<5; i++) { /* wait for RNGNUMGEN ready */
1794                 volatile int x, y;
1795                 x = RNGNUMGEN1;
1796                 y = RNGNUMGEN2;
1797                 (void)x;
1798                 (void)y;
1799             }
1800             do {
1801                 rnd32[0] = RNGNUMGEN1;
1802                 rnd32[1] = RNGNUMGEN2;
1803 
1804                 for(i=0; i<8; i++, op++) {
1805                     *op = rnd[i];
1806                     size --;
1807                     if(size==0)break;
1808                 }
1809             } while(size);
1810             return 0;
1811         }
1812     #else  /* WOLFSSL_PIC32MZ_RNG */
1813         /* uses the core timer, in nanoseconds to seed srand */
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1814         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1815         {
1816             int i;
1817             srand(PIC32_SEED_COUNT() * 25);
1818 
1819             for (i = 0; i < sz; i++ ) {
1820                 output[i] = rand() % 256;
1821                 if ( (i % 8) == 7)
1822                     srand(PIC32_SEED_COUNT() * 25);
1823             }
1824             return 0;
1825         }
1826     #endif /* WOLFSSL_PIC32MZ_RNG */
1827 
1828 #elif defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA)
1829     /*
1830      * wc_Generates a RNG seed using the Random Number Generator Accelerator
1831      * on the Kinetis K70. Documentation located in Chapter 37 of
1832      * K70 Sub-Family Reference Manual (see Note 3 in the README for link).
1833      */
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1834     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1835     {
1836         word32 i;
1837 
1838         /* turn on RNGA module */
1839         #if defined(SIM_SCGC3_RNGA_MASK)
1840             SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK;
1841         #endif
1842         #if defined(SIM_SCGC6_RNGA_MASK)
1843             /* additionally needed for at least K64F */
1844             SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK;
1845         #endif
1846 
1847         /* set SLP bit to 0 - "RNGA is not in sleep mode" */
1848         RNG_CR &= ~RNG_CR_SLP_MASK;
1849 
1850         /* set HA bit to 1 - "security violations masked" */
1851         RNG_CR |= RNG_CR_HA_MASK;
1852 
1853         /* set GO bit to 1 - "output register loaded with data" */
1854         RNG_CR |= RNG_CR_GO_MASK;
1855 
1856         for (i = 0; i < sz; i++) {
1857 
1858             /* wait for RNG FIFO to be full */
1859             while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {}
1860 
1861             /* get value */
1862             output[i] = RNG_OR;
1863         }
1864 
1865         return 0;
1866     }
1867 
1868 #elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB)
1869     /*
1870      * wc_Generates a RNG seed using the Random Number Generator (RNGB)
1871      * on the Kinetis K53. Documentation located in Chapter 33 of
1872      * K53 Sub-Family Reference Manual (see note in the README for link).
1873      */
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1874     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1875     {
1876         int i;
1877 
1878         /* turn on RNGB module */
1879         SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK;
1880 
1881         /* reset RNGB */
1882         RNG_CMD |= RNG_CMD_SR_MASK;
1883 
1884         /* FIFO generate interrupt, return all zeros on underflow,
1885          * set auto reseed */
1886         RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK);
1887 
1888         /* gen seed, clear interrupts, clear errors */
1889         RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK);
1890 
1891         /* wait for seeding to complete */
1892         while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {}
1893 
1894         for (i = 0; i < sz; i++) {
1895 
1896             /* wait for a word to be available from FIFO */
1897             while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {}
1898 
1899             /* get value */
1900             output[i] = RNG_OUT;
1901         }
1902 
1903         return 0;
1904     }
1905 
1906 #elif defined(FREESCALE_KSDK_2_0_TRNG)
1907     #ifndef TRNG0
1908     #define TRNG0 TRNG
1909     #endif
1910 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1911     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1912     {
1913         status_t status;
1914         status = TRNG_GetRandomData(TRNG0, output, sz);
1915         (void)os;
1916         if (status == kStatus_Success)
1917         {
1918             return(0);
1919         }
1920         return RAN_BLOCK_E;
1921     }
1922 
1923 #elif defined(FREESCALE_KSDK_2_0_RNGA)
1924 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1925     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1926     {
1927         status_t status;
1928         status = RNGA_GetRandomData(RNG, output, sz);
1929         (void)os;
1930         if (status == kStatus_Success)
1931         {
1932             return(0);
1933         }
1934         return RAN_BLOCK_E;
1935     }
1936 
1937 
1938 #elif defined(FREESCALE_RNGA)
1939 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1940     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1941     {
1942         status_t status;
1943         status = RNGA_GetRandomData(RNG, output, sz);
1944         (void)os;
1945         if (status == kStatus_Success)
1946         {
1947             return(0);
1948         }
1949         return RAN_BLOCK_E;
1950     }
1951 
1952 #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \
1953     defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS)
1954     /*
1955      * Fallback to USE_TEST_GENSEED if a FREESCALE platform did not match any
1956      * of the TRNG/RNGA/RNGB support
1957      */
1958     #define USE_TEST_GENSEED
1959 
1960 #elif defined(WOLFSSL_SILABS_SE_ACCEL)
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1961     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1962     {
1963         (void)os;
1964         return silabs_GenerateRand(output, sz);
1965     }
1966 
1967 #elif defined(STM32_RNG)
1968      /* Generate a RNG seed using the hardware random number generator
1969       * on the STM32F2/F4/F7/L4. */
1970 
1971     #ifdef WOLFSSL_STM32_CUBEMX
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)1972     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1973     {
1974         int ret;
1975         RNG_HandleTypeDef hrng;
1976         word32 i = 0;
1977         (void)os;
1978 
1979         ret = wolfSSL_CryptHwMutexLock();
1980         if (ret != 0) {
1981             return ret;
1982         }
1983 
1984         /* enable RNG clock source */
1985         __HAL_RCC_RNG_CLK_ENABLE();
1986 
1987         /* enable RNG peripheral */
1988         XMEMSET(&hrng, 0, sizeof(hrng));
1989         hrng.Instance = RNG;
1990         HAL_RNG_Init(&hrng);
1991 
1992         while (i < sz) {
1993             /* If not aligned or there is odd/remainder */
1994             if( (i + sizeof(word32)) > sz ||
1995                 ((wc_ptr_t)&output[i] % sizeof(word32)) != 0
1996             ) {
1997                 /* Single byte at a time */
1998                 uint32_t tmpRng = 0;
1999                 if (HAL_RNG_GenerateRandomNumber(&hrng, &tmpRng) != HAL_OK) {
2000                     wolfSSL_CryptHwMutexUnLock();
2001                     return RAN_BLOCK_E;
2002                 }
2003                 output[i++] = (byte)tmpRng;
2004             }
2005             else {
2006                 /* Use native 32 instruction */
2007                 if (HAL_RNG_GenerateRandomNumber(&hrng, (uint32_t*)&output[i]) != HAL_OK) {
2008                     wolfSSL_CryptHwMutexUnLock();
2009                     return RAN_BLOCK_E;
2010                 }
2011                 i += sizeof(word32);
2012             }
2013         }
2014 
2015         wolfSSL_CryptHwMutexUnLock();
2016 
2017         return 0;
2018     }
2019     #elif defined(WOLFSSL_STM32F427_RNG) || defined(WOLFSSL_STM32_RNG_NOLIB)
2020 
2021     /* Generate a RNG seed using the hardware RNG on the STM32F427
2022      * directly, following steps outlined in STM32F4 Reference
2023      * Manual (Chapter 24) for STM32F4xx family. */
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2024     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2025     {
2026         int ret;
2027         word32 i;
2028         (void)os;
2029 
2030         ret = wolfSSL_CryptHwMutexLock();
2031         if (ret != 0) {
2032             return ret;
2033         }
2034 
2035         /* enable RNG peripheral clock */
2036         RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN;
2037 
2038         /* enable RNG interrupt, set IE bit in RNG->CR register */
2039         RNG->CR |= RNG_CR_IE;
2040 
2041         /* enable RNG, set RNGEN bit in RNG->CR. Activates RNG,
2042          * RNG_LFSR, and error detector */
2043         RNG->CR |= RNG_CR_RNGEN;
2044 
2045         /* verify no errors, make sure SEIS and CEIS bits are 0
2046          * in RNG->SR register */
2047         if (RNG->SR & (RNG_SR_SECS | RNG_SR_CECS)) {
2048             wolfSSL_CryptHwMutexUnLock();
2049             return RNG_FAILURE_E;
2050         }
2051 
2052         for (i = 0; i < sz; i++) {
2053             /* wait until RNG number is ready */
2054             while ((RNG->SR & RNG_SR_DRDY) == 0) { }
2055 
2056             /* get value */
2057             output[i] = RNG->DR;
2058         }
2059 
2060         wolfSSL_CryptHwMutexUnLock();
2061 
2062         return 0;
2063     }
2064 
2065     #else
2066 
2067     /* Generate a RNG seed using the STM32 Standard Peripheral Library */
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2068     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2069     {
2070         int ret;
2071         word32 i;
2072         (void)os;
2073 
2074         ret = wolfSSL_CryptHwMutexLock();
2075         if (ret != 0) {
2076             return ret;
2077         }
2078 
2079         /* enable RNG clock source */
2080         RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
2081 
2082         /* reset RNG */
2083         RNG_DeInit();
2084 
2085         /* enable RNG peripheral */
2086         RNG_Cmd(ENABLE);
2087 
2088         /* verify no errors with RNG_CLK or Seed */
2089         if (RNG_GetFlagStatus(RNG_FLAG_SECS | RNG_FLAG_CECS) != RESET) {
2090             wolfSSL_CryptHwMutexUnLock();
2091             return RNG_FAILURE_E;
2092         }
2093 
2094         for (i = 0; i < sz; i++) {
2095             /* wait until RNG number is ready */
2096             while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) { }
2097 
2098             /* get value */
2099             output[i] = RNG_GetRandomNumber();
2100         }
2101 
2102         wolfSSL_CryptHwMutexUnLock();
2103 
2104         return 0;
2105     }
2106     #endif /* WOLFSSL_STM32_CUBEMX */
2107 
2108 #elif defined(WOLFSSL_TIRTOS)
2109 
2110     #include <xdc/runtime/Timestamp.h>
2111     #include <stdlib.h>
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2112     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2113     {
2114         int i;
2115         srand(xdc_runtime_Timestamp_get32());
2116 
2117         for (i = 0; i < sz; i++ ) {
2118             output[i] = rand() % 256;
2119             if ((i % 8) == 7) {
2120                 srand(xdc_runtime_Timestamp_get32());
2121             }
2122         }
2123 
2124         return 0;
2125     }
2126 
2127 #elif defined(WOLFSSL_PB)
2128 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2129     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2130     {
2131         word32 i;
2132         for (i = 0; i < sz; i++)
2133             output[i] = UTL_Rand();
2134 
2135         (void)os;
2136 
2137         return 0;
2138     }
2139 
2140 #elif defined(WOLFSSL_NUCLEUS)
2141 #include "nucleus.h"
2142 #include "kernel/plus_common.h"
2143 
2144 #warning "potential for not enough entropy, currently being used for testing"
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2145 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2146 {
2147     int i;
2148     srand(NU_Get_Time_Stamp());
2149 
2150     for (i = 0; i < sz; i++ ) {
2151         output[i] = rand() % 256;
2152         if ((i % 8) == 7) {
2153             srand(NU_Get_Time_Stamp());
2154         }
2155     }
2156 
2157     return 0;
2158 }
2159 #elif defined(WOLFSSL_DEOS) && !defined(CUSTOM_RAND_GENERATE)
2160     #include "stdlib.h"
2161 
2162     #warning "potential for not enough entropy, currently being used for testing Deos"
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2163     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2164     {
2165         int i;
2166         int seed = XTIME(0);
2167         (void)os;
2168 
2169         for (i = 0; i < sz; i++ ) {
2170             output[i] = rand_r(&seed) % 256;
2171             if ((i % 8) == 7) {
2172                 seed = XTIME(0);
2173                 rand_r(&seed);
2174             }
2175         }
2176 
2177         return 0;
2178     }
2179 #elif defined(WOLFSSL_VXWORKS)
2180 
2181     #include <randomNumGen.h>
2182 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2183     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) {
2184         STATUS        status;
2185 
2186         #ifdef VXWORKS_SIM
2187             /* cannot generate true entropy with VxWorks simulator */
2188             #warning "not enough entropy, simulator for testing only"
2189             int i = 0;
2190 
2191             for (i = 0; i < 1000; i++) {
2192                 randomAddTimeStamp();
2193             }
2194         #endif
2195 
2196         status = randBytes (output, sz);
2197         if (status == ERROR) {
2198             return RNG_FAILURE_E;
2199         }
2200 
2201         return 0;
2202     }
2203 
2204 #elif defined(WOLFSSL_NRF51) || defined(WOLFSSL_NRF5x)
2205     #include "app_error.h"
2206     #include "nrf_drv_rng.h"
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2207     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2208     {
2209         int remaining = sz, length, pos = 0;
2210         word32 err_code;
2211         byte available;
2212         static byte initialized = 0;
2213 
2214         (void)os;
2215 
2216         /* Make sure RNG is running */
2217         if (!initialized) {
2218             err_code = nrf_drv_rng_init(NULL);
2219             if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE
2220             #ifdef NRF_ERROR_MODULE_ALREADY_INITIALIZED
2221                 && err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED
2222             #endif
2223             ) {
2224                 return -1;
2225             }
2226             initialized = 1;
2227         }
2228 
2229         while (remaining > 0) {
2230             available = 0;
2231             nrf_drv_rng_bytes_available(&available); /* void func */
2232             length = (remaining < available) ? remaining : available;
2233             if (length > 0) {
2234                 err_code = nrf_drv_rng_rand(&output[pos], length);
2235                 if (err_code != NRF_SUCCESS) {
2236                     break;
2237                 }
2238                 remaining -= length;
2239                 pos += length;
2240             }
2241         }
2242 
2243         return (err_code == NRF_SUCCESS) ? 0 : -1;
2244     }
2245 
2246 #elif defined(HAVE_WNR)
2247 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2248     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2249     {
2250         if (os == NULL || output == NULL || wnr_ctx == NULL ||
2251                 wnr_timeout < 0) {
2252             return BAD_FUNC_ARG;
2253         }
2254 
2255         if (wnr_mutex_init == 0) {
2256             WOLFSSL_MSG("netRandom context must be created before use");
2257             return RNG_FAILURE_E;
2258         }
2259 
2260         if (wc_LockMutex(&wnr_mutex) != 0) {
2261             WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
2262             return BAD_MUTEX_E;
2263         }
2264 
2265         if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) !=
2266                 WNR_ERROR_NONE)
2267             return RNG_FAILURE_E;
2268 
2269         wc_UnLockMutex(&wnr_mutex);
2270 
2271         return 0;
2272     }
2273 
2274 #elif defined(INTIME_RTOS)
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2275     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2276     {
2277         uint32_t randval;
2278         word32 len;
2279 
2280         if (output == NULL) {
2281             return BUFFER_E;
2282         }
2283 
2284     #ifdef INTIMEVER
2285         /* If INTIMEVER exists then it is INTIME RTOS v6 or later */
2286         #define INTIME_RAND_FUNC arc4random
2287         len = 4;
2288     #else
2289         /* v5 and older */
2290         #define INTIME_RAND_FUNC rand
2291         srand(time(0));
2292         len = 2; /* don't use all 31 returned bits */
2293     #endif
2294 
2295         while (sz > 0) {
2296             if (sz < len)
2297                 len = sz;
2298             randval = INTIME_RAND_FUNC();
2299             XMEMCPY(output, &randval, len);
2300             output += len;
2301             sz -= len;
2302         }
2303         (void)os;
2304 
2305         return 0;
2306     }
2307 
2308 #elif defined(WOLFSSL_WICED)
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2309     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2310     {
2311         int ret;
2312         (void)os;
2313 
2314         if (output == NULL || UINT16_MAX < sz) {
2315             return BUFFER_E;
2316         }
2317 
2318         if ((ret = wiced_crypto_get_random((void*) output, sz) )
2319                          != WICED_SUCCESS) {
2320             return ret;
2321         }
2322 
2323         return ret;
2324     }
2325 
2326 #elif defined(WOLFSSL_NETBURNER)
2327     #warning using NetBurner pseudo random GetRandomByte for seed
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2328     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2329     {
2330         word32 i;
2331         (void)os;
2332 
2333         if (output == NULL) {
2334             return BUFFER_E;
2335         }
2336 
2337         for (i = 0; i < sz; i++) {
2338             output[i] = GetRandomByte();
2339 
2340             /* check if was a valid random number */
2341             if (!RandomValid())
2342                 return RNG_FAILURE_E;
2343         }
2344 
2345         return 0;
2346     }
2347 #elif defined(IDIRECT_DEV_RANDOM)
2348 
2349     extern int getRandom( int sz, unsigned char *output );
2350 
GenerateSeed(OS_Seed * os,byte * output,word32 sz)2351     int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2352     {
2353         int num_bytes_returned = 0;
2354 
2355         num_bytes_returned = getRandom( (int) sz, (unsigned char *) output );
2356 
2357         return 0;
2358     }
2359 
2360 #elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG))
2361 
2362     #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
2363 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2364     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2365     {
2366         unsigned int args[4] = {0};
2367         CAAM_BUFFER buf[1];
2368         int ret    = 0;
2369         int times  = 1000, i; /* 1000 is an arbitrary number chosen */
2370         word32 idx = 0;
2371 
2372         (void)os;
2373 
2374         if (output == NULL) {
2375             return BUFFER_E;
2376         }
2377 
2378         /* Check Waiting to make sure entropy is ready */
2379         for (i = 0; i < times; i++) {
2380             buf[0].BufferType = DataBuffer | LastBuffer;
2381             buf[0].TheAddress = (CAAM_ADDRESS)(output + idx);
2382             buf[0].Length     = ((sz - idx) < WC_CAAM_MAX_ENTROPY)?
2383                                 sz - idx : WC_CAAM_MAX_ENTROPY;
2384 
2385             args[0] = buf[0].Length;
2386             ret = wc_caamAddAndWait(buf, 1, args, CAAM_ENTROPY);
2387             if (ret == 0) {
2388                 idx += buf[0].Length;
2389                 if (idx == sz)
2390                     break;
2391             }
2392 
2393             /* driver could be waiting for entropy */
2394             if (ret != RAN_BLOCK_E && ret != 0) {
2395                 return ret;
2396             }
2397             usleep(100);
2398         }
2399 
2400         if (i == times && ret != 0) {
2401              return RNG_FAILURE_E;
2402         }
2403         else { /* Success case */
2404             ret = 0;
2405         }
2406 
2407         return ret;
2408     }
2409 
2410 #elif defined(WOLFSSL_APACHE_MYNEWT)
2411 
2412     #include <stdlib.h>
2413     #include "os/os_time.h"
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2414     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2415     {
2416         int i;
2417         srand(os_time_get());
2418 
2419         for (i = 0; i < sz; i++ ) {
2420             output[i] = rand() % 256;
2421             if ((i % 8) == 7) {
2422                 srand(os_time_get());
2423             }
2424         }
2425 
2426         return 0;
2427     }
2428 
2429 #elif defined(WOLFSSL_ESPIDF)
2430     #if defined(WOLFSSL_ESPWROOM32) || defined(WOLFSSL_ESPWROOM32SE)
2431         #include <esp_system.h>
2432 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2433         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2434         {
2435             word32 rand;
2436             while (sz > 0) {
2437                 word32 len = sizeof(rand);
2438                 if (sz < len)
2439                     len = sz;
2440                 /* Get one random 32-bit word from hw RNG */
2441                 rand = esp_random( );
2442                 XMEMCPY(output, &rand, len);
2443                 output += len;
2444                 sz -= len;
2445             }
2446 
2447             return 0;
2448         }
2449     #endif /* end WOLFSSL_ESPWROOM32 */
2450 
2451 #elif defined(WOLFSSL_LINUXKM)
2452     #include <linux/random.h>
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2453     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2454     {
2455         (void)os;
2456 
2457         get_random_bytes(output, sz);
2458 
2459         return 0;
2460     }
2461 
2462 #elif defined(WOLFSSL_RENESAS_TSIP)
2463 #if defined(WOLFSSL_RENESA_TSIP_IAREWRX)
2464    #include "r_bsp/mcu/all/r_rx_compiler.h"
2465 #endif
2466    #include "r_bsp/platform.h"
2467     #include "r_tsip_rx_if.h"
2468 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2469     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2470     {
2471         int ret;
2472         word32 buffer[4];
2473 
2474         while (sz > 0) {
2475             word32 len = sizeof(buffer);
2476 
2477             if (sz < len) {
2478                 len = sz;
2479             }
2480             /* return 4 words random number*/
2481             ret = R_TSIP_GenerateRandomNumber(buffer);
2482             if(ret == TSIP_SUCCESS) {
2483                 XMEMCPY(output, &buffer, len);
2484                 output += len;
2485                 sz -= len;
2486             } else
2487                 return ret;
2488         }
2489         return ret;
2490     }
2491 #elif defined(WOLFSSL_RENESAS_SCEPROTECT)
2492     #include "r_sce.h"
2493 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2494     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2495     {
2496         int ret;
2497         word32 buffer[4];
2498 
2499         while (sz > 0) {
2500             word32 len = sizeof(buffer);
2501 
2502             if (sz < len) {
2503                 len = sz;
2504             }
2505             /* return 4 words random number*/
2506             ret = R_SCE_RandomNumberGenerate(buffer);
2507             if(ret == FSP_SUCCESS) {
2508                 XMEMCPY(output, &buffer, len);
2509                 output += len;
2510                 sz -= len;
2511             } else
2512                 return ret;
2513         }
2514         return ret;
2515     }
2516 
2517 #elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG)
2518     #include "hal_data.h"
2519 
2520     #ifndef WOLFSSL_SCE_TRNG_HANDLE
2521         #define WOLFSSL_SCE_TRNG_HANDLE g_sce_trng
2522     #endif
2523 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2524     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2525     {
2526         word32 ret;
2527         word32 blocks;
2528         word32 len = sz;
2529 
2530         ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->open(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
2531                                                   WOLFSSL_SCE_TRNG_HANDLE.p_cfg);
2532         if (ret != SSP_SUCCESS && ret != SSP_ERR_CRYPTO_ALREADY_OPEN) {
2533             /* error opening TRNG driver */
2534             return -1;
2535         }
2536 
2537         blocks = sz / sizeof(word32);
2538         if (blocks > 0) {
2539             ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
2540                                                        (word32*)output, blocks);
2541             if (ret != SSP_SUCCESS) {
2542                 return -1;
2543             }
2544         }
2545 
2546         len = len - (blocks * sizeof(word32));
2547         if (len > 0) {
2548             word32 tmp;
2549 
2550             if (len > sizeof(word32)) {
2551                 return -1;
2552             }
2553             ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
2554                                                       (word32*)tmp, 1);
2555             if (ret != SSP_SUCCESS) {
2556                 return -1;
2557             }
2558             XMEMCPY(output + (blocks * sizeof(word32)), (byte*)&tmp, len);
2559         }
2560 
2561         ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->close(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl);
2562         if (ret != SSP_SUCCESS) {
2563             /* error opening TRNG driver */
2564             return -1;
2565         }
2566         return 0;
2567     }
2568 #elif defined(CUSTOM_RAND_GENERATE_BLOCK)
2569     /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
2570      * extern int myRngFunc(byte* output, word32 sz);
2571      */
2572 
2573 #elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \
2574       defined(WOLFSSL_IAR_ARM)  || defined(WOLFSSL_MDK_ARM) || \
2575       defined(WOLFSSL_uITRON4)  || defined(WOLFSSL_uTKERNEL2) || \
2576       defined(WOLFSSL_LPC43xx)  || defined(NO_STM32_RNG) || \
2577       defined(MBED)             || defined(WOLFSSL_EMBOS) || \
2578       defined(WOLFSSL_GENSEED_FORTEST) || defined(WOLFSSL_CHIBIOS) || \
2579       defined(WOLFSSL_CONTIKI)  || defined(WOLFSSL_AZSPHERE)
2580 
2581     /* these platforms do not have a default random seed and
2582        you'll need to implement your own wc_GenerateSeed or define via
2583        CUSTOM_RAND_GENERATE_BLOCK */
2584 
2585     #define USE_TEST_GENSEED
2586 
2587 #elif defined(WOLFSSL_ZEPHYR)
2588 
2589         #include <random/rand32.h>
2590     #ifndef _POSIX_C_SOURCE
2591         #include <posix/time.h>
2592     #else
2593         #include <sys/time.h>
2594     #endif
2595 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2596         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2597         {
2598             sys_rand_get(output, sz);
2599             return 0;
2600         }
2601 
2602 #elif defined(WOLFSSL_TELIT_M2MB)
2603 
2604         #include "stdlib.h"
get_timestamp(void)2605         static long get_timestamp(void) {
2606             long myTime = 0;
2607             INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
2608             if (fd >= 0) {
2609                 M2MB_RTC_TIMEVAL_T timeval;
2610                 m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
2611                 myTime = timeval.msec;
2612                 m2mb_rtc_close(fd);
2613             }
2614             return myTime;
2615         }
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2616         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2617         {
2618             int i;
2619             srand(get_timestamp());
2620             for (i = 0; i < sz; i++ ) {
2621                 output[i] = rand() % 256;
2622                 if ((i % 8) == 7) {
2623                     srand(get_timestamp());
2624                 }
2625             }
2626             return 0;
2627         }
2628 #elif defined(WOLFSSL_SE050)
2629      #include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
2630 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2631     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz){
2632         int ret = 0;
2633 
2634         (void)os;
2635 
2636         if (output == NULL) {
2637             return BUFFER_E;
2638         }
2639         ret = wolfSSL_CryptHwMutexLock();
2640         if (ret == 0) {
2641             ret = se050_get_random_number(sz, output);
2642             wolfSSL_CryptHwMutexUnLock();
2643         }
2644         return ret;
2645     }
2646 
2647 #elif defined(DOLPHIN_EMULATOR)
2648 
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2649         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2650         {
2651             word32 i;
2652             (void)os;
2653             srand(time(NULL));
2654             for (i = 0; i < sz; i++)
2655                 output[i] = (byte)rand();
2656             return 0;
2657         }
2658 
2659 #elif defined(NO_DEV_RANDOM)
2660 
2661     #error "you need to write an os specific wc_GenerateSeed() here"
2662 
2663     /*
2664     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2665     {
2666         return 0;
2667     }
2668     */
2669 
2670 #else
2671 
2672     /* may block */
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2673     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2674     {
2675         int ret = 0;
2676 
2677         if (os == NULL) {
2678             return BAD_FUNC_ARG;
2679         }
2680 
2681     #ifdef WOLF_CRYPTO_CB
2682         if (os->devId != INVALID_DEVID) {
2683             ret = wc_CryptoCb_RandomSeed(os, output, sz);
2684             if (ret != CRYPTOCB_UNAVAILABLE)
2685                 return ret;
2686             /* fall-through when unavailable */
2687             ret = 0; /* reset error code */
2688         }
2689     #endif
2690 
2691     #ifdef HAVE_INTEL_RDSEED
2692         if (IS_INTEL_RDSEED(intel_flags)) {
2693              ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
2694              if (ret == 0) {
2695                  /* success, we're done */
2696                  return ret;
2697              }
2698         #ifdef FORCE_FAILURE_RDSEED
2699              /* don't fallback to /dev/urandom */
2700              return ret;
2701         #else
2702              /* reset error and fallback to using /dev/urandom */
2703              ret = 0;
2704         #endif
2705         }
2706     #endif /* HAVE_INTEL_RDSEED */
2707 
2708     #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
2709         os->fd = open("/dev/urandom", O_RDONLY);
2710         if (os->fd == -1)
2711     #endif
2712         {
2713             /* may still have /dev/random */
2714             os->fd = open("/dev/random", O_RDONLY);
2715             if (os->fd == -1)
2716                 return OPEN_RAN_E;
2717         }
2718 
2719         while (sz) {
2720             int len = (int)read(os->fd, output, sz);
2721             if (len == -1) {
2722                 ret = READ_RAN_E;
2723                 break;
2724             }
2725 
2726             sz     -= len;
2727             output += len;
2728 
2729             if (sz) {
2730     #if defined(BLOCKING) || defined(WC_RNG_BLOCKING)
2731                 sleep(0);             /* context switch */
2732     #else
2733                 ret = RAN_BLOCK_E;
2734                 break;
2735     #endif
2736             }
2737         }
2738         close(os->fd);
2739 
2740         return ret;
2741     }
2742 
2743 #endif
2744 
2745 #ifdef USE_TEST_GENSEED
2746     #ifndef _MSC_VER
2747         #warning "write a real random seed!!!!, just for testing now"
2748     #else
2749         #pragma message("Warning: write a real random seed!!!!, just for testing now")
2750     #endif
wc_GenerateSeed(OS_Seed * os,byte * output,word32 sz)2751     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2752     {
2753         word32 i;
2754         for (i = 0; i < sz; i++ )
2755             output[i] = i;
2756 
2757         (void)os;
2758 
2759         return 0;
2760     }
2761 #endif
2762 
2763 
2764 /* End wc_GenerateSeed */
2765 #endif /* WC_NO_RNG */
2766 #endif /* HAVE_FIPS */
2767