]> pd.if.org Git - zpackage/blob - libtomcrypt/src/prngs/rng_get_bytes.c
commit files needed for zpm-fetchurl
[zpackage] / libtomcrypt / src / prngs / rng_get_bytes.c
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 #include "tomcrypt.h"
10
11 #ifdef LTC_RNG_GET_BYTES
12 /**
13    @file rng_get_bytes.c
14    portable way to get secure random bits to feed a PRNG (Tom St Denis)
15 */
16
17 #if defined(LTC_DEVRANDOM) && !defined(_WIN32)
18 /* on *NIX read /dev/random */
19 static unsigned long _rng_nix(unsigned char *buf, unsigned long len,
20                              void (*callback)(void))
21 {
22 #ifdef LTC_NO_FILE
23     LTC_UNUSED_PARAM(callback);
24     LTC_UNUSED_PARAM(buf);
25     LTC_UNUSED_PARAM(len);
26     return 0;
27 #else
28     FILE *f;
29     unsigned long x;
30     LTC_UNUSED_PARAM(callback);
31 #ifdef LTC_TRY_URANDOM_FIRST
32     f = fopen("/dev/urandom", "rb");
33     if (f == NULL)
34 #endif /* LTC_TRY_URANDOM_FIRST */
35        f = fopen("/dev/random", "rb");
36
37     if (f == NULL) {
38        return 0;
39     }
40
41     /* disable buffering */
42     if (setvbuf(f, NULL, _IONBF, 0) != 0) {
43        fclose(f);
44        return 0;
45     }
46
47     x = (unsigned long)fread(buf, 1, (size_t)len, f);
48     fclose(f);
49     return x;
50 #endif /* LTC_NO_FILE */
51 }
52
53 #endif /* LTC_DEVRANDOM */
54
55 #if !defined(_WIN32_WCE)
56
57 #define ANSI_RNG
58
59 static unsigned long _rng_ansic(unsigned char *buf, unsigned long len,
60                                void (*callback)(void))
61 {
62    clock_t t1;
63    int l, acc, bits, a, b;
64
65    l = len;
66    bits = 8;
67    acc  = a = b = 0;
68    while (len--) {
69        if (callback != NULL) callback();
70        while (bits--) {
71           do {
72              t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
73              t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
74           } while (a == b);
75           acc = (acc << 1) | a;
76        }
77        *buf++ = acc;
78        acc  = 0;
79        bits = 8;
80    }
81    return l;
82 }
83
84 #endif
85
86 /* Try the Microsoft CSP */
87 #if defined(_WIN32) || defined(_WIN32_WCE)
88 #ifndef _WIN32_WINNT
89   #define _WIN32_WINNT 0x0400
90 #endif
91 #ifdef _WIN32_WCE
92    #define UNDER_CE
93    #define ARM
94 #endif
95
96 #define WIN32_LEAN_AND_MEAN
97 #include <windows.h>
98 #include <wincrypt.h>
99
100 static unsigned long _rng_win32(unsigned char *buf, unsigned long len,
101                                void (*callback)(void))
102 {
103    HCRYPTPROV hProv = 0;
104    LTC_UNUSED_PARAM(callback);
105    if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
106                             (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
107        !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
108                             CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
109       return 0;
110
111    if (CryptGenRandom(hProv, len, buf) == TRUE) {
112       CryptReleaseContext(hProv, 0);
113       return len;
114    } else {
115       CryptReleaseContext(hProv, 0);
116       return 0;
117    }
118 }
119
120 #endif /* WIN32 */
121
122 /**
123   Read the system RNG
124   @param out       Destination
125   @param outlen    Length desired (octets)
126   @param callback  Pointer to void function to act as "callback" when RNG is slow.  This can be NULL
127   @return Number of octets read
128 */
129 unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen,
130                             void (*callback)(void))
131 {
132    unsigned long x;
133
134    LTC_ARGCHK(out != NULL);
135
136 #ifdef LTC_PRNG_ENABLE_LTC_RNG
137    if (ltc_rng) {
138       x = ltc_rng(out, outlen, callback);
139       if (x != 0) {
140          return x;
141       }
142    }
143 #endif
144
145 #if defined(_WIN32) || defined(_WIN32_WCE)
146    x = _rng_win32(out, outlen, callback); if (x != 0) { return x; }
147 #elif defined(LTC_DEVRANDOM)
148    x = _rng_nix(out, outlen, callback);   if (x != 0) { return x; }
149 #endif
150 #ifdef ANSI_RNG
151    x = _rng_ansic(out, outlen, callback); if (x != 0) { return x; }
152 #endif
153    return 0;
154 }
155 #endif /* #ifdef LTC_RNG_GET_BYTES */
156
157 /* ref:         $Format:%D$ */
158 /* git commit:  $Format:%H$ */
159 /* commit time: $Format:%ai$ */