Line data Source code
1 : #include "tommath_private.h"
2 : #ifdef BN_S_MP_RAND_PLATFORM_C
3 : /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4 : /* SPDX-License-Identifier: Unlicense */
5 :
6 : /* First the OS-specific special cases
7 : * - *BSD
8 : * - Windows
9 : */
10 : #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
11 : #define BN_S_READ_ARC4RANDOM_C
12 : static mp_err s_read_arc4random(void *p, size_t n)
13 : {
14 : arc4random_buf(p, n);
15 : return MP_OKAY;
16 : }
17 : #endif
18 :
19 : #if defined(_WIN32) || defined(_WIN32_WCE)
20 : #define BN_S_READ_WINCSP_C
21 :
22 : #ifndef _WIN32_WINNT
23 : #define _WIN32_WINNT 0x0400
24 : #endif
25 : #ifdef _WIN32_WCE
26 : #define UNDER_CE
27 : #define ARM
28 : #endif
29 :
30 : #define WIN32_LEAN_AND_MEAN
31 : #include <windows.h>
32 : #include <wincrypt.h>
33 :
34 : static mp_err s_read_wincsp(void *p, size_t n)
35 : {
36 : static HCRYPTPROV hProv = 0;
37 : if (hProv == 0) {
38 : HCRYPTPROV h = 0;
39 : if (!CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL,
40 : (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
41 : !CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL,
42 : CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) {
43 : return MP_ERR;
44 : }
45 : hProv = h;
46 : }
47 : return CryptGenRandom(hProv, (DWORD)n, (BYTE *)p) == TRUE ? MP_OKAY : MP_ERR;
48 : }
49 : #endif /* WIN32 */
50 :
51 : #if !defined(BN_S_READ_WINCSP_C) && defined(__linux__) && defined(__GLIBC_PREREQ)
52 : #if __GLIBC_PREREQ(2, 25)
53 : #define BN_S_READ_GETRANDOM_C
54 : #include <sys/random.h>
55 : #include <errno.h>
56 :
57 0 : static mp_err s_read_getrandom(void *p, size_t n)
58 : {
59 0 : char *q = (char *)p;
60 0 : while (n > 0u) {
61 0 : ssize_t ret = getrandom(q, n, 0);
62 0 : if (ret < 0) {
63 0 : if (errno == EINTR) {
64 0 : continue;
65 : }
66 0 : return MP_ERR;
67 : }
68 0 : q += ret;
69 0 : n -= (size_t)ret;
70 : }
71 0 : return MP_OKAY;
72 : }
73 : #endif
74 : #endif
75 :
76 : /* We assume all platforms besides windows provide "/dev/urandom".
77 : * In case yours doesn't, define MP_NO_DEV_URANDOM at compile-time.
78 : */
79 : #if !defined(BN_S_READ_WINCSP_C) && !defined(MP_NO_DEV_URANDOM)
80 : #define BN_S_READ_URANDOM_C
81 : #ifndef MP_DEV_URANDOM
82 : #define MP_DEV_URANDOM "/dev/urandom"
83 : #endif
84 : #include <fcntl.h>
85 : #include <errno.h>
86 : #include <unistd.h>
87 :
88 0 : static mp_err s_read_urandom(void *p, size_t n)
89 : {
90 0 : int fd;
91 0 : char *q = (char *)p;
92 :
93 0 : do {
94 0 : fd = open(MP_DEV_URANDOM, O_RDONLY);
95 0 : } while ((fd == -1) && (errno == EINTR));
96 0 : if (fd == -1) return MP_ERR;
97 :
98 0 : while (n > 0u) {
99 0 : ssize_t ret = read(fd, q, n);
100 0 : if (ret < 0) {
101 0 : if (errno == EINTR) {
102 0 : continue;
103 : }
104 0 : close(fd);
105 0 : return MP_ERR;
106 : }
107 0 : q += ret;
108 0 : n -= (size_t)ret;
109 : }
110 :
111 0 : close(fd);
112 0 : return MP_OKAY;
113 : }
114 : #endif
115 :
116 : #if defined(MP_PRNG_ENABLE_LTM_RNG)
117 : #define BN_S_READ_LTM_RNG
118 : unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void));
119 : void (*ltm_rng_callback)(void);
120 :
121 : static mp_err s_read_ltm_rng(void *p, size_t n)
122 : {
123 : unsigned long res;
124 : if (ltm_rng == NULL) return MP_ERR;
125 : res = ltm_rng(p, n, ltm_rng_callback);
126 : if (res != n) return MP_ERR;
127 : return MP_OKAY;
128 : }
129 : #endif
130 :
131 : #ifdef BN_S_READ_ARC4RANDOM_C
132 : mp_err s_read_arc4random(void *p, size_t n);
133 : #endif
134 : #ifdef BN_S_READ_WINCSP_C
135 : mp_err s_read_wincsp(void *p, size_t n);
136 : #endif
137 : #ifdef BN_S_READ_GETRANDOM_C
138 : mp_err s_read_getrandom(void *p, size_t n);
139 : #endif
140 : #ifdef BN_S_READ_URANDOM_C
141 : mp_err s_read_urandom(void *p, size_t n);
142 : #endif
143 : #ifdef BN_S_READ_LTM_RNG
144 : mp_err s_read_ltm_rng(void *p, size_t n);
145 : #endif
146 :
147 0 : mp_err s_mp_rand_platform(void *p, size_t n)
148 : {
149 0 : mp_err err = MP_ERR;
150 : #ifdef BN_S_READ_ARC4RANDOM_C
151 : if ((err != MP_OKAY) && MP_HAS(S_READ_ARC4RANDOM)) err = s_read_arc4random(p, n);
152 : #endif
153 : #ifdef BN_S_READ_WINCSP_C
154 : if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n);
155 : #endif
156 : #ifdef BN_S_READ_GETRANDOM_C
157 0 : if ((err != MP_OKAY) && MP_HAS(S_READ_GETRANDOM)) err = s_read_getrandom(p, n);
158 : #endif
159 : #ifdef BN_S_READ_URANDOM_C
160 0 : if ((err != MP_OKAY) && MP_HAS(S_READ_URANDOM)) err = s_read_urandom(p, n);
161 : #endif
162 : #ifdef BN_S_READ_LTM_RNG
163 : if ((err != MP_OKAY) && MP_HAS(S_READ_LTM_RNG)) err = s_read_ltm_rng(p, n);
164 : #endif
165 0 : return err;
166 : }
167 :
168 : #endif
|