xref: /xnu-11215/bsd/dev/random/randomdev.c (revision 186b8fce)
1 /*
2  * Copyright (c) 1999-2009 Apple, 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 /*
30 	WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
31 
32 	THIS FILE IS NEEDED TO PASS FIPS ACCEPTANCE FOR THE RANDOM NUMBER GENERATOR.
33 	IF YOU ALTER IT IN ANY WAY, WE WILL NEED TO GO THOUGH FIPS ACCEPTANCE AGAIN,
34 	AN OPERATION THAT IS VERY EXPENSIVE AND TIME CONSUMING.  IN OTHER WORDS,
35 	DON'T MESS WITH THIS FILE.
36 
37 	WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
38 */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/proc.h>
43 #include <sys/errno.h>
44 #include <sys/ioctl.h>
45 #include <sys/conf.h>
46 #include <sys/fcntl.h>
47 #include <string.h>
48 #include <miscfs/devfs/devfs.h>
49 #include <kern/lock.h>
50 #include <kern/clock.h>
51 #include <sys/time.h>
52 #include <sys/malloc.h>
53 #include <sys/uio_internal.h>
54 
55 #include <dev/random/randomdev.h>
56 #include <dev/random/YarrowCoreLib/include/yarrow.h>
57 
58 #include <libkern/OSByteOrder.h>
59 #include <libkern/OSAtomic.h>
60 
61 #include <mach/mach_time.h>
62 #include <machine/machine_routines.h>
63 
64 #include "fips_sha1.h"
65 
66 #define RANDOM_MAJOR  -1 /* let the kernel pick the device number */
67 
68 d_ioctl_t       random_ioctl;
69 
70 /* To generate the seed for the RNG */
71 extern uint64_t early_random();
72 
73 /*
74  * A struct describing which functions will get invoked for certain
75  * actions.
76  */
77 static struct cdevsw random_cdevsw =
78 {
79 	random_open,		/* open */
80 	random_close,		/* close */
81 	random_read,		/* read */
82 	random_write,		/* write */
83 	random_ioctl,		/* ioctl */
84 	(stop_fcn_t *)nulldev, /* stop */
85 	(reset_fcn_t *)nulldev, /* reset */
86 	NULL,				/* tty's */
87 	eno_select,			/* select */
88 	eno_mmap,			/* mmap */
89 	eno_strat,			/* strategy */
90 	eno_getc,			/* getc */
91 	eno_putc,			/* putc */
92 	0					/* type */
93 };
94 
95 
96 /*
97 	WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
98 
99 	ANY CODE PROTECTED UNDER "#ifdef __arm__" IS SERIOUSLY SUPPOSED TO BE THERE!
100 	IF YOU REMOVE ARM CODE, RANDOM WILL NOT MEAN ANYTHING FOR iPHONES ALL OVER.
101 	PLEASE DON'T TOUCH __arm__ CODE IN THIS FILE!
102 
103 	WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
104 */
105 
106 
107 /* Used to detect whether we've already been initialized */
108 static UInt8 gRandomInstalled = 0;
109 static PrngRef gPrngRef;
110 static int gRandomError = 1;
111 static lck_grp_t *gYarrowGrp;
112 static lck_attr_t *gYarrowAttr;
113 static lck_grp_attr_t *gYarrowGrpAttr;
114 static lck_mtx_t *gYarrowMutex = 0;
115 static UInt8 gYarrowInitializationLock = 0;
116 
117 #define RESEED_TICKS 50 /* how long a reseed operation can take */
118 
119 
120 typedef u_int8_t BlockWord;
121 enum {kBSize = 20};
122 typedef BlockWord Block[kBSize];
123 enum {kBlockSize = sizeof(Block)};
124 
125 /* define prototypes to keep the compiler happy... */
126 
127 void add_blocks(Block a, Block b, BlockWord carry);
128 void fips_initialize(void);
129 void random_block(Block b, int addOptional);
130 u_int32_t CalculateCRC(u_int8_t* buffer, size_t length);
131 
132 /*
133  * Get 120 bits from yarrow
134  */
135 
136 /*
137  * add block b to block a
138  */
139 void
140 add_blocks(Block a, Block b, BlockWord carry)
141 {
142 	int i = kBlockSize - 1;
143 	while (i >= 0)
144 	{
145 		u_int32_t c = (u_int32_t)carry +
146 					  (u_int32_t)a[i] +
147 					  (u_int32_t)b[i];
148 		a[i] = c & 0xff;
149 		carry = c >> 8;
150 		i -= 1;
151 	}
152 }
153 
154 
155 
156 static char zeros[(512 - kBSize * 8) / 8];
157 static Block g_xkey;
158 static Block g_random_data;
159 static int g_bytes_used;
160 static unsigned char g_SelfTestInitialized = 0;
161 static u_int32_t gLastBlockChecksum;
162 
163 static const u_int32_t g_crc_table[] =
164 {
165 	0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
166 	0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
167 	0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
168 	0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
169 	0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
170 	0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
171 	0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
172 	0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
173 	0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
174 	0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
175 	0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
176 	0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
177 	0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
178 	0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
179 	0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
180 	0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
181 	0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
182 	0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
183 	0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
184 	0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
185 	0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
186 	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
187 	0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
188 	0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
189 	0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
190 	0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
191 	0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
192 	0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
193 	0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
194 	0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
195 	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
196 	0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
197 };
198 
199 /*
200  * Setup for fips compliance
201  */
202 
203 /*
204  * calculate a crc-32 checksum
205  */
206 u_int32_t CalculateCRC(u_int8_t* buffer, size_t length)
207 {
208 	u_int32_t crc = 0;
209 
210 	size_t i;
211 	for (i = 0; i < length; ++i)
212 	{
213 		u_int32_t temp = (crc ^ ((u_int32_t) buffer[i])) & 0xFF;
214 		crc = (crc >> 8) ^ g_crc_table[temp];
215 	}
216 
217 	return crc;
218 }
219 
220 /*
221  * get a random block of data per fips 186-2
222  */
223 void
224 random_block(Block b, int addOptional)
225 {
226 	SHA1_CTX sha1_ctx;
227 
228 	int repeatCount = 0;
229 	do
230 	{
231 		// do one iteration
232 
233 		if (addOptional)
234 		{
235 			// create an xSeed to add.
236 			Block xSeed;
237 			prngOutput (gPrngRef, (BYTE*) &xSeed, sizeof (xSeed));
238 
239 			// add the seed to the previous value of g_xkey
240 			add_blocks (g_xkey, xSeed, 0);
241 		}
242 
243 		// initialize the value of H
244 		FIPS_SHA1Init(&sha1_ctx);
245 
246 		// to stay compatible with the FIPS specification, we need to flip the bytes in
247 		// g_xkey to little endian byte order.  In our case, this makes exactly no difference
248 		// (random is random), but we need to do it anyway to keep FIPS happy
249 
250 		// compute "G"
251 		FIPS_SHA1Update(&sha1_ctx, g_xkey, kBlockSize);
252 
253 		// add zeros to fill the internal SHA-1 buffer
254 		FIPS_SHA1Update (&sha1_ctx, (const u_int8_t *)zeros, sizeof (zeros));
255 
256 		// we have to do a byte order correction here because the sha1 math is being done internally
257 		// as u_int32_t, not a stream of bytes.  Since we maintain our data as a byte stream, we need
258 		// to convert
259 
260 		u_int32_t* finger = (u_int32_t*) b;
261 
262 		unsigned j;
263 		for (j = 0; j < kBlockSize / sizeof (u_int32_t); ++j)
264 		{
265 			*finger++ = OSSwapHostToBigInt32(sha1_ctx.h.b32[j]);
266 		}
267 
268 		// calculate the CRC-32 of the block
269 		u_int32_t new_crc = CalculateCRC(sha1_ctx.h.b8, sizeof (Block));
270 
271 		// make sure we don't repeat
272 		int cmp = new_crc == gLastBlockChecksum;
273 		gLastBlockChecksum = new_crc;
274 		if (!g_SelfTestInitialized)
275 		{
276 			g_SelfTestInitialized = 1;
277 			return;
278 		}
279 		else if (!cmp)
280 		{
281 			return;
282 		}
283 
284 		repeatCount += 1;
285 
286 		// fix up the next value of g_xkey
287 		add_blocks (g_xkey, b, 1);
288 	} while (repeatCount < 2);
289 
290 	/*
291 	 * If we got here, three sucessive checksums of the random number
292 	 * generator have been the same.  Since the odds of this happening are
293 	 * 1 in 18,446,744,073,709,551,616, (1 in 18 quintillion) one of the following has
294 	 * most likely happened:
295 	 *
296 	 * 1: There is a significant bug in this code.
297 	 * 2: There has been a massive system failure.
298 	 * 3: The universe has ceased to exist.
299 	 *
300 	 * There is no good way to recover from any of these cases. We
301 	 * therefore panic.
302 	 */
303 
304 	 panic("FIPS random self-test failed.");
305 }
306 
307 /*
308  *Initialize ONLY the Yarrow generator.
309  */
310 void
311 PreliminarySetup(void)
312 {
313     prng_error_status perr;
314 
315 	/* Multiple threads can enter this as a result of an earlier
316 	 * check of gYarrowMutex.  We make sure that only one of them
317 	 * can enter at a time.  If one of them enters and discovers
318 	 * that gYarrowMutex is no longer NULL, we know that another
319 	 * thread has initialized the Yarrow state and we can exit.
320 	 */
321 
322 	/* The first thread that enters this function will find
323 	 * gYarrowInitializationLock set to 0.  It will atomically
324 	 * set the value to 1 and, seeing that it was zero, drop
325 	 * out of the loop.  Other threads will see that the value is
326 	 * 1 and continue to loop until we are initialized.
327      */
328 
329 	while (OSTestAndSet(0, &gYarrowInitializationLock)); /* serialize access to this function */
330 
331 	if (gYarrowMutex) {
332 		/*  we've already been initialized, clear and get out */
333 		goto function_exit;
334 	}
335 
336     /* create a Yarrow object */
337     perr = prngInitialize(&gPrngRef);
338     if (perr != 0) {
339         printf ("Couldn't initialize Yarrow, /dev/random will not work.\n");
340         return;
341     }
342 
343 	/* clear the error flag, reads and write should then work */
344     gRandomError = 0;
345 
346     uint64_t tt;
347     char buffer [16];
348 
349     /* get a little non-deterministic data as an initial seed. */
350 	/* On OSX, securityd will add much more entropy as soon as it */
351 	/* comes up.  On iOS, entropy is added with each system interrupt. */
352     tt = early_random();
353 
354     perr = prngInput(gPrngRef, (BYTE*) &tt, sizeof (tt), SYSTEM_SOURCE, 8);
355     if (perr != 0) {
356         /* an error, complain */
357         printf ("Couldn't seed Yarrow.\n");
358         goto function_exit;
359     }
360 
361     /* turn the data around */
362     perr = prngOutput(gPrngRef, (BYTE*) buffer, sizeof (buffer));
363 
364     /* and scramble it some more */
365     perr = prngForceReseed(gPrngRef, RESEED_TICKS);
366 
367     /* make a mutex to control access */
368     gYarrowGrpAttr = lck_grp_attr_alloc_init();
369     gYarrowGrp     = lck_grp_alloc_init("random", gYarrowGrpAttr);
370     gYarrowAttr    = lck_attr_alloc_init();
371     gYarrowMutex   = lck_mtx_alloc_init(gYarrowGrp, gYarrowAttr);
372 
373 	fips_initialize ();
374 
375 function_exit:
376 	/* allow other threads to figure out whether or not we have been initialized. */
377 	gYarrowInitializationLock = 0;
378 }
379 
380 const Block kKnownAnswer = {0x92, 0xb4, 0x04, 0xe5, 0x56, 0x58, 0x8c, 0xed, 0x6c, 0x1a, 0xcd, 0x4e, 0xbf, 0x05, 0x3f, 0x68, 0x09, 0xf7, 0x3a, 0x93};
381 
382 void
383 fips_initialize(void)
384 {
385 	/* So that we can do the self test, set the seed to zero */
386 	memset(&g_xkey, 0, sizeof(g_xkey));
387 
388 	/* other initializations */
389 	memset (zeros, 0, sizeof (zeros));
390 	g_bytes_used = 0;
391 	random_block(g_random_data, FALSE);
392 
393 	// check here to see if we got the initial data we were expecting
394 	if (memcmp(kKnownAnswer, g_random_data, kBlockSize) != 0)
395 	{
396 		panic("FIPS random self test failed");
397 	}
398 
399 	// now do the random block again to make sure that userland doesn't get predicatable data
400 	random_block(g_random_data, TRUE);
401 }
402 
403 /*
404  * Called to initialize our device,
405  * and to register ourselves with devfs
406  */
407 void
408 random_init(void)
409 {
410 	int ret;
411 
412 	if (OSTestAndSet(0, &gRandomInstalled)) {
413 		/* do this atomically so that it works correctly with
414 		 multiple threads */
415 		return;
416 	}
417 
418 	ret = cdevsw_add(RANDOM_MAJOR, &random_cdevsw);
419 	if (ret < 0) {
420 		printf("random_init: failed to allocate a major number!\n");
421 		gRandomInstalled = 0;
422 		return;
423 	}
424 
425 	devfs_make_node(makedev (ret, 0), DEVFS_CHAR,
426 		UID_ROOT, GID_WHEEL, 0666, "random", 0);
427 
428 	/*
429 	 * also make urandom
430 	 * (which is exactly the same thing in our context)
431 	 */
432 	devfs_make_node(makedev (ret, 1), DEVFS_CHAR,
433 		UID_ROOT, GID_WHEEL, 0666, "urandom", 0);
434 
435 	/* setup yarrow and the mutex if needed*/
436 	PreliminarySetup();
437 }
438 
439 int
440 random_ioctl(	__unused dev_t dev, u_long cmd, __unused caddr_t data,
441 				__unused int flag, __unused struct proc *p  )
442 {
443 	switch (cmd) {
444 	case FIONBIO:
445 	case FIOASYNC:
446 		break;
447 	default:
448 		return ENODEV;
449 	}
450 
451 	return (0);
452 }
453 
454 /*
455  * Open the device.  Make sure init happened, and make sure the caller is
456  * authorized.
457  */
458 
459 int
460 random_open(__unused dev_t dev, int flags, __unused int devtype, __unused struct proc *p)
461 {
462 	if (gRandomError != 0) {
463 		/* forget it, yarrow didn't come up */
464 		return (ENOTSUP);
465 	}
466 
467 	/*
468 	 * if we are being opened for write,
469 	 * make sure that we have privledges do so
470 	 */
471 	if (flags & FWRITE) {
472 		if (securelevel >= 2)
473 			return (EPERM);
474 #ifndef __APPLE__
475 		if ((securelevel >= 1) && proc_suser(p))
476 			return (EPERM);
477 #endif	/* !__APPLE__ */
478 	}
479 
480 	return (0);
481 }
482 
483 
484 /*
485  * close the device.
486  */
487 
488 int
489 random_close(__unused dev_t dev, __unused int flags, __unused int mode, __unused struct proc *p)
490 {
491 	return (0);
492 }
493 
494 
495 /*
496  * Get entropic data from the Security Server, and use it to reseed the
497  * prng.
498  */
499 int
500 random_write (__unused dev_t dev, struct uio *uio, __unused int ioflag)
501 {
502     int retCode = 0;
503     char rdBuffer[256];
504 
505     if (gRandomError != 0) {
506         return (ENOTSUP);
507     }
508 
509     /* get control of the Yarrow instance, Yarrow is NOT thread safe */
510     lck_mtx_lock(gYarrowMutex);
511 
512     /* Security server is sending us entropy */
513 
514     while (uio_resid(uio) > 0 && retCode == 0) {
515         /* get the user's data */
516         int bytesToInput = min(uio_resid(uio), sizeof (rdBuffer));
517         retCode = uiomove(rdBuffer, bytesToInput, uio);
518         if (retCode != 0)
519             goto /*ugh*/ error_exit;
520 
521         /* put it in Yarrow */
522         if (prngInput(gPrngRef, (BYTE*) rdBuffer,
523 			bytesToInput, SYSTEM_SOURCE,
524         	bytesToInput * 8) != 0) {
525             retCode = EIO;
526             goto error_exit;
527         }
528     }
529 
530     /* force a reseed */
531     if (prngForceReseed(gPrngRef, RESEED_TICKS) != 0) {
532         retCode = EIO;
533         goto error_exit;
534     }
535 
536     /* retCode should be 0 at this point */
537 
538 error_exit: /* do this to make sure the mutex unlocks. */
539     lck_mtx_unlock(gYarrowMutex);
540     return (retCode);
541 }
542 
543 
544 /* export good random numbers to the rest of the kernel */
545 void
546 read_random(void* buffer, u_int numbytes)
547 {
548     if (gYarrowMutex == 0) { /* are we initialized? */
549         PreliminarySetup ();
550     }
551 
552     lck_mtx_lock(gYarrowMutex);
553 
554 
555 	int bytes_read = 0;
556 
557 	int bytes_remaining = numbytes;
558     while (bytes_remaining > 0) {
559         int bytes_to_read = min(bytes_remaining, kBlockSize - g_bytes_used);
560         if (bytes_to_read == 0)
561 		{
562 			random_block(g_random_data, TRUE);
563 			g_bytes_used = 0;
564 			bytes_to_read = min(bytes_remaining, kBlockSize);
565 		}
566 
567 		memmove ((u_int8_t*) buffer + bytes_read, ((u_int8_t*)g_random_data)+ g_bytes_used, bytes_to_read);
568 		g_bytes_used += bytes_to_read;
569 		bytes_read += bytes_to_read;
570 		bytes_remaining -= bytes_to_read;
571     }
572 
573     lck_mtx_unlock(gYarrowMutex);
574 }
575 
576 /*
577  * return data to the caller.  Results unpredictable.
578  */
579 int
580 random_read(__unused dev_t dev, struct uio *uio, __unused int ioflag)
581 {
582     int retCode = 0;
583 
584     if (gRandomError != 0)
585         return (ENOTSUP);
586 
587     char buffer[64];
588 
589 	user_ssize_t bytes_remaining = uio_resid(uio);
590     while (bytes_remaining > 0 && retCode == 0) {
591 		user_ssize_t bytesToRead = min(sizeof(buffer), bytes_remaining);
592         read_random(buffer, bytesToRead);
593         retCode = uiomove(buffer, bytesToRead, uio);
594 
595         if (retCode != 0)
596             goto error_exit;
597 
598 		bytes_remaining = uio_resid(uio);
599     }
600 
601     retCode = 0;
602 
603 error_exit:
604     return retCode;
605 }
606 /*
607  * Return an u_int32_t pseudo-random number.
608  */
609 u_int32_t
610 RandomULong(void)
611 {
612 	u_int32_t buf;
613 	read_random(&buf, sizeof (buf));
614 	return (buf);
615 }
616 
617