xnu-1228.15.4.tar.gz
[apple/xnu.git] / bsd / dev / random / randomdev.c
CommitLineData
0b4e3aa0 1/*
2d21ac55 2 * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0b4e3aa0 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
0b4e3aa0
A
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>
8ad349bb 36#include <string.h>
0b4e3aa0
A
37#include <miscfs/devfs/devfs.h>
38#include <kern/lock.h>
2d21ac55 39#include <kern/clock.h>
0b4e3aa0
A
40#include <sys/time.h>
41#include <sys/malloc.h>
91447636 42#include <sys/uio_internal.h>
0b4e3aa0
A
43
44#include <dev/random/randomdev.h>
45#include <dev/random/YarrowCoreLib/include/yarrow.h>
2d21ac55
A
46#include <libkern/crypto/sha1.h>
47
48#include <mach/mach_time.h>
49#include <machine/machine_routines.h>
0b4e3aa0
A
50
51#define RANDOM_MAJOR -1 /* let the kernel pick the device number */
52
55e303ae
A
53d_ioctl_t random_ioctl;
54
0b4e3aa0
A
55/*
56 * A struct describing which functions will get invoked for certain
57 * actions.
58 */
59static struct cdevsw random_cdevsw =
60{
61 random_open, /* open */
62 random_close, /* close */
63 random_read, /* read */
64 random_write, /* write */
91447636
A
65 random_ioctl, /* ioctl */
66 (stop_fcn_t *)nulldev, /* stop */
67 (reset_fcn_t *)nulldev, /* reset */
0b4e3aa0
A
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 */
78static int gRandomInstalled = 0;
79static PrngRef gPrngRef;
80static int gRandomError = 1;
2d21ac55
A
81static lck_grp_t *gYarrowGrp;
82static lck_attr_t *gYarrowAttr;
83static lck_grp_attr_t *gYarrowGrpAttr;
84static lck_mtx_t *gYarrowMutex = 0;
85
86void CheckReseed(void);
0b4e3aa0
A
87
88#define RESEED_TICKS 50 /* how long a reseed operation can take */
89
91447636 90
8ad349bb
A
91enum {kBSizeInBits = 160}; // MUST be a multiple of 32!!!
92enum {kBSizeInBytes = kBSizeInBits / 8};
93typedef u_int32_t BlockWord;
94enum {kWordSizeInBits = 32};
95enum {kBSize = 5};
96typedef BlockWord Block[kBSize];
97
98/* define prototypes to keep the compiler happy... */
99
100void add_blocks(Block a, Block b, BlockWord carry);
101void fips_initialize(void);
4a3eedf9 102void random_block(Block b, int addOptional);
21362eb3 103u_int32_t CalculateCRC(u_int8_t* buffer, size_t length);
8ad349bb
A
104
105/*
106 * Get 120 bits from yarrow
107 */
108
109/*
110 * add block b to block a
111 */
112void
113add_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
128struct sha1_ctxt g_sha1_ctx;
129char zeros[(512 - kBSizeInBits) / 8];
130Block g_xkey;
131Block g_random_data;
132int g_bytes_used;
21362eb3
A
133unsigned char g_SelfTestInitialized = 0;
134u_int32_t gLastBlockChecksum;
135
136static 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};
8ad349bb
A
171
172/*
173 * Setup for fips compliance
174 */
175
21362eb3
A
176/*
177 * calculate a crc-32 checksum
178 */
179u_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
8ad349bb
A
193/*
194 * get a random block of data per fips 186-2
195 */
196void
4a3eedf9 197random_block(Block b, int addOptional)
8ad349bb 198{
21362eb3
A
199 int repeatCount = 0;
200 do
201 {
2d21ac55 202 // do one iteration
21362eb3 203
4a3eedf9
A
204 if (addOptional)
205 {
206 Block xSeed;
207 prngOutput (gPrngRef, (BYTE*) &xSeed, sizeof (xSeed));
208
209 // add the seed to the previous value of g_xkey
210 add_blocks (g_xkey, xSeed, 0);
211 }
212
21362eb3
A
213 // compute "G"
214 SHA1Update (&g_sha1_ctx, (const u_int8_t *) &g_xkey, sizeof (g_xkey));
215
216 // add zeros to fill the internal SHA-1 buffer
217 SHA1Update (&g_sha1_ctx, (const u_int8_t *)zeros, sizeof (zeros));
218
219 // write the resulting block
220 memmove(b, g_sha1_ctx.h.b8, sizeof (Block));
221
222 // calculate the CRC-32 of the block
223 u_int32_t new_crc = CalculateCRC(g_sha1_ctx.h.b8, sizeof (Block));
224
225 // make sure we don't repeat
226 int cmp = new_crc == gLastBlockChecksum;
227 gLastBlockChecksum = new_crc;
228 if (!g_SelfTestInitialized)
229 {
230 g_SelfTestInitialized = 1;
231 return;
232 }
233 else if (!cmp)
234 {
235 return;
236 }
237
238 repeatCount += 1;
239
240 // fix up the next value of g_xkey
241 add_blocks (g_xkey, b, 1);
242 } while (repeatCount < 2);
8ad349bb 243
21362eb3
A
244 /*
245 * If we got here, three sucessive checksums of the random number
246 * generator have been the same. Since the odds of this happening are
247 * 1 in 18,446,744,073,709,551,616, (1 in 18 quintillion) one of the following has
248 * most likely happened:
249 *
250 * 1: There is a significant bug in this code.
251 * 2: There has been a massive system failure.
252 * 3: The universe has ceased to exist.
253 *
254 * There is no good way to recover from any of these cases. We
255 * therefore panic.
256 */
257
258 panic("FIPS random self-test failed.");
8ad349bb
A
259}
260
0b4e3aa0
A
261/*
262 *Initialize ONLY the Yarrow generator.
263 */
8ad349bb
A
264void
265PreliminarySetup(void)
0b4e3aa0
A
266{
267 prng_error_status perr;
0b4e3aa0
A
268
269 /* create a Yarrow object */
270 perr = prngInitialize(&gPrngRef);
271 if (perr != 0) {
272 printf ("Couldn't initialize Yarrow, /dev/random will not work.\n");
273 return;
274 }
275
276 /* clear the error flag, reads and write should then work */
277 gRandomError = 0;
278
2d21ac55
A
279 {
280 struct timeval tt;
281 char buffer [16];
282
0b4e3aa0
A
283 /* get a little non-deterministic data as an initial seed. */
284 microtime(&tt);
285
286 /*
287 * So how much of the system clock is entropic?
288 * It's hard to say, but assume that at least the
289 * least significant byte of a 64 bit structure
290 * is entropic. It's probably more, how can you figure
291 * the exact time the user turned the computer on, for example.
292 */
293 perr = prngInput(gPrngRef, (BYTE*) &tt, sizeof (tt), SYSTEM_SOURCE, 8);
294 if (perr != 0) {
295 /* an error, complain */
296 printf ("Couldn't seed Yarrow.\n");
297 return;
298 }
299
300 /* turn the data around */
2d21ac55 301 perr = prngOutput(gPrngRef, (BYTE*) buffer, sizeof (buffer));
0b4e3aa0
A
302
303 /* and scramble it some more */
304 perr = prngForceReseed(gPrngRef, RESEED_TICKS);
2d21ac55 305 }
0b4e3aa0
A
306
307 /* make a mutex to control access */
2d21ac55
A
308 gYarrowGrpAttr = lck_grp_attr_alloc_init();
309 gYarrowGrp = lck_grp_alloc_init("random", gYarrowGrpAttr);
310 gYarrowAttr = lck_attr_alloc_init();
311 gYarrowMutex = lck_mtx_alloc_init(gYarrowGrp, gYarrowAttr);
8ad349bb
A
312
313 fips_initialize ();
314}
315
4a3eedf9
A
316const Block kKnownAnswer = {0x92b404e5, 0x56588ced, 0x6c1acd4e, 0xbf053f68, 0x9f73a93};
317
8ad349bb
A
318void
319fips_initialize(void)
320{
4a3eedf9
A
321 /* So that we can do the self test, set the seed to zero */
322 memset(&g_xkey, 0, sizeof(g_xkey));
8ad349bb
A
323
324 /* initialize our SHA1 generator */
325 SHA1Init (&g_sha1_ctx);
326
327 /* other initializations */
328 memset (zeros, 0, sizeof (zeros));
329 g_bytes_used = 0;
4a3eedf9
A
330 random_block(g_random_data, FALSE);
331
332 // check here to see if we got the initial data we were expecting
333 int i;
334 for (i = 0; i < kBSize; ++i)
335 {
336 if (kKnownAnswer[i] != g_random_data[i])
337 {
338 panic("FIPS random self test failed");
339 }
340 }
341
342 // now do the random block again to make sure that userland doesn't get predicatable data
343 random_block(g_random_data, TRUE);
0b4e3aa0
A
344}
345
346/*
347 * Called to initialize our device,
348 * and to register ourselves with devfs
349 */
350void
8ad349bb 351random_init(void)
0b4e3aa0
A
352{
353 int ret;
354
355 if (gRandomInstalled)
356 return;
357
358 /* install us in the file system */
359 gRandomInstalled = 1;
360
2d21ac55 361#ifndef ARM_BOARD_CONFIG_S5L8900XFPGA_1136JFS
0b4e3aa0
A
362 /* setup yarrow and the mutex */
363 PreliminarySetup();
2d21ac55 364#endif
0b4e3aa0
A
365
366 ret = cdevsw_add(RANDOM_MAJOR, &random_cdevsw);
367 if (ret < 0) {
368 printf("random_init: failed to allocate a major number!\n");
369 gRandomInstalled = 0;
370 return;
371 }
372
373 devfs_make_node(makedev (ret, 0), DEVFS_CHAR,
55e303ae 374 UID_ROOT, GID_WHEEL, 0666, "random", 0);
0b4e3aa0
A
375
376 /*
377 * also make urandom
378 * (which is exactly the same thing in our context)
379 */
380 devfs_make_node(makedev (ret, 1), DEVFS_CHAR,
55e303ae
A
381 UID_ROOT, GID_WHEEL, 0666, "urandom", 0);
382}
383
384int
91447636
A
385random_ioctl( __unused dev_t dev, u_long cmd, __unused caddr_t data,
386 __unused int flag, __unused struct proc *p )
55e303ae
A
387{
388 switch (cmd) {
389 case FIONBIO:
390 case FIOASYNC:
391 break;
392 default:
393 return ENODEV;
394 }
395
396 return (0);
0b4e3aa0
A
397}
398
399/*
400 * Open the device. Make sure init happened, and make sure the caller is
401 * authorized.
402 */
403
404int
91447636 405random_open(__unused dev_t dev, int flags, __unused int devtype, __unused struct proc *p)
0b4e3aa0
A
406{
407 if (gRandomError != 0) {
408 /* forget it, yarrow didn't come up */
409 return (ENOTSUP);
410 }
411
412 /*
413 * if we are being opened for write,
414 * make sure that we have privledges do so
415 */
416 if (flags & FWRITE) {
417 if (securelevel >= 2)
418 return (EPERM);
55e303ae 419#ifndef __APPLE__
91447636 420 if ((securelevel >= 1) && proc_suser(p))
0b4e3aa0 421 return (EPERM);
55e303ae 422#endif /* !__APPLE__ */
0b4e3aa0
A
423 }
424
425 return (0);
426}
427
428
429/*
430 * close the device.
431 */
432
433int
91447636 434random_close(__unused dev_t dev, __unused int flags, __unused int mode, __unused struct proc *p)
0b4e3aa0
A
435{
436 return (0);
437}
438
439
440/*
441 * Get entropic data from the Security Server, and use it to reseed the
442 * prng.
443 */
444int
91447636 445random_write (__unused dev_t dev, struct uio *uio, __unused int ioflag)
0b4e3aa0
A
446{
447 int retCode = 0;
448 char rdBuffer[256];
449
450 if (gRandomError != 0) {
451 return (ENOTSUP);
452 }
453
454 /* get control of the Yarrow instance, Yarrow is NOT thread safe */
2d21ac55 455 lck_mtx_lock(gYarrowMutex);
0b4e3aa0
A
456
457 /* Security server is sending us entropy */
458
91447636 459 while (uio_resid(uio) > 0 && retCode == 0) {
0b4e3aa0 460 /* get the user's data */
91447636
A
461 // LP64todo - fix this! uio_resid may be 64-bit value
462 int bytesToInput = min(uio_resid(uio), sizeof (rdBuffer));
0b4e3aa0
A
463 retCode = uiomove(rdBuffer, bytesToInput, uio);
464 if (retCode != 0)
465 goto /*ugh*/ error_exit;
466
467 /* put it in Yarrow */
2d21ac55 468 if (prngInput(gPrngRef, (BYTE*) rdBuffer,
c0fea474
A
469 bytesToInput, SYSTEM_SOURCE,
470 bytesToInput * 8) != 0) {
0b4e3aa0
A
471 retCode = EIO;
472 goto error_exit;
473 }
474 }
475
476 /* force a reseed */
477 if (prngForceReseed(gPrngRef, RESEED_TICKS) != 0) {
478 retCode = EIO;
479 goto error_exit;
480 }
481
482 /* retCode should be 0 at this point */
483
484error_exit: /* do this to make sure the mutex unlocks. */
2d21ac55 485 lck_mtx_unlock(gYarrowMutex);
0b4e3aa0
A
486 return (retCode);
487}
488
489/*
490 * return data to the caller. Results unpredictable.
491 */
2d21ac55
A
492int
493random_read(__unused dev_t dev, struct uio *uio, __unused int ioflag)
0b4e3aa0
A
494{
495 int retCode = 0;
8ad349bb 496
0b4e3aa0
A
497 if (gRandomError != 0)
498 return (ENOTSUP);
499
500 /* lock down the mutex */
2d21ac55 501 lck_mtx_lock(gYarrowMutex);
0b4e3aa0 502
2d21ac55 503 CheckReseed();
8ad349bb
A
504 int bytes_remaining = uio_resid(uio);
505 while (bytes_remaining > 0 && retCode == 0) {
0b4e3aa0 506 /* get the user's data */
8ad349bb
A
507 int bytes_to_read = 0;
508
509 int bytes_available = kBSizeInBytes - g_bytes_used;
510 if (bytes_available == 0)
511 {
4a3eedf9 512 random_block(g_random_data, TRUE);
8ad349bb
A
513 g_bytes_used = 0;
514 bytes_available = kBSizeInBytes;
515 }
516
517 bytes_to_read = min (bytes_remaining, bytes_available);
518
2d21ac55 519 retCode = uiomove(((caddr_t)g_random_data)+ g_bytes_used, bytes_to_read, uio);
8ad349bb
A
520 g_bytes_used += bytes_to_read;
521
0b4e3aa0
A
522 if (retCode != 0)
523 goto error_exit;
8ad349bb
A
524
525 bytes_remaining = uio_resid(uio);
0b4e3aa0
A
526 }
527
528 retCode = 0;
529
530error_exit:
2d21ac55 531 lck_mtx_unlock(gYarrowMutex);
0b4e3aa0
A
532 return retCode;
533}
534
535/* export good random numbers to the rest of the kernel */
536void
537read_random(void* buffer, u_int numbytes)
538{
539 if (gYarrowMutex == 0) { /* are we initialized? */
2d21ac55 540#ifndef ARM_BOARD_CONFIG_S5L8900XFPGA_1136JFS
0b4e3aa0 541 PreliminarySetup ();
2d21ac55 542#endif
0b4e3aa0
A
543 }
544
2d21ac55
A
545 lck_mtx_lock(gYarrowMutex);
546 CheckReseed();
547
21362eb3 548 int bytes_read = 0;
8ad349bb
A
549
550 int bytes_remaining = numbytes;
551 while (bytes_remaining > 0) {
552 int bytes_to_read = min(bytes_remaining, kBSizeInBytes - g_bytes_used);
553 if (bytes_to_read == 0)
554 {
4a3eedf9 555 random_block(g_random_data, TRUE);
8ad349bb
A
556 g_bytes_used = 0;
557 bytes_to_read = min(bytes_remaining, kBSizeInBytes);
558 }
559
2d21ac55 560 memmove ((u_int8_t*) buffer + bytes_read, ((u_int8_t*)g_random_data)+ g_bytes_used, bytes_to_read);
8ad349bb 561 g_bytes_used += bytes_to_read;
21362eb3 562 bytes_read += bytes_to_read;
8ad349bb
A
563 bytes_remaining -= bytes_to_read;
564 }
565
2d21ac55 566 lck_mtx_unlock(gYarrowMutex);
0b4e3aa0
A
567}
568
569/*
570 * Return an unsigned long pseudo-random number.
571 */
572u_long
8ad349bb 573RandomULong(void)
0b4e3aa0
A
574{
575 u_long buf;
576 read_random(&buf, sizeof (buf));
577 return (buf);
578}
579
2d21ac55
A
580void
581CheckReseed(void)
582{
583}