MultiTech / CyaSSL

Dependents:   HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers random.c Source File

random.c

00001 /* random.c
00002  *
00003  * Copyright (C) 2006-2014 wolfSSL Inc.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL 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  * CyaSSL 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-1301, USA
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023     #include <config.h>
00024 #endif
00025 
00026 #include <cyassl/ctaocrypt/settings.h>
00027 
00028 /* on HPUX 11 you may need to install /dev/random see
00029    http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
00030 
00031 */
00032 
00033 #ifdef HAVE_FIPS
00034     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
00035     #define FIPS_NO_WRAPPERS
00036 #endif
00037 
00038 #include <cyassl/ctaocrypt/random.h>
00039 #include <cyassl/ctaocrypt/error-crypt.h>
00040 
00041 #if defined(HAVE_HASHDRBG) || defined(NO_RC4)
00042 
00043     #include <cyassl/ctaocrypt/sha256.h>
00044 
00045     #ifdef NO_INLINE
00046         #include <cyassl/ctaocrypt/misc.h>
00047     #else
00048         #include <ctaocrypt/src/misc.c>
00049     #endif
00050 #endif /* HAVE_HASHDRBG || NO_RC4 */
00051 
00052 #if defined(USE_WINDOWS_API)
00053     #ifndef _WIN32_WINNT
00054         #define _WIN32_WINNT 0x0400
00055     #endif
00056     #include <windows.h>
00057     #include <wincrypt.h>
00058 #else
00059     #if !defined(NO_DEV_RANDOM) && !defined(CYASSL_MDK_ARM) \
00060                                 && !defined(CYASSL_IAR_ARM)
00061             #include <fcntl.h>
00062         #ifndef EBSNET
00063             #include <unistd.h>
00064         #endif
00065     #else
00066         /* include headers that may be needed to get good seed */
00067     #endif
00068 #endif /* USE_WINDOWS_API */
00069 
00070 
00071 #if defined(HAVE_HASHDRBG) || defined(NO_RC4)
00072 
00073 /* Start NIST DRBG code */
00074 
00075 #define OUTPUT_BLOCK_LEN  (SHA256_DIGEST_SIZE)
00076 #define MAX_REQUEST_LEN   (0x10000)
00077 #define RESEED_INTERVAL   (1000000)
00078 #define SECURITY_STRENGTH (256)
00079 #define ENTROPY_SZ        (SECURITY_STRENGTH/8)
00080 #define NONCE_SZ          (ENTROPY_SZ/2)
00081 #define ENTROPY_NONCE_SZ  (ENTROPY_SZ+NONCE_SZ)
00082 
00083 /* Internal return codes */
00084 #define DRBG_SUCCESS      0
00085 #define DRBG_ERROR        1
00086 #define DRBG_FAILURE      2
00087 #define DRBG_NEED_RESEED  3
00088 #define DRBG_CONT_FAILURE 4
00089 
00090 /* RNG health states */
00091 #define DRBG_NOT_INIT     0
00092 #define DRBG_OK           1
00093 #define DRBG_FAILED       2
00094 #define DRBG_CONT_FAILED  3
00095 
00096 
00097 enum {
00098     drbgInitC     = 0,
00099     drbgReseed    = 1,
00100     drbgGenerateW = 2,
00101     drbgGenerateH = 3,
00102     drbgInitV
00103 };
00104 
00105 
00106 typedef struct DRBG {
00107     Sha256 sha;
00108     byte digest[SHA256_DIGEST_SIZE];
00109     byte V[DRBG_SEED_LEN];
00110     byte C[DRBG_SEED_LEN];
00111     word32 reseedCtr;
00112     word32 lastBlock;
00113     byte   matchCount;
00114 } DRBG;
00115 
00116 
00117 /* Hash Derivation Function */
00118 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
00119 static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type,
00120                                                   const byte* inA, word32 inASz,
00121                                                   const byte* inB, word32 inBSz)
00122 {
00123     byte ctr;
00124     int i;
00125     int len;
00126     word32 bits = (outSz * 8); /* reverse byte order */
00127 
00128     #ifdef LITTLE_ENDIAN_ORDER
00129         bits = ByteReverseWord32(bits);
00130     #endif
00131     len = (outSz / OUTPUT_BLOCK_LEN)
00132         + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
00133 
00134     for (i = 0, ctr = 1; i < len; i++, ctr++)
00135     {
00136         if (InitSha256(&drbg->sha) != 0)
00137             return DRBG_FAILURE;
00138 
00139         if (Sha256Update(&drbg->sha, &ctr, sizeof(ctr)) != 0)
00140             return DRBG_FAILURE;
00141 
00142         if (Sha256Update(&drbg->sha, (byte*)&bits, sizeof(bits)) != 0)
00143             return DRBG_FAILURE;
00144 
00145         /* churning V is the only string that doesn't have 
00146          * the type added */
00147         if (type != drbgInitV)
00148             if (Sha256Update(&drbg->sha, &type, sizeof(type)) != 0)
00149                 return DRBG_FAILURE;
00150 
00151         if (Sha256Update(&drbg->sha, inA, inASz) != 0)
00152             return DRBG_FAILURE;
00153 
00154         if (inB != NULL && inBSz > 0)
00155             if (Sha256Update(&drbg->sha, inB, inBSz) != 0)
00156                 return DRBG_FAILURE;
00157 
00158         if (Sha256Final(&drbg->sha, drbg->digest) != 0)
00159             return DRBG_FAILURE;
00160 
00161         if (outSz > OUTPUT_BLOCK_LEN) {
00162             XMEMCPY(out, drbg->digest, OUTPUT_BLOCK_LEN);
00163             outSz -= OUTPUT_BLOCK_LEN;
00164             out += OUTPUT_BLOCK_LEN;
00165         }
00166         else {
00167             XMEMCPY(out, drbg->digest, outSz);
00168         }
00169     }
00170 
00171     return DRBG_SUCCESS;
00172 }
00173 
00174 
00175 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
00176 static int Hash_DRBG_Reseed(DRBG* drbg, const byte* entropy, word32 entropySz)
00177 {
00178     byte seed[DRBG_SEED_LEN];
00179 
00180     if (Hash_df(drbg, seed, sizeof(seed), drbgReseed, drbg->V, sizeof(drbg->V),
00181                                           entropy, entropySz) != DRBG_SUCCESS) {
00182         return DRBG_FAILURE;
00183     }
00184 
00185     XMEMCPY(drbg->V, seed, sizeof(drbg->V));
00186     XMEMSET(seed, 0, sizeof(seed));
00187 
00188     if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
00189                                     sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) {
00190         return DRBG_FAILURE;
00191     }
00192 
00193     drbg->reseedCtr = 1;
00194     drbg->lastBlock = 0;
00195     drbg->matchCount = 0;
00196     return DRBG_SUCCESS;
00197 }
00198 
00199 static INLINE void array_add_one(byte* data, word32 dataSz)
00200 {
00201     int i;
00202 
00203     for (i = dataSz - 1; i >= 0; i--)
00204     {
00205         data[i]++;
00206         if (data[i] != 0) break;
00207     }
00208 }
00209 
00210 
00211 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
00212 static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V)
00213 {
00214     byte data[DRBG_SEED_LEN];
00215     int i;
00216     int len;
00217     word32 checkBlock;
00218 
00219     /* Special case: outSz is 0 and out is NULL. Generate a block to save for
00220      * the continuous test. */
00221 
00222     if (outSz == 0) outSz = 1;
00223 
00224     len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
00225 
00226     XMEMCPY(data, V, sizeof(data));
00227     for (i = 0; i < len; i++) {
00228         if (InitSha256(&drbg->sha) != 0 ||
00229             Sha256Update(&drbg->sha, data, sizeof(data)) != 0 ||
00230             Sha256Final(&drbg->sha, drbg->digest) != 0) {
00231 
00232             return DRBG_FAILURE;
00233         }
00234 
00235         checkBlock = *(word32*)drbg->digest;
00236         if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) {
00237             if (drbg->matchCount == 1) {
00238                 return DRBG_CONT_FAILURE;
00239             }
00240             else {
00241                 if (i == len) {
00242                     len++;
00243                 }
00244                 drbg->matchCount = 1;
00245             }
00246         }
00247         else {
00248             drbg->matchCount = 0;
00249             drbg->lastBlock = checkBlock;
00250         }
00251 
00252         if (outSz >= OUTPUT_BLOCK_LEN) {
00253             XMEMCPY(out, drbg->digest, OUTPUT_BLOCK_LEN);
00254             outSz -= OUTPUT_BLOCK_LEN;
00255             out += OUTPUT_BLOCK_LEN;
00256             array_add_one(data, DRBG_SEED_LEN);
00257         }
00258         else if (out != NULL && outSz != 0) {
00259             XMEMCPY(out, drbg->digest, outSz);
00260             outSz = 0;
00261         }
00262     }
00263     XMEMSET(data, 0, sizeof(data));
00264 
00265     return DRBG_SUCCESS;
00266 }
00267 
00268 
00269 static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
00270 {
00271     word16 carry = 0;
00272 
00273     if (dLen > 0 && sLen > 0 && dLen >= sLen) {
00274         int sIdx, dIdx;
00275 
00276         for (sIdx = sLen - 1, dIdx = dLen - 1; sIdx >= 0; dIdx--, sIdx--)
00277         {
00278             carry += d[dIdx] + s[sIdx];
00279             d[dIdx] = carry;
00280             carry >>= 8;
00281         }
00282 
00283         for (; carry != 0 && dIdx >= 0; dIdx--) {
00284             carry += d[dIdx];
00285             d[dIdx] = carry;
00286             carry >>= 8;
00287         }
00288     }
00289 }
00290 
00291 
00292 /* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */
00293 static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz)
00294 {
00295     int ret = DRBG_NEED_RESEED;
00296 
00297     if (drbg->reseedCtr != RESEED_INTERVAL) {
00298         byte type = drbgGenerateH;
00299         word32 reseedCtr = drbg->reseedCtr;
00300 
00301         ret = Hash_gen(drbg, out, outSz, drbg->V);
00302         if (ret == DRBG_SUCCESS) {
00303             if (InitSha256(&drbg->sha) != 0 ||
00304                 Sha256Update(&drbg->sha, &type, sizeof(type)) != 0 ||
00305                 Sha256Update(&drbg->sha, drbg->V, sizeof(drbg->V)) != 0 ||
00306                 Sha256Final(&drbg->sha, drbg->digest) != 0) {
00307 
00308                 ret = DRBG_FAILURE;
00309             }
00310             else {
00311                 array_add(drbg->V, sizeof(drbg->V),
00312                                             drbg->digest, sizeof(drbg->digest));
00313                 array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
00314                 #ifdef LITTLE_ENDIAN_ORDER
00315                     reseedCtr = ByteReverseWord32(reseedCtr);
00316                 #endif
00317                 array_add(drbg->V, sizeof(drbg->V),
00318                                           (byte*)&reseedCtr, sizeof(reseedCtr));
00319                 ret = DRBG_SUCCESS;
00320             }
00321             drbg->reseedCtr++;
00322         }
00323     }
00324 
00325     return ret;
00326 }
00327 
00328 
00329 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
00330 static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz,
00331                                              const byte* nonce, word32 nonceSz)
00332 {
00333     int ret = DRBG_FAILURE;
00334 
00335     XMEMSET(drbg, 0, sizeof(DRBG));
00336 
00337     if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
00338                                               nonce, nonceSz) == DRBG_SUCCESS &&
00339         Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
00340                                     sizeof(drbg->V), NULL, 0) == DRBG_SUCCESS) {
00341 
00342         drbg->reseedCtr = 1;
00343         drbg->lastBlock = 0;
00344         drbg->matchCount = 0;
00345         ret = DRBG_SUCCESS;
00346     }
00347 
00348     return ret;
00349 }
00350 
00351 
00352 /* Returns: DRBG_SUCCESS */
00353 static int Hash_DRBG_Uninstantiate(DRBG* drbg)
00354 {
00355     XMEMSET(drbg, 0, sizeof(DRBG));
00356 
00357     return DRBG_SUCCESS;
00358 }
00359 
00360 /* End NIST DRBG Code */
00361 
00362 
00363 /* Get seed and key cipher */
00364 int InitRng(RNG* rng)
00365 {
00366     int ret = BAD_FUNC_ARG;
00367 
00368     if (rng != NULL) {
00369         byte entropy[ENTROPY_NONCE_SZ];
00370 
00371         rng->drbg = (struct DRBG*)XMALLOC(sizeof(DRBG), NULL, DYNAMIC_TYPE_RNG);
00372         if (rng->drbg == NULL) {
00373             ret = MEMORY_E;
00374         }
00375         /* This doesn't use a separate nonce. The entropy input will be
00376          * the default size plus the size of the nonce making the seed
00377          * size. */
00378         else if (GenerateSeed(&rng->seed, entropy, ENTROPY_NONCE_SZ) == 0 &&
00379                  Hash_DRBG_Instantiate(rng->drbg, entropy, ENTROPY_NONCE_SZ,
00380                                                      NULL, 0) == DRBG_SUCCESS) {
00381 
00382             ret = Hash_DRBG_Generate(rng->drbg, NULL, 0);
00383         }
00384         else
00385             ret = DRBG_FAILURE;
00386 
00387         XMEMSET(entropy, 0, ENTROPY_NONCE_SZ);
00388 
00389         if (ret == DRBG_SUCCESS) {
00390             rng->status = DRBG_OK;
00391             ret = 0;
00392         }
00393         else if (ret == DRBG_CONT_FAILURE) {
00394             rng->status = DRBG_CONT_FAILED;
00395             ret = DRBG_CONT_FIPS_E;
00396         }
00397         else if (ret == DRBG_FAILURE) {
00398             rng->status = DRBG_FAILED;
00399             ret = RNG_FAILURE_E;
00400         }
00401         else {
00402             rng->status = DRBG_FAILED;
00403         }
00404     }
00405 
00406     return ret;
00407 }
00408 
00409 
00410 /* place a generated block in output */
00411 int RNG_GenerateBlock(RNG* rng, byte* output, word32 sz)
00412 {
00413     int ret;
00414 
00415     if (rng == NULL || output == NULL || sz > MAX_REQUEST_LEN)
00416         return BAD_FUNC_ARG;
00417 
00418     if (rng->status != DRBG_OK)
00419         return RNG_FAILURE_E;
00420 
00421     ret = Hash_DRBG_Generate(rng->drbg, output, sz);
00422 
00423     if (ret == DRBG_NEED_RESEED) {
00424         byte entropy[ENTROPY_SZ];
00425 
00426         if (GenerateSeed(&rng->seed, entropy, ENTROPY_SZ) == 0 &&
00427             Hash_DRBG_Reseed(rng->drbg, entropy, ENTROPY_SZ) == DRBG_SUCCESS) {
00428 
00429             ret = Hash_DRBG_Generate(rng->drbg, NULL, 0);
00430             if (ret == DRBG_SUCCESS)
00431                 ret = Hash_DRBG_Generate(rng->drbg, output, sz);
00432         }
00433         else
00434             ret = DRBG_FAILURE;
00435 
00436         XMEMSET(entropy, 0, ENTROPY_SZ);
00437     }
00438 
00439     if (ret == DRBG_SUCCESS) {
00440         ret = 0;
00441     }
00442     else if (ret == DRBG_CONT_FAILURE) {
00443         ret = DRBG_CONT_FIPS_E;
00444         rng->status = DRBG_CONT_FAILED;
00445     }
00446     else {
00447         ret = RNG_FAILURE_E;
00448         rng->status = DRBG_FAILED;
00449     }
00450 
00451     return ret;
00452 }
00453 
00454 
00455 int RNG_GenerateByte(RNG* rng, byte* b)
00456 {
00457     return RNG_GenerateBlock(rng, b, 1);
00458 }
00459 
00460 
00461 int FreeRng(RNG* rng)
00462 {
00463     int ret = BAD_FUNC_ARG;
00464 
00465     if (rng != NULL) {
00466         if (Hash_DRBG_Uninstantiate(rng->drbg) == DRBG_SUCCESS)
00467             ret = 0;
00468         else
00469             ret = RNG_FAILURE_E;
00470 
00471         XFREE(rng->drbg, NULL, DYNAMIC_TYPE_RNG);
00472         rng->drbg = NULL;
00473         rng->status = DRBG_NOT_INIT;
00474     }
00475 
00476     return ret;
00477 }
00478 
00479 
00480 int RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz,
00481                                const byte* entropyB, word32 entropyBSz,
00482                                byte* output, word32 outputSz)
00483 {
00484     DRBG drbg;
00485 
00486     if (entropyA == NULL || output == NULL)
00487         return BAD_FUNC_ARG;
00488 
00489     if (reseed != 0 && entropyB == NULL)
00490         return BAD_FUNC_ARG;
00491 
00492     if (outputSz != (SHA256_DIGEST_SIZE * 4))
00493         return -1;
00494 
00495     if (Hash_DRBG_Instantiate(&drbg, entropyA, entropyASz, NULL, 0) != 0)
00496         return -1;
00497 
00498     if (reseed) {
00499         if (Hash_DRBG_Reseed(&drbg, entropyB, entropyBSz) != 0) {
00500             Hash_DRBG_Uninstantiate(&drbg);
00501             return -1;
00502         }
00503     }
00504 
00505     if (Hash_DRBG_Generate(&drbg, output, outputSz) != 0) {
00506         Hash_DRBG_Uninstantiate(&drbg);
00507         return -1;
00508     }
00509 
00510     if (Hash_DRBG_Generate(&drbg, output, outputSz) != 0) {
00511         Hash_DRBG_Uninstantiate(&drbg);
00512         return -1;
00513     }
00514 
00515     Hash_DRBG_Uninstantiate(&drbg);
00516 
00517     return 0;
00518 }
00519 
00520 
00521 #else /* HAVE_HASHDRBG || NO_RC4 */
00522 
00523 /* Get seed and key cipher */
00524 int InitRng(RNG* rng)
00525 {
00526     int  ret;
00527 #ifdef CYASSL_SMALL_STACK
00528     byte* key;
00529     byte* junk;
00530 #else
00531     byte key[32];
00532     byte junk[256];
00533 #endif
00534 
00535 #ifdef HAVE_CAVIUM
00536     if (rng->magic == CYASSL_RNG_CAVIUM_MAGIC)
00537         return 0;
00538 #endif
00539 
00540 #ifdef CYASSL_SMALL_STACK
00541     key = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00542     if (key == NULL)
00543         return MEMORY_E;
00544 
00545     junk = (byte*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00546     if (junk == NULL) {
00547         XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00548         return MEMORY_E;
00549     }
00550 #endif
00551 
00552     ret = GenerateSeed(&rng->seed, key, 32);
00553 
00554     if (ret == 0) {
00555         Arc4SetKey(&rng->cipher, key, sizeof(key));
00556 
00557         ret = RNG_GenerateBlock(rng, junk, 256); /*rid initial state*/
00558     }
00559 
00560 #ifdef CYASSL_SMALL_STACK
00561     XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00562     XFREE(junk, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00563 #endif
00564 
00565     return ret;
00566 }
00567 
00568 #ifdef HAVE_CAVIUM
00569     static void CaviumRNG_GenerateBlock(RNG* rng, byte* output, word32 sz);
00570 #endif
00571 
00572 /* place a generated block in output */
00573 int RNG_GenerateBlock(RNG* rng, byte* output, word32 sz)
00574 {
00575 #ifdef HAVE_CAVIUM
00576     if (rng->magic == CYASSL_RNG_CAVIUM_MAGIC)
00577         return CaviumRNG_GenerateBlock(rng, output, sz);
00578 #endif
00579     XMEMSET(output, 0, sz);
00580     Arc4Process(&rng->cipher, output, output, sz);
00581 
00582     return 0;
00583 }
00584 
00585 
00586 int RNG_GenerateByte(RNG* rng, byte* b)
00587 {
00588     return RNG_GenerateBlock(rng, b, 1);
00589 }
00590 
00591 
00592 #ifdef HAVE_CAVIUM
00593 
00594 #include <cyassl/ctaocrypt/logging.h>
00595 #include "cavium_common.h"
00596 
00597 /* Initiliaze RNG for use with Nitrox device */
00598 int InitRngCavium(RNG* rng, int devId)
00599 {
00600     if (rng == NULL)
00601         return -1;
00602 
00603     rng->devId = devId;
00604     rng->magic = CYASSL_RNG_CAVIUM_MAGIC;
00605 
00606     return 0;
00607 }
00608 
00609 
00610 static void CaviumRNG_GenerateBlock(RNG* rng, byte* output, word32 sz)
00611 {
00612     cyassl_word offset = 0;
00613     word32      requestId;
00614 
00615     while (sz > CYASSL_MAX_16BIT) {
00616         word16 slen = (word16)CYASSL_MAX_16BIT;
00617         if (CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId,
00618                       rng->devId) != 0) {
00619             CYASSL_MSG("Cavium RNG failed");
00620         }
00621         sz     -= CYASSL_MAX_16BIT;
00622         offset += CYASSL_MAX_16BIT;
00623     }
00624     if (sz) {
00625         word16 slen = (word16)sz;
00626         if (CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId,
00627                       rng->devId) != 0) {
00628             CYASSL_MSG("Cavium RNG failed");
00629         }
00630     }
00631 }
00632 
00633 #endif /* HAVE_CAVIUM */
00634 
00635 #endif /* HAVE_HASHDRBG || NO_RC4 */
00636 
00637 
00638 #if defined(USE_WINDOWS_API)
00639 
00640 
00641 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00642 {
00643     if(!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
00644                             CRYPT_VERIFYCONTEXT))
00645         return WINCRYPT_E;
00646 
00647     if (!CryptGenRandom(os->handle, sz, output))
00648         return CRYPTGEN_E;
00649 
00650     CryptReleaseContext(os->handle, 0);
00651 
00652     return 0;
00653 }
00654 
00655 
00656 #elif defined(HAVE_RTP_SYS) || defined(EBSNET)
00657 
00658 #include "rtprand.h"   /* rtp_rand () */
00659 #include "rtptime.h"   /* rtp_get_system_msec() */
00660 
00661 
00662 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00663 {
00664     int i;
00665     rtp_srand(rtp_get_system_msec());
00666 
00667     for (i = 0; i < sz; i++ ) {
00668         output[i] = rtp_rand() % 256;
00669         if ( (i % 8) == 7)
00670             rtp_srand(rtp_get_system_msec());
00671     }
00672 
00673     return 0;
00674 }
00675 
00676 
00677 #elif defined(MICRIUM)
00678 
00679 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00680 {
00681     #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
00682         NetSecure_InitSeed(output, sz);
00683     #endif
00684     return 0;
00685 }
00686 
00687 #elif defined(MBED)
00688 
00689 /* write a real one !!!, just for testing board */
00690 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00691 {
00692     int i;
00693     for (i = 0; i < sz; i++ )
00694         output[i] = i;
00695 
00696     return 0;
00697 }
00698 
00699 #elif defined(MICROCHIP_PIC32)
00700 
00701 #ifdef MICROCHIP_MPLAB_HARMONY
00702     #define PIC32_SEED_COUNT _CP0_GET_COUNT
00703 #else
00704     #if !defined(CYASSL_MICROCHIP_PIC32MZ)
00705         #include <peripheral/timer.h>
00706     #endif
00707     #define PIC32_SEED_COUNT ReadCoreTimer
00708 #endif
00709     #ifdef CYASSL_MIC32MZ_RNG
00710         #include "xc.h"
00711         int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00712         {
00713             int i ;
00714             byte rnd[8] ;
00715             word32 *rnd32 = (word32 *)rnd ;
00716             word32 size = sz ;
00717             byte* op = output ;
00718 
00719             /* This part has to be replaced with better random seed */
00720             RNGNUMGEN1 = ReadCoreTimer();
00721             RNGPOLY1 = ReadCoreTimer();
00722             RNGPOLY2 = ReadCoreTimer();
00723             RNGNUMGEN2 = ReadCoreTimer();
00724 #ifdef DEBUG_CYASSL
00725             printf("GenerateSeed::Seed=%08x, %08x\n", RNGNUMGEN1, RNGNUMGEN2) ;
00726 #endif
00727             RNGCONbits.PLEN = 0x40;
00728             RNGCONbits.PRNGEN = 1;
00729             for(i=0; i<5; i++) { /* wait for RNGNUMGEN ready */
00730                 volatile int x ;
00731                 x = RNGNUMGEN1 ;
00732                 x = RNGNUMGEN2 ;
00733             }
00734             do {
00735                 rnd32[0] = RNGNUMGEN1;
00736                 rnd32[1] = RNGNUMGEN2;
00737 
00738                 for(i=0; i<8; i++, op++) {
00739                     *op = rnd[i] ;
00740                     size -- ;
00741                     if(size==0)break ;
00742                 }
00743             } while(size) ;
00744             return 0;
00745         }
00746     #else  /* CYASSL_MIC32MZ_RNG */
00747         /* uses the core timer, in nanoseconds to seed srand */
00748         int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00749         {
00750             int i;
00751             srand(PIC32_SEED_COUNT() * 25);
00752 
00753             for (i = 0; i < sz; i++ ) {
00754                 output[i] = rand() % 256;
00755                 if ( (i % 8) == 7)
00756                     srand(PIC32_SEED_COUNT() * 25);
00757             }
00758             return 0;
00759         }
00760     #endif /* CYASSL_MIC32MZ_RNG */
00761 
00762 #elif defined(FREESCALE_MQX)
00763 
00764     #ifdef FREESCALE_K70_RNGA
00765         /*
00766          * Generates a RNG seed using the Random Number Generator Accelerator
00767          * on the Kinetis K70. Documentation located in Chapter 37 of
00768          * K70 Sub-Family Reference Manual (see Note 3 in the README for link).
00769          */
00770         int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00771         {
00772             int i;
00773 
00774             /* turn on RNGA module */
00775             SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK;
00776 
00777             /* set SLP bit to 0 - "RNGA is not in sleep mode" */
00778             RNG_CR &= ~RNG_CR_SLP_MASK;
00779 
00780             /* set HA bit to 1 - "security violations masked" */
00781             RNG_CR |= RNG_CR_HA_MASK;
00782 
00783             /* set GO bit to 1 - "output register loaded with data" */
00784             RNG_CR |= RNG_CR_GO_MASK;
00785 
00786             for (i = 0; i < sz; i++) {
00787 
00788                 /* wait for RNG FIFO to be full */
00789                 while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {}
00790 
00791                 /* get value */
00792                 output[i] = RNG_OR;
00793             }
00794 
00795             return 0;
00796         }
00797 
00798     #elif defined(FREESCALE_K53_RNGB)
00799         /*
00800          * Generates a RNG seed using the Random Number Generator (RNGB)
00801          * on the Kinetis K53. Documentation located in Chapter 33 of
00802          * K53 Sub-Family Reference Manual (see note in the README for link).
00803          */
00804         int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00805         {
00806             int i;
00807 
00808             /* turn on RNGB module */
00809             SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK;
00810 
00811             /* reset RNGB */
00812             RNG_CMD |= RNG_CMD_SR_MASK;
00813 
00814             /* FIFO generate interrupt, return all zeros on underflow,
00815              * set auto reseed */
00816             RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK);
00817 
00818             /* gen seed, clear interrupts, clear errors */
00819             RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK);
00820 
00821             /* wait for seeding to complete */
00822             while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {}
00823 
00824             for (i = 0; i < sz; i++) {
00825 
00826                 /* wait for a word to be available from FIFO */
00827                 while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {}
00828 
00829                 /* get value */
00830                 output[i] = RNG_OUT;
00831             }
00832 
00833             return 0;
00834         }
00835 
00836     #else
00837         #warning "write a real random seed!!!!, just for testing now"
00838 
00839         int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00840         {
00841             int i;
00842             for (i = 0; i < sz; i++ )
00843                 output[i] = i;
00844 
00845             return 0;
00846         }
00847     #endif /* FREESCALE_K70_RNGA */
00848 
00849 #elif defined(CYASSL_SAFERTOS) || defined(CYASSL_LEANPSK) \
00850    || defined(CYASSL_IAR_ARM)  || defined(CYASSL_MDK_ARM)
00851 
00852 #warning "write a real random seed!!!!, just for testing now"
00853 
00854 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00855 {
00856     word32 i;
00857     for (i = 0; i < sz; i++ )
00858         output[i] = i;
00859 
00860     (void)os;
00861 
00862     return 0;
00863 }
00864 
00865 #elif defined(STM32F2_RNG)
00866     #undef RNG
00867     #include "stm32f2xx_rng.h"
00868     #include "stm32f2xx_rcc.h"
00869     /*
00870      * Generate a RNG seed using the hardware random number generator
00871      * on the STM32F2. Documentation located in STM32F2xx Standard Peripheral
00872      * Library document (See note in README).
00873      */
00874     int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00875     {
00876         int i;
00877 
00878         /* enable RNG clock source */
00879         RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
00880 
00881         /* enable RNG peripheral */
00882         RNG_Cmd(ENABLE);
00883 
00884         for (i = 0; i < sz; i++) {
00885             /* wait until RNG number is ready */
00886             while(RNG_GetFlagStatus(RNG_FLAG_DRDY)== RESET) { }
00887 
00888             /* get value */
00889             output[i] = RNG_GetRandomNumber();
00890         }
00891 
00892         return 0;
00893     }
00894 #elif defined(CYASSL_LPC43xx) || defined(CYASSL_STM32F2xx)
00895 
00896     #warning "write a real random seed!!!!, just for testing now"
00897 
00898     int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00899     {
00900         int i;
00901 
00902         for (i = 0; i < sz; i++ )
00903             output[i] = i;
00904 
00905         return 0;
00906     }
00907 
00908 #elif defined(CYASSL_TIRTOS)
00909 
00910     #include <xdc/runtime/Timestamp.h>
00911     #include <stdlib.h>
00912     int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00913     {
00914         int i;
00915         srand(xdc_runtime_Timestamp_get32());
00916 
00917         for (i = 0; i < sz; i++ ) {
00918             output[i] = rand() % 256;
00919             if ((i % 8) == 7) {
00920                 srand(xdc_runtime_Timestamp_get32());
00921             }
00922         }
00923 
00924         return 0;
00925     }
00926 
00927 #elif defined(CUSTOM_RAND_GENERATE)
00928 
00929    /* Implement your own random generation function
00930     * word32 rand_gen(void);
00931     * #define CUSTOM_RAND_GENERATE  rand_gen  */
00932 
00933    int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00934    {
00935      int i;
00936 
00937      for (i = 0; i < sz; i++ )
00938          output[i] = CUSTOM_RAND_GENERATE();
00939 
00940      return 0;
00941    }
00942 
00943 #elif defined(NO_DEV_RANDOM)
00944 
00945 #error "you need to write an os specific GenerateSeed() here"
00946 
00947 /*
00948 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00949 {
00950     return 0;
00951 }
00952 */
00953 
00954 
00955 #else /* !USE_WINDOWS_API && !HAVE_RPT_SYS && !MICRIUM && !NO_DEV_RANDOM */
00956 
00957 
00958 /* may block */
00959 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
00960 {
00961     int ret = 0;
00962 
00963     os->fd = open("/dev/urandom",O_RDONLY);
00964     if (os->fd == -1) {
00965         /* may still have /dev/random */
00966         os->fd = open("/dev/random",O_RDONLY);
00967         if (os->fd == -1)
00968             return OPEN_RAN_E;
00969     }
00970 
00971     while (sz) {
00972         int len = (int)read(os->fd, output, sz);
00973         if (len == -1) {
00974             ret = READ_RAN_E;
00975             break;
00976         }
00977 
00978         sz     -= len;
00979         output += len;
00980 
00981         if (sz) {
00982 #ifdef BLOCKING
00983             sleep(0);             /* context switch */
00984 #else
00985             ret = RAN_BLOCK_E;
00986             break;
00987 #endif
00988         }
00989     }
00990     close(os->fd);
00991 
00992     return ret;
00993 }
00994 
00995 #endif /* USE_WINDOWS_API */
00996