1 /*-
2  * Copyright (c) 2010, 2011, 2012, 2014
3  *	Thorsten Glaser <tg@mirbsd.org>
4  *
5  * Provided that these terms and disclaimer and all copyright notices
6  * are retained or reproduced in an accompanying document, permission
7  * is granted to deal in this work without restriction, including un-
8  * limited rights to use, publicly perform, distribute, sell, modify,
9  * merge, give away, or sublicence.
10  *
11  * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
12  * the utmost extent permitted by applicable law, neither express nor
13  * implied; without malicious intent or gross negligence. In no event
14  * may a licensor, author or contributor be held liable for indirect,
15  * direct, other damage, loss, or other issues arising in any way out
16  * of dealing in the work, even if advised of the possibility of such
17  * damage or existence of a defect, except proven that it results out
18  * of said person's immediate fault when using the work as intended.
19  *-
20  * The idea of an arc4random(3) stems from David Mazieres for OpenBSD
21  * but this has been reimplemented, improved, corrected, modularised.
22  * The idea of pushing entropy back to the kernel on stir and after a
23  * fork or before an exit is MirBSD specific.
24  */
25 
26 #include <sys/param.h>
27 #include <sys/sysctl.h>
28 #include <sys/time.h>
29 #include <syskern/libckern.h>
30 #include <syskern/mirhash.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include "arc4random.h"
35 #include "thread_private.h"
36 
37 __RCSID("$MirOS: src/lib/libc/crypt/arc4random_base.c,v 1.15 2014/04/09 23:10:51 tg Exp $");
38 
39 /* zero-initialises */
40 struct arc4random_status a4state;
41 
42 void
arc4random_atexit(void)43 arc4random_atexit(void)
44 {
45 	arc4random_ctl(1);
46 }
47 
48 u_int32_t
arc4random(void)49 arc4random(void)
50 {
51 	uint32_t v;
52 	pid_t mypid = 0;
53 
54 	_ARC4_LOCK();
55 
56 	/* reinitialise after fork, (count) bytes or if not initialised */
57 	a4state.a4s_count -= 4;
58 	if (a4state.a4s_count <= 0 || !a4state.a4s_initialised ||
59 	    (a4state.a4s_stir_pid != (mypid = getpid())))
60 		arc4random_stir_locked(mypid);
61 
62 	/* randomly skip a byte or two */
63 	/*XXX this should be constant-time */
64 	if (arcfour_byte(&a4state.cipher) & 1)
65 		(void)arcfour_byte(&a4state.cipher);
66 
67 	v = ((uint32_t)arcfour_byte(&a4state.cipher) << 24) |
68 	    ((uint32_t)arcfour_byte(&a4state.cipher) << 16) |
69 	    ((uint32_t)arcfour_byte(&a4state.cipher) << 8) |
70 	    ((uint32_t)arcfour_byte(&a4state.cipher));
71 
72 	_ARC4_UNLOCK();
73 	return (v);
74 }
75 
76 void
arc4random_stir_locked(pid_t mypid)77 arc4random_stir_locked(pid_t mypid)
78 {
79 	size_t n;
80 	unsigned int carry;
81 	int mib[2];
82 	union {
83 		uint8_t charbuf[256];
84 		uint32_t intbuf[64];
85 		struct {
86 			struct timespec rtime;
87 #if 0
88 			struct timespec vtime;
89 			struct timespec ptime;
90 #endif
91 			struct timespec ntime;
92 			pid_t thepid;
93 		} tmpbuf;
94 	} sbuf;
95 
96 	if (!a4state.a4s_initialised) {
97 		arcfour_init(&a4state.cipher);
98 		a4state.a4s_poolptr = 0;
99 	}
100 	carry = arcfour_byte(&a4state.cipher);
101 	/* throw stuff into the roundhash pool */
102 	arc4random_roundhash(a4state.pool, &a4state.a4s_poolptr,
103 	    &a4state.otherinfo, sizeof(a4state.otherinfo));
104 	clock_gettime(CLOCK_REALTIME, &sbuf.tmpbuf.rtime);
105 #if 0
106 	clock_gettime(CLOCK_VIRTUAL, &sbuf.tmpbuf.vtime);
107 	clock_gettime(CLOCK_PROF, &sbuf.tmpbuf.ptime);
108 #endif
109 	clock_gettime(CLOCK_MONOTONIC, &sbuf.tmpbuf.ntime);
110 	sbuf.tmpbuf.thepid = mypid = mypid ? mypid : getpid();
111 	arc4random_roundhash(a4state.pool, &a4state.a4s_poolptr,
112 	    &sbuf.tmpbuf, sizeof(sbuf.tmpbuf));
113 
114 	/* fill first 128 bytes with roundhash pool */
115 	n = 1 + (carry & 1);
116 	carry >>= 1;
117 	while (n--)
118 		(void)arcfour_byte(&a4state.cipher);
119 	for (n = 0; n < 32; ++n) {
120 		register uint32_t h;
121 
122 		h = a4state.pool[n];
123 		/* mask and mix */
124 		BAFHUpdateOctet_reg(h, arcfour_byte(&a4state.cipher));
125 		BAFHFinish_reg(h);
126 		sbuf.intbuf[n] = h;
127 	}
128 
129 	/* fill second 128 bytes with local random stuff */
130 	n = 1 + (carry & 1);
131 	carry >>= 1;
132 	while (n--)
133 		(void)arcfour_byte(&a4state.cipher);
134 	for (n = 128; n < 256; ++n)
135 		sbuf.charbuf[n] = arcfour_byte(&a4state.cipher);
136 	n = carry & 3;
137 	carry &= 0x3C;
138 	while (n--)
139 		(void)arcfour_byte(&a4state.cipher);
140 
141 	/* exchange full 256 bytes with kernel */
142 	mib[0] = CTL_KERN;
143 	mib[1] = KERN_ARND;
144 	n = sizeof(sbuf);
145 	sysctl(mib, 2, sbuf.charbuf, &n, sbuf.charbuf, sizeof(sbuf));
146 	/* if (n != sizeof(sbuf)) something went wrong inside the kernel */
147 
148 	/* mix first 128 bytes with/into roundhash pool */
149 	for (n = 0; n < 32; ++n) {
150 		register uint32_t ha, hr;
151 
152 		ha = (a4state.pool[n] & 0xFFFF0000) |
153 		    (sbuf.intbuf[n] & 0x0000FFFF);
154 		hr = (a4state.pool[n] & 0x0000FFFF) |
155 		    (sbuf.intbuf[n] & 0xFFFF0000);
156 		/* mix then mask for arc4random */
157 		BAFHFinish_reg(ha);
158 		BAFHUpdateOctet_reg(ha, arcfour_byte(&a4state.cipher));
159 		sbuf.intbuf[n] = ha;
160 		/* mix then mask for roundhash */
161 		BAFHFinish_reg(hr);
162 		BAFHUpdateOctet_reg(hr, arcfour_byte(&a4state.cipher));
163 		a4state.pool[n] = hr;
164 	}
165 	/* mix full 256 bytes into arc4random pool */
166 	arcfour_ksa(&a4state.cipher, sbuf.charbuf, 256);
167 
168 	/* trash stack */
169 	bzero(sbuf.charbuf, sizeof(sbuf));
170 
171 	/* discard early keystream */
172 	carry += 256 * 12 + (arcfour_byte(&a4state.cipher) & 0x1F);
173 	while (carry--)
174 		(void)arcfour_byte(&a4state.cipher);
175 
176 	a4state.a4s_poolptr = 0;
177 	a4state.a4s_initialised = 1;
178 	a4state.a4s_stir_pid = mypid;
179 	a4state.a4s_count = 1600000;
180 }
181 
182 /*
183  * This is a deliberately undocumented internal API.
184  * - whence & 7 = mode
185  *   + 0 = shuffle user-space only
186  *   + 1 = move stuff to kernel (e.g. for reboot)
187  *   + 2 = schedule stirring upon next access
188  * - rest MBZ
189  */
190 void
arc4random_ctl(unsigned int whence)191 arc4random_ctl(unsigned int whence)
192 {
193 	size_t n;
194 	uint8_t *buf;
195 	struct {
196 		struct timespec tp;
197 		const void *dp, *sp;
198 		unsigned int wi;
199 		struct arcfour_otherinfo oi;
200 	} pbuf;
201 	int mib[2];
202 
203 	clock_gettime(CLOCK_MONOTONIC, &pbuf.tp);
204 	pbuf.sp = &pbuf;
205 	pbuf.dp = &whence;
206 	pbuf.wi = whence;
207 	_ARC4_LOCK();
208 	memcpy(&pbuf.oi, &a4state.otherinfo, sizeof(struct arcfour_otherinfo));
209 	if (!a4state.a4s_initialised)
210 		arc4random_stir_locked(0);
211 	arc4random_roundhash(a4state.pool, &a4state.a4s_poolptr,
212 	    &pbuf, sizeof(pbuf));
213 
214 	switch (whence /* & 7 */) {
215 	default:
216 		break;
217 	case 2:
218 		a4state.a4s_count = -1;
219 		break;
220 	case 1:
221 		/* first put everything we have into the pool */
222 		arc4random_roundhash(a4state.pool, &a4state.a4s_poolptr,
223 		    &a4state.cipher, sizeof(a4state.cipher));
224 		/* then write the pool into the kernel and overwrite it */
225 		mib[0] = CTL_KERN;
226 		mib[1] = KERN_ARND;
227 		n = sizeof(a4state.pool);
228 		sysctl(mib, 2, a4state.pool, &n, a4state.pool,
229 		    sizeof(a4state.pool));
230 		/* then blind a bit for continued use, just in case */
231 		a4state.a4s_count = n * 24 + 1024;
232 		/* FALLTHROUGH */
233 	case 0:
234 		n = arcfour_byte(&a4state.cipher);
235 		buf = (void *)a4state.pool;
236 		arcfour_ksa(&a4state.cipher, buf, sizeof(a4state.pool));
237 		while (n--)
238 			(void)arcfour_byte(&a4state.cipher);
239 		n = sizeof(a4state.pool);
240 		while (n--)
241 			*buf++ = arcfour_byte(&a4state.cipher);
242 		a4state.a4s_poolptr = 0;
243 		break;
244 	}
245 	_ARC4_UNLOCK();
246 }
247