wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

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