summaryrefslogtreecommitdiff
path: root/src/lib/libc/crypt/arc4random.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/crypt/arc4random.c')
-rw-r--r--src/lib/libc/crypt/arc4random.c64
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
193void
194arc4random_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 */
218u_int32_t
219arc4random_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>