wolf SSL / CyaSSL

Dependents:   HTTPClient-SSL HTTPClient HTTPClient-SSL http_access ... more

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