Mercurial > dropbear
comparison libtommath/bn_mp_rand.c @ 1655:f52919ffd3b1
update ltm to 1.1.0 and enable FIPS 186.4 compliant key-generation (#79)
* make key-generation compliant to FIPS 186.4
* fix includes in tommath_class.h
* update fuzzcorpus instead of error-out
* fixup fuzzing make-targets
* update Makefile.in
* apply necessary patches to ltm sources
* clean-up not required ltm files
* update to vanilla ltm 1.1.0
this already only contains the required files
* remove set/get double
author | Steffen Jaeckel <s_jaeckel@gmx.de> |
---|---|
date | Mon, 16 Sep 2019 15:50:38 +0200 |
parents | 8bba51a55704 |
children | 1051e4eea25a |
comparison
equal
deleted
inserted
replaced
1654:cc0fc5131c5c | 1655:f52919ffd3b1 |
---|---|
1 #include <tommath_private.h> | 1 #include "tommath_private.h" |
2 #ifdef BN_MP_RAND_C | 2 #ifdef BN_MP_RAND_C |
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis | 3 /* LibTomMath, multiple-precision integer library -- Tom St Denis |
4 * | 4 * |
5 * LibTomMath is a library that provides multiple-precision | 5 * LibTomMath is a library that provides multiple-precision |
6 * integer arithmetic as well as number theoretic functionality. | 6 * integer arithmetic as well as number theoretic functionality. |
7 * | 7 * |
8 * The library was designed directly after the MPI library by | 8 * The library was designed directly after the MPI library by |
9 * Michael Fromberger but has been written from scratch with | 9 * Michael Fromberger but has been written from scratch with |
10 * additional optimizations in place. | 10 * additional optimizations in place. |
11 * | 11 * |
12 * The library is free for all purposes without any express | 12 * SPDX-License-Identifier: Unlicense |
13 * guarantee it works. | |
14 * | |
15 * Tom St Denis, [email protected], http://libtom.org | |
16 */ | 13 */ |
17 | 14 |
18 #if MP_GEN_RANDOM_MAX == 0xffffffff | 15 /* First the OS-specific special cases |
19 #define MP_GEN_RANDOM_SHIFT 32 | 16 * - *BSD |
20 #elif MP_GEN_RANDOM_MAX == 32767 | 17 * - Windows |
21 /* SHRT_MAX */ | 18 */ |
22 #define MP_GEN_RANDOM_SHIFT 15 | 19 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) |
23 #elif MP_GEN_RANDOM_MAX == 2147483647 | 20 #define MP_ARC4RANDOM |
24 /* INT_MAX */ | 21 #define MP_GEN_RANDOM_MAX 0xffffffffu |
25 #define MP_GEN_RANDOM_SHIFT 31 | 22 #define MP_GEN_RANDOM_SHIFT 32 |
26 #elif !defined(MP_GEN_RANDOM_SHIFT) | 23 |
27 #error Thou shalt define their own valid MP_GEN_RANDOM_SHIFT | 24 static int s_read_arc4random(mp_digit *p) |
28 #endif | 25 { |
26 mp_digit d = 0, msk = 0; | |
27 do { | |
28 d <<= MP_GEN_RANDOM_SHIFT; | |
29 d |= ((mp_digit) arc4random()); | |
30 msk <<= MP_GEN_RANDOM_SHIFT; | |
31 msk |= (MP_MASK & MP_GEN_RANDOM_MAX); | |
32 } while ((MP_MASK & msk) != MP_MASK); | |
33 *p = d; | |
34 return MP_OKAY; | |
35 } | |
36 #endif | |
37 | |
38 #if defined(_WIN32) || defined(_WIN32_WCE) | |
39 #define MP_WIN_CSP | |
40 | |
41 #ifndef _WIN32_WINNT | |
42 #define _WIN32_WINNT 0x0400 | |
43 #endif | |
44 #ifdef _WIN32_WCE | |
45 #define UNDER_CE | |
46 #define ARM | |
47 #endif | |
48 | |
49 #define WIN32_LEAN_AND_MEAN | |
50 #include <windows.h> | |
51 #include <wincrypt.h> | |
52 | |
53 static HCRYPTPROV hProv = 0; | |
54 | |
55 static void s_cleanup_win_csp(void) | |
56 { | |
57 CryptReleaseContext(hProv, 0); | |
58 hProv = 0; | |
59 } | |
60 | |
61 static int s_read_win_csp(mp_digit *p) | |
62 { | |
63 int ret = -1; | |
64 if (hProv == 0) { | |
65 if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, | |
66 (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && | |
67 !CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, | |
68 CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) { | |
69 hProv = 0; | |
70 return ret; | |
71 } | |
72 atexit(s_cleanup_win_csp); | |
73 } | |
74 if (CryptGenRandom(hProv, sizeof(*p), (void *)p) == TRUE) { | |
75 ret = MP_OKAY; | |
76 } | |
77 return ret; | |
78 } | |
79 #endif /* WIN32 */ | |
80 | |
81 #if !defined(MP_WIN_CSP) && defined(__linux__) && defined(__GLIBC_PREREQ) | |
82 #if __GLIBC_PREREQ(2, 25) | |
83 #define MP_GETRANDOM | |
84 #include <sys/random.h> | |
85 #include <errno.h> | |
86 | |
87 static int s_read_getrandom(mp_digit *p) | |
88 { | |
89 int ret; | |
90 do { | |
91 ret = getrandom(p, sizeof(*p), 0); | |
92 } while ((ret == -1) && (errno == EINTR)); | |
93 if (ret == sizeof(*p)) return MP_OKAY; | |
94 return -1; | |
95 } | |
96 #endif | |
97 #endif | |
98 | |
99 /* We assume all platforms besides windows provide "/dev/urandom". | |
100 * In case yours doesn't, define MP_NO_DEV_URANDOM at compile-time. | |
101 */ | |
102 #if !defined(MP_WIN_CSP) && !defined(MP_NO_DEV_URANDOM) | |
103 #ifndef MP_DEV_URANDOM | |
104 #define MP_DEV_URANDOM "/dev/urandom" | |
105 #endif | |
106 #include <fcntl.h> | |
107 #include <errno.h> | |
108 #include <unistd.h> | |
109 | |
110 static int s_read_dev_urandom(mp_digit *p) | |
111 { | |
112 ssize_t r; | |
113 int fd; | |
114 do { | |
115 fd = open(MP_DEV_URANDOM, O_RDONLY); | |
116 } while ((fd == -1) && (errno == EINTR)); | |
117 if (fd == -1) return -1; | |
118 do { | |
119 r = read(fd, p, sizeof(*p)); | |
120 } while ((r == -1) && (errno == EINTR)); | |
121 close(fd); | |
122 if (r != sizeof(*p)) return -1; | |
123 return MP_OKAY; | |
124 } | |
125 #endif | |
126 | |
127 #if defined(MP_PRNG_ENABLE_LTM_RNG) | |
128 unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); | |
129 void (*ltm_rng_callback)(void); | |
130 | |
131 static int s_read_ltm_rng(mp_digit *p) | |
132 { | |
133 unsigned long ret; | |
134 if (ltm_rng == NULL) return -1; | |
135 ret = ltm_rng((void *)p, sizeof(*p), ltm_rng_callback); | |
136 if (ret != sizeof(*p)) return -1; | |
137 return MP_OKAY; | |
138 } | |
139 #endif | |
140 | |
141 static int s_rand_digit(mp_digit *p) | |
142 { | |
143 int ret = -1; | |
144 | |
145 #if defined(MP_ARC4RANDOM) | |
146 ret = s_read_arc4random(p); | |
147 if (ret == MP_OKAY) return ret; | |
148 #endif | |
149 | |
150 #if defined(MP_WIN_CSP) | |
151 ret = s_read_win_csp(p); | |
152 if (ret == MP_OKAY) return ret; | |
153 #else | |
154 | |
155 #if defined(MP_GETRANDOM) | |
156 ret = s_read_getrandom(p); | |
157 if (ret == MP_OKAY) return ret; | |
158 #endif | |
159 #if defined(MP_DEV_URANDOM) | |
160 ret = s_read_dev_urandom(p); | |
161 if (ret == MP_OKAY) return ret; | |
162 #endif | |
163 | |
164 #endif /* MP_WIN_CSP */ | |
165 | |
166 #if defined(MP_PRNG_ENABLE_LTM_RNG) | |
167 ret = s_read_ltm_rng(p); | |
168 if (ret == MP_OKAY) return ret; | |
169 #endif | |
170 | |
171 return ret; | |
172 } | |
29 | 173 |
30 /* makes a pseudo-random int of a given size */ | 174 /* makes a pseudo-random int of a given size */ |
31 static mp_digit s_gen_random(void) | 175 int mp_rand_digit(mp_digit *r) |
32 { | 176 { |
33 mp_digit d = 0, msk = 0; | 177 int ret = s_rand_digit(r); |
34 do { | 178 *r &= MP_MASK; |
35 d <<= MP_GEN_RANDOM_SHIFT; | 179 return ret; |
36 d |= ((mp_digit) MP_GEN_RANDOM()); | 180 } |
37 msk <<= MP_GEN_RANDOM_SHIFT; | 181 |
38 msk |= (MP_MASK & MP_GEN_RANDOM_MAX); | 182 int mp_rand(mp_int *a, int digits) |
39 } while ((MP_MASK & msk) != MP_MASK); | 183 { |
40 d &= MP_MASK; | 184 int res; |
41 return d; | 185 mp_digit d; |
42 } | 186 |
43 | 187 mp_zero(a); |
44 int | 188 if (digits <= 0) { |
45 mp_rand (mp_int * a, int digits) | 189 return MP_OKAY; |
46 { | 190 } |
47 int res; | 191 |
48 mp_digit d; | 192 /* first place a random non-zero digit */ |
49 | 193 do { |
50 mp_zero (a); | 194 if (mp_rand_digit(&d) != MP_OKAY) { |
51 if (digits <= 0) { | 195 return MP_VAL; |
52 return MP_OKAY; | 196 } |
53 } | 197 } while (d == 0u); |
54 | 198 |
55 /* first place a random non-zero digit */ | 199 if ((res = mp_add_d(a, d, a)) != MP_OKAY) { |
56 do { | |
57 d = s_gen_random(); | |
58 } while (d == 0); | |
59 | |
60 if ((res = mp_add_d (a, d, a)) != MP_OKAY) { | |
61 return res; | |
62 } | |
63 | |
64 while (--digits > 0) { | |
65 if ((res = mp_lshd (a, 1)) != MP_OKAY) { | |
66 return res; | 200 return res; |
67 } | 201 } |
68 | 202 |
69 if ((res = mp_add_d (a, s_gen_random(), a)) != MP_OKAY) { | 203 while (--digits > 0) { |
70 return res; | 204 if ((res = mp_lshd(a, 1)) != MP_OKAY) { |
71 } | 205 return res; |
72 } | 206 } |
73 | 207 |
74 return MP_OKAY; | 208 if (mp_rand_digit(&d) != MP_OKAY) { |
75 } | 209 return MP_VAL; |
76 #endif | 210 } |
77 | 211 if ((res = mp_add_d(a, d, a)) != MP_OKAY) { |
78 /* ref: $Format:%D$ */ | 212 return res; |
79 /* git commit: $Format:%H$ */ | 213 } |
80 /* commit time: $Format:%ai$ */ | 214 } |
215 | |
216 return MP_OKAY; | |
217 } | |
218 #endif | |
219 | |
220 /* ref: HEAD -> master, tag: v1.1.0 */ | |
221 /* git commit: 08549ad6bc8b0cede0b357a9c341c5c6473a9c55 */ | |
222 /* commit time: 2019-01-28 20:32:32 +0100 */ |