wolf SSL / CyaSSL-2.9.4

Dependents:  

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