]> git.saurik.com Git - apple/xnu.git/blame - bsd/dev/random/randomdev.c
xnu-1228.0.2.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);
2d21ac55 102void random_block(Block b);
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
2d21ac55 197random_block(Block b)
8ad349bb 198{
21362eb3
A
199 int repeatCount = 0;
200 do
201 {
2d21ac55
A
202 // do one iteration
203 Block xSeed;
204 prngOutput (gPrngRef, (BYTE*) &xSeed, sizeof (xSeed));
21362eb3 205
2d21ac55
A
206 // add the seed to the previous value of g_xkey
207 add_blocks (g_xkey, xSeed, 0);
208
21362eb3
A
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);
8ad349bb 239
21362eb3
A
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.");
8ad349bb
A
255}
256
0b4e3aa0
A
257/*
258 *Initialize ONLY the Yarrow generator.
259 */
8ad349bb
A
260void
261PreliminarySetup(void)
0b4e3aa0
A
262{
263 prng_error_status perr;
0b4e3aa0
A
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
2d21ac55
A
275 {
276 struct timeval tt;
277 char buffer [16];
278
0b4e3aa0
A
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 */
2d21ac55 297 perr = prngOutput(gPrngRef, (BYTE*) buffer, sizeof (buffer));
0b4e3aa0
A
298
299 /* and scramble it some more */
300 perr = prngForceReseed(gPrngRef, RESEED_TICKS);
2d21ac55 301 }
0b4e3aa0
A
302
303 /* make a mutex to control access */
2d21ac55
A
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);
8ad349bb
A
308
309 fips_initialize ();
310}
311
312void
313fips_initialize(void)
314{
2d21ac55
A
315 /* Read the initial value of g_xkey from yarrow */
316 prngOutput (gPrngRef, (BYTE*) &g_xkey, sizeof (g_xkey));
8ad349bb
A
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;
2d21ac55 324 random_block(g_random_data);
0b4e3aa0
A
325}
326
327/*
328 * Called to initialize our device,
329 * and to register ourselves with devfs
330 */
331void
8ad349bb 332random_init(void)
0b4e3aa0
A
333{
334 int ret;
335
336 if (gRandomInstalled)
337 return;
338
339 /* install us in the file system */
340 gRandomInstalled = 1;
341
2d21ac55 342#ifndef ARM_BOARD_CONFIG_S5L8900XFPGA_1136JFS
0b4e3aa0
A
343 /* setup yarrow and the mutex */
344 PreliminarySetup();
2d21ac55 345#endif
0b4e3aa0
A
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,
55e303ae 355 UID_ROOT, GID_WHEEL, 0666, "random", 0);
0b4e3aa0
A
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,
55e303ae
A
362 UID_ROOT, GID_WHEEL, 0666, "urandom", 0);
363}
364
365int
91447636
A
366random_ioctl( __unused dev_t dev, u_long cmd, __unused caddr_t data,
367 __unused int flag, __unused struct proc *p )
55e303ae
A
368{
369 switch (cmd) {
370 case FIONBIO:
371 case FIOASYNC:
372 break;
373 default:
374 return ENODEV;
375 }
376
377 return (0);
0b4e3aa0
A
378}
379
380/*
381 * Open the device. Make sure init happened, and make sure the caller is
382 * authorized.
383 */
384
385int
91447636 386random_open(__unused dev_t dev, int flags, __unused int devtype, __unused struct proc *p)
0b4e3aa0
A
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);
55e303ae 400#ifndef __APPLE__
91447636 401 if ((securelevel >= 1) && proc_suser(p))
0b4e3aa0 402 return (EPERM);
55e303ae 403#endif /* !__APPLE__ */
0b4e3aa0
A
404 }
405
406 return (0);
407}
408
409
410/*
411 * close the device.
412 */
413
414int
91447636 415random_close(__unused dev_t dev, __unused int flags, __unused int mode, __unused struct proc *p)
0b4e3aa0
A
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 */
425int
91447636 426random_write (__unused dev_t dev, struct uio *uio, __unused int ioflag)
0b4e3aa0
A
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 */
2d21ac55 436 lck_mtx_lock(gYarrowMutex);
0b4e3aa0
A
437
438 /* Security server is sending us entropy */
439
91447636 440 while (uio_resid(uio) > 0 && retCode == 0) {
0b4e3aa0 441 /* get the user's data */
91447636
A
442 // LP64todo - fix this! uio_resid may be 64-bit value
443 int bytesToInput = min(uio_resid(uio), sizeof (rdBuffer));
0b4e3aa0
A
444 retCode = uiomove(rdBuffer, bytesToInput, uio);
445 if (retCode != 0)
446 goto /*ugh*/ error_exit;
447
448 /* put it in Yarrow */
2d21ac55 449 if (prngInput(gPrngRef, (BYTE*) rdBuffer,
c0fea474
A
450 bytesToInput, SYSTEM_SOURCE,
451 bytesToInput * 8) != 0) {
0b4e3aa0
A
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
465error_exit: /* do this to make sure the mutex unlocks. */
2d21ac55 466 lck_mtx_unlock(gYarrowMutex);
0b4e3aa0
A
467 return (retCode);
468}
469
470/*
471 * return data to the caller. Results unpredictable.
472 */
2d21ac55
A
473int
474random_read(__unused dev_t dev, struct uio *uio, __unused int ioflag)
0b4e3aa0
A
475{
476 int retCode = 0;
8ad349bb 477
0b4e3aa0
A
478 if (gRandomError != 0)
479 return (ENOTSUP);
480
481 /* lock down the mutex */
2d21ac55 482 lck_mtx_lock(gYarrowMutex);
0b4e3aa0 483
2d21ac55 484 CheckReseed();
8ad349bb
A
485 int bytes_remaining = uio_resid(uio);
486 while (bytes_remaining > 0 && retCode == 0) {
0b4e3aa0 487 /* get the user's data */
8ad349bb
A
488 int bytes_to_read = 0;
489
490 int bytes_available = kBSizeInBytes - g_bytes_used;
491 if (bytes_available == 0)
492 {
2d21ac55 493 random_block(g_random_data);
8ad349bb
A
494 g_bytes_used = 0;
495 bytes_available = kBSizeInBytes;
496 }
497
498 bytes_to_read = min (bytes_remaining, bytes_available);
499
2d21ac55 500 retCode = uiomove(((caddr_t)g_random_data)+ g_bytes_used, bytes_to_read, uio);
8ad349bb
A
501 g_bytes_used += bytes_to_read;
502
0b4e3aa0
A
503 if (retCode != 0)
504 goto error_exit;
8ad349bb
A
505
506 bytes_remaining = uio_resid(uio);
0b4e3aa0
A
507 }
508
509 retCode = 0;
510
511error_exit:
2d21ac55 512 lck_mtx_unlock(gYarrowMutex);
0b4e3aa0
A
513 return retCode;
514}
515
516/* export good random numbers to the rest of the kernel */
517void
518read_random(void* buffer, u_int numbytes)
519{
520 if (gYarrowMutex == 0) { /* are we initialized? */
2d21ac55 521#ifndef ARM_BOARD_CONFIG_S5L8900XFPGA_1136JFS
0b4e3aa0 522 PreliminarySetup ();
2d21ac55 523#endif
0b4e3aa0
A
524 }
525
2d21ac55
A
526 lck_mtx_lock(gYarrowMutex);
527 CheckReseed();
528
21362eb3 529 int bytes_read = 0;
8ad349bb
A
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 {
2d21ac55 536 random_block(g_random_data);
8ad349bb
A
537 g_bytes_used = 0;
538 bytes_to_read = min(bytes_remaining, kBSizeInBytes);
539 }
540
2d21ac55 541 memmove ((u_int8_t*) buffer + bytes_read, ((u_int8_t*)g_random_data)+ g_bytes_used, bytes_to_read);
8ad349bb 542 g_bytes_used += bytes_to_read;
21362eb3 543 bytes_read += bytes_to_read;
8ad349bb
A
544 bytes_remaining -= bytes_to_read;
545 }
546
2d21ac55 547 lck_mtx_unlock(gYarrowMutex);
0b4e3aa0
A
548}
549
550/*
551 * Return an unsigned long pseudo-random number.
552 */
553u_long
8ad349bb 554RandomULong(void)
0b4e3aa0
A
555{
556 u_long buf;
557 read_random(&buf, sizeof (buf));
558 return (buf);
559}
560
2d21ac55
A
561void
562CheckReseed(void)
563{
564}