1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 *
4 * LibTomCrypt is a library that provides various cryptographic
5 * algorithms in a highly modular and flexible manner.
6 *
7 * The library is free for all purposes without any express
8 * guarantee it works.
9 */
10 #include "tomcrypt_private.h"
11
12 #ifdef LTC_RNG_GET_BYTES
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 #if defined(LTC_DEVRANDOM) && !defined(_WIN32)
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 LTC_UNUSED_PARAM(callback);
25 LTC_UNUSED_PARAM(buf);
26 LTC_UNUSED_PARAM(len);
27 return 0;
28 #else
29 FILE *f;
30 unsigned long x;
31 LTC_UNUSED_PARAM(callback);
32 #ifdef LTC_TRY_URANDOM_FIRST
33 f = fopen("/dev/urandom", "rb");
34 if (f == NULL) {
35 f = fopen("/dev/random", "rb");
36 }
37 #else
38 f = fopen("/dev/random", "rb");
39 #endif /* LTC_TRY_URANDOM_FIRST */
40
41 if (f == NULL) {
42 return 0;
43 }
44
45 /* disable buffering */
46 if (setvbuf(f, NULL, _IONBF, 0) != 0) {
47 fclose(f);
48 return 0;
49 }
50
51 x = (unsigned long)fread(buf, 1, (size_t)len, f);
52 fclose(f);
53 return x;
54 #endif /* LTC_NO_FILE */
55 }
56
57 #endif /* LTC_DEVRANDOM */
58
59 #if !defined(_WIN32_WCE)
60
61 #define ANSI_RNG
62
_rng_ansic(unsigned char * buf,unsigned long len,void (* callback)(void))63 static unsigned long _rng_ansic(unsigned char *buf, unsigned long len,
64 void (*callback)(void))
65 {
66 clock_t t1;
67 int l, acc, bits, a, b;
68
69 l = len;
70 bits = 8;
71 acc = a = b = 0;
72 while (len--) {
73 if (callback != NULL) callback();
74 while (bits--) {
75 do {
76 t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
77 t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
78 } while (a == b);
79 acc = (acc << 1) | a;
80 }
81 *buf++ = acc;
82 acc = 0;
83 bits = 8;
84 }
85 return l;
86 }
87
88 #endif
89
90 /* Try the Microsoft CSP */
91 #if defined(_WIN32) || defined(_WIN32_WCE)
92 #ifndef _WIN32_WINNT
93 #define _WIN32_WINNT 0x0400
94 #endif
95 #ifdef _WIN32_WCE
96 #define UNDER_CE
97 #define ARM
98 #endif
99
100 #define WIN32_LEAN_AND_MEAN
101 #include <windows.h>
102 #include <wincrypt.h>
103
_rng_win32(unsigned char * buf,unsigned long len,void (* callback)(void))104 static unsigned long _rng_win32(unsigned char *buf, unsigned long len,
105 void (*callback)(void))
106 {
107 HCRYPTPROV hProv = 0;
108 LTC_UNUSED_PARAM(callback);
109 if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
110 (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
111 !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
112 CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
113 return 0;
114
115 if (CryptGenRandom(hProv, len, buf) == TRUE) {
116 CryptReleaseContext(hProv, 0);
117 return len;
118 } else {
119 CryptReleaseContext(hProv, 0);
120 return 0;
121 }
122 }
123
124 #endif /* WIN32 */
125
126 /**
127 Read the system RNG
128 @param out Destination
129 @param outlen Length desired (octets)
130 @param callback Pointer to void function to act as "callback" when RNG is slow. This can be NULL
131 @return Number of octets read
132 */
rng_get_bytes(unsigned char * out,unsigned long outlen,void (* callback)(void))133 unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen,
134 void (*callback)(void))
135 {
136 unsigned long x;
137
138 LTC_ARGCHK(out != NULL);
139
140 #ifdef LTC_PRNG_ENABLE_LTC_RNG
141 if (ltc_rng) {
142 x = ltc_rng(out, outlen, callback);
143 if (x != 0) {
144 return x;
145 }
146 }
147 #endif
148
149 #if defined(_WIN32) || defined(_WIN32_WCE)
150 x = _rng_win32(out, outlen, callback); if (x != 0) { return x; }
151 #elif defined(LTC_DEVRANDOM)
152 x = _rng_nix(out, outlen, callback); if (x != 0) { return x; }
153 #endif
154 #ifdef ANSI_RNG
155 x = _rng_ansic(out, outlen, callback); if (x != 0) { return x; }
156 #endif
157 return 0;
158 }
159 #endif /* #ifdef LTC_RNG_GET_BYTES */
160
161 /* ref: $Format:%D$ */
162 /* git commit: $Format:%H$ */
163 /* commit time: $Format:%ai$ */
164