1 /* OPENBSD ORIGINAL: lib/libc/crypto/arc4random.c */
3 /* $OpenBSD: arc4random.c,v 1.25 2013/10/01 18:34:57 markus Exp $ */
6 * Copyright (c) 1996, David Mazieres <dm@uun.org>
7 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
8 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * ChaCha based random number generator for OpenBSD.
32 #include <sys/types.h>
34 #ifndef HAVE_ARC4RANDOM
36 #include <openssl/rand.h>
37 #include <openssl/err.h>
41 #define KEYSTREAM_ONLY
42 #include "chacha_private.h"
45 #define inline __inline
48 #endif /* !__GNUC__ */
50 /* OpenSSH isn't multithreaded */
52 #define _ARC4_UNLOCK()
57 #define RSBUFSZ (16*BLOCKSZ)
58 static int rs_initialized
;
59 static pid_t rs_stir_pid
;
60 static chacha_ctx rs
; /* chacha context for random keystream */
61 static u_char rs_buf
[RSBUFSZ
]; /* keystream blocks */
62 static size_t rs_have
; /* valid bytes at end of rs_buf */
63 static size_t rs_count
; /* bytes till reseed */
65 static inline void _rs_rekey(u_char
*dat
, size_t datlen
);
68 _rs_init(u_char
*buf
, size_t n
)
72 chacha_keysetup(&rs
, buf
, KEYSZ
* 8, 0);
73 chacha_ivsetup(&rs
, buf
+ KEYSZ
);
79 u_char rnd
[KEYSZ
+ IVSZ
];
81 if (RAND_bytes(rnd
, sizeof(rnd
)) <= 0)
82 fatal("Couldn't obtain random bytes (error %ld)",
85 if (!rs_initialized
) {
87 _rs_init(rnd
, sizeof(rnd
));
89 _rs_rekey(rnd
, sizeof(rnd
));
90 explicit_bzero(rnd
, sizeof(rnd
));
92 /* invalidate rs_buf */
94 memset(rs_buf
, 0, RSBUFSZ
);
100 _rs_stir_if_needed(size_t len
)
102 pid_t pid
= getpid();
104 if (rs_count
<= len
|| !rs_initialized
|| rs_stir_pid
!= pid
) {
112 _rs_rekey(u_char
*dat
, size_t datlen
)
114 #ifndef KEYSTREAM_ONLY
115 memset(rs_buf
, 0,RSBUFSZ
);
117 /* fill rs_buf with the keystream */
118 chacha_encrypt_bytes(&rs
, rs_buf
, rs_buf
, RSBUFSZ
);
119 /* mix in optional user provided data */
123 m
= MIN(datlen
, KEYSZ
+ IVSZ
);
124 for (i
= 0; i
< m
; i
++)
127 /* immediately reinit for backtracking resistance */
128 _rs_init(rs_buf
, KEYSZ
+ IVSZ
);
129 memset(rs_buf
, 0, KEYSZ
+ IVSZ
);
130 rs_have
= RSBUFSZ
- KEYSZ
- IVSZ
;
134 _rs_random_buf(void *_buf
, size_t n
)
136 u_char
*buf
= (u_char
*)_buf
;
139 _rs_stir_if_needed(n
);
143 memcpy(buf
, rs_buf
+ RSBUFSZ
- rs_have
, m
);
144 memset(rs_buf
+ RSBUFSZ
- rs_have
, 0, m
);
155 _rs_random_u32(u_int32_t
*val
)
157 _rs_stir_if_needed(sizeof(*val
));
158 if (rs_have
< sizeof(*val
))
160 memcpy(val
, rs_buf
+ RSBUFSZ
- rs_have
, sizeof(*val
));
161 memset(rs_buf
+ RSBUFSZ
- rs_have
, 0, sizeof(*val
));
162 rs_have
-= sizeof(*val
);
167 arc4random_stir(void)
175 arc4random_addrandom(u_char
*dat
, int datlen
)
183 m
= MIN(datlen
, KEYSZ
+ IVSZ
);
197 _rs_random_u32(&val
);
203 * If we are providing arc4random, then we can provide a more efficient
206 # ifndef HAVE_ARC4RANDOM_BUF
208 arc4random_buf(void *buf
, size_t n
)
211 _rs_random_buf(buf
, n
);
214 # endif /* !HAVE_ARC4RANDOM_BUF */
215 #endif /* !HAVE_ARC4RANDOM */
217 /* arc4random_buf() that uses platform arc4random() */
218 #if !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM)
220 arc4random_buf(void *_buf
, size_t n
)
224 char *buf
= (char *)_buf
;
226 for (i
= 0; i
< n
; i
++) {
232 explicit_bzero(&r
, sizeof(r
));
234 #endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */
236 #ifndef HAVE_ARC4RANDOM_UNIFORM
238 * Calculate a uniformly distributed random number less than upper_bound
239 * avoiding "modulo bias".
241 * Uniformity is achieved by generating new random numbers until the one
242 * returned is outside the range [0, 2**32 % upper_bound). This
243 * guarantees the selected random number will be inside
244 * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
245 * after reduction modulo upper_bound.
248 arc4random_uniform(u_int32_t upper_bound
)
255 /* 2**32 % x == (2**32 - x) % x */
256 min
= -upper_bound
% upper_bound
;
259 * This could theoretically loop forever but each retry has
260 * p > 0.5 (worst case, usually far better) of selecting a
261 * number inside the range we need, so it should rarely need
270 return r
% upper_bound
;
272 #endif /* !HAVE_ARC4RANDOM_UNIFORM */
275 /*-------- Test code for i386 --------*/
277 #include <machine/pctr.h>
279 main(int argc
, char **argv
)
281 const int iter
= 1000000;
286 for (i
= 0; i
< iter
; i
++)
291 printf("%qd cycles\n", v
);