3
|
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, [email protected], http://libtomcrypt.org |
|
10 */ |
|
11 /* portable way to get secure random bits to feed a PRNG */ |
|
12 #include "mycrypt.h" |
|
13 |
|
14 #ifdef DEVRANDOM |
|
15 /* on *NIX read /dev/random */ |
|
16 static unsigned long rng_nix(unsigned char *buf, unsigned long len, |
|
17 void (*callback)(void)) |
|
18 { |
|
19 #ifdef NO_FILE |
|
20 return 0; |
|
21 #else |
|
22 FILE *f; |
|
23 unsigned long x; |
|
24 #ifdef TRY_URANDOM_FIRST |
|
25 f = fopen("/dev/urandom", "rb"); |
|
26 if (f == NULL) |
|
27 #endif /* TRY_URANDOM_FIRST */ |
|
28 f = fopen("/dev/random", "rb"); |
|
29 |
|
30 if (f == NULL) { |
|
31 return 0; |
|
32 } |
|
33 |
|
34 /* disable buffering */ |
|
35 if (setvbuf(f, NULL, _IONBF, 0) != 0) { |
|
36 fclose(f); |
|
37 return 0; |
|
38 } |
|
39 |
|
40 x = (unsigned long)fread(buf, 1, (size_t)len, f); |
|
41 fclose(f); |
|
42 return x; |
|
43 #endif /* NO_FILE */ |
|
44 } |
|
45 |
|
46 #endif /* DEVRANDOM */ |
|
47 |
|
48 /* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */ |
|
49 #if defined(CLOCKS_PER_SEC) |
|
50 |
|
51 #define ANSI_RNG |
|
52 |
|
53 static unsigned long rng_ansic(unsigned char *buf, unsigned long len, |
|
54 void (*callback)(void)) |
|
55 { |
|
56 clock_t t1; |
|
57 int l, acc, bits, a, b; |
|
58 |
|
59 if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) { |
|
60 return 0; |
|
61 } |
|
62 |
|
63 l = len; |
|
64 bits = 8; |
|
65 acc = a = b = 0; |
|
66 while (len--) { |
|
67 if (callback != NULL) callback(); |
|
68 while (bits--) { |
|
69 do { |
|
70 t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1; |
|
71 t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1; |
|
72 } while (a == b); |
|
73 acc = (acc << 1) | a; |
|
74 } |
|
75 *buf++ = acc; |
|
76 acc = 0; |
|
77 bits = 8; |
|
78 } |
|
79 acc = bits = a = b = 0; |
|
80 return l; |
|
81 } |
|
82 |
|
83 #endif |
|
84 |
|
85 /* Try the Microsoft CSP */ |
|
86 #ifdef WIN32 |
|
87 #define _WIN32_WINNT 0x0400 |
|
88 #include <windows.h> |
|
89 #include <wincrypt.h> |
|
90 |
|
91 static unsigned long rng_win32(unsigned char *buf, unsigned long len, |
|
92 void (*callback)(void)) |
|
93 { |
|
94 HCRYPTPROV hProv = 0; |
|
95 if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, |
|
96 (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && |
|
97 !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, |
|
98 CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) |
|
99 return 0; |
|
100 |
|
101 if (CryptGenRandom(hProv, len, buf) == TRUE) { |
|
102 CryptReleaseContext(hProv, 0); |
|
103 return len; |
|
104 } else { |
|
105 CryptReleaseContext(hProv, 0); |
|
106 return 0; |
|
107 } |
|
108 } |
|
109 |
|
110 #endif /* WIN32 */ |
|
111 |
|
112 unsigned long rng_get_bytes(unsigned char *buf, unsigned long len, |
|
113 void (*callback)(void)) |
|
114 { |
|
115 unsigned long x; |
|
116 |
|
117 _ARGCHK(buf != NULL); |
|
118 |
|
119 #if defined(DEVRANDOM) |
|
120 x = rng_nix(buf, len, callback); if (x != 0) { return x; } |
|
121 #endif |
|
122 #ifdef WIN32 |
|
123 x = rng_win32(buf, len, callback); if (x != 0) { return x; } |
|
124 #endif |
|
125 #ifdef ANSI_RNG |
|
126 x = rng_ansic(buf, len, callback); if (x != 0) { return x; } |
|
127 #endif |
|
128 return 0; |
|
129 } |