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