2 * Copyright (c) 2013 Apple 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 <mach/machine.h>
30 #include <mach/processor.h>
31 #include <kern/processor.h>
32 #include <kern/cpu_data.h>
33 #include <kern/cpu_number.h>
34 #include <kern/kalloc.h>
35 #include <kern/machine.h>
36 #include <kern/misc_protos.h>
37 #include <kern/startup.h>
38 #include <kern/sched.h>
39 #include <kern/thread.h>
40 #include <kern/thread_call.h>
41 #include <machine/cpu_data.h>
42 #include <machine/simple_lock.h>
44 #include <vm/vm_page.h>
45 #include <sys/kdebug.h>
46 #include <sys/random.h>
48 #include <prng/random.h>
49 #include <corecrypto/ccdrbg.h>
50 #include <corecrypto/ccsha1.h>
52 #include <pexpert/pexpert.h>
53 #include <console/serial_protos.h>
54 #include <IOKit/IOPlatformExpert.h>
56 static lck_grp_t
*gPRNGGrp
;
57 static lck_attr_t
*gPRNGAttr
;
58 static lck_grp_attr_t
*gPRNGGrpAttr
;
59 static lck_mtx_t
*gPRNGMutex
= NULL
;
61 typedef struct prngContext
{
62 struct ccdrbg_info
*infop
;
63 struct ccdrbg_state
*statep
;
64 uint64_t bytes_generated
;
65 uint64_t bytes_reseeded
;
68 ccdrbg_factory_t prng_ccdrbg_factory
= NULL
;
70 entropy_data_t EntropyData
= { .index_ptr
= EntropyData
.buffer
};
72 boolean_t erandom_seed_set
= FALSE
;
73 char erandom_seed
[EARLY_RANDOM_SEED_SIZE
];
74 typedef struct ccdrbg_state ccdrbg_state_t
;
75 uint8_t master_erandom_state
[EARLY_RANDOM_STATE_STATIC_SIZE
];
76 ccdrbg_state_t
*erandom_state
[MAX_CPUS
];
77 struct ccdrbg_info erandom_info
;
78 decl_simple_lock_data(,entropy_lock
);
80 struct ccdrbg_nisthmac_custom erandom_custom
= {
85 static void read_erandom(void *buffer
, u_int numBytes
); /* Forward */
88 entropy_buffer_read(char *buffer
,
91 boolean_t current_state
;
94 if (!erandom_seed_set
) {
95 panic("early_random was never invoked");
98 if ((*count
) > (ENTROPY_BUFFER_SIZE
* sizeof(unsigned int)))
99 *count
= ENTROPY_BUFFER_SIZE
* sizeof(unsigned int);
101 current_state
= ml_set_interrupts_enabled(FALSE
);
102 #if defined (__x86_64__)
103 simple_lock(&entropy_lock
);
106 memcpy((char *) buffer
, (char *) EntropyData
.buffer
, *count
);
108 for (i
= 0, j
= (ENTROPY_BUFFER_SIZE
- 1); i
< ENTROPY_BUFFER_SIZE
; j
= i
, i
++)
109 EntropyData
.buffer
[i
] = EntropyData
.buffer
[i
] ^ EntropyData
.buffer
[j
];
111 #if defined (__x86_64__)
112 simple_unlock(&entropy_lock
);
114 (void) ml_set_interrupts_enabled(current_state
);
116 #if DEVELOPMENT || DEBUG
117 uint32_t *word
= (uint32_t *) (void *) buffer
;
118 /* Good for both 32-bit and 64-bit kernels. */
119 for (i
= 0; i
< ENTROPY_BUFFER_SIZE
; i
+= 4)
121 * We use "EARLY" here so that we can grab early entropy on
122 * ARM, where tracing is not started until after PRNG is
125 KERNEL_DEBUG_EARLY(ENTROPY_READ(i
/4),
126 word
[i
+0], word
[i
+1], word
[i
+2], word
[i
+3]);
131 * Return a uniformly distributed 64-bit random number.
133 * This interface should have minimal dependencies on kernel
134 * services, and thus be available very early in the life
136 * This provides cryptographically secure randomness.
137 * Each processor has its own generator instance.
138 * It is seeded (lazily) with entropy provided by the Booter.
140 * For <rdar://problem/17292592> the algorithm switched from LCG to
141 * NIST HMAC DBRG as follows:
142 * - When first called (on OSX this is very early while page tables are being
143 * built) early_random() calls ccdrbg_factory_hmac() to set-up a ccdbrg info
145 * - The boot processor's ccdrbg state structure is a statically allocated area
146 * which is then initialized by calling the ccdbrg_init method.
147 * The initial entropy is 16 bytes of boot entropy.
148 * The nonce is the first 8 bytes of entropy xor'ed with a timestamp
149 * from ml_get_timebase().
150 * The personalization data provided is null.
151 * - The first 64-bit random value is returned on the boot processor from
152 * an invocation of the ccdbrg_generate method.
153 * - Non-boot processor's DRBG state structures are allocated dynamically
154 * from prng_init(). Each is initialized with the same 16 bytes of entropy
155 * but with a different timestamped nonce and cpu number as personalization.
156 * - Subsequent calls to early_random() pass to read_erandom() to generate
157 * an 8-byte random value. read_erandom() ensures that pre-emption is
158 * disabled and selects the DBRG state from the current processor.
159 * The ccdbrg_generate method is called for the required random output.
160 * If this method returns CCDRBG_STATUS_NEED_RESEED, the erandom_seed buffer
161 * is re-filled with kernel-harvested entropy and the ccdbrg_reseed method is
162 * called with this new entropy. The kernel panics if a reseed fails.
172 ccdrbg_state_t
*state
;
174 if (!erandom_seed_set
) {
175 simple_lock_init(&entropy_lock
,0);
176 erandom_seed_set
= TRUE
;
177 cnt
= PE_get_random_seed((unsigned char *) EntropyData
.buffer
,
178 sizeof(EntropyData
.buffer
));
180 if (cnt
< sizeof(EntropyData
.buffer
)) {
182 * Insufficient entropy is fatal. We must fill the
183 * entire entropy buffer during initializaton.
185 panic("EntropyData needed %lu bytes, but got %u.\n",
186 sizeof(EntropyData
.buffer
), cnt
);
190 * Use some of the supplied entropy as a basis for early_random;
191 * reuse is ugly, but simplifies things. Ideally, we would guard
192 * early random values well enough that it isn't safe to attack
193 * them, but this cannot be guaranteed; thus, initial entropy
194 * can be considered 8 bytes weaker for a given boot if any
195 * early random values are conclusively determined.
197 * early_random_seed could be larger than EntopyData.buffer...
200 bcopy(EntropyData
.buffer
, &erandom_seed
, sizeof(erandom_seed
));
202 /* Init DRBG for NIST HMAC */
203 ccdrbg_factory_nisthmac(&erandom_info
, &erandom_custom
);
204 assert(erandom_info
.size
<= sizeof(master_erandom_state
));
205 state
= (ccdrbg_state_t
*) master_erandom_state
;
206 erandom_state
[0] = state
;
209 * Init our DBRG from the boot entropy and a timestamp as nonce
210 * and the cpu number as personalization.
212 assert(sizeof(erandom_seed
) > sizeof(nonce
));
213 nonce
= ml_get_timebase();
214 ps
= 0; /* boot cpu */
215 rc
= ccdrbg_init(&erandom_info
, state
,
216 sizeof(erandom_seed
), erandom_seed
,
217 sizeof(nonce
), &nonce
,
219 cc_clear(sizeof(nonce
), &nonce
);
220 if (rc
!= CCDRBG_STATUS_OK
)
221 panic("ccdrbg_init() returned %d", rc
);
223 /* Generate output */
224 rc
= ccdrbg_generate(&erandom_info
, state
,
225 sizeof(result
), &result
,
227 if (rc
!= CCDRBG_STATUS_OK
)
228 panic("ccdrbg_generate() returned %d", rc
);
233 read_erandom(&result
, sizeof(result
));
239 read_erandom(void *buffer
, u_int numBytes
)
244 ccdrbg_state_t
*state
;
246 mp_disable_preemption();
248 state
= erandom_state
[cpu
];
251 /* Generate output */
252 rc
= ccdrbg_generate(&erandom_info
, state
,
255 if (rc
== CCDRBG_STATUS_OK
)
257 if (rc
== CCDRBG_STATUS_NEED_RESEED
) {
258 /* It's time to reseed. Get more entropy */
259 cnt
= sizeof(erandom_seed
);
260 entropy_buffer_read(erandom_seed
, &cnt
);
261 assert(cnt
== sizeof(erandom_seed
));
262 rc
= ccdrbg_reseed(&erandom_info
, state
,
263 sizeof(erandom_seed
), erandom_seed
,
265 cc_clear(sizeof(erandom_seed
), erandom_seed
);
266 if (rc
== CCDRBG_STATUS_OK
)
268 panic("read_erandom reseed error %d\n", rc
);
270 panic("read_erandom ccdrbg error %d\n", rc
);
272 mp_enable_preemption();
276 read_frandom(void *buffer
, u_int numBytes
)
278 char *cp
= (char *) buffer
;
282 * Split up into requests for blocks smaller than
283 * than the DBRG request limit. iThis limit is private but
284 * for NISTHMAC it's known to be greater then 4096.
287 nbytes
= MIN(numBytes
, PAGE_SIZE
);
288 read_erandom(cp
, nbytes
);
295 * Register a DRBG factory routine to e used in constructing the kernel PRNG.
296 * XXX to be called from the corecrypto kext.
299 prng_factory_register(ccdrbg_factory_t factory
)
301 prng_ccdrbg_factory
= factory
;
302 thread_wakeup((event_t
) &prng_ccdrbg_factory
);
306 prng_cpu_init(int cpu
)
310 ccdrbg_state_t
*state
;
314 * Allocate state and initialize DBRG state for early_random()
315 * for this processor, if necessary.
317 if (erandom_state
[cpu
] == NULL
) {
319 state
= kalloc(erandom_info
.size
);
321 panic("prng_init kalloc failed\n");
323 erandom_state
[cpu
] = state
;
326 * Init our DBRG from boot entropy, nonce as timestamp
327 * and use the cpu number as the personalization parameter.
329 nonce
= ml_get_timebase();
330 rc
= ccdrbg_init(&erandom_info
, state
,
331 sizeof(erandom_seed
), erandom_seed
,
332 sizeof(nonce
), &nonce
,
334 cc_clear(sizeof(nonce
), &nonce
);
335 if (rc
!= CCDRBG_STATUS_OK
)
336 panic("ccdrbg_init() returned %d", rc
);
339 /* Non-boot cpus use the master cpu's global context */
340 if (cpu
!= master_cpu
) {
341 cpu_datap(cpu
)->cpu_prng
= master_prng_context();
345 assert(gPRNGMutex
== NULL
); /* Once only, please */
347 /* make a mutex to control access */
348 gPRNGGrpAttr
= lck_grp_attr_alloc_init();
349 gPRNGGrp
= lck_grp_alloc_init("random", gPRNGGrpAttr
);
350 gPRNGAttr
= lck_attr_alloc_init();
351 gPRNGMutex
= lck_mtx_alloc_init(gPRNGGrp
, gPRNGAttr
);
353 pp
= kalloc(sizeof(*pp
));
355 panic("Unable to allocate prng context");
356 pp
->bytes_generated
= 0;
357 pp
->bytes_reseeded
= 0;
360 /* XXX Temporary registration */
361 prng_factory_register(ccdrbg_factory_yarrow
);
363 master_prng_context() = pp
;
366 static ccdrbg_info_t
*
367 prng_infop(prngContextp pp
)
369 lck_mtx_assert(gPRNGMutex
, LCK_MTX_ASSERT_OWNED
);
371 /* Usual case: the info is all set */
376 * Possibly wait for the CCDRBG factory routune to be registered
377 * by corecypto. But panic after waiting for more than 10 seconds.
379 while (prng_ccdrbg_factory
== NULL
) {
380 wait_result_t wait_result
;
381 assert_wait_timeout((event_t
) &prng_ccdrbg_factory
, TRUE
,
383 lck_mtx_unlock(gPRNGMutex
);
384 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
385 if (wait_result
== THREAD_TIMED_OUT
)
386 panic("prng_ccdrbg_factory registration timeout");
387 lck_mtx_lock(gPRNGMutex
);
389 /* Check we didn't lose the set-up race */
393 pp
->infop
= (ccdrbg_info_t
*) kalloc(sizeof(ccdrbg_info_t
));
394 if (pp
->infop
== NULL
)
395 panic("Unable to allocate prng info");
397 prng_ccdrbg_factory(pp
->infop
, NULL
);
399 pp
->statep
= kalloc(pp
->infop
->size
);
400 if (pp
->statep
== NULL
)
401 panic("Unable to allocate prng state");
403 char rdBuffer
[ENTROPY_BUFFER_BYTE_SIZE
];
404 unsigned int bytesToInput
= sizeof(rdBuffer
);
406 entropy_buffer_read(rdBuffer
, &bytesToInput
);
408 (void) ccdrbg_init(pp
->infop
, pp
->statep
,
409 bytesToInput
, rdBuffer
,
412 cc_clear(sizeof(rdBuffer
), rdBuffer
);
417 Reseed(prngContextp pp
)
419 char rdBuffer
[ENTROPY_BUFFER_BYTE_SIZE
];
420 unsigned int bytesToInput
= sizeof(rdBuffer
);
422 entropy_buffer_read(rdBuffer
, &bytesToInput
);
424 PRNG_CCDRBG((void) ccdrbg_reseed(pp
->infop
, pp
->statep
,
425 bytesToInput
, rdBuffer
,
428 cc_clear(sizeof(rdBuffer
), rdBuffer
);
429 pp
->bytes_reseeded
= pp
->bytes_generated
;
433 /* export good random numbers to the rest of the kernel */
435 read_random(void* buffer
, u_int numbytes
)
438 ccdrbg_info_t
*infop
;
441 lck_mtx_lock(gPRNGMutex
);
443 pp
= current_prng_context();
444 infop
= prng_infop(pp
);
447 * Call DRBG, reseeding and retrying if requested.
451 ccdrbg_err
= ccdrbg_generate(infop
, pp
->statep
,
454 if (ccdrbg_err
== CCDRBG_STATUS_OK
)
456 if (ccdrbg_err
== CCDRBG_STATUS_NEED_RESEED
) {
460 panic("read_random ccdrbg error %d\n", ccdrbg_err
);
463 pp
->bytes_generated
+= numbytes
;
464 lck_mtx_unlock(gPRNGMutex
);
468 write_random(void* buffer
, u_int numbytes
)
474 lck_mtx_lock(gPRNGMutex
);
476 pp
= current_prng_context();
478 if (ccdrbg_reseed(prng_infop(pp
), pp
->statep
,
479 bytesToInput
, rdBuffer
, 0, NULL
) != 0)
482 lck_mtx_unlock(gPRNGMutex
);
485 #pragma unused(buffer, numbytes)