xref: /xnu-11215/bsd/dev/random/randomdev.c (revision e13b1fa5)
1 /*
2  * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/proc.h>
32 #include <sys/errno.h>
33 #include <sys/ioctl.h>
34 #include <sys/conf.h>
35 #include <sys/fcntl.h>
36 #include <string.h>
37 #include <miscfs/devfs/devfs.h>
38 #include <kern/lock.h>
39 #include <kern/clock.h>
40 #include <sys/time.h>
41 #include <sys/malloc.h>
42 #include <sys/uio_internal.h>
43 
44 #include <dev/random/randomdev.h>
45 #include <dev/random/YarrowCoreLib/include/yarrow.h>
46 #include <libkern/crypto/sha1.h>
47 
48 #include <mach/mach_time.h>
49 #include <machine/machine_routines.h>
50 
51 #define RANDOM_MAJOR  -1 /* let the kernel pick the device number */
52 
53 d_ioctl_t       random_ioctl;
54 
55 /*
56  * A struct describing which functions will get invoked for certain
57  * actions.
58  */
59 static struct cdevsw random_cdevsw =
60 {
61 	random_open,		/* open */
62 	random_close,		/* close */
63 	random_read,		/* read */
64 	random_write,		/* write */
65 	random_ioctl,		/* ioctl */
66 	(stop_fcn_t *)nulldev, /* stop */
67 	(reset_fcn_t *)nulldev, /* reset */
68 	NULL,				/* tty's */
69 	eno_select,			/* select */
70 	eno_mmap,			/* mmap */
71 	eno_strat,			/* strategy */
72 	eno_getc,			/* getc */
73 	eno_putc,			/* putc */
74 	0					/* type */
75 };
76 
77 /* Used to detect whether we've already been initialized */
78 static int gRandomInstalled = 0;
79 static PrngRef gPrngRef;
80 static int gRandomError = 1;
81 static lck_grp_t *gYarrowGrp;
82 static lck_attr_t *gYarrowAttr;
83 static lck_grp_attr_t *gYarrowGrpAttr;
84 static lck_mtx_t *gYarrowMutex = 0;
85 
86 void CheckReseed(void);
87 
88 #define RESEED_TICKS 50 /* how long a reseed operation can take */
89 
90 
91 enum {kBSizeInBits = 160}; // MUST be a multiple of 32!!!
92 enum {kBSizeInBytes = kBSizeInBits / 8};
93 typedef u_int32_t BlockWord;
94 enum {kWordSizeInBits = 32};
95 enum {kBSize = 5};
96 typedef BlockWord Block[kBSize];
97 
98 /* define prototypes to keep the compiler happy... */
99 
100 void add_blocks(Block a, Block b, BlockWord carry);
101 void fips_initialize(void);
102 void random_block(Block b);
103 u_int32_t CalculateCRC(u_int8_t* buffer, size_t length);
104 
105 /*
106  * Get 120 bits from yarrow
107  */
108 
109 /*
110  * add block b to block a
111  */
112 void
113 add_blocks(Block a, Block b, BlockWord carry)
114 {
115 	int i = kBSize;
116 	while (--i >= 0)
117 	{
118 		u_int64_t c = (u_int64_t)carry +
119 					  (u_int64_t)a[i] +
120 					  (u_int64_t)b[i];
121 		a[i] = c & ((1LL << kWordSizeInBits) - 1);
122 		carry = c >> kWordSizeInBits;
123 	}
124 }
125 
126 
127 
128 struct sha1_ctxt g_sha1_ctx;
129 char zeros[(512 - kBSizeInBits) / 8];
130 Block g_xkey;
131 Block g_random_data;
132 int g_bytes_used;
133 unsigned char g_SelfTestInitialized = 0;
134 u_int32_t gLastBlockChecksum;
135 
136 static const u_int32_t g_crc_table[] =
137 {
138 	0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
139 	0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
140 	0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
141 	0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
142 	0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
143 	0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
144 	0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
145 	0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
146 	0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
147 	0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
148 	0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
149 	0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
150 	0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
151 	0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
152 	0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
153 	0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
154 	0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
155 	0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
156 	0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
157 	0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
158 	0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
159 	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
160 	0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
161 	0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
162 	0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
163 	0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
164 	0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
165 	0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
166 	0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
167 	0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
168 	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
169 	0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
170 };
171 
172 /*
173  * Setup for fips compliance
174  */
175 
176 /*
177  * calculate a crc-32 checksum
178  */
179 u_int32_t CalculateCRC(u_int8_t* buffer, size_t length)
180 {
181 	u_int32_t crc = 0;
182 
183 	size_t i;
184 	for (i = 0; i < length; ++i)
185 	{
186 		u_int32_t temp = (crc ^ ((u_int32_t) buffer[i])) & 0xFF;
187 		crc = (crc >> 8) ^ g_crc_table[temp];
188 	}
189 
190 	return crc;
191 }
192 
193 /*
194  * get a random block of data per fips 186-2
195  */
196 void
197 random_block(Block b)
198 {
199 	int repeatCount = 0;
200 	do
201 	{
202 		// do one iteration
203 		Block xSeed;
204 		prngOutput (gPrngRef, (BYTE*) &xSeed, sizeof (xSeed));
205 
206 		// add the seed to the previous value of g_xkey
207 		add_blocks (g_xkey, xSeed, 0);
208 
209 		// compute "G"
210 		SHA1Update (&g_sha1_ctx, (const u_int8_t *) &g_xkey, sizeof (g_xkey));
211 
212 		// add zeros to fill the internal SHA-1 buffer
213 		SHA1Update (&g_sha1_ctx, (const u_int8_t *)zeros, sizeof (zeros));
214 
215 		// write the resulting block
216 		memmove(b, g_sha1_ctx.h.b8, sizeof (Block));
217 
218 		// calculate the CRC-32 of the block
219 		u_int32_t new_crc = CalculateCRC(g_sha1_ctx.h.b8, sizeof (Block));
220 
221 		// make sure we don't repeat
222 		int cmp = new_crc == gLastBlockChecksum;
223 		gLastBlockChecksum = new_crc;
224 		if (!g_SelfTestInitialized)
225 		{
226 			g_SelfTestInitialized = 1;
227 			return;
228 		}
229 		else if (!cmp)
230 		{
231 			return;
232 		}
233 
234 		repeatCount += 1;
235 
236 		// fix up the next value of g_xkey
237 		add_blocks (g_xkey, b, 1);
238 	} while (repeatCount < 2);
239 
240 	/*
241 	 * If we got here, three sucessive checksums of the random number
242 	 * generator have been the same.  Since the odds of this happening are
243 	 * 1 in 18,446,744,073,709,551,616, (1 in 18 quintillion) one of the following has
244 	 * most likely happened:
245 	 *
246 	 * 1: There is a significant bug in this code.
247 	 * 2: There has been a massive system failure.
248 	 * 3: The universe has ceased to exist.
249 	 *
250 	 * There is no good way to recover from any of these cases. We
251 	 * therefore panic.
252 	 */
253 
254 	 panic("FIPS random self-test failed.");
255 }
256 
257 /*
258  *Initialize ONLY the Yarrow generator.
259  */
260 void
261 PreliminarySetup(void)
262 {
263     prng_error_status perr;
264 
265     /* create a Yarrow object */
266     perr = prngInitialize(&gPrngRef);
267     if (perr != 0) {
268         printf ("Couldn't initialize Yarrow, /dev/random will not work.\n");
269         return;
270     }
271 
272 	/* clear the error flag, reads and write should then work */
273     gRandomError = 0;
274 
275    {
276     struct timeval tt;
277     char buffer [16];
278 
279     /* get a little non-deterministic data as an initial seed. */
280     microtime(&tt);
281 
282     /*
283 	 * So how much of the system clock is entropic?
284 	 * It's hard to say, but assume that at least the
285 	 * least significant byte of a 64 bit structure
286 	 * is entropic.  It's probably more, how can you figure
287 	 * the exact time the user turned the computer on, for example.
288     */
289     perr = prngInput(gPrngRef, (BYTE*) &tt, sizeof (tt), SYSTEM_SOURCE, 8);
290     if (perr != 0) {
291         /* an error, complain */
292         printf ("Couldn't seed Yarrow.\n");
293         return;
294     }
295 
296     /* turn the data around */
297     perr = prngOutput(gPrngRef, (BYTE*) buffer, sizeof (buffer));
298 
299     /* and scramble it some more */
300     perr = prngForceReseed(gPrngRef, RESEED_TICKS);
301     }
302 
303     /* make a mutex to control access */
304     gYarrowGrpAttr = lck_grp_attr_alloc_init();
305     gYarrowGrp     = lck_grp_alloc_init("random", gYarrowGrpAttr);
306     gYarrowAttr    = lck_attr_alloc_init();
307     gYarrowMutex   = lck_mtx_alloc_init(gYarrowGrp, gYarrowAttr);
308 
309 	fips_initialize ();
310 }
311 
312 void
313 fips_initialize(void)
314 {
315 	/* Read the initial value of g_xkey from yarrow */
316 	prngOutput (gPrngRef, (BYTE*) &g_xkey, sizeof (g_xkey));
317 
318 	/* initialize our SHA1 generator */
319 	SHA1Init (&g_sha1_ctx);
320 
321 	/* other initializations */
322 	memset (zeros, 0, sizeof (zeros));
323 	g_bytes_used = 0;
324 	random_block(g_random_data);
325 }
326 
327 /*
328  * Called to initialize our device,
329  * and to register ourselves with devfs
330  */
331 void
332 random_init(void)
333 {
334 	int ret;
335 
336 	if (gRandomInstalled)
337 		return;
338 
339 	/* install us in the file system */
340 	gRandomInstalled = 1;
341 
342 #ifndef ARM_BOARD_CONFIG_S5L8900XFPGA_1136JFS
343 	/* setup yarrow and the mutex */
344 	PreliminarySetup();
345 #endif
346 
347 	ret = cdevsw_add(RANDOM_MAJOR, &random_cdevsw);
348 	if (ret < 0) {
349 		printf("random_init: failed to allocate a major number!\n");
350 		gRandomInstalled = 0;
351 		return;
352 	}
353 
354 	devfs_make_node(makedev (ret, 0), DEVFS_CHAR,
355 		UID_ROOT, GID_WHEEL, 0666, "random", 0);
356 
357 	/*
358 	 * also make urandom
359 	 * (which is exactly the same thing in our context)
360 	 */
361 	devfs_make_node(makedev (ret, 1), DEVFS_CHAR,
362 		UID_ROOT, GID_WHEEL, 0666, "urandom", 0);
363 }
364 
365 int
366 random_ioctl(	__unused dev_t dev, u_long cmd, __unused caddr_t data,
367 				__unused int flag, __unused struct proc *p  )
368 {
369 	switch (cmd) {
370 	case FIONBIO:
371 	case FIOASYNC:
372 		break;
373 	default:
374 		return ENODEV;
375 	}
376 
377 	return (0);
378 }
379 
380 /*
381  * Open the device.  Make sure init happened, and make sure the caller is
382  * authorized.
383  */
384 
385 int
386 random_open(__unused dev_t dev, int flags, __unused int devtype, __unused struct proc *p)
387 {
388 	if (gRandomError != 0) {
389 		/* forget it, yarrow didn't come up */
390 		return (ENOTSUP);
391 	}
392 
393 	/*
394 	 * if we are being opened for write,
395 	 * make sure that we have privledges do so
396 	 */
397 	if (flags & FWRITE) {
398 		if (securelevel >= 2)
399 			return (EPERM);
400 #ifndef __APPLE__
401 		if ((securelevel >= 1) && proc_suser(p))
402 			return (EPERM);
403 #endif	/* !__APPLE__ */
404 	}
405 
406 	return (0);
407 }
408 
409 
410 /*
411  * close the device.
412  */
413 
414 int
415 random_close(__unused dev_t dev, __unused int flags, __unused int mode, __unused struct proc *p)
416 {
417 	return (0);
418 }
419 
420 
421 /*
422  * Get entropic data from the Security Server, and use it to reseed the
423  * prng.
424  */
425 int
426 random_write (__unused dev_t dev, struct uio *uio, __unused int ioflag)
427 {
428     int retCode = 0;
429     char rdBuffer[256];
430 
431     if (gRandomError != 0) {
432         return (ENOTSUP);
433     }
434 
435     /* get control of the Yarrow instance, Yarrow is NOT thread safe */
436     lck_mtx_lock(gYarrowMutex);
437 
438     /* Security server is sending us entropy */
439 
440     while (uio_resid(uio) > 0 && retCode == 0) {
441         /* get the user's data */
442         // LP64todo - fix this!  uio_resid may be 64-bit value
443         int bytesToInput = min(uio_resid(uio), sizeof (rdBuffer));
444         retCode = uiomove(rdBuffer, bytesToInput, uio);
445         if (retCode != 0)
446             goto /*ugh*/ error_exit;
447 
448         /* put it in Yarrow */
449         if (prngInput(gPrngRef, (BYTE*) rdBuffer,
450 			bytesToInput, SYSTEM_SOURCE,
451         	bytesToInput * 8) != 0) {
452             retCode = EIO;
453             goto error_exit;
454         }
455     }
456 
457     /* force a reseed */
458     if (prngForceReseed(gPrngRef, RESEED_TICKS) != 0) {
459         retCode = EIO;
460         goto error_exit;
461     }
462 
463     /* retCode should be 0 at this point */
464 
465 error_exit: /* do this to make sure the mutex unlocks. */
466     lck_mtx_unlock(gYarrowMutex);
467     return (retCode);
468 }
469 
470 /*
471  * return data to the caller.  Results unpredictable.
472  */
473 int
474 random_read(__unused dev_t dev, struct uio *uio, __unused int ioflag)
475 {
476     int retCode = 0;
477 
478     if (gRandomError != 0)
479         return (ENOTSUP);
480 
481    /* lock down the mutex */
482     lck_mtx_lock(gYarrowMutex);
483 
484     CheckReseed();
485 	int bytes_remaining = uio_resid(uio);
486     while (bytes_remaining > 0 && retCode == 0) {
487         /* get the user's data */
488 		int bytes_to_read = 0;
489 
490 		int bytes_available = kBSizeInBytes - g_bytes_used;
491         if (bytes_available == 0)
492 		{
493 			random_block(g_random_data);
494 			g_bytes_used = 0;
495 			bytes_available = kBSizeInBytes;
496 		}
497 
498 		bytes_to_read = min (bytes_remaining, bytes_available);
499 
500         retCode = uiomove(((caddr_t)g_random_data)+ g_bytes_used, bytes_to_read, uio);
501         g_bytes_used += bytes_to_read;
502 
503         if (retCode != 0)
504             goto error_exit;
505 
506 		bytes_remaining = uio_resid(uio);
507     }
508 
509     retCode = 0;
510 
511 error_exit:
512     lck_mtx_unlock(gYarrowMutex);
513     return retCode;
514 }
515 
516 /* export good random numbers to the rest of the kernel */
517 void
518 read_random(void* buffer, u_int numbytes)
519 {
520     if (gYarrowMutex == 0) { /* are we initialized? */
521 #ifndef ARM_BOARD_CONFIG_S5L8900XFPGA_1136JFS
522         PreliminarySetup ();
523 #endif
524     }
525 
526     lck_mtx_lock(gYarrowMutex);
527     CheckReseed();
528 
529 	int bytes_read = 0;
530 
531 	int bytes_remaining = numbytes;
532     while (bytes_remaining > 0) {
533         int bytes_to_read = min(bytes_remaining, kBSizeInBytes - g_bytes_used);
534         if (bytes_to_read == 0)
535 		{
536 			random_block(g_random_data);
537 			g_bytes_used = 0;
538 			bytes_to_read = min(bytes_remaining, kBSizeInBytes);
539 		}
540 
541 		memmove ((u_int8_t*) buffer + bytes_read, ((u_int8_t*)g_random_data)+ g_bytes_used, bytes_to_read);
542 		g_bytes_used += bytes_to_read;
543 		bytes_read += bytes_to_read;
544 		bytes_remaining -= bytes_to_read;
545     }
546 
547     lck_mtx_unlock(gYarrowMutex);
548 }
549 
550 /*
551  * Return an unsigned long pseudo-random number.
552  */
553 u_long
554 RandomULong(void)
555 {
556 	u_long buf;
557 	read_random(&buf, sizeof (buf));
558 	return (buf);
559 }
560 
561 void
562 CheckReseed(void)
563 {
564 }
565