Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers random.c Source File

random.c

00001 /* random.c
00002  *
00003  * Copyright (C) 2006-2016 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfssl/wolfcrypt/settings.h>
00028 
00029 /* on HPUX 11 you may need to install /dev/random see
00030    http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
00031 
00032 */
00033 
00034 #include <wolfssl/wolfcrypt/random.h>
00035 
00036 #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