xref: /freebsd/crypto/openssh/openbsd-compat/arc4random.c (revision f7167e0ea0bf5aaabff9490453b3b71b3f1b4d51)
1*f7167e0eSDag-Erling Smørgrav /* OPENBSD ORIGINAL: lib/libc/crypto/arc4random.c */
2*f7167e0eSDag-Erling Smørgrav 
3*f7167e0eSDag-Erling Smørgrav /*	$OpenBSD: arc4random.c,v 1.25 2013/10/01 18:34:57 markus Exp $	*/
4*f7167e0eSDag-Erling Smørgrav 
5*f7167e0eSDag-Erling Smørgrav /*
6*f7167e0eSDag-Erling Smørgrav  * Copyright (c) 1996, David Mazieres <dm@uun.org>
7*f7167e0eSDag-Erling Smørgrav  * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
8*f7167e0eSDag-Erling Smørgrav  * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
9*f7167e0eSDag-Erling Smørgrav  *
10*f7167e0eSDag-Erling Smørgrav  * Permission to use, copy, modify, and distribute this software for any
11*f7167e0eSDag-Erling Smørgrav  * purpose with or without fee is hereby granted, provided that the above
12*f7167e0eSDag-Erling Smørgrav  * copyright notice and this permission notice appear in all copies.
13*f7167e0eSDag-Erling Smørgrav  *
14*f7167e0eSDag-Erling Smørgrav  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15*f7167e0eSDag-Erling Smørgrav  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16*f7167e0eSDag-Erling Smørgrav  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17*f7167e0eSDag-Erling Smørgrav  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18*f7167e0eSDag-Erling Smørgrav  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19*f7167e0eSDag-Erling Smørgrav  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20*f7167e0eSDag-Erling Smørgrav  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21*f7167e0eSDag-Erling Smørgrav  */
22*f7167e0eSDag-Erling Smørgrav 
23*f7167e0eSDag-Erling Smørgrav /*
24*f7167e0eSDag-Erling Smørgrav  * ChaCha based random number generator for OpenBSD.
25*f7167e0eSDag-Erling Smørgrav  */
26*f7167e0eSDag-Erling Smørgrav 
27*f7167e0eSDag-Erling Smørgrav #include "includes.h"
28*f7167e0eSDag-Erling Smørgrav 
29*f7167e0eSDag-Erling Smørgrav #include <stdlib.h>
30*f7167e0eSDag-Erling Smørgrav #include <string.h>
31*f7167e0eSDag-Erling Smørgrav #include <unistd.h>
32*f7167e0eSDag-Erling Smørgrav #include <sys/types.h>
33*f7167e0eSDag-Erling Smørgrav 
34*f7167e0eSDag-Erling Smørgrav #ifndef HAVE_ARC4RANDOM
35*f7167e0eSDag-Erling Smørgrav 
36*f7167e0eSDag-Erling Smørgrav #include <openssl/rand.h>
37*f7167e0eSDag-Erling Smørgrav #include <openssl/err.h>
38*f7167e0eSDag-Erling Smørgrav 
39*f7167e0eSDag-Erling Smørgrav #include "log.h"
40*f7167e0eSDag-Erling Smørgrav 
41*f7167e0eSDag-Erling Smørgrav #define KEYSTREAM_ONLY
42*f7167e0eSDag-Erling Smørgrav #include "chacha_private.h"
43*f7167e0eSDag-Erling Smørgrav 
44*f7167e0eSDag-Erling Smørgrav #ifdef __GNUC__
45*f7167e0eSDag-Erling Smørgrav #define inline __inline
46*f7167e0eSDag-Erling Smørgrav #else				/* !__GNUC__ */
47*f7167e0eSDag-Erling Smørgrav #define inline
48*f7167e0eSDag-Erling Smørgrav #endif				/* !__GNUC__ */
49*f7167e0eSDag-Erling Smørgrav 
50*f7167e0eSDag-Erling Smørgrav /* OpenSSH isn't multithreaded */
51*f7167e0eSDag-Erling Smørgrav #define _ARC4_LOCK()
52*f7167e0eSDag-Erling Smørgrav #define _ARC4_UNLOCK()
53*f7167e0eSDag-Erling Smørgrav 
54*f7167e0eSDag-Erling Smørgrav #define KEYSZ	32
55*f7167e0eSDag-Erling Smørgrav #define IVSZ	8
56*f7167e0eSDag-Erling Smørgrav #define BLOCKSZ	64
57*f7167e0eSDag-Erling Smørgrav #define RSBUFSZ	(16*BLOCKSZ)
58*f7167e0eSDag-Erling Smørgrav static int rs_initialized;
59*f7167e0eSDag-Erling Smørgrav static pid_t rs_stir_pid;
60*f7167e0eSDag-Erling Smørgrav static chacha_ctx rs;		/* chacha context for random keystream */
61*f7167e0eSDag-Erling Smørgrav static u_char rs_buf[RSBUFSZ];	/* keystream blocks */
62*f7167e0eSDag-Erling Smørgrav static size_t rs_have;		/* valid bytes at end of rs_buf */
63*f7167e0eSDag-Erling Smørgrav static size_t rs_count;		/* bytes till reseed */
64*f7167e0eSDag-Erling Smørgrav 
65*f7167e0eSDag-Erling Smørgrav static inline void _rs_rekey(u_char *dat, size_t datlen);
66*f7167e0eSDag-Erling Smørgrav 
67*f7167e0eSDag-Erling Smørgrav static inline void
68*f7167e0eSDag-Erling Smørgrav _rs_init(u_char *buf, size_t n)
69*f7167e0eSDag-Erling Smørgrav {
70*f7167e0eSDag-Erling Smørgrav 	if (n < KEYSZ + IVSZ)
71*f7167e0eSDag-Erling Smørgrav 		return;
72*f7167e0eSDag-Erling Smørgrav 	chacha_keysetup(&rs, buf, KEYSZ * 8, 0);
73*f7167e0eSDag-Erling Smørgrav 	chacha_ivsetup(&rs, buf + KEYSZ);
74*f7167e0eSDag-Erling Smørgrav }
75*f7167e0eSDag-Erling Smørgrav 
76*f7167e0eSDag-Erling Smørgrav static void
77*f7167e0eSDag-Erling Smørgrav _rs_stir(void)
78*f7167e0eSDag-Erling Smørgrav {
79*f7167e0eSDag-Erling Smørgrav 	u_char rnd[KEYSZ + IVSZ];
80*f7167e0eSDag-Erling Smørgrav 
81*f7167e0eSDag-Erling Smørgrav 	if (RAND_bytes(rnd, sizeof(rnd)) <= 0)
82*f7167e0eSDag-Erling Smørgrav 		fatal("Couldn't obtain random bytes (error %ld)",
83*f7167e0eSDag-Erling Smørgrav 		    ERR_get_error());
84*f7167e0eSDag-Erling Smørgrav 
85*f7167e0eSDag-Erling Smørgrav 	if (!rs_initialized) {
86*f7167e0eSDag-Erling Smørgrav 		rs_initialized = 1;
87*f7167e0eSDag-Erling Smørgrav 		_rs_init(rnd, sizeof(rnd));
88*f7167e0eSDag-Erling Smørgrav 	} else
89*f7167e0eSDag-Erling Smørgrav 		_rs_rekey(rnd, sizeof(rnd));
90*f7167e0eSDag-Erling Smørgrav 	memset(rnd, 0, sizeof(rnd));
91*f7167e0eSDag-Erling Smørgrav 
92*f7167e0eSDag-Erling Smørgrav 	/* invalidate rs_buf */
93*f7167e0eSDag-Erling Smørgrav 	rs_have = 0;
94*f7167e0eSDag-Erling Smørgrav 	memset(rs_buf, 0, RSBUFSZ);
95*f7167e0eSDag-Erling Smørgrav 
96*f7167e0eSDag-Erling Smørgrav 	rs_count = 1600000;
97*f7167e0eSDag-Erling Smørgrav }
98*f7167e0eSDag-Erling Smørgrav 
99*f7167e0eSDag-Erling Smørgrav static inline void
100*f7167e0eSDag-Erling Smørgrav _rs_stir_if_needed(size_t len)
101*f7167e0eSDag-Erling Smørgrav {
102*f7167e0eSDag-Erling Smørgrav 	pid_t pid = getpid();
103*f7167e0eSDag-Erling Smørgrav 
104*f7167e0eSDag-Erling Smørgrav 	if (rs_count <= len || !rs_initialized || rs_stir_pid != pid) {
105*f7167e0eSDag-Erling Smørgrav 		rs_stir_pid = pid;
106*f7167e0eSDag-Erling Smørgrav 		_rs_stir();
107*f7167e0eSDag-Erling Smørgrav 	} else
108*f7167e0eSDag-Erling Smørgrav 		rs_count -= len;
109*f7167e0eSDag-Erling Smørgrav }
110*f7167e0eSDag-Erling Smørgrav 
111*f7167e0eSDag-Erling Smørgrav static inline void
112*f7167e0eSDag-Erling Smørgrav _rs_rekey(u_char *dat, size_t datlen)
113*f7167e0eSDag-Erling Smørgrav {
114*f7167e0eSDag-Erling Smørgrav #ifndef KEYSTREAM_ONLY
115*f7167e0eSDag-Erling Smørgrav 	memset(rs_buf, 0,RSBUFSZ);
116*f7167e0eSDag-Erling Smørgrav #endif
117*f7167e0eSDag-Erling Smørgrav 	/* fill rs_buf with the keystream */
118*f7167e0eSDag-Erling Smørgrav 	chacha_encrypt_bytes(&rs, rs_buf, rs_buf, RSBUFSZ);
119*f7167e0eSDag-Erling Smørgrav 	/* mix in optional user provided data */
120*f7167e0eSDag-Erling Smørgrav 	if (dat) {
121*f7167e0eSDag-Erling Smørgrav 		size_t i, m;
122*f7167e0eSDag-Erling Smørgrav 
123*f7167e0eSDag-Erling Smørgrav 		m = MIN(datlen, KEYSZ + IVSZ);
124*f7167e0eSDag-Erling Smørgrav 		for (i = 0; i < m; i++)
125*f7167e0eSDag-Erling Smørgrav 			rs_buf[i] ^= dat[i];
126*f7167e0eSDag-Erling Smørgrav 	}
127*f7167e0eSDag-Erling Smørgrav 	/* immediately reinit for backtracking resistance */
128*f7167e0eSDag-Erling Smørgrav 	_rs_init(rs_buf, KEYSZ + IVSZ);
129*f7167e0eSDag-Erling Smørgrav 	memset(rs_buf, 0, KEYSZ + IVSZ);
130*f7167e0eSDag-Erling Smørgrav 	rs_have = RSBUFSZ - KEYSZ - IVSZ;
131*f7167e0eSDag-Erling Smørgrav }
132*f7167e0eSDag-Erling Smørgrav 
133*f7167e0eSDag-Erling Smørgrav static inline void
134*f7167e0eSDag-Erling Smørgrav _rs_random_buf(void *_buf, size_t n)
135*f7167e0eSDag-Erling Smørgrav {
136*f7167e0eSDag-Erling Smørgrav 	u_char *buf = (u_char *)_buf;
137*f7167e0eSDag-Erling Smørgrav 	size_t m;
138*f7167e0eSDag-Erling Smørgrav 
139*f7167e0eSDag-Erling Smørgrav 	_rs_stir_if_needed(n);
140*f7167e0eSDag-Erling Smørgrav 	while (n > 0) {
141*f7167e0eSDag-Erling Smørgrav 		if (rs_have > 0) {
142*f7167e0eSDag-Erling Smørgrav 			m = MIN(n, rs_have);
143*f7167e0eSDag-Erling Smørgrav 			memcpy(buf, rs_buf + RSBUFSZ - rs_have, m);
144*f7167e0eSDag-Erling Smørgrav 			memset(rs_buf + RSBUFSZ - rs_have, 0, m);
145*f7167e0eSDag-Erling Smørgrav 			buf += m;
146*f7167e0eSDag-Erling Smørgrav 			n -= m;
147*f7167e0eSDag-Erling Smørgrav 			rs_have -= m;
148*f7167e0eSDag-Erling Smørgrav 		}
149*f7167e0eSDag-Erling Smørgrav 		if (rs_have == 0)
150*f7167e0eSDag-Erling Smørgrav 			_rs_rekey(NULL, 0);
151*f7167e0eSDag-Erling Smørgrav 	}
152*f7167e0eSDag-Erling Smørgrav }
153*f7167e0eSDag-Erling Smørgrav 
154*f7167e0eSDag-Erling Smørgrav static inline void
155*f7167e0eSDag-Erling Smørgrav _rs_random_u32(u_int32_t *val)
156*f7167e0eSDag-Erling Smørgrav {
157*f7167e0eSDag-Erling Smørgrav 	_rs_stir_if_needed(sizeof(*val));
158*f7167e0eSDag-Erling Smørgrav 	if (rs_have < sizeof(*val))
159*f7167e0eSDag-Erling Smørgrav 		_rs_rekey(NULL, 0);
160*f7167e0eSDag-Erling Smørgrav 	memcpy(val, rs_buf + RSBUFSZ - rs_have, sizeof(*val));
161*f7167e0eSDag-Erling Smørgrav 	memset(rs_buf + RSBUFSZ - rs_have, 0, sizeof(*val));
162*f7167e0eSDag-Erling Smørgrav 	rs_have -= sizeof(*val);
163*f7167e0eSDag-Erling Smørgrav 	return;
164*f7167e0eSDag-Erling Smørgrav }
165*f7167e0eSDag-Erling Smørgrav 
166*f7167e0eSDag-Erling Smørgrav void
167*f7167e0eSDag-Erling Smørgrav arc4random_stir(void)
168*f7167e0eSDag-Erling Smørgrav {
169*f7167e0eSDag-Erling Smørgrav 	_ARC4_LOCK();
170*f7167e0eSDag-Erling Smørgrav 	_rs_stir();
171*f7167e0eSDag-Erling Smørgrav 	_ARC4_UNLOCK();
172*f7167e0eSDag-Erling Smørgrav }
173*f7167e0eSDag-Erling Smørgrav 
174*f7167e0eSDag-Erling Smørgrav void
175*f7167e0eSDag-Erling Smørgrav arc4random_addrandom(u_char *dat, int datlen)
176*f7167e0eSDag-Erling Smørgrav {
177*f7167e0eSDag-Erling Smørgrav 	int m;
178*f7167e0eSDag-Erling Smørgrav 
179*f7167e0eSDag-Erling Smørgrav 	_ARC4_LOCK();
180*f7167e0eSDag-Erling Smørgrav 	if (!rs_initialized)
181*f7167e0eSDag-Erling Smørgrav 		_rs_stir();
182*f7167e0eSDag-Erling Smørgrav 	while (datlen > 0) {
183*f7167e0eSDag-Erling Smørgrav 		m = MIN(datlen, KEYSZ + IVSZ);
184*f7167e0eSDag-Erling Smørgrav 		_rs_rekey(dat, m);
185*f7167e0eSDag-Erling Smørgrav 		dat += m;
186*f7167e0eSDag-Erling Smørgrav 		datlen -= m;
187*f7167e0eSDag-Erling Smørgrav 	}
188*f7167e0eSDag-Erling Smørgrav 	_ARC4_UNLOCK();
189*f7167e0eSDag-Erling Smørgrav }
190*f7167e0eSDag-Erling Smørgrav 
191*f7167e0eSDag-Erling Smørgrav u_int32_t
192*f7167e0eSDag-Erling Smørgrav arc4random(void)
193*f7167e0eSDag-Erling Smørgrav {
194*f7167e0eSDag-Erling Smørgrav 	u_int32_t val;
195*f7167e0eSDag-Erling Smørgrav 
196*f7167e0eSDag-Erling Smørgrav 	_ARC4_LOCK();
197*f7167e0eSDag-Erling Smørgrav 	_rs_random_u32(&val);
198*f7167e0eSDag-Erling Smørgrav 	_ARC4_UNLOCK();
199*f7167e0eSDag-Erling Smørgrav 	return val;
200*f7167e0eSDag-Erling Smørgrav }
201*f7167e0eSDag-Erling Smørgrav 
202*f7167e0eSDag-Erling Smørgrav /*
203*f7167e0eSDag-Erling Smørgrav  * If we are providing arc4random, then we can provide a more efficient
204*f7167e0eSDag-Erling Smørgrav  * arc4random_buf().
205*f7167e0eSDag-Erling Smørgrav  */
206*f7167e0eSDag-Erling Smørgrav # ifndef HAVE_ARC4RANDOM_BUF
207*f7167e0eSDag-Erling Smørgrav void
208*f7167e0eSDag-Erling Smørgrav arc4random_buf(void *buf, size_t n)
209*f7167e0eSDag-Erling Smørgrav {
210*f7167e0eSDag-Erling Smørgrav 	_ARC4_LOCK();
211*f7167e0eSDag-Erling Smørgrav 	_rs_random_buf(buf, n);
212*f7167e0eSDag-Erling Smørgrav 	_ARC4_UNLOCK();
213*f7167e0eSDag-Erling Smørgrav }
214*f7167e0eSDag-Erling Smørgrav # endif /* !HAVE_ARC4RANDOM_BUF */
215*f7167e0eSDag-Erling Smørgrav #endif /* !HAVE_ARC4RANDOM */
216*f7167e0eSDag-Erling Smørgrav 
217*f7167e0eSDag-Erling Smørgrav /* arc4random_buf() that uses platform arc4random() */
218*f7167e0eSDag-Erling Smørgrav #if !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM)
219*f7167e0eSDag-Erling Smørgrav void
220*f7167e0eSDag-Erling Smørgrav arc4random_buf(void *_buf, size_t n)
221*f7167e0eSDag-Erling Smørgrav {
222*f7167e0eSDag-Erling Smørgrav 	size_t i;
223*f7167e0eSDag-Erling Smørgrav 	u_int32_t r = 0;
224*f7167e0eSDag-Erling Smørgrav 	char *buf = (char *)_buf;
225*f7167e0eSDag-Erling Smørgrav 
226*f7167e0eSDag-Erling Smørgrav 	for (i = 0; i < n; i++) {
227*f7167e0eSDag-Erling Smørgrav 		if (i % 4 == 0)
228*f7167e0eSDag-Erling Smørgrav 			r = arc4random();
229*f7167e0eSDag-Erling Smørgrav 		buf[i] = r & 0xff;
230*f7167e0eSDag-Erling Smørgrav 		r >>= 8;
231*f7167e0eSDag-Erling Smørgrav 	}
232*f7167e0eSDag-Erling Smørgrav 	i = r = 0;
233*f7167e0eSDag-Erling Smørgrav }
234*f7167e0eSDag-Erling Smørgrav #endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */
235*f7167e0eSDag-Erling Smørgrav 
236*f7167e0eSDag-Erling Smørgrav #ifndef HAVE_ARC4RANDOM_UNIFORM
237*f7167e0eSDag-Erling Smørgrav /*
238*f7167e0eSDag-Erling Smørgrav  * Calculate a uniformly distributed random number less than upper_bound
239*f7167e0eSDag-Erling Smørgrav  * avoiding "modulo bias".
240*f7167e0eSDag-Erling Smørgrav  *
241*f7167e0eSDag-Erling Smørgrav  * Uniformity is achieved by generating new random numbers until the one
242*f7167e0eSDag-Erling Smørgrav  * returned is outside the range [0, 2**32 % upper_bound).  This
243*f7167e0eSDag-Erling Smørgrav  * guarantees the selected random number will be inside
244*f7167e0eSDag-Erling Smørgrav  * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
245*f7167e0eSDag-Erling Smørgrav  * after reduction modulo upper_bound.
246*f7167e0eSDag-Erling Smørgrav  */
247*f7167e0eSDag-Erling Smørgrav u_int32_t
248*f7167e0eSDag-Erling Smørgrav arc4random_uniform(u_int32_t upper_bound)
249*f7167e0eSDag-Erling Smørgrav {
250*f7167e0eSDag-Erling Smørgrav 	u_int32_t r, min;
251*f7167e0eSDag-Erling Smørgrav 
252*f7167e0eSDag-Erling Smørgrav 	if (upper_bound < 2)
253*f7167e0eSDag-Erling Smørgrav 		return 0;
254*f7167e0eSDag-Erling Smørgrav 
255*f7167e0eSDag-Erling Smørgrav 	/* 2**32 % x == (2**32 - x) % x */
256*f7167e0eSDag-Erling Smørgrav 	min = -upper_bound % upper_bound;
257*f7167e0eSDag-Erling Smørgrav 
258*f7167e0eSDag-Erling Smørgrav 	/*
259*f7167e0eSDag-Erling Smørgrav 	 * This could theoretically loop forever but each retry has
260*f7167e0eSDag-Erling Smørgrav 	 * p > 0.5 (worst case, usually far better) of selecting a
261*f7167e0eSDag-Erling Smørgrav 	 * number inside the range we need, so it should rarely need
262*f7167e0eSDag-Erling Smørgrav 	 * to re-roll.
263*f7167e0eSDag-Erling Smørgrav 	 */
264*f7167e0eSDag-Erling Smørgrav 	for (;;) {
265*f7167e0eSDag-Erling Smørgrav 		r = arc4random();
266*f7167e0eSDag-Erling Smørgrav 		if (r >= min)
267*f7167e0eSDag-Erling Smørgrav 			break;
268*f7167e0eSDag-Erling Smørgrav 	}
269*f7167e0eSDag-Erling Smørgrav 
270*f7167e0eSDag-Erling Smørgrav 	return r % upper_bound;
271*f7167e0eSDag-Erling Smørgrav }
272*f7167e0eSDag-Erling Smørgrav #endif /* !HAVE_ARC4RANDOM_UNIFORM */
273*f7167e0eSDag-Erling Smørgrav 
274*f7167e0eSDag-Erling Smørgrav #if 0
275*f7167e0eSDag-Erling Smørgrav /*-------- Test code for i386 --------*/
276*f7167e0eSDag-Erling Smørgrav #include <stdio.h>
277*f7167e0eSDag-Erling Smørgrav #include <machine/pctr.h>
278*f7167e0eSDag-Erling Smørgrav int
279*f7167e0eSDag-Erling Smørgrav main(int argc, char **argv)
280*f7167e0eSDag-Erling Smørgrav {
281*f7167e0eSDag-Erling Smørgrav 	const int iter = 1000000;
282*f7167e0eSDag-Erling Smørgrav 	int     i;
283*f7167e0eSDag-Erling Smørgrav 	pctrval v;
284*f7167e0eSDag-Erling Smørgrav 
285*f7167e0eSDag-Erling Smørgrav 	v = rdtsc();
286*f7167e0eSDag-Erling Smørgrav 	for (i = 0; i < iter; i++)
287*f7167e0eSDag-Erling Smørgrav 		arc4random();
288*f7167e0eSDag-Erling Smørgrav 	v = rdtsc() - v;
289*f7167e0eSDag-Erling Smørgrav 	v /= iter;
290*f7167e0eSDag-Erling Smørgrav 
291*f7167e0eSDag-Erling Smørgrav 	printf("%qd cycles\n", v);
292*f7167e0eSDag-Erling Smørgrav 	exit(0);
293*f7167e0eSDag-Erling Smørgrav }
294*f7167e0eSDag-Erling Smørgrav #endif
295