s4:torture: Adapt KDC canon test to Heimdal upstream changes
[samba.git] / third_party / heimdal / lib / hcrypto / libtommath / bn_s_mp_rand_platform.c
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 static mp_err s_read_getrandom(void *p, size_t n)
58 {
59    char *q = (char *)p;
60    while (n > 0u) {
61       ssize_t ret = getrandom(q, n, 0);
62       if (ret < 0) {
63          if (errno == EINTR) {
64             continue;
65          }
66          return MP_ERR;
67       }
68       q += ret;
69       n -= (size_t)ret;
70    }
71    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 static mp_err s_read_urandom(void *p, size_t n)
89 {
90    int fd;
91    char *q = (char *)p;
92
93    do {
94       fd = open(MP_DEV_URANDOM, O_RDONLY);
95    } while ((fd == -1) && (errno == EINTR));
96    if (fd == -1) return MP_ERR;
97
98    while (n > 0u) {
99       ssize_t ret = read(fd, p, n);
100       if (ret < 0) {
101          if (errno == EINTR) {
102             continue;
103          }
104          close(fd);
105          return MP_ERR;
106       }
107       q += ret;
108       n -= (size_t)ret;
109    }
110
111    close(fd);
112    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 mp_err s_mp_rand_platform(void *p, size_t n)
148 {
149    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    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    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    return err;
166 }
167
168 #endif