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.
Fork of wolfSSL by
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
Generated on Tue Jul 12 2022 23:30:59 by
1.7.2
