Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Jul 12 2022 16:58:06 by
1.7.2