diff options
Diffstat (limited to 'src/lib/libc/crypt/arc4random.c')
-rw-r--r-- | src/lib/libc/crypt/arc4random.c | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/src/lib/libc/crypt/arc4random.c b/src/lib/libc/crypt/arc4random.c index 8604548f3f..bbe42bd204 100644 --- a/src/lib/libc/crypt/arc4random.c +++ b/src/lib/libc/crypt/arc4random.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* $OpenBSD: arc4random.c,v 1.17 2008/01/01 00:43:39 kurt Exp $ */ | 1 | /* $OpenBSD: arc4random.c,v 1.18 2008/03/16 19:47:43 otto Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 1996, David Mazieres <dm@uun.org> | 4 | * Copyright (c) 1996, David Mazieres <dm@uun.org> |
5 | * Copyright (c) 2008, Damien Miller <djm@openbsd.org> | ||
5 | * | 6 | * |
6 | * Permission to use, copy, modify, and distribute this software for any | 7 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above | 8 | * purpose with or without fee is hereby granted, provided that the above |
@@ -34,6 +35,7 @@ | |||
34 | */ | 35 | */ |
35 | 36 | ||
36 | #include <fcntl.h> | 37 | #include <fcntl.h> |
38 | #include <limits.h> | ||
37 | #include <stdlib.h> | 39 | #include <stdlib.h> |
38 | #include <unistd.h> | 40 | #include <unistd.h> |
39 | #include <sys/types.h> | 41 | #include <sys/types.h> |
@@ -188,6 +190,66 @@ arc4random(void) | |||
188 | return val; | 190 | return val; |
189 | } | 191 | } |
190 | 192 | ||
193 | void | ||
194 | arc4random_buf(void *_buf, size_t n) | ||
195 | { | ||
196 | u_char *buf = (u_char *)_buf; | ||
197 | _ARC4_LOCK(); | ||
198 | if (!rs_initialized || arc4_stir_pid != getpid()) | ||
199 | arc4_stir(); | ||
200 | while (n--) { | ||
201 | if (--arc4_count <= 0) | ||
202 | arc4_stir(); | ||
203 | buf[n] = arc4_getbyte(); | ||
204 | } | ||
205 | _ARC4_UNLOCK(); | ||
206 | } | ||
207 | |||
208 | /* | ||
209 | * Calculate a uniformly distributed random number less than upper_bound | ||
210 | * avoiding "modulo bias". | ||
211 | * | ||
212 | * Uniformity is achieved by generating new random numbers until the one | ||
213 | * returned is outside the range [0, 2**32 % upper_bound). This | ||
214 | * guarantees the selected random number will be inside | ||
215 | * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) | ||
216 | * after reduction modulo upper_bound. | ||
217 | */ | ||
218 | u_int32_t | ||
219 | arc4random_uniform(u_int32_t upper_bound) | ||
220 | { | ||
221 | u_int32_t r, min; | ||
222 | |||
223 | if (upper_bound < 2) | ||
224 | return 0; | ||
225 | |||
226 | #if (ULONG_MAX > 0xffffffffUL) | ||
227 | min = 0x100000000UL % upper_bound; | ||
228 | #else | ||
229 | /* Calculate (2**32 % upper_bound) avoiding 64-bit math */ | ||
230 | if (upper_bound > 0x80000000) | ||
231 | min = 1 + ~upper_bound; /* 2**32 - upper_bound */ | ||
232 | else { | ||
233 | /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */ | ||
234 | min = ((0xffffffff - (upper_bound << 2)) + 1) % upper_bound; | ||
235 | } | ||
236 | #endif | ||
237 | |||
238 | /* | ||
239 | * This could theoretically loop forever but each retry has | ||
240 | * p > 0.5 (worst case, usually far better) of selecting a | ||
241 | * number inside the range we need, so it should rarely need | ||
242 | * to re-roll. | ||
243 | */ | ||
244 | for (;;) { | ||
245 | r = arc4random(); | ||
246 | if (r >= min) | ||
247 | break; | ||
248 | } | ||
249 | |||
250 | return r % upper_bound; | ||
251 | } | ||
252 | |||
191 | #if 0 | 253 | #if 0 |
192 | /*-------- Test code for i386 --------*/ | 254 | /*-------- Test code for i386 --------*/ |
193 | #include <stdio.h> | 255 | #include <stdio.h> |