source: azure_iot_hub/trunk/wolfssl-3.15.7/wolfcrypt/src/random.c@ 388

Last change on this file since 388 was 388, checked in by coas-nagasima, 5 years ago

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 57.5 KB
Line 
1/* random.c
2 *
3 * Copyright (C) 2006-2017 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#ifdef HAVE_CONFIG_H
24 #include <config.h>
25#endif
26
27#include <wolfssl/wolfcrypt/settings.h>
28#include <wolfssl/wolfcrypt/error-crypt.h>
29
30/* on HPUX 11 you may need to install /dev/random see
31 http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
32
33*/
34
35#if defined(HAVE_FIPS) && \
36 defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
37
38 /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
39 #define FIPS_NO_WRAPPERS
40
41 #ifdef USE_WINDOWS_API
42 #pragma code_seg(".fipsA$c")
43 #pragma const_seg(".fipsB$c")
44 #endif
45#endif
46
47
48#include <wolfssl/wolfcrypt/random.h>
49#include <wolfssl/wolfcrypt/cpuid.h>
50
51
52/* If building for old FIPS. */
53#if defined(HAVE_FIPS) && \
54 (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
55
56int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz)
57{
58 return GenerateSeed(os, seed, sz);
59}
60
61int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
62{
63 (void)heap;
64 (void)devId;
65 return InitRng_fips(rng);
66}
67
68int wc_InitRng(WC_RNG* rng)
69{
70 return InitRng_fips(rng);
71}
72
73
74int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz)
75{
76 return RNG_GenerateBlock_fips(rng, b, sz);
77}
78
79
80int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
81{
82 return RNG_GenerateByte(rng, b);
83}
84
85#ifdef HAVE_HASHDRBG
86
87 int wc_FreeRng(WC_RNG* rng)
88 {
89 return FreeRng_fips(rng);
90 }
91
92 int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz,
93 const byte* seedB, word32 seedBSz,
94 byte* output, word32 outputSz)
95 {
96 return RNG_HealthTest_fips(reseed, seedA, seedASz,
97 seedB, seedBSz, output, outputSz);
98 }
99#endif /* HAVE_HASHDRBG */
100
101#else /* else build without fips, or for new fips */
102
103#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
104
105#include <wolfssl/wolfcrypt/sha256.h>
106
107#ifdef NO_INLINE
108 #include <wolfssl/wolfcrypt/misc.h>
109#else
110 #define WOLFSSL_MISC_INCLUDED
111 #include <wolfcrypt/src/misc.c>
112#endif
113
114#if defined(WOLFSSL_SGX)
115 #include <sgx_trts.h>
116#elif defined(USE_WINDOWS_API)
117 #ifndef _WIN32_WINNT
118 #define _WIN32_WINNT 0x0400
119 #endif
120 #include <windows.h>
121 #include <wincrypt.h>
122#elif defined(HAVE_WNR)
123 #include <wnr.h>
124 #include <wolfssl/wolfcrypt/logging.h>
125 wolfSSL_Mutex wnr_mutex; /* global netRandom mutex */
126 int wnr_timeout = 0; /* entropy timeout, mililseconds */
127 int wnr_mutex_init = 0; /* flag for mutex init */
128 wnr_context* wnr_ctx; /* global netRandom context */
129#elif defined(FREESCALE_KSDK_2_0_TRNG)
130 #include "fsl_trng.h"
131#elif defined(FREESCALE_KSDK_2_0_RNGA)
132 #include "fsl_rnga.h"
133
134#elif defined(NO_DEV_RANDOM)
135#elif defined(CUSTOM_RAND_GENERATE)
136#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
137#elif defined(CUSTOM_RAND_GENERATE_SEED)
138#elif defined(WOLFSSL_GENSEED_FORTEST)
139#elif defined(WOLFSSL_MDK_ARM)
140#elif defined(WOLFSSL_IAR_ARM)
141#elif defined(WOLFSSL_ROWLEY_ARM)
142#elif defined(WOLFSSL_EMBOS)
143#elif defined(MICRIUM)
144#elif defined(WOLFSSL_NUCLEUS)
145#elif defined(WOLFSSL_PB)
146#else
147 /* include headers that may be needed to get good seed */
148 #include <fcntl.h>
149 #ifndef EBSNET
150 #include <unistd.h>
151 #endif
152#endif
153
154
155#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
156 static word32 intel_flags = 0;
157 static void wc_InitRng_IntelRD(void)
158 {
159 intel_flags = cpuid_get_flags();
160 }
161 #ifdef HAVE_INTEL_RDSEED
162 static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz);
163 #endif
164 #ifdef HAVE_INTEL_RDRAND
165 static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz);
166 #endif
167
168#ifdef USE_WINDOWS_API
169 #include <immintrin.h>
170#endif /* USE_WINDOWS_API */
171#endif
172
173/* Start NIST DRBG code */
174#ifdef HAVE_HASHDRBG
175
176#define OUTPUT_BLOCK_LEN (WC_SHA256_DIGEST_SIZE)
177#define MAX_REQUEST_LEN (0x10000)
178#define RESEED_INTERVAL WC_RESEED_INTERVAL
179
180
181/* For FIPS builds, the user should not be adjusting the values. */
182#if defined(HAVE_FIPS) && \
183 defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
184 #if defined(RNG_SECURITY_STRENGTH) \
185 || defined(ENTROPY_SCALE_FACTOR) \
186 || defined(SEED_BLOCK_SZ)
187
188 #error "Do not change the RNG parameters for FIPS builds."
189 #endif
190#endif
191
192
193/* The security strength for the RNG is the target number of bits of
194 * entropy you are looking for in a seed. */
195#ifndef RNG_SECURITY_STRENGTH
196 #if defined(HAVE_FIPS) && \
197 defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
198 /* SHA-256 requires a minimum of 256-bits of entropy. The goal
199 * of 1024 will provide 4 times that. */
200 #define RNG_SECURITY_STRENGTH (1024)
201 #else
202 /* If not using FIPS or using old FIPS, set the number down a bit.
203 * More is better, but more is also slower. */
204 #define RNG_SECURITY_STRENGTH (256)
205 #endif
206#endif
207
208#ifndef ENTROPY_SCALE_FACTOR
209 /* The entropy scale factor should be the whole number inverse of the
210 * minimum bits of entropy per bit of NDRNG output. */
211 #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
212 /* The value of 2 applies to Intel's RDSEED which provides about
213 * 0.5 bits minimum of entropy per bit. */
214 #define ENTROPY_SCALE_FACTOR 2
215 #else
216 /* Setting the default to 1. */
217 #define ENTROPY_SCALE_FACTOR 1
218 #endif
219#endif
220
221#ifndef SEED_BLOCK_SZ
222 /* The seed block size, is the size of the output of the underlying NDRNG.
223 * This value is used for testing the output of the NDRNG. */
224 #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
225 /* RDSEED outputs in blocks of 64-bits. */
226 #define SEED_BLOCK_SZ sizeof(word64)
227 #else
228 /* Setting the default to 4. */
229 #define SEED_BLOCK_SZ 4
230 #endif
231#endif
232
233#define SEED_SZ (RNG_SECURITY_STRENGTH*ENTROPY_SCALE_FACTOR/8)
234
235/* The maximum seed size will be the seed size plus a seed block for the
236 * test, and an additional half of the seed size. This additional half
237 * is in case the user does not supply a nonce. A nonce will be obtained
238 * from the NDRNG. */
239#define MAX_SEED_SZ (SEED_SZ + SEED_SZ/2 + SEED_BLOCK_SZ)
240
241
242/* Internal return codes */
243#define DRBG_SUCCESS 0
244#define DRBG_FAILURE 1
245#define DRBG_NEED_RESEED 2
246#define DRBG_CONT_FAILURE 3
247
248/* RNG health states */
249#define DRBG_NOT_INIT 0
250#define DRBG_OK 1
251#define DRBG_FAILED 2
252#define DRBG_CONT_FAILED 3
253
254#define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4)
255
256/* Verify max gen block len */
257#if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN
258 #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length
259#endif
260
261enum {
262 drbgInitC = 0,
263 drbgReseed = 1,
264 drbgGenerateW = 2,
265 drbgGenerateH = 3,
266 drbgInitV
267};
268
269
270typedef struct DRBG {
271 word32 reseedCtr;
272 word32 lastBlock;
273 byte V[DRBG_SEED_LEN];
274 byte C[DRBG_SEED_LEN];
275#ifdef WOLFSSL_ASYNC_CRYPT
276 void* heap;
277 int devId;
278#endif
279 byte matchCount;
280#ifdef WOLFSSL_SMALL_STACK_CACHE
281 wc_Sha256 sha256;
282#endif
283} DRBG;
284
285
286static int wc_RNG_HealthTestLocal(int reseed);
287
288/* Hash Derivation Function */
289/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
290static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type,
291 const byte* inA, word32 inASz,
292 const byte* inB, word32 inBSz)
293{
294 int ret = DRBG_FAILURE;
295 byte ctr;
296 int i;
297 int len;
298 word32 bits = (outSz * 8); /* reverse byte order */
299#ifdef WOLFSSL_SMALL_STACK_CACHE
300 wc_Sha256* sha = &drbg->sha256;
301#else
302 wc_Sha256 sha[1];
303#endif
304#ifdef WC_ASYNC_ENABLE_SHA256
305 DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
306#else
307 byte digest[WC_SHA256_DIGEST_SIZE];
308#endif
309
310 (void)drbg;
311#ifdef WC_ASYNC_ENABLE_SHA256
312 if (digest == NULL)
313 return DRBG_FAILURE;
314#endif
315
316#ifdef LITTLE_ENDIAN_ORDER
317 bits = ByteReverseWord32(bits);
318#endif
319 len = (outSz / OUTPUT_BLOCK_LEN)
320 + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
321
322 for (i = 0, ctr = 1; i < len; i++, ctr++) {
323#ifndef WOLFSSL_SMALL_STACK_CACHE
324 #ifdef WOLFSSL_ASYNC_CRYPT
325 ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
326 #else
327 ret = wc_InitSha256(sha);
328 #endif
329 if (ret != 0)
330 break;
331
332 if (ret == 0)
333#endif
334 ret = wc_Sha256Update(sha, &ctr, sizeof(ctr));
335 if (ret == 0)
336 ret = wc_Sha256Update(sha, (byte*)&bits, sizeof(bits));
337
338 if (ret == 0) {
339 /* churning V is the only string that doesn't have the type added */
340 if (type != drbgInitV)
341 ret = wc_Sha256Update(sha, &type, sizeof(type));
342 }
343 if (ret == 0)
344 ret = wc_Sha256Update(sha, inA, inASz);
345 if (ret == 0) {
346 if (inB != NULL && inBSz > 0)
347 ret = wc_Sha256Update(sha, inB, inBSz);
348 }
349 if (ret == 0)
350 ret = wc_Sha256Final(sha, digest);
351
352#ifndef WOLFSSL_SMALL_STACK_CACHE
353 wc_Sha256Free(sha);
354#endif
355 if (ret == 0) {
356 if (outSz > OUTPUT_BLOCK_LEN) {
357 XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
358 outSz -= OUTPUT_BLOCK_LEN;
359 out += OUTPUT_BLOCK_LEN;
360 }
361 else {
362 XMEMCPY(out, digest, outSz);
363 }
364 }
365 }
366
367 ForceZero(digest, WC_SHA256_DIGEST_SIZE);
368
369#ifdef WC_ASYNC_ENABLE_SHA256
370 FREE_VAR(digest, drbg->heap);
371#endif
372
373 return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
374}
375
376/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
377static int Hash_DRBG_Reseed(DRBG* drbg, const byte* seed, word32 seedSz)
378{
379 byte newV[DRBG_SEED_LEN];
380
381 XMEMSET(newV, 0, DRBG_SEED_LEN);
382
383 if (Hash_df(drbg, newV, sizeof(newV), drbgReseed,
384 drbg->V, sizeof(drbg->V), seed, seedSz) != DRBG_SUCCESS) {
385 return DRBG_FAILURE;
386 }
387
388 XMEMCPY(drbg->V, newV, sizeof(drbg->V));
389 ForceZero(newV, sizeof(newV));
390
391 if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
392 sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) {
393 return DRBG_FAILURE;
394 }
395
396 drbg->reseedCtr = 1;
397 drbg->lastBlock = 0;
398 drbg->matchCount = 0;
399 return DRBG_SUCCESS;
400}
401
402/* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */
403int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz)
404{
405 if (rng == NULL || seed == NULL) {
406 return BAD_FUNC_ARG;
407 }
408
409 return Hash_DRBG_Reseed(rng->drbg, seed, seedSz);
410}
411
412static WC_INLINE void array_add_one(byte* data, word32 dataSz)
413{
414 int i;
415
416 for (i = dataSz - 1; i >= 0; i--)
417 {
418 data[i]++;
419 if (data[i] != 0) break;
420 }
421}
422
423/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
424static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V)
425{
426 int ret = DRBG_FAILURE;
427 byte data[DRBG_SEED_LEN];
428 int i;
429 int len;
430 word32 checkBlock;
431#ifdef WOLFSSL_SMALL_STACK_CACHE
432 wc_Sha256* sha = &drbg->sha256;
433#else
434 wc_Sha256 sha[1];
435#endif
436#ifdef WC_ASYNC_ENABLE_SHA256
437 DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
438#else
439 byte digest[WC_SHA256_DIGEST_SIZE];
440#endif
441
442 /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for
443 * the continuous test. */
444
445 if (outSz == 0) outSz = 1;
446
447 len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
448
449 XMEMCPY(data, V, sizeof(data));
450 for (i = 0; i < len; i++) {
451#ifndef WOLFSSL_SMALL_STACK_CACHE
452 #ifdef WOLFSSL_ASYNC_CRYPT
453 ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
454 #else
455 ret = wc_InitSha256(sha);
456 #endif
457 if (ret == 0)
458#endif
459 ret = wc_Sha256Update(sha, data, sizeof(data));
460 if (ret == 0)
461 ret = wc_Sha256Final(sha, digest);
462#ifndef WOLFSSL_SMALL_STACK_CACHE
463 wc_Sha256Free(sha);
464#endif
465
466 if (ret == 0) {
467 XMEMCPY(&checkBlock, digest, sizeof(word32));
468 if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) {
469 if (drbg->matchCount == 1) {
470 return DRBG_CONT_FAILURE;
471 }
472 else {
473 if (i == len) {
474 len++;
475 }
476 drbg->matchCount = 1;
477 }
478 }
479 else {
480 drbg->matchCount = 0;
481 drbg->lastBlock = checkBlock;
482 }
483
484 if (out != NULL && outSz != 0) {
485 if (outSz >= OUTPUT_BLOCK_LEN) {
486 XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
487 outSz -= OUTPUT_BLOCK_LEN;
488 out += OUTPUT_BLOCK_LEN;
489 array_add_one(data, DRBG_SEED_LEN);
490 }
491 else {
492 XMEMCPY(out, digest, outSz);
493 outSz = 0;
494 }
495 }
496 }
497 }
498 ForceZero(data, sizeof(data));
499
500#ifdef WC_ASYNC_ENABLE_SHA256
501 FREE_VAR(digest, drbg->heap);
502#endif
503
504 return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
505}
506
507static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
508{
509 word16 carry = 0;
510
511 if (dLen > 0 && sLen > 0 && dLen >= sLen) {
512 int sIdx, dIdx;
513
514 for (sIdx = sLen - 1, dIdx = dLen - 1; sIdx >= 0; dIdx--, sIdx--)
515 {
516 carry += d[dIdx] + s[sIdx];
517 d[dIdx] = (byte)carry;
518 carry >>= 8;
519 }
520
521 for (; carry != 0 && dIdx >= 0; dIdx--) {
522 carry += d[dIdx];
523 d[dIdx] = (byte)carry;
524 carry >>= 8;
525 }
526 }
527}
528
529/* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */
530static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz)
531{
532 int ret;
533#ifdef WOLFSSL_SMALL_STACK_CACHE
534 wc_Sha256* sha = &drbg->sha256;
535#else
536 wc_Sha256 sha[1];
537#endif
538 byte type;
539 word32 reseedCtr;
540
541 if (drbg->reseedCtr == RESEED_INTERVAL) {
542 return DRBG_NEED_RESEED;
543 } else {
544 #ifdef WC_ASYNC_ENABLE_SHA256
545 DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
546 #else
547 byte digest[WC_SHA256_DIGEST_SIZE];
548 #endif
549 type = drbgGenerateH;
550 reseedCtr = drbg->reseedCtr;
551
552 ret = Hash_gen(drbg, out, outSz, drbg->V);
553 if (ret == DRBG_SUCCESS) {
554#ifndef WOLFSSL_SMALL_STACK_CACHE
555 #ifdef WOLFSSL_ASYNC_CRYPT
556 ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
557 #else
558 ret = wc_InitSha256(sha);
559 #endif
560 if (ret == 0)
561#endif
562 ret = wc_Sha256Update(sha, &type, sizeof(type));
563 if (ret == 0)
564 ret = wc_Sha256Update(sha, drbg->V, sizeof(drbg->V));
565 if (ret == 0)
566 ret = wc_Sha256Final(sha, digest);
567
568#ifndef WOLFSSL_SMALL_STACK_CACHE
569 wc_Sha256Free(sha);
570#endif
571
572 if (ret == 0) {
573 array_add(drbg->V, sizeof(drbg->V), digest, WC_SHA256_DIGEST_SIZE);
574 array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
575 #ifdef LITTLE_ENDIAN_ORDER
576 reseedCtr = ByteReverseWord32(reseedCtr);
577 #endif
578 array_add(drbg->V, sizeof(drbg->V),
579 (byte*)&reseedCtr, sizeof(reseedCtr));
580 ret = DRBG_SUCCESS;
581 }
582 drbg->reseedCtr++;
583 }
584 ForceZero(digest, WC_SHA256_DIGEST_SIZE);
585 #ifdef WC_ASYNC_ENABLE_SHA256
586 FREE_VAR(digest, drbg->heap);
587 #endif
588 }
589
590 return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
591}
592
593/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
594static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz,
595 const byte* nonce, word32 nonceSz,
596 void* heap, int devId)
597{
598 int ret = DRBG_FAILURE;
599
600 XMEMSET(drbg, 0, sizeof(DRBG));
601#ifdef WOLFSSL_ASYNC_CRYPT
602 drbg->heap = heap;
603 drbg->devId = devId;
604#else
605 (void)heap;
606 (void)devId;
607#endif
608
609#ifdef WOLFSSL_SMALL_STACK_CACHE
610 #ifdef WOLFSSL_ASYNC_CRYPT
611 ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId);
612 #else
613 ret = wc_InitSha256(&drbg->sha256);
614 #endif
615 if (ret != 0)
616 return ret;
617#endif
618
619 if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
620 nonce, nonceSz) == DRBG_SUCCESS &&
621 Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
622 sizeof(drbg->V), NULL, 0) == DRBG_SUCCESS) {
623
624 drbg->reseedCtr = 1;
625 drbg->lastBlock = 0;
626 drbg->matchCount = 0;
627 ret = DRBG_SUCCESS;
628 }
629
630 return ret;
631}
632
633/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
634static int Hash_DRBG_Uninstantiate(DRBG* drbg)
635{
636 word32 i;
637 int compareSum = 0;
638 byte* compareDrbg = (byte*)drbg;
639
640#ifdef WOLFSSL_SMALL_STACK_CACHE
641 wc_Sha256Free(&drbg->sha256);
642#endif
643
644 ForceZero(drbg, sizeof(DRBG));
645
646 for (i = 0; i < sizeof(DRBG); i++)
647 compareSum |= compareDrbg[i] ^ 0;
648
649 return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
650}
651
652
653int wc_RNG_TestSeed(const byte* seed, word32 seedSz)
654{
655 int ret = DRBG_SUCCESS;
656
657 /* Check the seed for duplicate words. */
658 word32 seedIdx = 0;
659 word32 scratchSz = min(SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ);
660
661 while (seedIdx < seedSz - SEED_BLOCK_SZ) {
662 if (ConstantCompare(seed + seedIdx,
663 seed + seedIdx + scratchSz,
664 scratchSz) == 0) {
665
666 ret = DRBG_CONT_FAILURE;
667 }
668 seedIdx += SEED_BLOCK_SZ;
669 scratchSz = min(SEED_BLOCK_SZ, (seedSz - seedIdx));
670 }
671
672 return ret;
673}
674#endif /* HAVE_HASHDRBG */
675/* End NIST DRBG Code */
676
677
678static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
679 void* heap, int devId)
680{
681 int ret = RNG_FAILURE_E;
682#ifdef HAVE_HASHDRBG
683 word32 seedSz = SEED_SZ + SEED_BLOCK_SZ;
684#endif
685
686 (void)nonce;
687 (void)nonceSz;
688
689 if (rng == NULL)
690 return BAD_FUNC_ARG;
691 if (nonce == NULL && nonceSz != 0)
692 return BAD_FUNC_ARG;
693
694#ifdef WOLFSSL_HEAP_TEST
695 rng->heap = (void*)WOLFSSL_HEAP_TEST;
696 (void)heap;
697#else
698 rng->heap = heap;
699#endif
700#ifdef WOLFSSL_ASYNC_CRYPT
701 rng->devId = devId;
702#else
703 (void)devId;
704#endif
705
706#ifdef HAVE_HASHDRBG
707 /* init the DBRG to known values */
708 rng->drbg = NULL;
709 rng->status = DRBG_NOT_INIT;
710#endif
711
712#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
713 /* init the intel RD seed and/or rand */
714 wc_InitRng_IntelRD();
715#endif
716
717 /* configure async RNG source if available */
718#ifdef WOLFSSL_ASYNC_CRYPT
719 ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG,
720 rng->heap, rng->devId);
721 if (ret != 0)
722 return ret;
723#endif
724
725#ifdef HAVE_INTEL_RDRAND
726 /* if CPU supports RDRAND, use it directly and by-pass DRBG init */
727 if (IS_INTEL_RDRAND(intel_flags))
728 return 0;
729#endif
730
731#ifdef CUSTOM_RAND_GENERATE_BLOCK
732 ret = 0; /* success */
733#else
734#ifdef HAVE_HASHDRBG
735 if (nonceSz == 0)
736 seedSz = MAX_SEED_SZ;
737
738 if (wc_RNG_HealthTestLocal(0) == 0) {
739 #ifdef WC_ASYNC_ENABLE_SHA256
740 DECLARE_VAR(seed, byte, MAX_SEED_SZ, rng->heap);
741 #else
742 byte seed[MAX_SEED_SZ];
743 #endif
744
745 rng->drbg =
746 (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap,
747 DYNAMIC_TYPE_RNG);
748 if (rng->drbg == NULL) {
749 ret = MEMORY_E;
750 }
751 else {
752 ret = wc_GenerateSeed(&rng->seed, seed, seedSz);
753 if (ret != 0)
754 ret = DRBG_FAILURE;
755 else
756 ret = wc_RNG_TestSeed(seed, seedSz);
757
758 if (ret == DRBG_SUCCESS)
759 ret = Hash_DRBG_Instantiate(rng->drbg,
760 seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ,
761 nonce, nonceSz, rng->heap, devId);
762
763 if (ret == DRBG_SUCCESS)
764 ret = Hash_DRBG_Generate(rng->drbg, NULL, 0);
765 }
766
767 ForceZero(seed, seedSz);
768 #ifdef WC_ASYNC_ENABLE_SHA256
769 FREE_VAR(seed, rng->heap);
770 #endif
771 }
772 else
773 ret = DRBG_CONT_FAILURE;
774
775 if (ret == DRBG_SUCCESS) {
776 rng->status = DRBG_OK;
777 ret = 0;
778 }
779 else if (ret == DRBG_CONT_FAILURE) {
780 rng->status = DRBG_CONT_FAILED;
781 ret = DRBG_CONT_FIPS_E;
782 }
783 else if (ret == DRBG_FAILURE) {
784 rng->status = DRBG_FAILED;
785 ret = RNG_FAILURE_E;
786 }
787 else {
788 rng->status = DRBG_FAILED;
789 }
790#endif /* HAVE_HASHDRBG */
791#endif /* CUSTOM_RAND_GENERATE_BLOCK */
792
793 return ret;
794}
795
796
797int wc_InitRng(WC_RNG* rng)
798{
799 return _InitRng(rng, NULL, 0, NULL, INVALID_DEVID);
800}
801
802
803int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
804{
805 return _InitRng(rng, NULL, 0, heap, devId);
806}
807
808
809int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz)
810{
811 return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID);
812}
813
814
815int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
816 void* heap, int devId)
817{
818 return _InitRng(rng, nonce, nonceSz, heap, devId);
819}
820
821
822/* place a generated block in output */
823int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
824{
825 int ret;
826
827 if (rng == NULL || output == NULL)
828 return BAD_FUNC_ARG;
829
830#ifdef HAVE_INTEL_RDRAND
831 if (IS_INTEL_RDRAND(intel_flags))
832 return wc_GenerateRand_IntelRD(NULL, output, sz);
833#endif
834
835#if defined(WOLFSSL_ASYNC_CRYPT)
836 if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) {
837 /* these are blocking */
838 #ifdef HAVE_CAVIUM
839 return NitroxRngGenerateBlock(rng, output, sz);
840 #elif defined(HAVE_INTEL_QA) && defined(QAT_ENABLE_RNG)
841 return IntelQaDrbg(&rng->asyncDev, output, sz);
842 #else
843 /* simulator not supported */
844 #endif
845 }
846#endif
847
848#ifdef CUSTOM_RAND_GENERATE_BLOCK
849 XMEMSET(output, 0, sz);
850 ret = CUSTOM_RAND_GENERATE_BLOCK(output, sz);
851#else
852
853#ifdef HAVE_HASHDRBG
854 if (sz > RNG_MAX_BLOCK_LEN)
855 return BAD_FUNC_ARG;
856
857 if (rng->status != DRBG_OK)
858 return RNG_FAILURE_E;
859
860 ret = Hash_DRBG_Generate(rng->drbg, output, sz);
861 if (ret == DRBG_NEED_RESEED) {
862 if (wc_RNG_HealthTestLocal(1) == 0) {
863 byte newSeed[SEED_SZ + SEED_BLOCK_SZ];
864
865 ret = wc_GenerateSeed(&rng->seed, newSeed,
866 SEED_SZ + SEED_BLOCK_SZ);
867 if (ret != 0)
868 ret = DRBG_FAILURE;
869 else
870 ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
871
872 if (ret == DRBG_SUCCESS)
873 ret = Hash_DRBG_Reseed(rng->drbg, newSeed + SEED_BLOCK_SZ,
874 SEED_SZ);
875 if (ret == DRBG_SUCCESS)
876 ret = Hash_DRBG_Generate(rng->drbg, NULL, 0);
877 if (ret == DRBG_SUCCESS)
878 ret = Hash_DRBG_Generate(rng->drbg, output, sz);
879
880 ForceZero(newSeed, sizeof(newSeed));
881 }
882 else
883 ret = DRBG_CONT_FAILURE;
884 }
885
886 if (ret == DRBG_SUCCESS) {
887 ret = 0;
888 }
889 else if (ret == DRBG_CONT_FAILURE) {
890 ret = DRBG_CONT_FIPS_E;
891 rng->status = DRBG_CONT_FAILED;
892 }
893 else {
894 ret = RNG_FAILURE_E;
895 rng->status = DRBG_FAILED;
896 }
897#else
898
899 /* if we get here then there is an RNG configuration error */
900 ret = RNG_FAILURE_E;
901
902#endif /* HAVE_HASHDRBG */
903#endif /* CUSTOM_RAND_GENERATE_BLOCK */
904
905 return ret;
906}
907
908
909int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
910{
911 return wc_RNG_GenerateBlock(rng, b, 1);
912}
913
914
915int wc_FreeRng(WC_RNG* rng)
916{
917 int ret = 0;
918
919 if (rng == NULL)
920 return BAD_FUNC_ARG;
921
922#if defined(WOLFSSL_ASYNC_CRYPT)
923 wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG);
924#endif
925
926#ifdef HAVE_HASHDRBG
927 if (rng->drbg != NULL) {
928 if (Hash_DRBG_Uninstantiate(rng->drbg) != DRBG_SUCCESS)
929 ret = RNG_FAILURE_E;
930
931 XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
932 rng->drbg = NULL;
933 }
934
935 rng->status = DRBG_NOT_INIT;
936#endif /* HAVE_HASHDRBG */
937
938 return ret;
939}
940
941#ifdef HAVE_HASHDRBG
942int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz,
943 const byte* seedB, word32 seedBSz,
944 byte* output, word32 outputSz)
945{
946 return wc_RNG_HealthTest_ex(reseed, NULL, 0,
947 seedA, seedASz, seedB, seedBSz,
948 output, outputSz,
949 NULL, INVALID_DEVID);
950}
951
952
953int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz,
954 const byte* seedA, word32 seedASz,
955 const byte* seedB, word32 seedBSz,
956 byte* output, word32 outputSz,
957 void* heap, int devId)
958{
959 int ret = -1;
960 DRBG* drbg;
961#ifndef WOLFSSL_SMALL_STACK
962 DRBG drbg_var;
963#endif
964
965 if (seedA == NULL || output == NULL) {
966 return BAD_FUNC_ARG;
967 }
968
969 if (reseed != 0 && seedB == NULL) {
970 return BAD_FUNC_ARG;
971 }
972
973 if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) {
974 return ret;
975 }
976
977#ifdef WOLFSSL_SMALL_STACK
978 drbg = (DRBG*)XMALLOC(sizeof(DRBG), NULL, DYNAMIC_TYPE_RNG);
979 if (drbg == NULL) {
980 return MEMORY_E;
981 }
982#else
983 drbg = &drbg_var;
984#endif
985
986 if (Hash_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
987 heap, devId) != 0) {
988 goto exit_rng_ht;
989 }
990
991 if (reseed) {
992 if (Hash_DRBG_Reseed(drbg, seedB, seedBSz) != 0) {
993 goto exit_rng_ht;
994 }
995 }
996
997 if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
998 goto exit_rng_ht;
999 }
1000
1001 if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
1002 goto exit_rng_ht;
1003 }
1004
1005 /* Mark success */
1006 ret = 0;
1007
1008exit_rng_ht:
1009
1010 /* This is safe to call even if Hash_DRBG_Instantiate fails */
1011 if (Hash_DRBG_Uninstantiate(drbg) != 0) {
1012 ret = -1;
1013 }
1014
1015#ifdef WOLFSSL_SMALL_STACK
1016 XFREE(drbg, NULL, DYNAMIC_TYPE_RNG);
1017#endif
1018
1019 return ret;
1020}
1021
1022
1023const byte seedA[] = {
1024 0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4,
1025 0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00,
1026 0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f,
1027 0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68
1028};
1029
1030const byte reseedSeedA[] = {
1031 0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3,
1032 0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22,
1033 0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3
1034};
1035
1036const byte outputA[] = {
1037 0x04, 0xee, 0xc6, 0x3b, 0xb2, 0x31, 0xdf, 0x2c, 0x63, 0x0a, 0x1a, 0xfb,
1038 0xe7, 0x24, 0x94, 0x9d, 0x00, 0x5a, 0x58, 0x78, 0x51, 0xe1, 0xaa, 0x79,
1039 0x5e, 0x47, 0x73, 0x47, 0xc8, 0xb0, 0x56, 0x62, 0x1c, 0x18, 0xbd, 0xdc,
1040 0xdd, 0x8d, 0x99, 0xfc, 0x5f, 0xc2, 0xb9, 0x20, 0x53, 0xd8, 0xcf, 0xac,
1041 0xfb, 0x0b, 0xb8, 0x83, 0x12, 0x05, 0xfa, 0xd1, 0xdd, 0xd6, 0xc0, 0x71,
1042 0x31, 0x8a, 0x60, 0x18, 0xf0, 0x3b, 0x73, 0xf5, 0xed, 0xe4, 0xd4, 0xd0,
1043 0x71, 0xf9, 0xde, 0x03, 0xfd, 0x7a, 0xea, 0x10, 0x5d, 0x92, 0x99, 0xb8,
1044 0xaf, 0x99, 0xaa, 0x07, 0x5b, 0xdb, 0x4d, 0xb9, 0xaa, 0x28, 0xc1, 0x8d,
1045 0x17, 0x4b, 0x56, 0xee, 0x2a, 0x01, 0x4d, 0x09, 0x88, 0x96, 0xff, 0x22,
1046 0x82, 0xc9, 0x55, 0xa8, 0x19, 0x69, 0xe0, 0x69, 0xfa, 0x8c, 0xe0, 0x07,
1047 0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17
1048};
1049
1050const byte seedB[] = {
1051 0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3,
1052 0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19,
1053 0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */
1054 0x85, 0x81, 0xf9, 0x31, 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d,
1055 0xdb, 0xcb, 0xcc, 0x2e
1056};
1057
1058const byte outputB[] = {
1059 0xd3, 0xe1, 0x60, 0xc3, 0x5b, 0x99, 0xf3, 0x40, 0xb2, 0x62, 0x82, 0x64,
1060 0xd1, 0x75, 0x10, 0x60, 0xe0, 0x04, 0x5d, 0xa3, 0x83, 0xff, 0x57, 0xa5,
1061 0x7d, 0x73, 0xa6, 0x73, 0xd2, 0xb8, 0xd8, 0x0d, 0xaa, 0xf6, 0xa6, 0xc3,
1062 0x5a, 0x91, 0xbb, 0x45, 0x79, 0xd7, 0x3f, 0xd0, 0xc8, 0xfe, 0xd1, 0x11,
1063 0xb0, 0x39, 0x13, 0x06, 0x82, 0x8a, 0xdf, 0xed, 0x52, 0x8f, 0x01, 0x81,
1064 0x21, 0xb3, 0xfe, 0xbd, 0xc3, 0x43, 0xe7, 0x97, 0xb8, 0x7d, 0xbb, 0x63,
1065 0xdb, 0x13, 0x33, 0xde, 0xd9, 0xd1, 0xec, 0xe1, 0x77, 0xcf, 0xa6, 0xb7,
1066 0x1f, 0xe8, 0xab, 0x1d, 0xa4, 0x66, 0x24, 0xed, 0x64, 0x15, 0xe5, 0x1c,
1067 0xcd, 0xe2, 0xc7, 0xca, 0x86, 0xe2, 0x83, 0x99, 0x0e, 0xea, 0xeb, 0x91,
1068 0x12, 0x04, 0x15, 0x52, 0x8b, 0x22, 0x95, 0x91, 0x02, 0x81, 0xb0, 0x2d,
1069 0xd4, 0x31, 0xf4, 0xc9, 0xf7, 0x04, 0x27, 0xdf
1070};
1071
1072
1073static int wc_RNG_HealthTestLocal(int reseed)
1074{
1075 int ret = 0;
1076#ifdef WOLFSSL_SMALL_STACK
1077 byte* check;
1078#else
1079 byte check[RNG_HEALTH_TEST_CHECK_SIZE];
1080#endif
1081
1082#ifdef WOLFSSL_SMALL_STACK
1083 check = (byte*)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, NULL,
1084 DYNAMIC_TYPE_TMP_BUFFER);
1085 if (check == NULL) {
1086 return MEMORY_E;
1087 }
1088#endif
1089
1090 if (reseed) {
1091 ret = wc_RNG_HealthTest(1, seedA, sizeof(seedA),
1092 reseedSeedA, sizeof(reseedSeedA),
1093 check, RNG_HEALTH_TEST_CHECK_SIZE);
1094 if (ret == 0) {
1095 if (ConstantCompare(check, outputA,
1096 RNG_HEALTH_TEST_CHECK_SIZE) != 0)
1097 ret = -1;
1098 }
1099 }
1100 else {
1101 ret = wc_RNG_HealthTest(0, seedB, sizeof(seedB),
1102 NULL, 0,
1103 check, RNG_HEALTH_TEST_CHECK_SIZE);
1104 if (ret == 0) {
1105 if (ConstantCompare(check, outputB,
1106 RNG_HEALTH_TEST_CHECK_SIZE) != 0)
1107 ret = -1;
1108 }
1109
1110 /* The previous test cases use a large seed instead of a seed and nonce.
1111 * seedB is actually from a test case with a seed and nonce, and
1112 * just concatenates them. The pivot point between seed and nonce is
1113 * byte 32, feed them into the health test separately. */
1114 if (ret == 0) {
1115 ret = wc_RNG_HealthTest_ex(0,
1116 seedB + 32, sizeof(seedB) - 32,
1117 seedB, 32,
1118 NULL, 0,
1119 check, RNG_HEALTH_TEST_CHECK_SIZE,
1120 NULL, INVALID_DEVID);
1121 if (ret == 0) {
1122 if (ConstantCompare(check, outputB, sizeof(outputB)) != 0)
1123 ret = -1;
1124 }
1125 }
1126 }
1127
1128#ifdef WOLFSSL_SMALL_STACK
1129 XFREE(check, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1130#endif
1131
1132 return ret;
1133}
1134
1135#endif /* HAVE_HASHDRBG */
1136
1137
1138#ifdef HAVE_WNR
1139
1140/*
1141 * Init global Whitewood netRandom context
1142 * Returns 0 on success, negative on error
1143 */
1144int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout)
1145{
1146 if (configFile == NULL || timeout < 0)
1147 return BAD_FUNC_ARG;
1148
1149 if (wnr_mutex_init > 0) {
1150 WOLFSSL_MSG("netRandom context already created, skipping");
1151 return 0;
1152 }
1153
1154 if (wc_InitMutex(&wnr_mutex) != 0) {
1155 WOLFSSL_MSG("Bad Init Mutex wnr_mutex");
1156 return BAD_MUTEX_E;
1157 }
1158 wnr_mutex_init = 1;
1159
1160 if (wc_LockMutex(&wnr_mutex) != 0) {
1161 WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
1162 return BAD_MUTEX_E;
1163 }
1164
1165 /* store entropy timeout */
1166 wnr_timeout = timeout;
1167
1168 /* create global wnr_context struct */
1169 if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) {
1170 WOLFSSL_MSG("Error creating global netRandom context");
1171 return RNG_FAILURE_E;
1172 }
1173
1174 /* load config file */
1175 if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) {
1176 WOLFSSL_MSG("Error loading config file into netRandom context");
1177 wnr_destroy(wnr_ctx);
1178 wnr_ctx = NULL;
1179 return RNG_FAILURE_E;
1180 }
1181
1182 /* create/init polling mechanism */
1183 if (wnr_poll_create() != WNR_ERROR_NONE) {
1184 printf("ERROR: wnr_poll_create() failed\n");
1185 WOLFSSL_MSG("Error initializing netRandom polling mechanism");
1186 wnr_destroy(wnr_ctx);
1187 wnr_ctx = NULL;
1188 return RNG_FAILURE_E;
1189 }
1190
1191 /* validate config, set HMAC callback (optional) */
1192 if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) {
1193 WOLFSSL_MSG("Error setting up netRandom context");
1194 wnr_destroy(wnr_ctx);
1195 wnr_ctx = NULL;
1196 wnr_poll_destroy();
1197 return RNG_FAILURE_E;
1198 }
1199
1200 wc_UnLockMutex(&wnr_mutex);
1201
1202 return 0;
1203}
1204
1205/*
1206 * Free global Whitewood netRandom context
1207 * Returns 0 on success, negative on error
1208 */
1209int wc_FreeNetRandom(void)
1210{
1211 if (wnr_mutex_init > 0) {
1212
1213 if (wc_LockMutex(&wnr_mutex) != 0) {
1214 WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
1215 return BAD_MUTEX_E;
1216 }
1217
1218 if (wnr_ctx != NULL) {
1219 wnr_destroy(wnr_ctx);
1220 wnr_ctx = NULL;
1221 }
1222 wnr_poll_destroy();
1223
1224 wc_UnLockMutex(&wnr_mutex);
1225
1226 wc_FreeMutex(&wnr_mutex);
1227 wnr_mutex_init = 0;
1228 }
1229
1230 return 0;
1231}
1232
1233#endif /* HAVE_WNR */
1234
1235
1236#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
1237
1238#ifdef WOLFSSL_ASYNC_CRYPT
1239 /* need more retries if multiple cores */
1240 #define INTELRD_RETRY (32 * 8)
1241#else
1242 #define INTELRD_RETRY 32
1243#endif
1244
1245#ifdef HAVE_INTEL_RDSEED
1246
1247#ifndef USE_WINDOWS_API
1248
1249/* return 0 on success */
1250 static WC_INLINE int IntelRDseed64(word64* seed)
1251{
1252 unsigned char ok;
1253
1254 __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok));
1255 return (ok) ? 0 : -1;
1256}
1257
1258#else /* USE_WINDOWS_API */
1259 /* The compiler Visual Studio uses does not allow inline assembly.
1260 * It does allow for Intel intrinsic functions. */
1261
1262/* return 0 on success */
1263 static WC_INLINE int IntelRDseed64(word64* seed)
1264 {
1265 int ok;
1266
1267 ok = _rdseed64_step(seed);
1268 return (ok) ? 0 : -1;
1269 }
1270
1271#endif /* USE_WINDOWS_API */
1272
1273/* return 0 on success */
1274static WC_INLINE int IntelRDseed64_r(word64* rnd)
1275{
1276 int i;
1277 for (i = 0; i < INTELRD_RETRY; i++) {
1278 if (IntelRDseed64(rnd) == 0)
1279 return 0;
1280 }
1281 return -1;
1282}
1283
1284/* return 0 on success */
1285static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz)
1286{
1287 int ret;
1288 word64 rndTmp;
1289
1290 (void)os;
1291
1292 if (!IS_INTEL_RDSEED(intel_flags))
1293 return -1;
1294
1295 for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
1296 output += sizeof(word64)) {
1297 ret = IntelRDseed64_r((word64*)output);
1298 if (ret != 0)
1299 return ret;
1300 }
1301 if (sz == 0)
1302 return 0;
1303
1304 /* handle unaligned remainder */
1305 ret = IntelRDseed64_r(&rndTmp);
1306 if (ret != 0)
1307 return ret;
1308
1309 XMEMCPY(output, &rndTmp, sz);
1310 ForceZero(&rndTmp, sizeof(rndTmp));
1311
1312 return 0;
1313}
1314
1315#endif /* HAVE_INTEL_RDSEED */
1316
1317#ifdef HAVE_INTEL_RDRAND
1318
1319#ifndef USE_WINDOWS_API
1320
1321/* return 0 on success */
1322static WC_INLINE int IntelRDrand64(word64 *rnd)
1323{
1324 unsigned char ok;
1325
1326 __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok));
1327
1328 return (ok) ? 0 : -1;
1329}
1330
1331#else /* USE_WINDOWS_API */
1332 /* The compiler Visual Studio uses does not allow inline assembly.
1333 * It does allow for Intel intrinsic functions. */
1334
1335/* return 0 on success */
1336static WC_INLINE int IntelRDrand64(word64 *rnd)
1337{
1338 int ok;
1339
1340 ok = _rdrand64_step(rnd);
1341
1342 return (ok) ? 0 : -1;
1343}
1344
1345#endif /* USE_WINDOWS_API */
1346
1347/* return 0 on success */
1348static WC_INLINE int IntelRDrand64_r(word64 *rnd)
1349{
1350 int i;
1351 for (i = 0; i < INTELRD_RETRY; i++) {
1352 if (IntelRDrand64(rnd) == 0)
1353 return 0;
1354 }
1355 return -1;
1356}
1357
1358/* return 0 on success */
1359static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz)
1360{
1361 int ret;
1362 word64 rndTmp;
1363
1364 (void)os;
1365
1366 if (!IS_INTEL_RDRAND(intel_flags))
1367 return -1;
1368
1369 for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
1370 output += sizeof(word64)) {
1371 ret = IntelRDrand64_r((word64 *)output);
1372 if (ret != 0)
1373 return ret;
1374 }
1375 if (sz == 0)
1376 return 0;
1377
1378 /* handle unaligned remainder */
1379 ret = IntelRDrand64_r(&rndTmp);
1380 if (ret != 0)
1381 return ret;
1382
1383 XMEMCPY(output, &rndTmp, sz);
1384
1385 return 0;
1386}
1387
1388#endif /* HAVE_INTEL_RDRAND */
1389#endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED */
1390
1391
1392/* Begin wc_GenerateSeed Implementations */
1393#if defined(CUSTOM_RAND_GENERATE_SEED)
1394
1395 /* Implement your own random generation function
1396 * Return 0 to indicate success
1397 * int rand_gen_seed(byte* output, word32 sz);
1398 * #define CUSTOM_RAND_GENERATE_SEED rand_gen_seed */
1399
1400 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1401 {
1402 extern int CUSTOM_RAND_GENERATE_SEED(byte* output, word32 sz);
1403 (void)os; /* Suppress unused arg warning */
1404 return CUSTOM_RAND_GENERATE_SEED(output, sz);
1405 }
1406
1407#elif defined(CUSTOM_RAND_GENERATE_SEED_OS)
1408
1409 /* Implement your own random generation function,
1410 * which includes OS_Seed.
1411 * Return 0 to indicate success
1412 * int rand_gen_seed(OS_Seed* os, byte* output, word32 sz);
1413 * #define CUSTOM_RAND_GENERATE_SEED_OS rand_gen_seed */
1414
1415 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1416 {
1417 return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz);
1418 }
1419
1420#elif defined(CUSTOM_RAND_GENERATE)
1421
1422 /* Implement your own random generation function
1423 * word32 rand_gen(void);
1424 * #define CUSTOM_RAND_GENERATE rand_gen */
1425
1426 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1427 {
1428 word32 i = 0;
1429
1430 (void)os;
1431
1432 while (i < sz)
1433 {
1434 /* If not aligned or there is odd/remainder */
1435 if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz ||
1436 ((wolfssl_word)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0
1437 ) {
1438 /* Single byte at a time */
1439 output[i++] = (byte)CUSTOM_RAND_GENERATE();
1440 }
1441 else {
1442 /* Use native 8, 16, 32 or 64 copy instruction */
1443 *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE();
1444 i += sizeof(CUSTOM_RAND_TYPE);
1445 }
1446 }
1447
1448 return 0;
1449 }
1450
1451#elif defined(WOLFSSL_SGX)
1452
1453int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1454{
1455 int ret = !SGX_SUCCESS;
1456 int i, read_max = 10;
1457
1458 for (i = 0; i < read_max && ret != SGX_SUCCESS; i++) {
1459 ret = sgx_read_rand(output, sz);
1460 }
1461
1462 (void)os;
1463 return (ret == SGX_SUCCESS) ? 0 : 1;
1464}
1465
1466#elif defined(USE_WINDOWS_API)
1467
1468int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1469{
1470 #ifdef HAVE_INTEL_RDSEED
1471 if (IS_INTEL_RDSEED(intel_flags)) {
1472 if (!wc_GenerateSeed_IntelRD(NULL, output, sz)) {
1473 /* success, we're done */
1474 return 0;
1475 }
1476 #ifdef FORCE_FAILURE_RDSEED
1477 /* don't fall back to CryptoAPI */
1478 return READ_RAN_E;
1479 #endif
1480 }
1481 #endif /* HAVE_INTEL_RDSEED */
1482
1483 if(!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
1484 CRYPT_VERIFYCONTEXT))
1485 return WINCRYPT_E;
1486
1487 if (!CryptGenRandom(os->handle, sz, output))
1488 return CRYPTGEN_E;
1489
1490 CryptReleaseContext(os->handle, 0);
1491
1492 return 0;
1493}
1494
1495
1496#elif defined(HAVE_RTP_SYS) || defined(EBSNET)
1497
1498#include "rtprand.h" /* rtp_rand () */
1499#include "rtptime.h" /* rtp_get_system_msec() */
1500
1501
1502int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1503{
1504 int i;
1505 rtp_srand(rtp_get_system_msec());
1506
1507 for (i = 0; i < sz; i++ ) {
1508 output[i] = rtp_rand() % 256;
1509 if ( (i % 8) == 7)
1510 rtp_srand(rtp_get_system_msec());
1511 }
1512
1513 return 0;
1514}
1515
1516
1517#elif defined(MICROCHIP_PIC32)
1518
1519 #ifdef MICROCHIP_MPLAB_HARMONY
1520 #define PIC32_SEED_COUNT _CP0_GET_COUNT
1521 #else
1522 #if !defined(WOLFSSL_MICROCHIP_PIC32MZ)
1523 #include <peripheral/timer.h>
1524 #endif
1525 extern word32 ReadCoreTimer(void);
1526 #define PIC32_SEED_COUNT ReadCoreTimer
1527 #endif
1528
1529 #ifdef WOLFSSL_PIC32MZ_RNG
1530 #include "xc.h"
1531 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1532 {
1533 int i;
1534 byte rnd[8];
1535 word32 *rnd32 = (word32 *)rnd;
1536 word32 size = sz;
1537 byte* op = output;
1538
1539#if ((__PIC32_FEATURE_SET0 == 'E') && (__PIC32_FEATURE_SET1 == 'C'))
1540 RNGNUMGEN1 = _CP0_GET_COUNT();
1541 RNGPOLY1 = _CP0_GET_COUNT();
1542 RNGPOLY2 = _CP0_GET_COUNT();
1543 RNGNUMGEN2 = _CP0_GET_COUNT();
1544#else
1545 // All others can be seeded from the TRNG
1546 RNGCONbits.TRNGMODE = 1;
1547 RNGCONbits.TRNGEN = 1;
1548 while (RNGCNT < 64);
1549 RNGCONbits.LOAD = 1;
1550 while (RNGCONbits.LOAD == 1);
1551 while (RNGCNT < 64);
1552 RNGPOLY2 = RNGSEED2;
1553 RNGPOLY1 = RNGSEED1;
1554#endif
1555
1556 RNGCONbits.PLEN = 0x40;
1557 RNGCONbits.PRNGEN = 1;
1558 for (i=0; i<5; i++) { /* wait for RNGNUMGEN ready */
1559 volatile int x;
1560 x = RNGNUMGEN1;
1561 x = RNGNUMGEN2;
1562 (void)x;
1563 }
1564 do {
1565 rnd32[0] = RNGNUMGEN1;
1566 rnd32[1] = RNGNUMGEN2;
1567
1568 for(i=0; i<8; i++, op++) {
1569 *op = rnd[i];
1570 size --;
1571 if(size==0)break;
1572 }
1573 } while(size);
1574 return 0;
1575 }
1576 #else /* WOLFSSL_PIC32MZ_RNG */
1577 /* uses the core timer, in nanoseconds to seed srand */
1578 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1579 {
1580 int i;
1581 srand(PIC32_SEED_COUNT() * 25);
1582
1583 for (i = 0; i < sz; i++ ) {
1584 output[i] = rand() % 256;
1585 if ( (i % 8) == 7)
1586 srand(PIC32_SEED_COUNT() * 25);
1587 }
1588 return 0;
1589 }
1590 #endif /* WOLFSSL_PIC32MZ_RNG */
1591
1592#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \
1593 defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS)
1594
1595 #if defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA)
1596 /*
1597 * wc_Generates a RNG seed using the Random Number Generator Accelerator
1598 * on the Kinetis K70. Documentation located in Chapter 37 of
1599 * K70 Sub-Family Reference Manual (see Note 3 in the README for link).
1600 */
1601 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1602 {
1603 word32 i;
1604
1605 /* turn on RNGA module */
1606 #if defined(SIM_SCGC3_RNGA_MASK)
1607 SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK;
1608 #endif
1609 #if defined(SIM_SCGC6_RNGA_MASK)
1610 /* additionally needed for at least K64F */
1611 SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK;
1612 #endif
1613
1614 /* set SLP bit to 0 - "RNGA is not in sleep mode" */
1615 RNG_CR &= ~RNG_CR_SLP_MASK;
1616
1617 /* set HA bit to 1 - "security violations masked" */
1618 RNG_CR |= RNG_CR_HA_MASK;
1619
1620 /* set GO bit to 1 - "output register loaded with data" */
1621 RNG_CR |= RNG_CR_GO_MASK;
1622
1623 for (i = 0; i < sz; i++) {
1624
1625 /* wait for RNG FIFO to be full */
1626 while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {}
1627
1628 /* get value */
1629 output[i] = RNG_OR;
1630 }
1631
1632 return 0;
1633 }
1634
1635 #elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB)
1636 /*
1637 * wc_Generates a RNG seed using the Random Number Generator (RNGB)
1638 * on the Kinetis K53. Documentation located in Chapter 33 of
1639 * K53 Sub-Family Reference Manual (see note in the README for link).
1640 */
1641 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1642 {
1643 int i;
1644
1645 /* turn on RNGB module */
1646 SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK;
1647
1648 /* reset RNGB */
1649 RNG_CMD |= RNG_CMD_SR_MASK;
1650
1651 /* FIFO generate interrupt, return all zeros on underflow,
1652 * set auto reseed */
1653 RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK);
1654
1655 /* gen seed, clear interrupts, clear errors */
1656 RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK);
1657
1658 /* wait for seeding to complete */
1659 while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {}
1660
1661 for (i = 0; i < sz; i++) {
1662
1663 /* wait for a word to be available from FIFO */
1664 while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {}
1665
1666 /* get value */
1667 output[i] = RNG_OUT;
1668 }
1669
1670 return 0;
1671 }
1672
1673 #elif defined(FREESCALE_KSDK_2_0_TRNG)
1674
1675 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1676 {
1677 status_t status;
1678 status = TRNG_GetRandomData(TRNG0, output, sz);
1679 if (status == kStatus_Success)
1680 {
1681 return(0);
1682 }
1683 else
1684 {
1685 return RAN_BLOCK_E;
1686 }
1687 }
1688
1689 #elif defined(FREESCALE_KSDK_2_0_RNGA)
1690
1691 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1692 {
1693 status_t status;
1694 status = RNGA_GetRandomData(RNG, output, sz);
1695 if (status == kStatus_Success)
1696 {
1697 return(0);
1698 }
1699 else
1700 {
1701 return RAN_BLOCK_E;
1702 }
1703 }
1704
1705
1706 #elif defined(FREESCALE_RNGA)
1707
1708 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1709 {
1710 RNGA_DRV_GetRandomData(RNGA_INSTANCE, output, sz);
1711 return 0;
1712 }
1713
1714 #else
1715 #define USE_TEST_GENSEED
1716 #endif /* FREESCALE_K70_RNGA */
1717
1718#elif defined(STM32_RNG)
1719 /* Generate a RNG seed using the hardware random number generator
1720 * on the STM32F2/F4/F7. */
1721
1722 #ifdef WOLFSSL_STM32_CUBEMX
1723 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1724 {
1725 RNG_HandleTypeDef hrng;
1726 int i;
1727 (void)os;
1728
1729 /* enable RNG clock source */
1730 __HAL_RCC_RNG_CLK_ENABLE();
1731
1732 /* enable RNG peripheral */
1733 hrng.Instance = RNG;
1734 HAL_RNG_Init(&hrng);
1735
1736 for (i = 0; i < (int)sz; i++) {
1737 /* get value */
1738 output[i] = (byte)HAL_RNG_GetRandomNumber(&hrng);
1739 }
1740
1741 return 0;
1742 }
1743 #elif defined(WOLFSSL_STM32F427_RNG)
1744
1745 /* Generate a RNG seed using the hardware RNG on the STM32F427
1746 * directly, following steps outlined in STM32F4 Reference
1747 * Manual (Chapter 24) for STM32F4xx family. */
1748 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1749 {
1750 int i;
1751 (void)os;
1752
1753 /* enable RNG peripheral clock */
1754 RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN;
1755
1756 /* enable RNG interrupt, set IE bit in RNG->CR register */
1757 RNG->CR |= RNG_CR_IE;
1758
1759 /* enable RNG, set RNGEN bit in RNG->CR. Activates RNG,
1760 * RNG_LFSR, and error detector */
1761 RNG->CR |= RNG_CR_RNGEN;
1762
1763 /* verify no errors, make sure SEIS and CEIS bits are 0
1764 * in RNG->SR register */
1765 if (RNG->SR & (RNG_SR_SECS | RNG_SR_CECS))
1766 return RNG_FAILURE_E;
1767
1768 for (i = 0; i < (int)sz; i++) {
1769 /* wait until RNG number is ready */
1770 while ((RNG->SR & RNG_SR_DRDY) == 0) { }
1771
1772 /* get value */
1773 output[i] = RNG->DR;
1774 }
1775
1776 return 0;
1777 }
1778
1779 #else
1780
1781 /* Generate a RNG seed using the STM32 Standard Peripheral Library */
1782 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1783 {
1784 int i;
1785 (void)os;
1786
1787 /* enable RNG clock source */
1788 RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
1789
1790 /* reset RNG */
1791 RNG_DeInit();
1792
1793 /* enable RNG peripheral */
1794 RNG_Cmd(ENABLE);
1795
1796 /* verify no errors with RNG_CLK or Seed */
1797 if (RNG_GetFlagStatus(RNG_FLAG_SECS | RNG_FLAG_CECS) != RESET)
1798 return RNG_FAILURE_E;
1799
1800 for (i = 0; i < (int)sz; i++) {
1801 /* wait until RNG number is ready */
1802 while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) { }
1803
1804 /* get value */
1805 output[i] = RNG_GetRandomNumber();
1806 }
1807
1808 return 0;
1809 }
1810 #endif /* WOLFSSL_STM32_CUBEMX */
1811
1812#elif defined(WOLFSSL_TIRTOS)
1813
1814 #include <xdc/runtime/Timestamp.h>
1815 #include <stdlib.h>
1816 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1817 {
1818 int i;
1819 srand(xdc_runtime_Timestamp_get32());
1820
1821 for (i = 0; i < sz; i++ ) {
1822 output[i] = rand() % 256;
1823 if ((i % 8) == 7) {
1824 srand(xdc_runtime_Timestamp_get32());
1825 }
1826 }
1827
1828 return 0;
1829 }
1830
1831#elif defined(WOLFSSL_PB)
1832
1833 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1834 {
1835 word32 i;
1836 for (i = 0; i < sz; i++)
1837 output[i] = UTL_Rand();
1838
1839 (void)os;
1840
1841 return 0;
1842 }
1843
1844#elif defined(WOLFSSL_NUCLEUS)
1845#include "nucleus.h"
1846#include "kernel/plus_common.h"
1847
1848#warning "potential for not enough entropy, currently being used for testing"
1849int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1850{
1851 int i;
1852 srand(NU_Get_Time_Stamp());
1853
1854 for (i = 0; i < sz; i++ ) {
1855 output[i] = rand() % 256;
1856 if ((i % 8) == 7) {
1857 srand(NU_Get_Time_Stamp());
1858 }
1859 }
1860
1861 return 0;
1862}
1863#elif defined(WOLFSSL_VXWORKS)
1864
1865 #include <randomNumGen.h>
1866
1867 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) {
1868 STATUS status;
1869
1870 #ifdef VXWORKS_SIM
1871 /* cannot generate true entropy with VxWorks simulator */
1872 #warning "not enough entropy, simulator for testing only"
1873 int i = 0;
1874
1875 for (i = 0; i < 1000; i++) {
1876 randomAddTimeStamp();
1877 }
1878 #endif
1879
1880 status = randBytes (output, sz);
1881 if (status == ERROR) {
1882 return RNG_FAILURE_E;
1883 }
1884
1885 return 0;
1886 }
1887
1888#elif defined(WOLFSSL_NRF51)
1889 #include "app_error.h"
1890 #include "nrf_drv_rng.h"
1891 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1892 {
1893 int remaining = sz, length, pos = 0;
1894 uint8_t available;
1895 uint32_t err_code;
1896
1897 (void)os;
1898
1899 /* Make sure RNG is running */
1900 err_code = nrf_drv_rng_init(NULL);
1901 if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) {
1902 return -1;
1903 }
1904
1905 while (remaining > 0) {
1906 err_code = nrf_drv_rng_bytes_available(&available);
1907 if (err_code == NRF_SUCCESS) {
1908 length = (remaining < available) ? remaining : available;
1909 if (length > 0) {
1910 err_code = nrf_drv_rng_rand(&output[pos], length);
1911 remaining -= length;
1912 pos += length;
1913 }
1914 }
1915
1916 if (err_code != NRF_SUCCESS) {
1917 break;
1918 }
1919 }
1920
1921 return (err_code == NRF_SUCCESS) ? 0 : -1;
1922 }
1923
1924#elif defined(HAVE_WNR)
1925
1926 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1927 {
1928 if (os == NULL || output == NULL || wnr_ctx == NULL ||
1929 wnr_timeout < 0) {
1930 return BAD_FUNC_ARG;
1931 }
1932
1933 if (wnr_mutex_init == 0) {
1934 WOLFSSL_MSG("netRandom context must be created before use");
1935 return RNG_FAILURE_E;
1936 }
1937
1938 if (wc_LockMutex(&wnr_mutex) != 0) {
1939 WOLFSSL_MSG("Bad Lock Mutex wnr_mutex\n");
1940 return BAD_MUTEX_E;
1941 }
1942
1943 if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) !=
1944 WNR_ERROR_NONE)
1945 return RNG_FAILURE_E;
1946
1947 wc_UnLockMutex(&wnr_mutex);
1948
1949 return 0;
1950 }
1951
1952#elif defined(WOLFSSL_ATMEL)
1953 #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
1954
1955 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1956 {
1957 int ret = 0;
1958
1959 (void)os;
1960 if (output == NULL) {
1961 return BUFFER_E;
1962 }
1963
1964 ret = atmel_get_random_number(sz, output);
1965
1966 return ret;
1967 }
1968
1969#elif defined(INTIME_RTOS)
1970 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1971 {
1972 int ret = 0;
1973
1974 (void)os;
1975
1976 if (output == NULL) {
1977 return BUFFER_E;
1978 }
1979
1980 /* Note: Investigate better solution */
1981 /* no return to check */
1982 arc4random_buf(output, sz);
1983
1984 return ret;
1985 }
1986
1987#elif defined(IDIRECT_DEV_RANDOM)
1988
1989 extern int getRandom( int sz, unsigned char *output );
1990
1991 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
1992 {
1993 int num_bytes_returned = 0;
1994
1995 num_bytes_returned = getRandom( (int) sz, (unsigned char *) output );
1996
1997 return 0;
1998 }
1999
2000#elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG))
2001
2002 #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
2003 #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
2004
2005 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2006 {
2007 Buffer buf[1];
2008 int ret = 0;
2009 int times = 1000, i;
2010
2011 (void)os;
2012
2013 if (output == NULL) {
2014 return BUFFER_E;
2015 }
2016
2017 buf[0].BufferType = DataBuffer | LastBuffer;
2018 buf[0].TheAddress = (Address)output;
2019 buf[0].Length = sz;
2020
2021 /* Check Waiting to make sure entropy is ready */
2022 for (i = 0; i < times; i++) {
2023 ret = wc_caamAddAndWait(buf, NULL, CAAM_ENTROPY);
2024 if (ret == Success) {
2025 break;
2026 }
2027
2028 /* driver could be waiting for entropy */
2029 if (ret != RAN_BLOCK_E) {
2030 return ret;
2031 }
2032 usleep(100);
2033 }
2034
2035 if (i == times && ret != Success) {
2036 return RNG_FAILURE_E;
2037 }
2038 else { /* Success case */
2039 ret = 0;
2040 }
2041
2042 return ret;
2043 }
2044
2045#elif defined(WOLFSSL_APACHE_MYNEWT)
2046
2047 #include <stdlib.h>
2048 #include "os/os_time.h"
2049 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2050 {
2051 int i;
2052 srand(os_time_get());
2053
2054 for (i = 0; i < sz; i++ ) {
2055 output[i] = rand() % 256;
2056 if ((i % 8) == 7) {
2057 srand(os_time_get());
2058 }
2059 }
2060
2061 return 0;
2062 }
2063
2064#elif defined(WOLFSSL_ESPIDF)
2065 #if defined(WOLFSSL_ESPWROOM32)
2066 #include <esp_system.h>
2067
2068 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2069 {
2070 int i;
2071
2072 for (i = 0; i< sz; i++) {
2073 output[i] = esp_random( );
2074 }
2075
2076 return 0;
2077 }
2078 #endif /* end WOLFSSL_ESPWROOM32 */
2079
2080#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
2081 /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
2082 * extern int myRngFunc(byte* output, word32 sz);
2083 */
2084
2085#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \
2086 defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) || \
2087 defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2) || \
2088 defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) || \
2089 defined(MBED) || defined(WOLFSSL_EMBOS) || \
2090 defined(WOLFSSL_GENSEED_FORTEST) || defined(WOLFSSL_CHIBIOS) || \
2091 defined(WOLFSSL_CONTIKI)
2092
2093 /* these platforms do not have a default random seed and
2094 you'll need to implement your own wc_GenerateSeed or define via
2095 CUSTOM_RAND_GENERATE_BLOCK */
2096
2097 #define USE_TEST_GENSEED
2098
2099#elif defined(NO_DEV_RANDOM)
2100
2101 #error "you need to write an os specific wc_GenerateSeed() here"
2102
2103 /*
2104 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2105 {
2106 return 0;
2107 }
2108 */
2109
2110#else
2111
2112 /* may block */
2113 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2114 {
2115 int ret = 0;
2116
2117 #ifdef HAVE_INTEL_RDSEED
2118 if (IS_INTEL_RDSEED(intel_flags)) {
2119 ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
2120 if (ret == 0) {
2121 /* success, we're done */
2122 return ret;
2123 }
2124 #ifdef FORCE_FAILURE_RDSEED
2125 /* don't fallback to /dev/urandom */
2126 return ret;
2127 #else
2128 /* reset error and fallback to using /dev/urandom */
2129 ret = 0;
2130 #endif
2131 }
2132 #endif /* HAVE_INTEL_RDSEED */
2133
2134 #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
2135 os->fd = open("/dev/urandom",O_RDONLY);
2136 if (os->fd == -1)
2137 #endif
2138 {
2139 /* may still have /dev/random */
2140 os->fd = open("/dev/random",O_RDONLY);
2141 if (os->fd == -1)
2142 return OPEN_RAN_E;
2143 }
2144
2145 while (sz) {
2146 int len = (int)read(os->fd, output, sz);
2147 if (len == -1) {
2148 ret = READ_RAN_E;
2149 break;
2150 }
2151
2152 sz -= len;
2153 output += len;
2154
2155 if (sz) {
2156 #if defined(BLOCKING) || defined(WC_RNG_BLOCKING)
2157 sleep(0); /* context switch */
2158 #else
2159 ret = RAN_BLOCK_E;
2160 break;
2161 #endif
2162 }
2163 }
2164 close(os->fd);
2165
2166 return ret;
2167 }
2168
2169#endif
2170
2171#ifdef USE_TEST_GENSEED
2172 #ifndef _MSC_VER
2173 #warning "write a real random seed!!!!, just for testing now"
2174 #else
2175 #pragma message("Warning: write a real random seed!!!!, just for testing now")
2176 #endif
2177
2178 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2179 {
2180 word32 i;
2181 for (i = 0; i < sz; i++ )
2182 output[i] = i;
2183
2184 (void)os;
2185
2186 return 0;
2187 }
2188#endif
2189
2190/* End wc_GenerateSeed */
2191#endif /* WC_NO_RNG */
2192#endif /* HAVE_FIPS */
Note: See TracBrowser for help on using the repository browser.