]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/random.c
7442fe123ec055e62244be3a5d221fc9ee64a00f
[freertos] / FreeRTOS-Plus / Source / WolfSSL / ctaocrypt / src / random.c
1 /* random.c
2  *
3  * Copyright (C) 2006-2014 wolfSSL Inc.
4  *
5  * This file is part of CyaSSL.
6  *
7  * CyaSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * CyaSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #include <cyassl/ctaocrypt/settings.h>
27
28 /* on HPUX 11 you may need to install /dev/random see
29    http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
30
31 */
32
33 #ifdef HAVE_FIPS
34     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
35     #define FIPS_NO_WRAPPERS
36 #endif
37
38 #include <cyassl/ctaocrypt/random.h>
39 #include <cyassl/ctaocrypt/error-crypt.h>
40
41 #if defined(HAVE_HASHDRBG) || defined(NO_RC4)
42
43     #include <cyassl/ctaocrypt/sha256.h>
44
45     #ifdef NO_INLINE
46         #include <cyassl/ctaocrypt/misc.h>
47     #else
48         #include <ctaocrypt/src/misc.c>
49     #endif
50 #endif /* HAVE_HASHDRBG || NO_RC4 */
51
52 #if defined(USE_WINDOWS_API)
53     #ifndef _WIN32_WINNT
54         #define _WIN32_WINNT 0x0400
55     #endif
56     #include <windows.h>
57     #include <wincrypt.h>
58 #else
59     #if !defined(NO_DEV_RANDOM) && !defined(CYASSL_MDK_ARM) \
60                                 && !defined(CYASSL_IAR_ARM)
61             #include <fcntl.h>
62         #ifndef EBSNET
63             #include <unistd.h>
64         #endif
65     #else
66         /* include headers that may be needed to get good seed */
67     #endif
68 #endif /* USE_WINDOWS_API */
69
70
71 #if defined(HAVE_HASHDRBG) || defined(NO_RC4)
72
73 /* Start NIST DRBG code */
74
75 #define OUTPUT_BLOCK_LEN  (SHA256_DIGEST_SIZE)
76 #define MAX_REQUEST_LEN   (0x10000)
77 #define RESEED_INTERVAL   (1000000)
78 #define SECURITY_STRENGTH (256)
79 #define ENTROPY_SZ        (SECURITY_STRENGTH/8)
80 #define NONCE_SZ          (ENTROPY_SZ/2)
81 #define ENTROPY_NONCE_SZ  (ENTROPY_SZ+NONCE_SZ)
82
83 /* Internal return codes */
84 #define DRBG_SUCCESS      0
85 #define DRBG_ERROR        1
86 #define DRBG_FAILURE      2
87 #define DRBG_NEED_RESEED  3
88
89 /* RNG health states */
90 #define DRBG_NOT_INIT     0
91 #define DRBG_OK           1
92 #define DRBG_FAILED       2
93
94
95 enum {
96     drbgInitC     = 0,
97     drbgReseed    = 1,
98     drbgGenerateW = 2,
99     drbgGenerateH = 3,
100     drbgInitV
101 };
102
103
104 /* Hash Derivation Function */
105 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
106 static int Hash_df(RNG* rng, byte* out, word32 outSz, byte type,
107                                                   const byte* inA, word32 inASz,
108                                                   const byte* inB, word32 inBSz)
109 {
110     byte ctr;
111     int i;
112     int len;
113     word32 bits = (outSz * 8); /* reverse byte order */
114
115     #ifdef LITTLE_ENDIAN_ORDER
116         bits = ByteReverseWord32(bits);
117     #endif
118     len = (outSz / OUTPUT_BLOCK_LEN)
119         + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
120
121     for (i = 0, ctr = 1; i < len; i++, ctr++)
122     {
123         if (InitSha256(&rng->sha) != 0)
124             return DRBG_FAILURE;
125
126         if (Sha256Update(&rng->sha, &ctr, sizeof(ctr)) != 0)
127             return DRBG_FAILURE;
128
129         if (Sha256Update(&rng->sha, (byte*)&bits, sizeof(bits)) != 0)
130             return DRBG_FAILURE;
131
132         /* churning V is the only string that doesn't have 
133          * the type added */
134         if (type != drbgInitV)
135             if (Sha256Update(&rng->sha, &type, sizeof(type)) != 0)
136                 return DRBG_FAILURE;
137
138         if (Sha256Update(&rng->sha, inA, inASz) != 0)
139             return DRBG_FAILURE;
140
141         if (inB != NULL && inBSz > 0)
142             if (Sha256Update(&rng->sha, inB, inBSz) != 0)
143                 return DRBG_FAILURE;
144
145         if (Sha256Final(&rng->sha, rng->digest) != 0)
146             return DRBG_FAILURE;
147
148         if (outSz > OUTPUT_BLOCK_LEN) {
149             XMEMCPY(out, rng->digest, OUTPUT_BLOCK_LEN);
150             outSz -= OUTPUT_BLOCK_LEN;
151             out += OUTPUT_BLOCK_LEN;
152         }
153         else {
154             XMEMCPY(out, rng->digest, outSz);
155         }
156     }
157
158     return DRBG_SUCCESS;
159 }
160
161
162 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
163 static int Hash_DRBG_Reseed(RNG* rng, const byte* entropy, word32 entropySz)
164 {
165     byte seed[DRBG_SEED_LEN];
166
167     if (Hash_df(rng, seed, sizeof(seed), drbgReseed, rng->V, sizeof(rng->V),
168                                           entropy, entropySz) != DRBG_SUCCESS) {
169         return DRBG_FAILURE;
170     }
171
172     XMEMCPY(rng->V, seed, sizeof(rng->V));
173     XMEMSET(seed, 0, sizeof(seed));
174
175     if (Hash_df(rng, rng->C, sizeof(rng->C), drbgInitC, rng->V,
176                                      sizeof(rng->V), NULL, 0) != DRBG_SUCCESS) {
177         return DRBG_FAILURE;
178     }
179
180     rng->reseedCtr = 1;
181     return DRBG_SUCCESS;
182 }
183
184 static INLINE void array_add_one(byte* data, word32 dataSz)
185 {
186     int i;
187
188     for (i = dataSz - 1; i >= 0; i--)
189     {
190         data[i]++;
191         if (data[i] != 0) break;
192     }
193 }
194
195
196 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
197 static int Hash_gen(RNG* rng, byte* out, word32 outSz, const byte* V)
198 {
199     byte data[DRBG_SEED_LEN];
200     int i;
201     int len = (outSz / OUTPUT_BLOCK_LEN)
202         + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
203
204     XMEMCPY(data, V, sizeof(data));
205     for (i = 0; i < len; i++) {
206         if (InitSha256(&rng->sha) != 0 ||
207             Sha256Update(&rng->sha, data, sizeof(data)) != 0 ||
208             Sha256Final(&rng->sha, rng->digest) != 0) {
209
210             return DRBG_FAILURE;
211         }
212
213         if (outSz > OUTPUT_BLOCK_LEN) {
214             XMEMCPY(out, rng->digest, OUTPUT_BLOCK_LEN);
215             outSz -= OUTPUT_BLOCK_LEN;
216             out += OUTPUT_BLOCK_LEN;
217             array_add_one(data, DRBG_SEED_LEN);
218         }
219         else {
220             XMEMCPY(out, rng->digest, outSz);
221         }
222     }
223     XMEMSET(data, 0, sizeof(data));
224
225     return DRBG_SUCCESS;
226 }
227
228
229 static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
230 {
231     word16 carry = 0;
232
233     if (dLen > 0 && sLen > 0 && dLen >= sLen) {
234         int sIdx, dIdx;
235
236         for (sIdx = sLen - 1, dIdx = dLen - 1; sIdx >= 0; dIdx--, sIdx--)
237         {
238             carry += d[dIdx] + s[sIdx];
239             d[dIdx] = carry;
240             carry >>= 8;
241         }
242         if (dIdx > 0)
243             d[dIdx] += carry;
244     }
245 }
246
247
248 /* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */
249 static int Hash_DRBG_Generate(RNG* rng, byte* out, word32 outSz)
250 {
251     int ret = DRBG_NEED_RESEED;
252
253     if (rng->reseedCtr != RESEED_INTERVAL) {
254         byte type = drbgGenerateH;
255         word32 reseedCtr = rng->reseedCtr;
256
257         rng->reseedCtr++;
258         if (Hash_gen(rng, out, outSz, rng->V) != 0 ||
259             InitSha256(&rng->sha) != 0 ||
260             Sha256Update(&rng->sha, &type, sizeof(type)) != 0 ||
261             Sha256Update(&rng->sha, rng->V, sizeof(rng->V)) != 0 ||
262             Sha256Final(&rng->sha, rng->digest) != 0) {
263
264             ret = DRBG_FAILURE;
265         }
266         else {
267             array_add(rng->V, sizeof(rng->V), rng->digest, sizeof(rng->digest));
268             array_add(rng->V, sizeof(rng->V), rng->C, sizeof(rng->C));
269             #ifdef LITTLE_ENDIAN_ORDER
270                 reseedCtr = ByteReverseWord32(reseedCtr);
271             #endif
272             array_add(rng->V, sizeof(rng->V),
273                                           (byte*)&reseedCtr, sizeof(reseedCtr));
274             ret = DRBG_SUCCESS;
275         }
276     }
277
278     return ret;
279 }
280
281
282 /* Returns: DRBG_SUCCESS or DRBG_FAILURE */
283 static int Hash_DRBG_Instantiate(RNG* rng, const byte* seed, word32 seedSz,
284                                            const byte* nonce, word32 nonceSz)
285 {
286     int ret = DRBG_FAILURE;
287
288     XMEMSET(rng, 0, sizeof(*rng));
289
290     if (Hash_df(rng, rng->V, sizeof(rng->V), drbgInitV, seed, seedSz,
291                                               nonce, nonceSz) == DRBG_SUCCESS &&
292         Hash_df(rng, rng->C, sizeof(rng->C), drbgInitC, rng->V,
293                                      sizeof(rng->V), NULL, 0) == DRBG_SUCCESS) {
294
295         rng->reseedCtr = 1;
296         ret = DRBG_SUCCESS;
297     }
298
299     return ret;
300 }
301
302
303 /* Returns: DRBG_SUCCESS */
304 static int Hash_DRBG_Uninstantiate(RNG* rng)
305 {
306     XMEMSET(rng, 0, sizeof(*rng));
307
308     return DRBG_SUCCESS;
309 }
310
311 /* End NIST DRBG Code */
312
313
314 /* Get seed and key cipher */
315 int InitRng(RNG* rng)
316 {
317     int ret = BAD_FUNC_ARG;
318
319     if (rng != NULL) {
320         byte entropy[ENTROPY_NONCE_SZ];
321
322         /* This doesn't use a separate nonce. The entropy input will be
323          * the default size plus the size of the nonce making the seed
324          * size. */
325         if (GenerateSeed(&rng->seed, entropy, ENTROPY_NONCE_SZ) == 0 &&
326             Hash_DRBG_Instantiate(rng, entropy, ENTROPY_NONCE_SZ,
327                                                      NULL, 0) == DRBG_SUCCESS) {
328             rng->status = DRBG_OK;
329             ret = 0;
330         }
331         else {
332             rng->status = DRBG_FAILED;
333             ret = RNG_FAILURE_E;
334         }
335
336         XMEMSET(entropy, 0, ENTROPY_NONCE_SZ);
337     }
338
339     return ret;
340 }
341
342
343 /* place a generated block in output */
344 int RNG_GenerateBlock(RNG* rng, byte* output, word32 sz)
345 {
346     int ret;
347
348     if (rng == NULL || output == NULL || sz > MAX_REQUEST_LEN)
349         return BAD_FUNC_ARG;
350
351     if (rng->status != DRBG_OK)
352         return RNG_FAILURE_E;
353
354     ret = Hash_DRBG_Generate(rng, output, sz);
355     if (ret == DRBG_SUCCESS) {
356         ret = 0;
357     }
358     else if (ret == DRBG_NEED_RESEED) {
359         byte entropy[ENTROPY_SZ];
360
361         if (GenerateSeed(&rng->seed, entropy, ENTROPY_SZ) == 0 &&
362                 Hash_DRBG_Reseed(rng, entropy, ENTROPY_SZ) == DRBG_SUCCESS &&
363                 Hash_DRBG_Generate(rng, output, sz) == DRBG_SUCCESS) {
364
365             ret = 0;
366         }
367         else {
368             ret = RNG_FAILURE_E;
369             rng->status = DRBG_FAILED;
370         }
371
372         XMEMSET(entropy, 0, ENTROPY_SZ);
373     }
374     else {
375         ret = RNG_FAILURE_E;
376         rng->status = DRBG_FAILED;
377     }
378
379     return ret;
380 }
381
382
383 int RNG_GenerateByte(RNG* rng, byte* b)
384 {
385     return RNG_GenerateBlock(rng, b, 1);
386 }
387
388
389 int FreeRng(RNG* rng)
390 {
391     int ret = BAD_FUNC_ARG;
392
393     if (rng != NULL) {
394         if (Hash_DRBG_Uninstantiate(rng) == DRBG_SUCCESS)
395             ret = 0;
396         else
397             ret = RNG_FAILURE_E;
398     }
399
400     return ret;
401 }
402
403
404 int RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz,
405                                const byte* entropyB, word32 entropyBSz,
406                                const byte* output, word32 outputSz)
407 {
408     RNG rng;
409     byte check[SHA256_DIGEST_SIZE * 4];
410
411     if (Hash_DRBG_Instantiate(&rng, entropyA, entropyASz, NULL, 0) != 0)
412         return -1;
413
414     if (reseed) {
415         if (Hash_DRBG_Reseed(&rng, entropyB, entropyBSz) != 0) {
416             Hash_DRBG_Uninstantiate(&rng);
417             return -1;
418         }
419     }
420
421     if (Hash_DRBG_Generate(&rng, check, sizeof(check)) != 0) {
422         Hash_DRBG_Uninstantiate(&rng);
423         return -1;
424     }
425
426     if (Hash_DRBG_Generate(&rng, check, sizeof(check)) != 0) {
427         Hash_DRBG_Uninstantiate(&rng);
428         return -1;
429     }
430
431     if (outputSz != sizeof(check) || XMEMCMP(output, check, sizeof(check))) {
432         Hash_DRBG_Uninstantiate(&rng);
433         return -1;
434     }
435
436     Hash_DRBG_Uninstantiate(&rng);
437
438     return 0;
439 }
440
441
442 #else /* HAVE_HASHDRBG || NO_RC4 */
443
444 /* Get seed and key cipher */
445 int InitRng(RNG* rng)
446 {
447     int  ret;
448 #ifdef CYASSL_SMALL_STACK
449     byte* key;
450     byte* junk;
451 #else
452     byte key[32];
453     byte junk[256];
454 #endif
455
456 #ifdef HAVE_CAVIUM
457     if (rng->magic == CYASSL_RNG_CAVIUM_MAGIC)
458         return 0;
459 #endif
460
461 #ifdef CYASSL_SMALL_STACK
462     key = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
463     if (key == NULL)
464         return MEMORY_E;
465
466     junk = (byte*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
467     if (junk == NULL) {
468         XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
469         return MEMORY_E;
470     }
471 #endif
472
473     ret = GenerateSeed(&rng->seed, key, 32);
474
475     if (ret == 0) {
476         Arc4SetKey(&rng->cipher, key, sizeof(key));
477
478         ret = RNG_GenerateBlock(rng, junk, 256); /*rid initial state*/
479     }
480
481 #ifdef CYASSL_SMALL_STACK
482     XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER);
483     XFREE(junk, NULL, DYNAMIC_TYPE_TMP_BUFFER);
484 #endif
485
486     return ret;
487 }
488
489 #ifdef HAVE_CAVIUM
490     static void CaviumRNG_GenerateBlock(RNG* rng, byte* output, word32 sz);
491 #endif
492
493 /* place a generated block in output */
494 int RNG_GenerateBlock(RNG* rng, byte* output, word32 sz)
495 {
496 #ifdef HAVE_CAVIUM
497     if (rng->magic == CYASSL_RNG_CAVIUM_MAGIC)
498         return CaviumRNG_GenerateBlock(rng, output, sz);
499 #endif
500     XMEMSET(output, 0, sz);
501     Arc4Process(&rng->cipher, output, output, sz);
502
503     return 0;
504 }
505
506
507 int RNG_GenerateByte(RNG* rng, byte* b)
508 {
509     return RNG_GenerateBlock(rng, b, 1);
510 }
511
512
513 #ifdef HAVE_CAVIUM
514
515 #include <cyassl/ctaocrypt/logging.h>
516 #include "cavium_common.h"
517
518 /* Initiliaze RNG for use with Nitrox device */
519 int InitRngCavium(RNG* rng, int devId)
520 {
521     if (rng == NULL)
522         return -1;
523
524     rng->devId = devId;
525     rng->magic = CYASSL_RNG_CAVIUM_MAGIC;
526
527     return 0;
528 }
529
530
531 static void CaviumRNG_GenerateBlock(RNG* rng, byte* output, word32 sz)
532 {
533     word   offset = 0;
534     word32 requestId;
535
536     while (sz > CYASSL_MAX_16BIT) {
537         word16 slen = (word16)CYASSL_MAX_16BIT;
538         if (CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId,
539                       rng->devId) != 0) {
540             CYASSL_MSG("Cavium RNG failed");
541         }
542         sz     -= CYASSL_MAX_16BIT;
543         offset += CYASSL_MAX_16BIT;
544     }
545     if (sz) {
546         word16 slen = (word16)sz;
547         if (CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId,
548                       rng->devId) != 0) {
549             CYASSL_MSG("Cavium RNG failed");
550         }
551     }
552 }
553
554 #endif /* HAVE_CAVIUM */
555
556 #endif /* HAVE_HASHDRBG || NO_RC4 */
557
558
559 #if defined(USE_WINDOWS_API)
560
561
562 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
563 {
564     if(!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
565                             CRYPT_VERIFYCONTEXT))
566         return WINCRYPT_E;
567
568     if (!CryptGenRandom(os->handle, sz, output))
569         return CRYPTGEN_E;
570
571     CryptReleaseContext(os->handle, 0);
572
573     return 0;
574 }
575
576
577 #elif defined(HAVE_RTP_SYS) || defined(EBSNET)
578
579 #include "rtprand.h"   /* rtp_rand () */
580 #include "rtptime.h"   /* rtp_get_system_msec() */
581
582
583 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
584 {
585     int i;
586     rtp_srand(rtp_get_system_msec());
587
588     for (i = 0; i < sz; i++ ) {
589         output[i] = rtp_rand() % 256;
590         if ( (i % 8) == 7)
591             rtp_srand(rtp_get_system_msec());
592     }
593
594     return 0;
595 }
596
597
598 #elif defined(MICRIUM)
599
600 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
601 {
602     #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
603         NetSecure_InitSeed(output, sz);
604     #endif
605     return 0;
606 }
607
608 #elif defined(MBED)
609
610 /* write a real one !!!, just for testing board */
611 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
612 {
613     int i;
614     for (i = 0; i < sz; i++ )
615         output[i] = i;
616
617     return 0;
618 }
619
620 #elif defined(MICROCHIP_PIC32)
621
622 #ifdef MICROCHIP_MPLAB_HARMONY
623     #define PIC32_SEED_COUNT _CP0_GET_COUNT
624 #else
625     #if !defined(CYASSL_MICROCHIP_PIC32MZ)
626         #include <peripheral/timer.h>
627     #endif
628     #define PIC32_SEED_COUNT ReadCoreTimer
629 #endif
630     #ifdef CYASSL_MIC32MZ_RNG
631         #include "xc.h"
632         int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
633         {
634             int i ;
635             byte rnd[8] ;
636             word32 *rnd32 = (word32 *)rnd ;
637             word32 size = sz ;
638             byte* op = output ;
639
640             /* This part has to be replaced with better random seed */
641             RNGNUMGEN1 = ReadCoreTimer();
642             RNGPOLY1 = ReadCoreTimer();
643             RNGPOLY2 = ReadCoreTimer();
644             RNGNUMGEN2 = ReadCoreTimer();
645 #ifdef DEBUG_CYASSL
646             printf("GenerateSeed::Seed=%08x, %08x\n", RNGNUMGEN1, RNGNUMGEN2) ;
647 #endif
648             RNGCONbits.PLEN = 0x40;
649             RNGCONbits.PRNGEN = 1;
650             for(i=0; i<5; i++) { /* wait for RNGNUMGEN ready */
651                 volatile int x ;
652                 x = RNGNUMGEN1 ;
653                 x = RNGNUMGEN2 ;
654             }
655             do {
656                 rnd32[0] = RNGNUMGEN1;
657                 rnd32[1] = RNGNUMGEN2;
658
659                 for(i=0; i<8; i++, op++) {
660                     *op = rnd[i] ;
661                     size -- ;
662                     if(size==0)break ;
663                 }
664             } while(size) ;
665             return 0;
666         }
667     #else  /* CYASSL_MIC32MZ_RNG */
668         /* uses the core timer, in nanoseconds to seed srand */
669         int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
670         {
671             int i;
672             srand(PIC32_SEED_COUNT() * 25);
673
674             for (i = 0; i < sz; i++ ) {
675                 output[i] = rand() % 256;
676                 if ( (i % 8) == 7)
677                     srand(PIC32_SEED_COUNT() * 25);
678             }
679             return 0;
680         }
681     #endif /* CYASSL_MIC32MZ_RNG */
682
683 #elif defined(FREESCALE_MQX)
684
685     #ifdef FREESCALE_K70_RNGA
686         /*
687          * Generates a RNG seed using the Random Number Generator Accelerator
688          * on the Kinetis K70. Documentation located in Chapter 37 of
689          * K70 Sub-Family Reference Manual (see Note 3 in the README for link).
690          */
691         int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
692         {
693             int i;
694
695             /* turn on RNGA module */
696             SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK;
697
698             /* set SLP bit to 0 - "RNGA is not in sleep mode" */
699             RNG_CR &= ~RNG_CR_SLP_MASK;
700
701             /* set HA bit to 1 - "security violations masked" */
702             RNG_CR |= RNG_CR_HA_MASK;
703
704             /* set GO bit to 1 - "output register loaded with data" */
705             RNG_CR |= RNG_CR_GO_MASK;
706
707             for (i = 0; i < sz; i++) {
708
709                 /* wait for RNG FIFO to be full */
710                 while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {}
711
712                 /* get value */
713                 output[i] = RNG_OR;
714             }
715
716             return 0;
717         }
718
719     #elif defined(FREESCALE_K53_RNGB)
720         /*
721          * Generates a RNG seed using the Random Number Generator (RNGB)
722          * on the Kinetis K53. Documentation located in Chapter 33 of
723          * K53 Sub-Family Reference Manual (see note in the README for link).
724          */
725         int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
726         {
727             int i;
728
729             /* turn on RNGB module */
730             SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK;
731
732             /* reset RNGB */
733             RNG_CMD |= RNG_CMD_SR_MASK;
734
735             /* FIFO generate interrupt, return all zeros on underflow,
736              * set auto reseed */
737             RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK);
738
739             /* gen seed, clear interrupts, clear errors */
740             RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK);
741
742             /* wait for seeding to complete */
743             while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {}
744
745             for (i = 0; i < sz; i++) {
746
747                 /* wait for a word to be available from FIFO */
748                 while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {}
749
750                 /* get value */
751                 output[i] = RNG_OUT;
752             }
753
754             return 0;
755         }
756
757         #else
758         #warning "write a real random seed!!!!, just for testing now"
759
760         int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
761         {
762             int i;
763             for (i = 0; i < sz; i++ )
764                 output[i] = i;
765
766             return 0;
767         }
768         #endif /* FREESCALE_K70_RNGA */
769
770 #elif defined(CYASSL_SAFERTOS) || defined(CYASSL_LEANPSK) \
771    || defined(CYASSL_IAR_ARM)  || defined(CYASSL_MDK_ARM)
772
773 #warning "write a real random seed!!!!, just for testing now"
774
775 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
776 {
777     word32 i;
778     for (i = 0; i < sz; i++ )
779         output[i] = i;
780
781     (void)os;
782
783     return 0;
784 }
785
786 #elif defined(STM32F2_RNG)
787     #undef RNG
788     #include "stm32f2xx_rng.h"
789     #include "stm32f2xx_rcc.h"
790     /*
791      * Generate a RNG seed using the hardware random number generator
792      * on the STM32F2. Documentation located in STM32F2xx Standard Peripheral
793      * Library document (See note in README).
794      */
795     int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
796     {
797         int i;
798
799         /* enable RNG clock source */
800         RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
801
802         /* enable RNG peripheral */
803         RNG_Cmd(ENABLE);
804
805         for (i = 0; i < sz; i++) {
806             /* wait until RNG number is ready */
807             while(RNG_GetFlagStatus(RNG_FLAG_DRDY)== RESET) { }
808
809             /* get value */
810             output[i] = RNG_GetRandomNumber();
811         }
812
813         return 0;
814     }
815 #elif defined(CYASSL_LPC43xx) || defined(CYASSL_STM32F2xx)
816
817     #warning "write a real random seed!!!!, just for testing now"
818
819     int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
820     {
821         int i;
822
823         for (i = 0; i < sz; i++ )
824             output[i] = i;
825
826         return 0;
827     }
828
829 #elif defined(CUSTOM_RAND_GENERATE)
830
831    /* Implement your own random generation function
832     * word32 rand_gen(void);
833     * #define CUSTOM_RAND_GENERATE  rand_gen  */
834
835    int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
836    {
837      int i;
838
839      for (i = 0; i < sz; i++ )
840          output[i] = CUSTOM_RAND_GENERATE();
841
842      return 0;
843    }
844
845 #elif defined(NO_DEV_RANDOM)
846
847 #error "you need to write an os specific GenerateSeed() here"
848
849 /*
850 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
851 {
852     return 0;
853 }
854 */
855
856
857 #else /* !USE_WINDOWS_API && !HAVE_RPT_SYS && !MICRIUM && !NO_DEV_RANDOM */
858
859
860 /* may block */
861 int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
862 {
863     int ret = 0;
864
865     os->fd = open("/dev/urandom",O_RDONLY);
866     if (os->fd == -1) {
867         /* may still have /dev/random */
868         os->fd = open("/dev/random",O_RDONLY);
869         if (os->fd == -1)
870             return OPEN_RAN_E;
871     }
872
873     while (sz) {
874         int len = (int)read(os->fd, output, sz);
875         if (len == -1) {
876             ret = READ_RAN_E;
877             break;
878         }
879
880         sz     -= len;
881         output += len;
882
883         if (sz) {
884 #ifdef BLOCKING
885             sleep(0);             /* context switch */
886 #else
887             ret = RAN_BLOCK_E;
888             break;
889 #endif
890         }
891     }
892     close(os->fd);
893
894     return ret;
895 }
896
897 #endif /* USE_WINDOWS_API */
898