2 * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/param.h>
30 #include <sys/systm.h>
32 #include <sys/errno.h>
33 #include <sys/ioctl.h>
35 #include <sys/fcntl.h>
37 #include <miscfs/devfs/devfs.h>
38 #include <kern/lock.h>
39 #include <kern/clock.h>
41 #include <sys/malloc.h>
42 #include <sys/uio_internal.h>
44 #include <dev/random/randomdev.h>
45 #include <dev/random/YarrowCoreLib/include/yarrow.h>
46 #include <libkern/crypto/sha1.h>
48 #include <mach/mach_time.h>
49 #include <machine/machine_routines.h>
51 #define RANDOM_MAJOR -1 /* let the kernel pick the device number */
53 d_ioctl_t random_ioctl
;
56 * A struct describing which functions will get invoked for certain
59 static struct cdevsw random_cdevsw
=
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 */
69 eno_select
, /* select */
71 eno_strat
, /* strategy */
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;
86 void CheckReseed(void);
88 #define RESEED_TICKS 50 /* how long a reseed operation can take */
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};
96 typedef BlockWord Block
[kBSize
];
98 /* define prototypes to keep the compiler happy... */
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
);
106 * Get 120 bits from yarrow
110 * add block b to block a
113 add_blocks(Block a
, Block b
, BlockWord carry
)
118 u_int64_t c
= (u_int64_t
)carry
+
121 a
[i
] = c
& ((1LL << kWordSizeInBits
) - 1);
122 carry
= c
>> kWordSizeInBits
;
128 struct sha1_ctxt g_sha1_ctx
;
129 char zeros
[(512 - kBSizeInBits
) / 8];
133 unsigned char g_SelfTestInitialized
= 0;
134 u_int32_t gLastBlockChecksum
;
136 static const u_int32_t g_crc_table
[] =
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,
173 * Setup for fips compliance
177 * calculate a crc-32 checksum
179 u_int32_t
CalculateCRC(u_int8_t
* buffer
, size_t length
)
184 for (i
= 0; i
< length
; ++i
)
186 u_int32_t temp
= (crc
^ ((u_int32_t
) buffer
[i
])) & 0xFF;
187 crc
= (crc
>> 8) ^ g_crc_table
[temp
];
194 * get a random block of data per fips 186-2
197 random_block(Block b
)
204 prngOutput (gPrngRef
, (BYTE
*) &xSeed
, sizeof (xSeed
));
206 // add the seed to the previous value of g_xkey
207 add_blocks (g_xkey
, xSeed
, 0);
210 SHA1Update (&g_sha1_ctx
, (const u_int8_t
*) &g_xkey
, sizeof (g_xkey
));
212 // add zeros to fill the internal SHA-1 buffer
213 SHA1Update (&g_sha1_ctx
, (const u_int8_t
*)zeros
, sizeof (zeros
));
215 // write the resulting block
216 memmove(b
, g_sha1_ctx
.h
.b8
, sizeof (Block
));
218 // calculate the CRC-32 of the block
219 u_int32_t new_crc
= CalculateCRC(g_sha1_ctx
.h
.b8
, sizeof (Block
));
221 // make sure we don't repeat
222 int cmp
= new_crc
== gLastBlockChecksum
;
223 gLastBlockChecksum
= new_crc
;
224 if (!g_SelfTestInitialized
)
226 g_SelfTestInitialized
= 1;
236 // fix up the next value of g_xkey
237 add_blocks (g_xkey
, b
, 1);
238 } while (repeatCount
< 2);
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:
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.
250 * There is no good way to recover from any of these cases. We
254 panic("FIPS random self-test failed.");
258 *Initialize ONLY the Yarrow generator.
261 PreliminarySetup(void)
263 prng_error_status perr
;
265 /* create a Yarrow object */
266 perr
= prngInitialize(&gPrngRef
);
268 printf ("Couldn't initialize Yarrow, /dev/random will not work.\n");
272 /* clear the error flag, reads and write should then work */
279 /* get a little non-deterministic data as an initial seed. */
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.
289 perr
= prngInput(gPrngRef
, (BYTE
*) &tt
, sizeof (tt
), SYSTEM_SOURCE
, 8);
291 /* an error, complain */
292 printf ("Couldn't seed Yarrow.\n");
296 /* turn the data around */
297 perr
= prngOutput(gPrngRef
, (BYTE
*) buffer
, sizeof (buffer
));
299 /* and scramble it some more */
300 perr
= prngForceReseed(gPrngRef
, RESEED_TICKS
);
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
);
313 fips_initialize(void)
315 /* Read the initial value of g_xkey from yarrow */
316 prngOutput (gPrngRef
, (BYTE
*) &g_xkey
, sizeof (g_xkey
));
318 /* initialize our SHA1 generator */
319 SHA1Init (&g_sha1_ctx
);
321 /* other initializations */
322 memset (zeros
, 0, sizeof (zeros
));
324 random_block(g_random_data
);
328 * Called to initialize our device,
329 * and to register ourselves with devfs
336 if (gRandomInstalled
)
339 /* install us in the file system */
340 gRandomInstalled
= 1;
342 #ifndef ARM_BOARD_CONFIG_S5L8900XFPGA_1136JFS
343 /* setup yarrow and the mutex */
347 ret
= cdevsw_add(RANDOM_MAJOR
, &random_cdevsw
);
349 printf("random_init: failed to allocate a major number!\n");
350 gRandomInstalled
= 0;
354 devfs_make_node(makedev (ret
, 0), DEVFS_CHAR
,
355 UID_ROOT
, GID_WHEEL
, 0666, "random", 0);
359 * (which is exactly the same thing in our context)
361 devfs_make_node(makedev (ret
, 1), DEVFS_CHAR
,
362 UID_ROOT
, GID_WHEEL
, 0666, "urandom", 0);
366 random_ioctl( __unused dev_t dev
, u_long cmd
, __unused caddr_t data
,
367 __unused
int flag
, __unused
struct proc
*p
)
381 * Open the device. Make sure init happened, and make sure the caller is
386 random_open(__unused dev_t dev
, int flags
, __unused
int devtype
, __unused
struct proc
*p
)
388 if (gRandomError
!= 0) {
389 /* forget it, yarrow didn't come up */
394 * if we are being opened for write,
395 * make sure that we have privledges do so
397 if (flags
& FWRITE
) {
398 if (securelevel
>= 2)
401 if ((securelevel
>= 1) && proc_suser(p
))
403 #endif /* !__APPLE__ */
415 random_close(__unused dev_t dev
, __unused
int flags
, __unused
int mode
, __unused
struct proc
*p
)
422 * Get entropic data from the Security Server, and use it to reseed the
426 random_write (__unused dev_t dev
, struct uio
*uio
, __unused
int ioflag
)
431 if (gRandomError
!= 0) {
435 /* get control of the Yarrow instance, Yarrow is NOT thread safe */
436 lck_mtx_lock(gYarrowMutex
);
438 /* Security server is sending us entropy */
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
);
446 goto /*ugh*/ error_exit
;
448 /* put it in Yarrow */
449 if (prngInput(gPrngRef
, (BYTE
*) rdBuffer
,
450 bytesToInput
, SYSTEM_SOURCE
,
451 bytesToInput
* 8) != 0) {
458 if (prngForceReseed(gPrngRef
, RESEED_TICKS
) != 0) {
463 /* retCode should be 0 at this point */
465 error_exit
: /* do this to make sure the mutex unlocks. */
466 lck_mtx_unlock(gYarrowMutex
);
471 * return data to the caller. Results unpredictable.
474 random_read(__unused dev_t dev
, struct uio
*uio
, __unused
int ioflag
)
478 if (gRandomError
!= 0)
481 /* lock down the mutex */
482 lck_mtx_lock(gYarrowMutex
);
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;
490 int bytes_available
= kBSizeInBytes
- g_bytes_used
;
491 if (bytes_available
== 0)
493 random_block(g_random_data
);
495 bytes_available
= kBSizeInBytes
;
498 bytes_to_read
= min (bytes_remaining
, bytes_available
);
500 retCode
= uiomove(((caddr_t
)g_random_data
)+ g_bytes_used
, bytes_to_read
, uio
);
501 g_bytes_used
+= bytes_to_read
;
506 bytes_remaining
= uio_resid(uio
);
512 lck_mtx_unlock(gYarrowMutex
);
516 /* export good random numbers to the rest of the kernel */
518 read_random(void* buffer
, u_int numbytes
)
520 if (gYarrowMutex
== 0) { /* are we initialized? */
521 #ifndef ARM_BOARD_CONFIG_S5L8900XFPGA_1136JFS
526 lck_mtx_lock(gYarrowMutex
);
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)
536 random_block(g_random_data
);
538 bytes_to_read
= min(bytes_remaining
, kBSizeInBytes
);
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
;
547 lck_mtx_unlock(gYarrowMutex
);
551 * Return an unsigned long pseudo-random number.
557 read_random(&buf
, sizeof (buf
));