1*e86afc8fSLeorize /* $OpenBSD: arc4random.c,v 1.54 2015/09/13 08:31:47 guenther Exp $ */
2*e86afc8fSLeorize
3*e86afc8fSLeorize /*
4*e86afc8fSLeorize * Copyright (c) 1996, David Mazieres <dm@uun.org>
5*e86afc8fSLeorize * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6*e86afc8fSLeorize * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7*e86afc8fSLeorize * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8*e86afc8fSLeorize *
9*e86afc8fSLeorize * Permission to use, copy, modify, and distribute this software for any
10*e86afc8fSLeorize * purpose with or without fee is hereby granted, provided that the above
11*e86afc8fSLeorize * copyright notice and this permission notice appear in all copies.
12*e86afc8fSLeorize *
13*e86afc8fSLeorize * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14*e86afc8fSLeorize * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15*e86afc8fSLeorize * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16*e86afc8fSLeorize * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17*e86afc8fSLeorize * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18*e86afc8fSLeorize * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19*e86afc8fSLeorize * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20*e86afc8fSLeorize */
21*e86afc8fSLeorize
22*e86afc8fSLeorize /*
23*e86afc8fSLeorize * ChaCha based random number generator for OpenBSD.
24*e86afc8fSLeorize */
25*e86afc8fSLeorize
26*e86afc8fSLeorize #include <fcntl.h>
27*e86afc8fSLeorize #include <limits.h>
28*e86afc8fSLeorize #include <signal.h>
29*e86afc8fSLeorize #include <stdint.h>
30*e86afc8fSLeorize #include <stdlib.h>
31*e86afc8fSLeorize #include <string.h>
32*e86afc8fSLeorize #include <unistd.h>
33*e86afc8fSLeorize #include <sys/types.h>
34*e86afc8fSLeorize #include <sys/time.h>
35*e86afc8fSLeorize
36*e86afc8fSLeorize #define KEYSTREAM_ONLY
37*e86afc8fSLeorize #include "chacha_private.h"
38*e86afc8fSLeorize
39*e86afc8fSLeorize #define minimum(a, b) ((a) < (b) ? (a) : (b))
40*e86afc8fSLeorize
41*e86afc8fSLeorize #if defined(__GNUC__) || defined(_MSC_VER)
42*e86afc8fSLeorize #define inline __inline
43*e86afc8fSLeorize #else /* __GNUC__ || _MSC_VER */
44*e86afc8fSLeorize #define inline
45*e86afc8fSLeorize #endif /* !__GNUC__ && !_MSC_VER */
46*e86afc8fSLeorize
47*e86afc8fSLeorize #define KEYSZ 32
48*e86afc8fSLeorize #define IVSZ 8
49*e86afc8fSLeorize #define BLOCKSZ 64
50*e86afc8fSLeorize #define RSBUFSZ (16*BLOCKSZ)
51*e86afc8fSLeorize
52*e86afc8fSLeorize /* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
53*e86afc8fSLeorize static struct _rs {
54*e86afc8fSLeorize size_t rs_have; /* valid bytes at end of rs_buf */
55*e86afc8fSLeorize size_t rs_count; /* bytes till reseed */
56*e86afc8fSLeorize } *rs;
57*e86afc8fSLeorize
58*e86afc8fSLeorize /* Maybe be preserved in fork children, if _rs_allocate() decides. */
59*e86afc8fSLeorize static struct _rsx {
60*e86afc8fSLeorize chacha_ctx rs_chacha; /* chacha context for random keystream */
61*e86afc8fSLeorize u_char rs_buf[RSBUFSZ]; /* keystream blocks */
62*e86afc8fSLeorize } *rsx;
63*e86afc8fSLeorize
64*e86afc8fSLeorize
65*e86afc8fSLeorize /*
66*e86afc8fSLeorize * Stub functions for portability.
67*e86afc8fSLeorize */
68*e86afc8fSLeorize
69*e86afc8fSLeorize #include <sys/mman.h>
70*e86afc8fSLeorize
71*e86afc8fSLeorize #include <pthread.h>
72*e86afc8fSLeorize #include <signal.h>
73*e86afc8fSLeorize
74*e86afc8fSLeorize static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
75*e86afc8fSLeorize #define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx)
76*e86afc8fSLeorize #define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
77*e86afc8fSLeorize
78*e86afc8fSLeorize #ifdef __GLIBC__
79*e86afc8fSLeorize extern void *__dso_handle;
80*e86afc8fSLeorize extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
81*e86afc8fSLeorize #define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
82*e86afc8fSLeorize #else
83*e86afc8fSLeorize /*
84*e86afc8fSLeorize * Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if
85*e86afc8fSLeorize * a program does not link to -lthr. Callbacks registered with pthread_atfork()
86*e86afc8fSLeorize * appear to fail silently. So, it is not always possible to detect a PID
87*e86afc8fSLeorize * wraparound.
88*e86afc8fSLeorize */
89*e86afc8fSLeorize #define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
90*e86afc8fSLeorize #endif
91*e86afc8fSLeorize
92*e86afc8fSLeorize static inline void
_getentropy_fail(void)93*e86afc8fSLeorize _getentropy_fail(void)
94*e86afc8fSLeorize {
95*e86afc8fSLeorize raise(SIGKILL);
96*e86afc8fSLeorize }
97*e86afc8fSLeorize
98*e86afc8fSLeorize static volatile sig_atomic_t _rs_forked;
99*e86afc8fSLeorize
100*e86afc8fSLeorize static inline void
_rs_forkhandler(void)101*e86afc8fSLeorize _rs_forkhandler(void)
102*e86afc8fSLeorize {
103*e86afc8fSLeorize _rs_forked = 1;
104*e86afc8fSLeorize }
105*e86afc8fSLeorize
106*e86afc8fSLeorize static inline void
_rs_forkdetect(void)107*e86afc8fSLeorize _rs_forkdetect(void)
108*e86afc8fSLeorize {
109*e86afc8fSLeorize static pid_t _rs_pid = 0;
110*e86afc8fSLeorize pid_t pid = getpid();
111*e86afc8fSLeorize
112*e86afc8fSLeorize if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
113*e86afc8fSLeorize _rs_pid = pid;
114*e86afc8fSLeorize _rs_forked = 0;
115*e86afc8fSLeorize if (rs)
116*e86afc8fSLeorize memset(rs, 0, sizeof(*rs));
117*e86afc8fSLeorize }
118*e86afc8fSLeorize }
119*e86afc8fSLeorize
120*e86afc8fSLeorize static inline int
_rs_allocate(struct _rs ** rsp,struct _rsx ** rsxp)121*e86afc8fSLeorize _rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
122*e86afc8fSLeorize {
123*e86afc8fSLeorize if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
124*e86afc8fSLeorize MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
125*e86afc8fSLeorize return (-1);
126*e86afc8fSLeorize
127*e86afc8fSLeorize if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
128*e86afc8fSLeorize MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
129*e86afc8fSLeorize munmap(*rsp, sizeof(**rsp));
130*e86afc8fSLeorize return (-1);
131*e86afc8fSLeorize }
132*e86afc8fSLeorize
133*e86afc8fSLeorize _ARC4_ATFORK(_rs_forkhandler);
134*e86afc8fSLeorize return (0);
135*e86afc8fSLeorize }
136*e86afc8fSLeorize
137*e86afc8fSLeorize static inline void _rs_rekey(u_char *dat, size_t datlen);
138*e86afc8fSLeorize
139*e86afc8fSLeorize static inline void
_rs_init(u_char * buf,size_t n)140*e86afc8fSLeorize _rs_init(u_char *buf, size_t n)
141*e86afc8fSLeorize {
142*e86afc8fSLeorize if (n < KEYSZ + IVSZ)
143*e86afc8fSLeorize return;
144*e86afc8fSLeorize
145*e86afc8fSLeorize if (rs == NULL) {
146*e86afc8fSLeorize if (_rs_allocate(&rs, &rsx) == -1)
147*e86afc8fSLeorize abort();
148*e86afc8fSLeorize }
149*e86afc8fSLeorize
150*e86afc8fSLeorize chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
151*e86afc8fSLeorize chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
152*e86afc8fSLeorize }
153*e86afc8fSLeorize
154*e86afc8fSLeorize static void
_rs_stir(void)155*e86afc8fSLeorize _rs_stir(void)
156*e86afc8fSLeorize {
157*e86afc8fSLeorize u_char rnd[KEYSZ + IVSZ];
158*e86afc8fSLeorize
159*e86afc8fSLeorize if (getentropy(rnd, sizeof rnd) == -1)
160*e86afc8fSLeorize _getentropy_fail();
161*e86afc8fSLeorize
162*e86afc8fSLeorize if (!rs)
163*e86afc8fSLeorize _rs_init(rnd, sizeof(rnd));
164*e86afc8fSLeorize else
165*e86afc8fSLeorize _rs_rekey(rnd, sizeof(rnd));
166*e86afc8fSLeorize explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
167*e86afc8fSLeorize
168*e86afc8fSLeorize /* invalidate rs_buf */
169*e86afc8fSLeorize rs->rs_have = 0;
170*e86afc8fSLeorize memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
171*e86afc8fSLeorize
172*e86afc8fSLeorize rs->rs_count = 1600000;
173*e86afc8fSLeorize }
174*e86afc8fSLeorize
175*e86afc8fSLeorize static inline void
_rs_stir_if_needed(size_t len)176*e86afc8fSLeorize _rs_stir_if_needed(size_t len)
177*e86afc8fSLeorize {
178*e86afc8fSLeorize _rs_forkdetect();
179*e86afc8fSLeorize if (!rs || rs->rs_count <= len)
180*e86afc8fSLeorize _rs_stir();
181*e86afc8fSLeorize if (rs->rs_count <= len)
182*e86afc8fSLeorize rs->rs_count = 0;
183*e86afc8fSLeorize else
184*e86afc8fSLeorize rs->rs_count -= len;
185*e86afc8fSLeorize }
186*e86afc8fSLeorize
187*e86afc8fSLeorize static inline void
_rs_rekey(u_char * dat,size_t datlen)188*e86afc8fSLeorize _rs_rekey(u_char *dat, size_t datlen)
189*e86afc8fSLeorize {
190*e86afc8fSLeorize #ifndef KEYSTREAM_ONLY
191*e86afc8fSLeorize memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
192*e86afc8fSLeorize #endif
193*e86afc8fSLeorize /* fill rs_buf with the keystream */
194*e86afc8fSLeorize chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
195*e86afc8fSLeorize rsx->rs_buf, sizeof(rsx->rs_buf));
196*e86afc8fSLeorize /* mix in optional user provided data */
197*e86afc8fSLeorize if (dat) {
198*e86afc8fSLeorize size_t i, m;
199*e86afc8fSLeorize
200*e86afc8fSLeorize m = minimum(datlen, KEYSZ + IVSZ);
201*e86afc8fSLeorize for (i = 0; i < m; i++)
202*e86afc8fSLeorize rsx->rs_buf[i] ^= dat[i];
203*e86afc8fSLeorize }
204*e86afc8fSLeorize /* immediately reinit for backtracking resistance */
205*e86afc8fSLeorize _rs_init(rsx->rs_buf, KEYSZ + IVSZ);
206*e86afc8fSLeorize memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
207*e86afc8fSLeorize rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
208*e86afc8fSLeorize }
209*e86afc8fSLeorize
210*e86afc8fSLeorize static inline void
_rs_random_buf(void * _buf,size_t n)211*e86afc8fSLeorize _rs_random_buf(void *_buf, size_t n)
212*e86afc8fSLeorize {
213*e86afc8fSLeorize u_char *buf = (u_char *)_buf;
214*e86afc8fSLeorize u_char *keystream;
215*e86afc8fSLeorize size_t m;
216*e86afc8fSLeorize
217*e86afc8fSLeorize _rs_stir_if_needed(n);
218*e86afc8fSLeorize while (n > 0) {
219*e86afc8fSLeorize if (rs->rs_have > 0) {
220*e86afc8fSLeorize m = minimum(n, rs->rs_have);
221*e86afc8fSLeorize keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
222*e86afc8fSLeorize - rs->rs_have;
223*e86afc8fSLeorize memcpy(buf, keystream, m);
224*e86afc8fSLeorize memset(keystream, 0, m);
225*e86afc8fSLeorize buf += m;
226*e86afc8fSLeorize n -= m;
227*e86afc8fSLeorize rs->rs_have -= m;
228*e86afc8fSLeorize }
229*e86afc8fSLeorize if (rs->rs_have == 0)
230*e86afc8fSLeorize _rs_rekey(NULL, 0);
231*e86afc8fSLeorize }
232*e86afc8fSLeorize }
233*e86afc8fSLeorize
234*e86afc8fSLeorize static inline void
_rs_random_u32(uint32_t * val)235*e86afc8fSLeorize _rs_random_u32(uint32_t *val)
236*e86afc8fSLeorize {
237*e86afc8fSLeorize u_char *keystream;
238*e86afc8fSLeorize
239*e86afc8fSLeorize _rs_stir_if_needed(sizeof(*val));
240*e86afc8fSLeorize if (rs->rs_have < sizeof(*val))
241*e86afc8fSLeorize _rs_rekey(NULL, 0);
242*e86afc8fSLeorize keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
243*e86afc8fSLeorize memcpy(val, keystream, sizeof(*val));
244*e86afc8fSLeorize memset(keystream, 0, sizeof(*val));
245*e86afc8fSLeorize rs->rs_have -= sizeof(*val);
246*e86afc8fSLeorize }
247*e86afc8fSLeorize
248*e86afc8fSLeorize uint32_t
arc4random(void)249*e86afc8fSLeorize arc4random(void)
250*e86afc8fSLeorize {
251*e86afc8fSLeorize uint32_t val;
252*e86afc8fSLeorize
253*e86afc8fSLeorize _ARC4_LOCK();
254*e86afc8fSLeorize _rs_random_u32(&val);
255*e86afc8fSLeorize _ARC4_UNLOCK();
256*e86afc8fSLeorize return val;
257*e86afc8fSLeorize }
258*e86afc8fSLeorize
259*e86afc8fSLeorize void
arc4random_buf(void * buf,size_t n)260*e86afc8fSLeorize arc4random_buf(void *buf, size_t n)
261*e86afc8fSLeorize {
262*e86afc8fSLeorize _ARC4_LOCK();
263*e86afc8fSLeorize _rs_random_buf(buf, n);
264*e86afc8fSLeorize _ARC4_UNLOCK();
265*e86afc8fSLeorize }
266