Mercurial > dropbear
comparison libtomcrypt/src/prngs/rng_get_bytes.c @ 391:00fcf5045160
propagate from branch 'au.asn.ucc.matt.ltc.dropbear' (head c1db4398d56c56c6d06ae1e20c1e0d04dbb598ed)
to branch 'au.asn.ucc.matt.dropbear' (head d26d5eb2837f46b56a33fb0e7573aa0201abd4d5)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 11 Jan 2007 04:29:08 +0000 |
parents | 0cbe8f6dbf9e |
children | f849a5ca2efc |
comparison
equal
deleted
inserted
replaced
390:d8e44bef7917 | 391:00fcf5045160 |
---|---|
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.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 */ | |
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 | |
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 | |
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 */ | |
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 $ */ |