• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2  *
3  * LibTomCrypt is a library that provides various cryptographic
4  * algorithms in a highly modular and flexible manner.
5  *
6  * The library is free for all purposes without any express
7  * guarantee it works.
8  *
9  * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10  */
11 #include "tomcrypt.h"
12 
13 /**
14    @file rng_get_bytes.c
15    portable way to get secure random bits to feed a PRNG (Tom St Denis)
16 */
17 
18 #ifdef DEVRANDOM
19 /* on *NIX read /dev/random */
rng_nix(unsigned char * buf,unsigned long len,void (* callback)(void))20 static unsigned long rng_nix(unsigned char *buf, unsigned long len,
21                              void (*callback)(void))
22 {
23 #ifdef LTC_NO_FILE
24     return 0;
25 #else
26     FILE *f;
27     unsigned long x;
28 #ifdef TRY_URANDOM_FIRST
29     f = fopen("/dev/urandom", "rb");
30     if (f == NULL)
31 #endif /* TRY_URANDOM_FIRST */
32        f = fopen("/dev/random", "rb");
33 
34     if (f == NULL) {
35        return 0;
36     }
37 
38     /* disable buffering */
39     if (setvbuf(f, NULL, _IONBF, 0) != 0) {
40        fclose(f);
41        return 0;
42     }
43 
44     x = (unsigned long)fread(buf, 1, (size_t)len, f);
45     fclose(f);
46     return x;
47 #endif /* LTC_NO_FILE */
48 }
49 
50 #endif /* DEVRANDOM */
51 
52 /* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */
53 #if defined(CLOCKS_PER_SEC) && !defined(WINCE)
54 
55 #define ANSI_RNG
56 
rng_ansic(unsigned char * buf,unsigned long len,void (* callback)(void))57 static unsigned long rng_ansic(unsigned char *buf, unsigned long len,
58                                void (*callback)(void))
59 {
60    clock_t t1;
61    int l, acc, bits, a, b;
62 
63    if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) {
64       return 0;
65    }
66 
67    l = len;
68    bits = 8;
69    acc  = a = b = 0;
70    while (len--) {
71        if (callback != NULL) callback();
72        while (bits--) {
73           do {
74              t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
75              t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
76           } while (a == b);
77           acc = (acc << 1) | a;
78        }
79        *buf++ = acc;
80        acc  = 0;
81        bits = 8;
82    }
83    acc = bits = a = b = 0;
84    return l;
85 }
86 
87 #endif
88 
89 /* Try the Microsoft CSP */
90 #if defined(WIN32) || defined(WINCE)
91 #define _WIN32_WINNT 0x0400
92 #ifdef WINCE
93    #define UNDER_CE
94    #define ARM
95 #endif
96 #include <windows.h>
97 #include <wincrypt.h>
98 
rng_win32(unsigned char * buf,unsigned long len,void (* callback)(void))99 static unsigned long rng_win32(unsigned char *buf, unsigned long len,
100                                void (*callback)(void))
101 {
102    HCRYPTPROV hProv = 0;
103    if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
104                             (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
105        !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
106                             CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
107       return 0;
108 
109    if (CryptGenRandom(hProv, len, buf) == TRUE) {
110       CryptReleaseContext(hProv, 0);
111       return len;
112    } else {
113       CryptReleaseContext(hProv, 0);
114       return 0;
115    }
116 }
117 
118 #endif /* WIN32 */
119 
120 /**
121   Read the system RNG
122   @param out       Destination
123   @param outlen    Length desired (octets)
124   @param callback  Pointer to void function to act as "callback" when RNG is slow.  This can be NULL
125   @return Number of octets read
126 */
rng_get_bytes(unsigned char * out,unsigned long outlen,void (* callback)(void))127 unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen,
128                             void (*callback)(void))
129 {
130    unsigned long x;
131 
132    LTC_ARGCHK(out != NULL);
133 
134 #if defined(DEVRANDOM)
135    x = rng_nix(out, outlen, callback);   if (x != 0) { return x; }
136 #endif
137 #ifdef WIN32
138    x = rng_win32(out, outlen, callback); if (x != 0) { return x; }
139 #endif
140 #ifdef ANSI_RNG
141    x = rng_ansic(out, outlen, callback); if (x != 0) { return x; }
142 #endif
143    return 0;
144 }
145 
146 /* $Source: /cvs/libtom/libtomcrypt/src/prngs/rng_get_bytes.c,v $ */
147 /* $Revision: 1.5 $ */
148 /* $Date: 2006/12/06 02:01:29 $ */
149