Xuyi Wang / wolfcrypt

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers random.c Source File

random.c

00001 /* random.c
00002  *
00003  * Copyright (C) 2006-2017 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfcrypt/settings.h>
00028 #include <wolfcrypt/error-crypt.h>
00029 
00030 /* on HPUX 11 you may need to install /dev/random see
00031    http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
00032 
00033 */
00034 
00035 #if defined(HAVE_FIPS) && \
00036     defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
00037 
00038     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
00039     #define FIPS_NO_WRAPPERS
00040 
00041     #ifdef USE_WINDOWS_API
00042         #pragma code_seg(".fipsA$c")
00043         #pragma const_seg(".fipsB$c")
00044     #endif
00045 #endif
00046 
00047 
00048 #include <wolfcrypt/random.h>
00049 #include <wolfcrypt/cpuid.h>
00050 
00051 
00052 /* If building for old FIPS. */
00053 #if defined(HAVE_FIPS) && \
00054     (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
00055 
00056 int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz)
00057 {
00058     return GenerateSeed(os, seed, sz);
00059 }
00060 
00061 int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
00062 {
00063     (void)heap;
00064     (void)devId;
00065     return InitRng_fips(rng);
00066 }
00067 
00068 int wc_InitRng(WC_RNG* rng)
00069 {
00070     return InitRng_fips(rng);
00071 }
00072 
00073 
00074 int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz)
00075 {
00076     return RNG_GenerateBlock_fips(rng, b, sz);
00077 }
00078 
00079 
00080 int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
00081 {
00082     return RNG_GenerateByte(rng, b);
00083 }
00084 
00085 #ifdef HAVE_HASHDRBG
00086 
00087     int wc_FreeRng(WC_RNG* rng)
00088     {
00089         return FreeRng_fips(rng);
00090     }
00091 
00092     int wc_RNG_HealthTest(int reseed,
00093                                         const byte* entropyA, word32 entropyASz,
00094                                         const byte* entropyB, word32 entropyBSz,
00095                                         byte* output, word32 outputSz)
00096     {
00097         return RNG_HealthTest_fips(reseed, entropyA, entropyASz,
00098                               entropyB, entropyBSz, output, outputSz);
00099    }
00100 #endif /* HAVE_HASHDRBG */
00101 
00102 #else /* else build without fips, or for new fips */
00103 
00104 #ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
00105 
00106 #include <wolfcrypt/sha256.h>
00107 
00108 #ifdef NO_INLINE
00109     #include <wolfcrypt/misc.h>
00110 #else
00111     #define WOLFSSL_MISC_INCLUDED
00112     #include <wolfcrypt/src/misc.c>
00113 #endif
00114 
00115 #if defined(WOLFSSL_SGX)
00116     #include <sgx_trts.h>
00117 #elif defined(USE_WINDOWS_API)
00118     #ifndef _WIN32_WINNT
00119         #define _WIN32_WINNT 0x0400
00120     #endif
00121     #include <windows.h>
00122     #include <wincrypt.h>
00123 #elif defined(HAVE_WNR)
00124     #include <wnr.h>
00125     #include <wolfcrypt/logging.h>
00126     wolfSSL_Mutex wnr_mutex;    /* global netRandom mutex */
00127     int wnr_timeout     = 0;    /* entropy timeout, mililseconds */
00128     int wnr_mutex_init  = 0;    /* flag for mutex init */
00129     wnr_context*  wnr_ctx;      /* global netRandom context */
00130 #elif defined(FREESCALE_KSDK_2_0_TRNG)
00131     #include "fsl_trng.h"
00132 #elif defined(FREESCALE_KSDK_2_0_RNGA)
00133     #include "fsl_rnga.h"
00134 
00135 #elif defined(NO_DEV_RANDOM)
00136 #elif defined(CUSTOM_RAND_GENERATE)
00137 #elif defined(CUSTOM_RAND_GENERATE_BLOCK)
00138 #elif defined(CUSTOM_RAND_GENERATE_SEED)
00139 #elif defined(WOLFSSL_GENSEED_FORTEST)
00140 #elif defined(WOLFSSL_MDK_ARM)
00141 #elif defined(WOLFSSL_IAR_ARM)
00142 #elif defined(WOLFSSL_ROWLEY_ARM)
00143 #elif defined(WOLFSSL_EMBOS)
00144 #elif defined(MICRIUM)
00145 #elif defined(WOLFSSL_NUCLEUS)
00146 #elif defined(WOLFSSL_PB)
00147 #else
00148     /* include headers that may be needed to get good seed */
00149     #include <fcntl.h>
00150     #ifndef EBSNET
00151         #include <unistd.h>
00152     #endif
00153 #endif
00154 
00155 
00156 #if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
00157     static word32 intel_flags = 0;
00158     static void wc_InitRng_IntelRD(void)
00159     {
00160         intel_flags = cpuid_get_flags();
00161     }
00162     #ifdef HAVE_INTEL_RDSEED
00163     static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz);
00164     #endif
00165     #ifdef HAVE_INTEL_RDRAND
00166     static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz);
00167     #endif
00168 
00169 #ifdef USE_WINDOWS_API
00170     #include <immintrin.h>
00171 #endif /* USE_WINDOWS_API */
00172 #endif
00173 
00174 /* Start NIST DRBG code */
00175 #ifdef HAVE_HASHDRBG
00176 
00177 #define OUTPUT_BLOCK_LEN  (WC_SHA256_DIGEST_SIZE)
00178 #define MAX_REQUEST_LEN   (0x10000)
00179 #define RESEED_INTERVAL   WC_RESEED_INTERVAL
00180 #define SECURITY_STRENGTH (2048)
00181 #define ENTROPY_SZ        (SECURITY_STRENGTH/8)
00182 #define MAX_ENTROPY_SZ    (ENTROPY_SZ + ENTROPY_SZ/2)
00183 
00184 /* Internal return codes */
00185 #define DRBG_SUCCESS      0
00186 #define DRBG_FAILURE      1
00187 #define DRBG_NEED_RESEED  2
00188 #define DRBG_CONT_FAILURE 3
00189 
00190 /* RNG health states */
00191 #define DRBG_NOT_INIT     0
00192 #define DRBG_OK           1
00193 #define DRBG_FAILED       2
00194 #define DRBG_CONT_FAILED  3
00195 
00196 #define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4)
00197 
00198 /* Verify max gen block len */
00199 #if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN
00200     #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length
00201 #endif
00202 
00203 enum {
00204     drbgInitC     = 0,
00205     drbgReseed    = 1,
00206     drbgGenerateW = 2,
00207     drbgGenerateH = 3,
00208     drbgInitV
00209 };
00210 
00211 
00212 typedef struct DRBG {
00213     word32 reseedCtr;
00214     word32 lastBlock;
00215     byte V[DRBG_SEED_LEN];
00216     byte C[DRBG_SEED_LEN];
00217 #ifdef WOLFSSL_ASYNC_CRYPT
00218     void* heap;
00219     int devId;
00220 #endif
00221     byte   matchCount;
00222 #ifdef WOLFSSL_SMALL_STACK_CACHE
00223     wc_Sha256 sha256;
00224 #endif
00225 } DRBG;
00226 
00227 
00228 static int wc_RNG_HealthTestLocal(int reseed);
00229 
00230 /* Hash Derivation Function */
00231 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
00232 static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type,
00233                                                   const byte* inA, word32 inASz,
00234                                                   const byte* inB, word32 inBSz)
00235 {
00236     int ret = DRBG_FAILURE;
00237     byte ctr;
00238     int i;
00239     int len;
00240     word32 bits = (outSz * 8); /* reverse byte order */
00241 #ifdef WOLFSSL_SMALL_STACK_CACHE
00242     wc_Sha256* sha = &drbg->sha256;
00243 #else
00244     wc_Sha256 sha[1];
00245 #endif
00246     DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
00247 
00248     (void)drbg;
00249 #ifdef WOLFSSL_ASYNC_CRYPT
00250     if (digest == NULL)
00251         return DRBG_FAILURE;
00252 #endif
00253 
00254 #ifdef LITTLE_ENDIAN_ORDER
00255     bits = ByteReverseWord32(bits);
00256 #endif
00257     len = (outSz / OUTPUT_BLOCK_LEN)
00258         + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
00259 
00260     for (i = 0, ctr = 1; i < len; i++, ctr++) {
00261 #ifndef WOLFSSL_SMALL_STACK_CACHE
00262     #ifdef WOLFSSL_ASYNC_CRYPT
00263         ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
00264     #else
00265         ret = wc_InitSha256(sha);
00266     #endif
00267         if (ret != 0)
00268             break;
00269 
00270         if (ret == 0)
00271 #endif
00272             ret = wc_Sha256Update(sha, &ctr, sizeof(ctr));
00273         if (ret == 0)
00274             ret = wc_Sha256Update(sha, (byte*)&bits, sizeof(bits));
00275 
00276         if (ret == 0) {
00277             /* churning V is the only string that doesn't have the type added */
00278             if (type != drbgInitV)
00279                 ret = wc_Sha256Update(sha, &type, sizeof(type));
00280         }
00281         if (ret == 0)
00282             ret = wc_Sha256Update(sha, inA, inASz);
00283         if (ret == 0) {
00284             if (inB != NULL && inBSz > 0)
00285                 ret = wc_Sha256Update(sha, inB, inBSz);
00286         }
00287         if (ret == 0)
00288             ret = wc_Sha256Final(sha, digest);
00289 
00290 #ifndef WOLFSSL_SMALL_STACK_CACHE
00291         wc_Sha256Free(sha);
00292 #endif
00293         if (ret == 0) {
00294             if (outSz > OUTPUT_BLOCK_LEN) {
00295                 XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
00296                 outSz -= OUTPUT_BLOCK_LEN;
00297                 out += OUTPUT_BLOCK_LEN;
00298             }
00299             else {
00300                 XMEMCPY(out, digest, outSz);
00301             }
00302         }
00303     }
00304 
00305     ForceZero(digest, WC_SHA256_DIGEST_SIZE);
00306 
00307     FREE_VAR(digest, drbg->heap);
00308 
00309     return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
00310 }
00311 
00312 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
00313 static int Hash_DRBG_Reseed(DRBG* drbg, const byte* entropy, word32 entropySz)
00314 {
00315     byte seed[DRBG_SEED_LEN];
00316 
00317     if (Hash_df(drbg, seed, sizeof(seed), drbgReseed, drbg->V, sizeof(drbg->V),
00318                                           entropy, entropySz) != DRBG_SUCCESS) {
00319         return DRBG_FAILURE;
00320     }
00321 
00322     XMEMCPY(drbg->V, seed, sizeof(drbg->V));
00323     ForceZero(seed, sizeof(seed));
00324 
00325     if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
00326                                     sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) {
00327         return DRBG_FAILURE;
00328     }
00329 
00330     drbg->reseedCtr = 1;
00331     drbg->lastBlock = 0;
00332     drbg->matchCount = 0;
00333     return DRBG_SUCCESS;
00334 }
00335 
00336 /* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */
00337 int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* entropy, word32 entropySz)
00338 {
00339     if (rng == NULL || entropy == NULL) {
00340         return BAD_FUNC_ARG;
00341     }
00342 
00343     return Hash_DRBG_Reseed(rng->drbg, entropy, entropySz);
00344 }
00345 
00346 static WC_INLINE void array_add_one(byte* data, word32 dataSz)
00347 {
00348     int i;
00349 
00350     for (i = dataSz - 1; i >= 0; i--)
00351     {
00352         data[i]++;
00353         if (data[i] != 0) break;
00354     }
00355 }
00356 
00357 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
00358 static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V)
00359 {
00360     int ret = DRBG_FAILURE;
00361     byte data[DRBG_SEED_LEN];
00362     int i;
00363     int len;
00364     word32 checkBlock;
00365 #ifdef WOLFSSL_SMALL_STACK_CACHE
00366     wc_Sha256* sha = &drbg->sha256;
00367 #else
00368     wc_Sha256 sha[1];
00369 #endif
00370     DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
00371 
00372     /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for
00373      * the continuous test. */
00374 
00375     if (outSz == 0) outSz = 1;
00376 
00377     len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
00378 
00379     XMEMCPY(data, V, sizeof(data));
00380     for (i = 0; i < len; i++) {
00381 #ifndef WOLFSSL_SMALL_STACK_CACHE
00382     #ifdef WOLFSSL_ASYNC_CRYPT
00383         ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
00384     #else
00385         ret = wc_InitSha256(sha);
00386     #endif
00387         if (ret == 0)
00388 #endif
00389             ret = wc_Sha256Update(sha, data, sizeof(data));
00390         if (ret == 0)
00391             ret = wc_Sha256Final(sha, digest);
00392 #ifndef WOLFSSL_SMALL_STACK_CACHE
00393         wc_Sha256Free(sha);
00394 #endif
00395 
00396         if (ret == 0) {
00397             XMEMCPY(&checkBlock, digest, sizeof(word32));
00398             if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) {
00399                 if (drbg->matchCount == 1) {
00400                     return DRBG_CONT_FAILURE;
00401                 }
00402                 else {
00403                     if (i == len) {
00404                         len++;
00405                     }
00406                     drbg->matchCount = 1;
00407                 }
00408             }
00409             else {
00410                 drbg->matchCount = 0;
00411                 drbg->lastBlock = checkBlock;
00412             }
00413 
00414             if (out != NULL && outSz != 0) {
00415                 if (outSz >= OUTPUT_BLOCK_LEN) {
00416                     XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
00417                     outSz -= OUTPUT_BLOCK_LEN;
00418                     out += OUTPUT_BLOCK_LEN;
00419                     array_add_one(data, DRBG_SEED_LEN);
00420                 }
00421                 else {
00422                     XMEMCPY(out, digest, outSz);
00423                     outSz = 0;
00424                 }
00425             }
00426         }
00427     }
00428     ForceZero(data, sizeof(data));
00429 
00430     FREE_VAR(digest, drbg->heap);
00431 
00432     return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
00433 }
00434 
00435 static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
00436 {
00437     word16 carry = 0;
00438 
00439     if (dLen > 0 && sLen > 0 && dLen >= sLen) {
00440         int sIdx, dIdx;
00441 
00442         for (sIdx = sLen - 1, dIdx = dLen - 1; sIdx >= 0; dIdx--, sIdx--)
00443         {
00444             carry += d[dIdx] + s[sIdx];
00445             d[dIdx] = (byte)carry;
00446             carry >>= 8;
00447         }
00448 
00449         for (; carry != 0 && dIdx >= 0; dIdx--) {
00450             carry += d[dIdx];
00451             d[dIdx] = (byte)carry;
00452             carry >>= 8;
00453         }
00454     }
00455 }
00456 
00457 /* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */
00458 static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz)
00459 {
00460     int ret;
00461 #ifdef WOLFSSL_SMALL_STACK_CACHE
00462     wc_Sha256* sha = &drbg->sha256;
00463 #else
00464     wc_Sha256 sha[1];
00465 #endif
00466     byte type;
00467     word32 reseedCtr;
00468 
00469     if (drbg->reseedCtr == RESEED_INTERVAL) {
00470         return DRBG_NEED_RESEED;
00471     } else {
00472         DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap);
00473         type = drbgGenerateH;
00474         reseedCtr = drbg->reseedCtr;
00475 
00476         ret = Hash_gen(drbg, out, outSz, drbg->V);
00477         if (ret == DRBG_SUCCESS) {
00478 #ifndef WOLFSSL_SMALL_STACK_CACHE
00479         #ifdef WOLFSSL_ASYNC_CRYPT
00480             ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
00481         #else
00482             ret = wc_InitSha256(sha);
00483         #endif
00484             if (ret == 0)
00485 #endif
00486                 ret = wc_Sha256Update(sha, &type, sizeof(type));
00487             if (ret == 0)
00488                 ret = wc_Sha256Update(sha, drbg->V, sizeof(drbg->V));
00489             if (ret == 0)
00490                 ret = wc_Sha256Final(sha, digest);
00491 
00492 #ifndef WOLFSSL_SMALL_STACK_CACHE
00493             wc_Sha256Free(sha);
00494 #endif
00495 
00496             if (ret == 0) {
00497                 array_add(drbg->V, sizeof(drbg->V), digest, WC_SHA256_DIGEST_SIZE);
00498                 array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
00499             #ifdef LITTLE_ENDIAN_ORDER
00500                 reseedCtr = ByteReverseWord32(reseedCtr);
00501             #endif
00502                 array_add(drbg->V, sizeof(drbg->V),
00503                                           (byte*)&reseedCtr, sizeof(reseedCtr));
00504                 ret = DRBG_SUCCESS;
00505             }
00506             drbg->reseedCtr++;
00507         }
00508         ForceZero(digest, WC_SHA256_DIGEST_SIZE);
00509         FREE_VAR(digest, drbg->heap);
00510     }
00511 
00512     return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
00513 }
00514 
00515 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
00516 static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz,
00517                                              const byte* nonce, word32 nonceSz,
00518                                              void* heap, int devId)
00519 {
00520     int ret = DRBG_FAILURE;
00521 
00522     XMEMSET(drbg, 0, sizeof(DRBG));
00523 #ifdef WOLFSSL_ASYNC_CRYPT
00524     drbg->heap = heap;
00525     drbg->devId = devId;
00526 #else
00527     (void)heap;
00528     (void)devId;
00529 #endif
00530 
00531 #ifdef WOLFSSL_SMALL_STACK_CACHE
00532     #ifdef WOLFSSL_ASYNC_CRYPT
00533         ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId);
00534     #else
00535         ret = wc_InitSha256(&drbg->sha256);
00536     #endif
00537     if (ret != 0)
00538         return ret;
00539 #endif
00540 
00541     if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
00542                                               nonce, nonceSz) == DRBG_SUCCESS &&
00543         Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
00544                                     sizeof(drbg->V), NULL, 0) == DRBG_SUCCESS) {
00545 
00546         drbg->reseedCtr = 1;
00547         drbg->lastBlock = 0;
00548         drbg->matchCount = 0;
00549         ret = DRBG_SUCCESS;
00550     }
00551 
00552     return ret;
00553 }
00554 
00555 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
00556 static int Hash_DRBG_Uninstantiate(DRBG* drbg)
00557 {
00558     word32 i;
00559     int    compareSum = 0;
00560     byte*  compareDrbg = (byte*)drbg;
00561 
00562 #ifdef WOLFSSL_SMALL_STACK_CACHE
00563     wc_Sha256Free(&drbg->sha256);
00564 #endif
00565 
00566     ForceZero(drbg, sizeof(DRBG));
00567 
00568     for (i = 0; i < sizeof(DRBG); i++)
00569         compareSum |= compareDrbg[i] ^ 0;
00570 
00571     return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
00572 }
00573 #endif /* HAVE_HASHDRBG */
00574 /* End NIST DRBG Code */
00575 
00576 
00577 static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
00578                     void* heap, int devId)
00579 {
00580     int ret = RNG_FAILURE_E;
00581 #ifdef HAVE_HASHDRBG
00582     word32 entropySz = ENTROPY_SZ;
00583 #endif
00584 
00585     (void)nonce;
00586     (void)nonceSz;
00587 
00588     if (rng == NULL)
00589         return BAD_FUNC_ARG;
00590     if (nonce == NULL && nonceSz != 0)
00591         return BAD_FUNC_ARG;
00592 
00593 #ifdef WOLFSSL_HEAP_TEST
00594     rng->heap = (void*)WOLFSSL_HEAP_TEST;
00595     (void)heap;
00596 #else
00597     rng->heap = heap;
00598 #endif
00599 #ifdef WOLFSSL_ASYNC_CRYPT
00600     rng->devId = devId;
00601 #else
00602     (void)devId;
00603 #endif
00604 
00605 #ifdef HAVE_HASHDRBG
00606     /* init the DBRG to known values */
00607     rng->drbg = NULL;
00608     rng->status = DRBG_NOT_INIT;
00609 #endif
00610 
00611 #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
00612     /* init the intel RD seed and/or rand */
00613     wc_InitRng_IntelRD();
00614 #endif
00615 
00616     /* configure async RNG source if available */
00617 #ifdef WOLFSSL_ASYNC_CRYPT
00618     ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG,
00619                                                         rng->heap, rng->devId);
00620     if (ret != 0)
00621         return ret;
00622 #endif
00623 
00624 #ifdef HAVE_INTEL_RDRAND
00625     /* if CPU supports RDRAND, use it directly and by-pass DRBG init */
00626     if (IS_INTEL_RDRAND(intel_flags))
00627         return 0;
00628 #endif
00629 
00630 #ifdef CUSTOM_RAND_GENERATE_BLOCK
00631     ret = 0; /* success */
00632 #else
00633 #ifdef HAVE_HASHDRBG
00634     if (nonceSz == 0)
00635         entropySz = MAX_ENTROPY_SZ;
00636 
00637     if (wc_RNG_HealthTestLocal(0) == 0) {
00638         DECLARE_VAR(entropy, byte, MAX_ENTROPY_SZ, rng->heap);
00639 
00640         rng->drbg =
00641                 (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap,
00642                                                           DYNAMIC_TYPE_RNG);
00643         if (rng->drbg == NULL) {
00644             ret = MEMORY_E;
00645         }
00646         else if (wc_GenerateSeed(&rng->seed, entropy, entropySz) == 0 &&
00647                  Hash_DRBG_Instantiate(rng->drbg, entropy, entropySz,
00648                             nonce, nonceSz, rng->heap, devId) == DRBG_SUCCESS) {
00649             ret = Hash_DRBG_Generate(rng->drbg, NULL, 0);
00650         }
00651         else
00652             ret = DRBG_FAILURE;
00653 
00654         ForceZero(entropy, entropySz);
00655         FREE_VAR(entropy, rng->heap);
00656     }
00657     else
00658         ret = DRBG_CONT_FAILURE;
00659 
00660     if (ret == DRBG_SUCCESS) {
00661         rng->status = DRBG_OK;
00662         ret = 0;
00663     }
00664     else if (ret == DRBG_CONT_FAILURE) {
00665         rng->status = DRBG_CONT_FAILED;
00666         ret = DRBG_CONT_FIPS_E;
00667     }
00668     else if (ret == DRBG_FAILURE) {
00669         rng->status = DRBG_FAILED;
00670         ret = RNG_FAILURE_E;
00671     }
00672     else {
00673         rng->status = DRBG_FAILED;
00674     }
00675 #endif /* HAVE_HASHDRBG */
00676 #endif /* CUSTOM_RAND_GENERATE_BLOCK */
00677 
00678     return ret;
00679 }
00680 
00681 
00682 int wc_InitRng(WC_RNG* rng)
00683 {
00684     return _InitRng(rng, NULL, 0, NULL, INVALID_DEVID);
00685 }
00686 
00687 
00688 int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
00689 {
00690     return _InitRng(rng, NULL, 0, heap, devId);
00691 }
00692 
00693 
00694 int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz)
00695 {
00696     return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID);
00697 }
00698 
00699 
00700 int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
00701                        void* heap, int devId)
00702 {
00703     return _InitRng(rng, nonce, nonceSz, heap, devId);
00704 }
00705 
00706 
00707 /* place a generated block in output */
00708 int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
00709 {
00710     int ret;
00711 
00712     if (rng == NULL || output == NULL)
00713         return BAD_FUNC_ARG;
00714 
00715 #ifdef HAVE_INTEL_RDRAND
00716     if (IS_INTEL_RDRAND(intel_flags))
00717         return wc_GenerateRand_IntelRD(NULL, output, sz);
00718 #endif
00719 
00720 #if defined(WOLFSSL_ASYNC_CRYPT)
00721     if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) {
00722         /* these are blocking */
00723     #ifdef HAVE_CAVIUM
00724         return NitroxRngGenerateBlock(rng, output, sz);
00725     #elif defined(HAVE_INTEL_QA)
00726         return IntelQaDrbg(&rng->asyncDev, output, sz);
00727     #else
00728         /* simulator not supported */
00729     #endif
00730     }
00731 #endif
00732 
00733 #ifdef CUSTOM_RAND_GENERATE_BLOCK
00734     XMEMSET(output, 0, sz);
00735     ret = CUSTOM_RAND_GENERATE_BLOCK(output, sz);
00736 #else
00737 
00738 #ifdef HAVE_HASHDRBG
00739     if (sz > RNG_MAX_BLOCK_LEN)
00740         return BAD_FUNC_ARG;
00741 
00742     if (rng->status != DRBG_OK)
00743         return RNG_FAILURE_E;
00744 
00745     ret = Hash_DRBG_Generate(rng->drbg, output, sz);
00746     if (ret == DRBG_NEED_RESEED) {
00747         if (wc_RNG_HealthTestLocal(1) == 0) {
00748             byte entropy[ENTROPY_SZ];
00749 
00750             if (wc_GenerateSeed(&rng->seed, entropy, ENTROPY_SZ) == 0 &&
00751                 Hash_DRBG_Reseed(rng->drbg, entropy, ENTROPY_SZ)
00752                                                               == DRBG_SUCCESS) {
00753 
00754                 ret = Hash_DRBG_Generate(rng->drbg, NULL, 0);
00755                 if (ret == DRBG_SUCCESS)
00756                     ret = Hash_DRBG_Generate(rng->drbg, output, sz);
00757             }
00758             else
00759                 ret = DRBG_FAILURE;
00760 
00761             ForceZero(entropy, ENTROPY_SZ);
00762         }
00763         else
00764             ret = DRBG_CONT_FAILURE;
00765     }
00766 
00767     if (ret == DRBG_SUCCESS) {
00768         ret = 0;
00769     }
00770     else if (ret == DRBG_CONT_FAILURE) {
00771         ret = DRBG_CONT_FIPS_E;
00772         rng->status = DRBG_CONT_FAILED;
00773     }
00774     else {
00775         ret = RNG_FAILURE_E;
00776         rng->status = DRBG_FAILED;
00777     }
00778 #else
00779 
00780     /* if we get here then there is an RNG configuration error */
00781     ret = RNG_FAILURE_E;
00782 
00783 #endif /* HAVE_HASHDRBG */
00784 #endif /* CUSTOM_RAND_GENERATE_BLOCK */
00785 
00786     return ret;
00787 }
00788 
00789 
00790 int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
00791 {
00792     return wc_RNG_GenerateBlock(rng, b, 1);
00793 }
00794 
00795 
00796 int wc_FreeRng(WC_RNG* rng)
00797 {
00798     int ret = 0;
00799 
00800     if (rng == NULL)
00801         return BAD_FUNC_ARG;
00802 
00803 #if defined(WOLFSSL_ASYNC_CRYPT)
00804     wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG);
00805 #endif
00806 
00807 #ifdef HAVE_HASHDRBG
00808     if (rng->drbg != NULL) {
00809         if (Hash_DRBG_Uninstantiate(rng->drbg) != DRBG_SUCCESS)
00810             ret = RNG_FAILURE_E;
00811 
00812         XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
00813         rng->drbg = NULL;
00814     }
00815 
00816     rng->status = DRBG_NOT_INIT;
00817 #endif /* HAVE_HASHDRBG */
00818 
00819     return ret;
00820 }
00821 
00822 #ifdef HAVE_HASHDRBG
00823 int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz,
00824                                   const byte* entropyB, word32 entropyBSz,
00825                                   byte* output, word32 outputSz)
00826 {
00827     return wc_RNG_HealthTest_ex(reseed, NULL, 0,
00828                                 entropyA, entropyASz,
00829                                 entropyB, entropyBSz,
00830                                 output, outputSz,
00831                                 NULL, INVALID_DEVID);
00832 }
00833 
00834 
00835 int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz,
00836                                   const byte* entropyA, word32 entropyASz,
00837                                   const byte* entropyB, word32 entropyBSz,
00838                                   byte* output, word32 outputSz,
00839                                   void* heap, int devId)
00840 {
00841     int ret = -1;
00842     DRBG* drbg;
00843 #ifndef WOLFSSL_SMALL_STACK
00844     DRBG  drbg_var;
00845 #endif
00846 
00847     if (entropyA == NULL || output == NULL) {
00848         return BAD_FUNC_ARG;
00849     }
00850 
00851     if (reseed != 0 && entropyB == NULL) {
00852         return BAD_FUNC_ARG;
00853     }
00854 
00855     if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) {
00856         return ret;
00857     }
00858 
00859 #ifdef WOLFSSL_SMALL_STACK
00860     drbg = (struct DRBG*)XMALLOC(sizeof(DRBG), NULL, DYNAMIC_TYPE_RNG);
00861     if (drbg == NULL) {
00862         return MEMORY_E;
00863     }
00864 #else
00865     drbg = &drbg_var;
00866 #endif
00867 
00868     if (Hash_DRBG_Instantiate(drbg, entropyA, entropyASz, nonce, nonceSz,
00869                               heap, devId) != 0) {
00870         goto exit_rng_ht;
00871     }
00872 
00873     if (reseed) {
00874         if (Hash_DRBG_Reseed(drbg, entropyB, entropyBSz) != 0) {
00875             goto exit_rng_ht;
00876         }
00877     }
00878 
00879     if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
00880         goto exit_rng_ht;
00881     }
00882 
00883     if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
00884         goto exit_rng_ht;
00885     }
00886 
00887     /* Mark success */
00888     ret = 0;
00889 
00890 exit_rng_ht:
00891 
00892     /* This is safe to call even if Hash_DRBG_Instantiate fails */
00893     if (Hash_DRBG_Uninstantiate(drbg) != 0) {
00894         ret = -1;
00895     }
00896 
00897 #ifdef WOLFSSL_SMALL_STACK
00898     XFREE(drbg, NULL, DYNAMIC_TYPE_RNG);
00899 #endif
00900 
00901     return ret;
00902 }
00903 
00904 
00905 const byte entropyA[] = {
00906     0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4,
00907     0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00,
00908     0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f,
00909     0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68
00910 };
00911 
00912 const byte reseedEntropyA[] = {
00913     0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3,
00914     0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22,
00915     0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3
00916 };
00917 
00918 const byte outputA[] = {
00919     0x04, 0xee, 0xc6, 0x3b, 0xb2, 0x31, 0xdf, 0x2c, 0x63, 0x0a, 0x1a, 0xfb,
00920     0xe7, 0x24, 0x94, 0x9d, 0x00, 0x5a, 0x58, 0x78, 0x51, 0xe1, 0xaa, 0x79,
00921     0x5e, 0x47, 0x73, 0x47, 0xc8, 0xb0, 0x56, 0x62, 0x1c, 0x18, 0xbd, 0xdc,
00922     0xdd, 0x8d, 0x99, 0xfc, 0x5f, 0xc2, 0xb9, 0x20, 0x53, 0xd8, 0xcf, 0xac,
00923     0xfb, 0x0b, 0xb8, 0x83, 0x12, 0x05, 0xfa, 0xd1, 0xdd, 0xd6, 0xc0, 0x71,
00924     0x31, 0x8a, 0x60, 0x18, 0xf0, 0x3b, 0x73, 0xf5, 0xed, 0xe4, 0xd4, 0xd0,
00925     0x71, 0xf9, 0xde, 0x03, 0xfd, 0x7a, 0xea, 0x10, 0x5d, 0x92, 0x99, 0xb8,
00926     0xaf, 0x99, 0xaa, 0x07, 0x5b, 0xdb, 0x4d, 0xb9, 0xaa, 0x28, 0xc1, 0x8d,
00927     0x17, 0x4b, 0x56, 0xee, 0x2a, 0x01, 0x4d, 0x09, 0x88, 0x96, 0xff, 0x22,
00928     0x82, 0xc9, 0x55, 0xa8, 0x19, 0x69, 0xe0, 0x69, 0xfa, 0x8c, 0xe0, 0x07,
00929     0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17
00930 };
00931 
00932 const byte entropyB[] = {
00933     0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3,
00934     0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19,
00935     0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */
00936     0x85, 0x81, 0xf9, 0x31, 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d,
00937     0xdb, 0xcb, 0xcc, 0x2e
00938 };
00939 
00940 const byte outputB[] = {
00941     0xd3, 0xe1, 0x60, 0xc3, 0x5b, 0x99, 0xf3, 0x40, 0xb2, 0x62, 0x82, 0x64,
00942     0xd1, 0x75, 0x10, 0x60, 0xe0, 0x04, 0x5d, 0xa3, 0x83, 0xff, 0x57, 0xa5,
00943     0x7d, 0x73, 0xa6, 0x73, 0xd2, 0xb8, 0xd8, 0x0d, 0xaa, 0xf6, 0xa6, 0xc3,
00944     0x5a, 0x91, 0xbb, 0x45, 0x79, 0xd7, 0x3f, 0xd0, 0xc8, 0xfe, 0xd1, 0x11,
00945     0xb0, 0x39, 0x13, 0x06, 0x82, 0x8a, 0xdf, 0xed, 0x52, 0x8f, 0x01, 0x81,
00946     0x21, 0xb3, 0xfe, 0xbd, 0xc3, 0x43, 0xe7, 0x97, 0xb8, 0x7d, 0xbb, 0x63,
00947     0xdb, 0x13, 0x33, 0xde, 0xd9, 0xd1, 0xec, 0xe1, 0x77, 0xcf, 0xa6, 0xb7,
00948     0x1f, 0xe8, 0xab, 0x1d, 0xa4, 0x66, 0x24, 0xed, 0x64, 0x15, 0xe5, 0x1c,
00949     0xcd, 0xe2, 0xc7, 0xca, 0x86, 0xe2, 0x83, 0x99, 0x0e, 0xea, 0xeb, 0x91,
00950     0x12, 0x04, 0x15, 0x52, 0x8b, 0x22, 0x95, 0x91, 0x02, 0x81, 0xb0, 0x2d,
00951     0xd4, 0x31, 0xf4, 0xc9, 0xf7, 0x04, 0x27, 0xdf
00952 };
00953 
00954 
00955 static int wc_RNG_HealthTestLocal(int reseed)
00956 {
00957     int ret = 0;
00958 #ifdef WOLFSSL_SMALL_STACK
00959     byte* check;
00960 #else
00961     byte  check[RNG_HEALTH_TEST_CHECK_SIZE];
00962 #endif
00963 
00964 #ifdef WOLFSSL_SMALL_STACK
00965     check = (byte*)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, NULL,
00966                            DYNAMIC_TYPE_TMP_BUFFER);
00967     if (check == NULL) {
00968         return MEMORY_E;
00969     }
00970 #endif
00971 
00972     if (reseed) {
00973         ret = wc_RNG_HealthTest(1, entropyA, sizeof(entropyA),
00974                                 reseedEntropyA, sizeof(reseedEntropyA),
00975                                 check, RNG_HEALTH_TEST_CHECK_SIZE);
00976         if (ret == 0) {
00977             if (ConstantCompare(check, outputA,
00978                                 RNG_HEALTH_TEST_CHECK_SIZE) != 0)
00979                 ret = -1;
00980         }
00981     }
00982     else {
00983         ret = wc_RNG_HealthTest(0, entropyB, sizeof(entropyB),
00984                                 NULL, 0,
00985                                 check, RNG_HEALTH_TEST_CHECK_SIZE);
00986         if (ret == 0) {
00987             if (ConstantCompare(check, outputB,
00988                                 RNG_HEALTH_TEST_CHECK_SIZE) != 0)
00989                 ret = -1;
00990         }
00991 
00992         /* The previous test cases use a large seed instead of a seed and nonce.
00993          * entropyB is actually from a test case with a seed and nonce, and
00994          * just concatenates them. The pivot point between seed and nonce is
00995          * byte 32, feed them into the health test separately. */
00996         if (ret == 0) {
00997             ret = wc_RNG_HealthTest_ex(0,
00998                                     entropyB + 32, sizeof(entropyB) - 32,
00999                                     entropyB, 32,
01000                                     NULL, 0,
01001                                     check, RNG_HEALTH_TEST_CHECK_SIZE,
01002                                     NULL, INVALID_DEVID);
01003             if (ret == 0) {
01004                 if (ConstantCompare(check, outputB, sizeof(outputB)) != 0)
01005                     ret = -1;
01006             }
01007         }
01008     }
01009 
01010 #ifdef WOLFSSL_SMALL_STACK
01011     XFREE(check, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01012 #endif
01013 
01014     return ret;
01015 }
01016 
01017 #endif /* HAVE_HASHDRBG */
01018 
01019 
01020 #ifdef HAVE_WNR
01021 
01022 /*
01023  * Init global Whitewood netRandom context
01024  * Returns 0 on success, negative on error
01025  */
01026 int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout)
01027 {
01028     if (configFile == NULL || timeout < 0)
01029         return BAD_FUNC_ARG;
01030 
01031     if (wnr_mutex_init > 0) {
01032         WOLFSSL_MSG("netRandom context already created, skipping");
01033         return 0;
01034     }
01035 
01036     if (wc_InitMutex(&wnr_mutex) != 0) {
01037         WOLFSSL_MSG("Bad Init Mutex wnr_mutex");
01038         return BAD_MUTEX_E;
01039     }
01040     wnr_mutex_init = 1;
01041 
01042     if (wc_LockMutex(&wnr_mutex) != 0) {
01043         WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
01044         return BAD_MUTEX_E;
01045     }
01046 
01047     /* store entropy timeout */
01048     wnr_timeout = timeout;
01049 
01050     /* create global wnr_context struct */
01051     if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) {
01052         WOLFSSL_MSG("Error creating global netRandom context");
01053         return RNG_FAILURE_E;
01054     }
01055 
01056     /* load config file */
01057     if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) {
01058         WOLFSSL_MSG("Error loading config file into netRandom context");
01059         wnr_destroy(wnr_ctx);
01060         wnr_ctx = NULL;
01061         return RNG_FAILURE_E;
01062     }
01063 
01064     /* create/init polling mechanism */
01065     if (wnr_poll_create() != WNR_ERROR_NONE) {
01066         printf("ERROR: wnr_poll_create() failed\n");
01067         WOLFSSL_MSG("Error initializing netRandom polling mechanism");
01068         wnr_destroy(wnr_ctx);
01069         wnr_ctx = NULL;
01070         return RNG_FAILURE_E;
01071     }
01072 
01073     /* validate config, set HMAC callback (optional) */
01074     if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) {
01075         WOLFSSL_MSG("Error setting up netRandom context");
01076         wnr_destroy(wnr_ctx);
01077         wnr_ctx = NULL;
01078         wnr_poll_destroy();
01079         return RNG_FAILURE_E;
01080     }
01081 
01082     wc_UnLockMutex(&wnr_mutex);
01083 
01084     return 0;
01085 }
01086 
01087 /*
01088  * Free global Whitewood netRandom context
01089  * Returns 0 on success, negative on error
01090  */
01091 int wc_FreeNetRandom(void)
01092 {
01093     if (wnr_mutex_init > 0) {
01094 
01095         if (wc_LockMutex(&wnr_mutex) != 0) {
01096             WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
01097             return BAD_MUTEX_E;
01098         }
01099 
01100         if (wnr_ctx != NULL) {
01101             wnr_destroy(wnr_ctx);
01102             wnr_ctx = NULL;
01103         }
01104         wnr_poll_destroy();
01105 
01106         wc_UnLockMutex(&wnr_mutex);
01107 
01108         wc_FreeMutex(&wnr_mutex);
01109         wnr_mutex_init = 0;
01110     }
01111 
01112     return 0;
01113 }
01114 
01115 #endif /* HAVE_WNR */
01116 
01117 
01118 #if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED)
01119 
01120 #ifdef WOLFSSL_ASYNC_CRYPT
01121     /* need more retries if multiple cores */
01122     #define INTELRD_RETRY (32 * 8)
01123 #else
01124     #define INTELRD_RETRY 32
01125 #endif
01126 
01127 #ifdef HAVE_INTEL_RDSEED
01128 
01129 #ifndef USE_WINDOWS_API
01130 
01131     /* return 0 on success */
01132     static WC_INLINE int IntelRDseed64(word64* seed)
01133     {
01134         unsigned char ok;
01135 
01136         __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok));
01137         return (ok) ? 0 : -1;
01138     }
01139 
01140 #else /* USE_WINDOWS_API */
01141     /* The compiler Visual Studio uses does not allow inline assembly.
01142      * It does allow for Intel intrinsic functions. */
01143 
01144     /* return 0 on success */
01145     static WC_INLINE int IntelRDseed64(word64* seed)
01146     {
01147         int ok;
01148 
01149         ok = _rdseed64_step(seed);
01150         return (ok) ? 0 : -1;
01151     }
01152 
01153 #endif /* USE_WINDOWS_API */
01154 
01155 /* return 0 on success */
01156 static WC_INLINE int IntelRDseed64_r(word64* rnd)
01157 {
01158     int i;
01159     for (i = 0; i < INTELRD_RETRY; i++) {
01160         if (IntelRDseed64(rnd) == 0)
01161             return 0;
01162     }
01163     return -1;
01164 }
01165 
01166 /* return 0 on success */
01167 static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz)
01168 {
01169     int ret;
01170     word64 rndTmp;
01171 
01172     (void)os;
01173 
01174     if (!IS_INTEL_RDSEED(intel_flags))
01175         return -1;
01176 
01177     for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
01178                                                     output += sizeof(word64)) {
01179         ret = IntelRDseed64_r((word64*)output);
01180         if (ret != 0)
01181             return ret;
01182     }
01183     if (sz == 0)
01184         return 0;
01185 
01186     /* handle unaligned remainder */
01187     ret = IntelRDseed64_r(&rndTmp);
01188     if (ret != 0)
01189         return ret;
01190 
01191     XMEMCPY(output, &rndTmp, sz);
01192     ForceZero(&rndTmp, sizeof(rndTmp));
01193 
01194     return 0;
01195 }
01196 
01197 #endif /* HAVE_INTEL_RDSEED */
01198 
01199 #ifdef HAVE_INTEL_RDRAND
01200 
01201 #ifndef USE_WINDOWS_API
01202 
01203 /* return 0 on success */
01204 static WC_INLINE int IntelRDrand64(word64 *rnd)
01205 {
01206     unsigned char ok;
01207 
01208     __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok));
01209 
01210     return (ok) ? 0 : -1;
01211 }
01212 
01213 #else /* USE_WINDOWS_API */
01214     /* The compiler Visual Studio uses does not allow inline assembly.
01215      * It does allow for Intel intrinsic functions. */
01216 
01217 /* return 0 on success */
01218 static WC_INLINE int IntelRDrand64(word64 *rnd)
01219 {
01220     int ok;
01221 
01222     ok = _rdrand64_step(rnd);
01223 
01224     return (ok) ? 0 : -1;
01225 }
01226 
01227 #endif /* USE_WINDOWS_API */
01228 
01229 /* return 0 on success */
01230 static WC_INLINE int IntelRDrand64_r(word64 *rnd)
01231 {
01232     int i;
01233     for (i = 0; i < INTELRD_RETRY; i++) {
01234         if (IntelRDrand64(rnd) == 0)
01235             return 0;
01236     }
01237     return -1;
01238 }
01239 
01240 /* return 0 on success */
01241 static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz)
01242 {
01243     int ret;
01244     word64 rndTmp;
01245 
01246     (void)os;
01247 
01248     if (!IS_INTEL_RDRAND(intel_flags))
01249         return -1;
01250 
01251     for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
01252                                                     output += sizeof(word64)) {
01253         ret = IntelRDrand64_r((word64 *)output);
01254         if (ret != 0)
01255             return ret;
01256     }
01257     if (sz == 0)
01258         return 0;
01259 
01260     /* handle unaligned remainder */
01261     ret = IntelRDrand64_r(&rndTmp);
01262     if (ret != 0)
01263         return ret;
01264 
01265     XMEMCPY(output, &rndTmp, sz);
01266 
01267     return 0;
01268 }
01269 
01270 #endif /* HAVE_INTEL_RDRAND */
01271 #endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED */
01272 
01273 
01274 /* Begin wc_GenerateSeed Implementations */
01275 #if defined(CUSTOM_RAND_GENERATE_SEED)
01276 
01277     /* Implement your own random generation function
01278      * Return 0 to indicate success
01279      * int rand_gen_seed(byte* output, word32 sz);
01280      * #define CUSTOM_RAND_GENERATE_SEED  rand_gen_seed */
01281 
01282     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01283     {
01284         (void)os; /* Suppress unused arg warning */
01285         return CUSTOM_RAND_GENERATE_SEED(output, sz);
01286     }
01287 
01288 #elif defined(CUSTOM_RAND_GENERATE_SEED_OS)
01289 
01290     /* Implement your own random generation function,
01291      *  which includes OS_Seed.
01292      * Return 0 to indicate success
01293      * int rand_gen_seed(OS_Seed* os, byte* output, word32 sz);
01294      * #define CUSTOM_RAND_GENERATE_SEED_OS  rand_gen_seed */
01295 
01296     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01297     {
01298         return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz);
01299     }
01300 
01301 #elif defined(CUSTOM_RAND_GENERATE)
01302 
01303    /* Implement your own random generation function
01304     * word32 rand_gen(void);
01305     * #define CUSTOM_RAND_GENERATE  rand_gen  */
01306 
01307     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01308     {
01309         word32 i = 0;
01310 
01311         (void)os;
01312 
01313         while (i < sz)
01314         {
01315             /* If not aligned or there is odd/remainder */
01316             if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz ||
01317                 ((wolfssl_word)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0
01318             ) {
01319                 /* Single byte at a time */
01320                 output[i++] = (byte)CUSTOM_RAND_GENERATE();
01321             }
01322             else {
01323                 /* Use native 8, 16, 32 or 64 copy instruction */
01324                 *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE();
01325                 i += sizeof(CUSTOM_RAND_TYPE);
01326             }
01327         }
01328 
01329         return 0;
01330     }
01331 
01332 #elif defined(WOLFSSL_SGX)
01333 
01334 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01335 {
01336     int ret = !SGX_SUCCESS;
01337     int i, read_max = 10;
01338 
01339     for (i = 0; i < read_max && ret != SGX_SUCCESS; i++) {
01340         ret = sgx_read_rand(output, sz);
01341     }
01342 
01343     (void)os;
01344     return (ret == SGX_SUCCESS) ? 0 : 1;
01345 }
01346 
01347 #elif defined(USE_WINDOWS_API)
01348 
01349 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01350 {
01351     if(!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
01352                             CRYPT_VERIFYCONTEXT))
01353         return WINCRYPT_E;
01354 
01355     if (!CryptGenRandom(os->handle, sz, output))
01356         return CRYPTGEN_E;
01357 
01358     CryptReleaseContext(os->handle, 0);
01359 
01360     return 0;
01361 }
01362 
01363 
01364 #elif defined(HAVE_RTP_SYS) || defined(EBSNET)
01365 
01366 #include "rtprand.h"   /* rtp_rand () */
01367 #include "rtptime.h"   /* rtp_get_system_msec() */
01368 
01369 
01370 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01371 {
01372     int i;
01373     rtp_srand(rtp_get_system_msec());
01374 
01375     for (i = 0; i < sz; i++ ) {
01376         output[i] = rtp_rand() % 256;
01377         if ( (i % 8) == 7)
01378             rtp_srand(rtp_get_system_msec());
01379     }
01380 
01381     return 0;
01382 }
01383 
01384 
01385 #elif defined(MICROCHIP_PIC32)
01386 
01387     #ifdef MICROCHIP_MPLAB_HARMONY
01388         #define PIC32_SEED_COUNT _CP0_GET_COUNT
01389     #else
01390         #if !defined(WOLFSSL_MICROCHIP_PIC32MZ)
01391             #include <peripheral/timer.h>
01392         #endif
01393         extern word32 ReadCoreTimer(void);
01394         #define PIC32_SEED_COUNT ReadCoreTimer
01395     #endif
01396 
01397     #ifdef WOLFSSL_PIC32MZ_RNG
01398         #include "xc.h"
01399         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01400         {
01401             int i;
01402             byte rnd[8];
01403             word32 *rnd32 = (word32 *)rnd;
01404             word32 size = sz;
01405             byte* op = output;
01406 
01407 #if ((__PIC32_FEATURE_SET0 == 'E') && (__PIC32_FEATURE_SET1 == 'C'))
01408             RNGNUMGEN1 = _CP0_GET_COUNT();
01409             RNGPOLY1 = _CP0_GET_COUNT();
01410             RNGPOLY2 = _CP0_GET_COUNT();
01411             RNGNUMGEN2 = _CP0_GET_COUNT();
01412 #else
01413             // All others can be seeded from the TRNG
01414             RNGCONbits.TRNGMODE = 1;
01415             RNGCONbits.TRNGEN = 1;
01416             while (RNGCNT < 64);
01417             RNGCONbits.LOAD = 1;
01418             while (RNGCONbits.LOAD == 1);
01419             while (RNGCNT < 64);
01420             RNGPOLY2 = RNGSEED2;
01421             RNGPOLY1 = RNGSEED1;
01422 #endif
01423 
01424             RNGCONbits.PLEN = 0x40;
01425             RNGCONbits.PRNGEN = 1;
01426             for (i=0; i<5; i++) { /* wait for RNGNUMGEN ready */
01427                 volatile int x;
01428                 x = RNGNUMGEN1;
01429                 x = RNGNUMGEN2;
01430                 (void)x;
01431             }
01432             do {
01433                 rnd32[0] = RNGNUMGEN1;
01434                 rnd32[1] = RNGNUMGEN2;
01435 
01436                 for(i=0; i<8; i++, op++) {
01437                     *op = rnd[i];
01438                     size --;
01439                     if(size==0)break;
01440                 }
01441             } while(size);
01442             return 0;
01443         }
01444     #else  /* WOLFSSL_PIC32MZ_RNG */
01445         /* uses the core timer, in nanoseconds to seed srand */
01446         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01447         {
01448             int i;
01449             srand(PIC32_SEED_COUNT() * 25);
01450 
01451             for (i = 0; i < sz; i++ ) {
01452                 output[i] = rand() % 256;
01453                 if ( (i % 8) == 7)
01454                     srand(PIC32_SEED_COUNT() * 25);
01455             }
01456             return 0;
01457         }
01458     #endif /* WOLFSSL_PIC32MZ_RNG */
01459 
01460 #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \
01461       defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS)
01462 
01463     #if defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA)
01464         /*
01465          * wc_Generates a RNG seed using the Random Number Generator Accelerator
01466          * on the Kinetis K70. Documentation located in Chapter 37 of
01467          * K70 Sub-Family Reference Manual (see Note 3 in the README for link).
01468          */
01469         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01470         {
01471             word32 i;
01472 
01473             /* turn on RNGA module */
01474             #if defined(SIM_SCGC3_RNGA_MASK)
01475                 SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK;
01476             #endif
01477             #if defined(SIM_SCGC6_RNGA_MASK)
01478                 /* additionally needed for at least K64F */
01479                 SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK;
01480             #endif
01481 
01482             /* set SLP bit to 0 - "RNGA is not in sleep mode" */
01483             RNG_CR &= ~RNG_CR_SLP_MASK;
01484 
01485             /* set HA bit to 1 - "security violations masked" */
01486             RNG_CR |= RNG_CR_HA_MASK;
01487 
01488             /* set GO bit to 1 - "output register loaded with data" */
01489             RNG_CR |= RNG_CR_GO_MASK;
01490 
01491             for (i = 0; i < sz; i++) {
01492 
01493                 /* wait for RNG FIFO to be full */
01494                 while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {}
01495 
01496                 /* get value */
01497                 output[i] = RNG_OR;
01498             }
01499 
01500             return 0;
01501         }
01502 
01503     #elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB)
01504         /*
01505          * wc_Generates a RNG seed using the Random Number Generator (RNGB)
01506          * on the Kinetis K53. Documentation located in Chapter 33 of
01507          * K53 Sub-Family Reference Manual (see note in the README for link).
01508          */
01509         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01510         {
01511             int i;
01512 
01513             /* turn on RNGB module */
01514             SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK;
01515 
01516             /* reset RNGB */
01517             RNG_CMD |= RNG_CMD_SR_MASK;
01518 
01519             /* FIFO generate interrupt, return all zeros on underflow,
01520              * set auto reseed */
01521             RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK);
01522 
01523             /* gen seed, clear interrupts, clear errors */
01524             RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK);
01525 
01526             /* wait for seeding to complete */
01527             while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {}
01528 
01529             for (i = 0; i < sz; i++) {
01530 
01531                 /* wait for a word to be available from FIFO */
01532                 while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {}
01533 
01534                 /* get value */
01535                 output[i] = RNG_OUT;
01536             }
01537 
01538             return 0;
01539         }
01540 
01541     #elif defined(FREESCALE_KSDK_2_0_TRNG)
01542 
01543         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01544         {
01545             status_t status;
01546             status = TRNG_GetRandomData(TRNG0, output, sz);
01547             if (status == kStatus_Success)
01548             {
01549                 return(0);
01550             }
01551             else
01552             {
01553                 return RAN_BLOCK_E;
01554             }
01555         }
01556 
01557     #elif defined(FREESCALE_KSDK_2_0_RNGA)
01558 
01559         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01560         {
01561             status_t status;
01562             status = RNGA_GetRandomData(RNG, output, sz);
01563             if (status == kStatus_Success)
01564             {
01565                 return(0);
01566             }
01567             else
01568             {
01569                 return RAN_BLOCK_E;
01570             }
01571         }
01572 
01573 
01574     #elif defined(FREESCALE_RNGA)
01575 
01576         int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01577         {
01578             RNGA_DRV_GetRandomData(RNGA_INSTANCE, output, sz);
01579             return 0;
01580         }
01581 
01582     #else
01583         #define USE_TEST_GENSEED
01584     #endif /* FREESCALE_K70_RNGA */
01585 
01586 #elif defined(STM32_RNG)
01587      /* Generate a RNG seed using the hardware random number generator
01588       * on the STM32F2/F4/F7. */
01589 
01590     #ifdef WOLFSSL_STM32_CUBEMX
01591     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01592     {
01593         RNG_HandleTypeDef hrng;
01594         int i;
01595         (void)os;
01596 
01597         /* enable RNG clock source */
01598         __HAL_RCC_RNG_CLK_ENABLE();
01599 
01600         /* enable RNG peripheral */
01601         hrng.Instance = RNG;
01602         HAL_RNG_Init(&hrng);
01603 
01604         for (i = 0; i < (int)sz; i++) {
01605             /* get value */
01606             output[i] = (byte)HAL_RNG_GetRandomNumber(&hrng);
01607         }
01608 
01609         return 0;
01610     }
01611     #elif defined(WOLFSSL_STM32F427_RNG)
01612 
01613     /* Generate a RNG seed using the hardware RNG on the STM32F427
01614      * directly, following steps outlined in STM32F4 Reference
01615      * Manual (Chapter 24) for STM32F4xx family. */
01616     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01617     {
01618         int i;
01619         (void)os;
01620 
01621         /* enable RNG interrupt, set IE bit in RNG->CR register */
01622         RNG->CR |= RNG_CR_IE;
01623 
01624         /* enable RNG, set RNGEN bit in RNG->CR. Activates RNG,
01625          * RNG_LFSR, and error detector */
01626         RNG->CR |= RNG_CR_RNGEN;
01627 
01628         /* verify no errors, make sure SEIS and CEIS bits are 0
01629          * in RNG->SR register */
01630         if (RNG->SR & (RNG_SR_SECS | RNG_SR_CECS))
01631             return RNG_FAILURE_E;
01632 
01633         for (i = 0; i < (int)sz; i++) {
01634             /* wait until RNG number is ready */
01635             while ((RNG->SR & RNG_SR_DRDY) == 0) { }
01636 
01637             /* get value */
01638             output[i] = RNG->DR;
01639         }
01640 
01641         return 0;
01642     }
01643 
01644     #else
01645 
01646     /* Generate a RNG seed using the STM32 Standard Peripheral Library */
01647     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01648     {
01649         int i;
01650         (void)os;
01651 
01652         /* enable RNG clock source */
01653         RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
01654 
01655         /* reset RNG */
01656         RNG_DeInit();
01657 
01658         /* enable RNG peripheral */
01659         RNG_Cmd(ENABLE);
01660 
01661         /* verify no errors with RNG_CLK or Seed */
01662         if (RNG_GetFlagStatus(RNG_FLAG_SECS | RNG_FLAG_CECS) != RESET)
01663             return RNG_FAILURE_E;
01664 
01665         for (i = 0; i < (int)sz; i++) {
01666             /* wait until RNG number is ready */
01667             while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) { }
01668 
01669             /* get value */
01670             output[i] = RNG_GetRandomNumber();
01671         }
01672 
01673         return 0;
01674     }
01675     #endif /* WOLFSSL_STM32_CUBEMX */
01676 
01677 #elif defined(WOLFSSL_TIRTOS)
01678 
01679     #include <xdc/runtime/Timestamp.h>
01680     #include <stdlib.h>
01681     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01682     {
01683         int i;
01684         srand(xdc_runtime_Timestamp_get32());
01685 
01686         for (i = 0; i < sz; i++ ) {
01687             output[i] = rand() % 256;
01688             if ((i % 8) == 7) {
01689                 srand(xdc_runtime_Timestamp_get32());
01690             }
01691         }
01692 
01693         return 0;
01694     }
01695 
01696 #elif defined(WOLFSSL_PB)
01697 
01698     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01699     {
01700         word32 i;
01701         for (i = 0; i < sz; i++)
01702             output[i] = UTL_Rand();
01703 
01704         (void)os;
01705 
01706         return 0;
01707     }
01708 
01709 #elif defined(WOLFSSL_NUCLEUS)
01710 #include "nucleus.h"
01711 #include "kernel/plus_common.h"
01712 
01713 #warning "potential for not enough entropy, currently being used for testing"
01714 int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01715 {
01716     int i;
01717     srand(NU_Get_Time_Stamp());
01718 
01719     for (i = 0; i < sz; i++ ) {
01720         output[i] = rand() % 256;
01721         if ((i % 8) == 7) {
01722             srand(NU_Get_Time_Stamp());
01723         }
01724     }
01725 
01726     return 0;
01727 }
01728 #elif defined(WOLFSSL_VXWORKS)
01729 
01730     #include <randomNumGen.h>
01731 
01732     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) {
01733         STATUS        status;
01734 
01735         #ifdef VXWORKS_SIM
01736             /* cannot generate true entropy with VxWorks simulator */
01737             #warning "not enough entropy, simulator for testing only"
01738             int i = 0;
01739 
01740             for (i = 0; i < 1000; i++) {
01741                 randomAddTimeStamp();
01742             }
01743         #endif
01744 
01745         status = randBytes (output, sz);
01746         if (status == ERROR) {
01747             return RNG_FAILURE_E;
01748         }
01749 
01750         return 0;
01751     }
01752 
01753 #elif defined(WOLFSSL_NRF51)
01754     #include "app_error.h"
01755     #include "nrf_drv_rng.h"
01756     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01757     {
01758         int remaining = sz, length, pos = 0;
01759         uint8_t available;
01760         uint32_t err_code;
01761 
01762         (void)os;
01763 
01764         /* Make sure RNG is running */
01765         err_code = nrf_drv_rng_init(NULL);
01766         if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) {
01767             return -1;
01768         }
01769 
01770         while (remaining > 0) {
01771             err_code = nrf_drv_rng_bytes_available(&available);
01772             if (err_code == NRF_SUCCESS) {
01773                 length = (remaining < available) ? remaining : available;
01774                 if (length > 0) {
01775                     err_code = nrf_drv_rng_rand(&output[pos], length);
01776                     remaining -= length;
01777                     pos += length;
01778                 }
01779             }
01780 
01781             if (err_code != NRF_SUCCESS) {
01782                 break;
01783             }
01784         }
01785 
01786         return (err_code == NRF_SUCCESS) ? 0 : -1;
01787     }
01788 
01789 #elif defined(HAVE_WNR)
01790 
01791     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01792     {
01793         if (os == NULL || output == NULL || wnr_ctx == NULL ||
01794                 wnr_timeout < 0) {
01795             return BAD_FUNC_ARG;
01796         }
01797 
01798         if (wnr_mutex_init == 0) {
01799             WOLFSSL_MSG("netRandom context must be created before use");
01800             return RNG_FAILURE_E;
01801         }
01802 
01803         if (wc_LockMutex(&wnr_mutex) != 0) {
01804             WOLFSSL_MSG("Bad Lock Mutex wnr_mutex\n");
01805             return BAD_MUTEX_E;
01806         }
01807 
01808         if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) !=
01809                 WNR_ERROR_NONE)
01810             return RNG_FAILURE_E;
01811 
01812         wc_UnLockMutex(&wnr_mutex);
01813 
01814         return 0;
01815     }
01816 
01817 #elif defined(WOLFSSL_ATMEL)
01818     #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
01819 
01820     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01821     {
01822         int ret = 0;
01823 
01824         (void)os;
01825         if (output == NULL) {
01826             return BUFFER_E;
01827         }
01828 
01829         ret = atmel_get_random_number(sz, output);
01830 
01831         return ret;
01832     }
01833 
01834 #elif defined(INTIME_RTOS)
01835     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01836     {
01837         int ret = 0;
01838 
01839         (void)os;
01840 
01841         if (output == NULL) {
01842             return BUFFER_E;
01843         }
01844 
01845         /* Note: Investigate better solution */
01846         /* no return to check */
01847         arc4random_buf(output, sz);
01848 
01849         return ret;
01850     }
01851 
01852 #elif defined(IDIRECT_DEV_RANDOM)
01853 
01854     extern int getRandom( int sz, unsigned char *output );
01855 
01856     int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01857     {
01858         int num_bytes_returned = 0;
01859 
01860         num_bytes_returned = getRandom( (int) sz, (unsigned char *) output );
01861 
01862         return 0;
01863     }
01864 
01865 #elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG))
01866 
01867     #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
01868     #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
01869 
01870     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01871     {
01872         Buffer buf[1];
01873         int ret  = 0;
01874         int times = 1000, i;
01875 
01876         (void)os;
01877 
01878         if (output == NULL) {
01879             return BUFFER_E;
01880         }
01881 
01882         buf[0].BufferType = DataBuffer | LastBuffer;
01883         buf[0].TheAddress = (Address)output;
01884         buf[0].Length     = sz;
01885 
01886         /* Check Waiting to make sure entropy is ready */
01887         for (i = 0; i < times; i++) {
01888             ret = wc_caamAddAndWait(buf, NULL, CAAM_ENTROPY);
01889             if (ret == Success) {
01890                 break;
01891             }
01892 
01893             /* driver could be waiting for entropy */
01894             if (ret != RAN_BLOCK_E) {
01895                 return ret;
01896             }
01897             usleep(100);
01898         }
01899 
01900         if (i == times && ret != Success) {
01901              return RNG_FAILURE_E;
01902         }
01903         else { /* Success case */
01904             ret = 0;
01905         }
01906 
01907         return ret;
01908     }
01909 
01910 #elif defined(CUSTOM_RAND_GENERATE_BLOCK)
01911     /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
01912      * extern int myRngFunc(byte* output, word32 sz);
01913      */
01914 
01915 #elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \
01916       defined(WOLFSSL_IAR_ARM)  || defined(WOLFSSL_MDK_ARM) || \
01917       defined(WOLFSSL_uITRON4)  || defined(WOLFSSL_uTKERNEL2) || \
01918       defined(WOLFSSL_LPC43xx)  || defined(WOLFSSL_STM32F2xx) || \
01919       defined(MBED)             || defined(WOLFSSL_EMBOS) || \
01920       defined(WOLFSSL_GENSEED_FORTEST) || defined(WOLFSSL_CHIBIOS)
01921 
01922     /* these platforms do not have a default random seed and
01923        you'll need to implement your own wc_GenerateSeed or define via
01924        CUSTOM_RAND_GENERATE_BLOCK */
01925 
01926     #define USE_TEST_GENSEED
01927 
01928 #elif defined(NO_DEV_RANDOM)
01929 
01930     //#error "you need to write an os specific wc_GenerateSeed() here"
01931 
01932     
01933     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01934     {
01935         return 0;
01936     }
01937     
01938 
01939 #else
01940 
01941     /* may block */
01942     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
01943     {
01944         int ret = 0;
01945 
01946     #ifdef HAVE_INTEL_RDSEED
01947         if (IS_INTEL_RDSEED(intel_flags)) {
01948              ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
01949              if (ret == 0) {
01950                  /* success, we're done */
01951                  return ret;
01952              }
01953         #ifdef FORCE_FAILURE_RDSEED
01954              /* don't fallback to /dev/urandom */
01955              return ret;
01956         #else
01957              /* reset error and fallback to using /dev/urandom */
01958              ret = 0;
01959         #endif
01960         }
01961     #endif /* HAVE_INTEL_RDSEED */
01962 
01963     #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
01964         os->fd = open("/dev/urandom", O_RDONLY);
01965         if (os->fd == -1)
01966     #endif
01967         {
01968             /* may still have /dev/random */
01969             os->fd = open("/dev/random", O_RDONLY);
01970             if (os->fd == -1)
01971                 return OPEN_RAN_E;
01972         }
01973 
01974         while (sz) {
01975             int len = (int)read(os->fd, output, sz);
01976             if (len == -1) {
01977                 ret = READ_RAN_E;
01978                 break;
01979             }
01980 
01981             sz     -= len;
01982             output += len;
01983 
01984             if (sz) {
01985     #if defined(BLOCKING) || defined(WC_RNG_BLOCKING)
01986                 sleep(0);             /* context switch */
01987     #else
01988                 ret = RAN_BLOCK_E;
01989                 break;
01990     #endif
01991             }
01992         }
01993         close(os->fd);
01994 
01995         return ret;
01996     }
01997 
01998 #endif
01999 
02000 #ifdef USE_TEST_GENSEED
02001     #ifndef _MSC_VER
02002         #warning "write a real random seed!!!!, just for testing now"
02003     #else
02004         #pragma message("Warning: write a real random seed!!!!, just for testing now")
02005     #endif
02006 
02007     int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
02008     {
02009         word32 i;
02010         for (i = 0; i < sz; i++ )
02011             output[i] = i;
02012 
02013         (void)os;
02014 
02015         return 0;
02016     }
02017 #endif
02018 
02019 /* End wc_GenerateSeed */
02020 
02021 #endif /* WC_NO_RNG */
02022 #endif /* HAVE_FIPS */
02023