]> git.saurik.com Git - apple/xnu.git/blame - osfmk/prng/random.c
xnu-4570.20.62.tar.gz
[apple/xnu.git] / osfmk / prng / random.c
CommitLineData
fe8ab488
A
1/*
2 * Copyright (c) 2013 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#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>
43#include <vm/pmap.h>
44#include <vm/vm_page.h>
45#include <sys/kdebug.h>
46#include <sys/random.h>
47
48#include <prng/random.h>
49#include <corecrypto/ccdrbg.h>
50#include <corecrypto/ccsha1.h>
5ba3f43e
A
51#include <corecrypto/ccdigest.h>
52#include <corecrypto/ccsha2.h>
fe8ab488
A
53
54#include <pexpert/pexpert.h>
55#include <console/serial_protos.h>
56#include <IOKit/IOPlatformExpert.h>
57
5ba3f43e
A
58#if defined(__x86_64__)
59#include <i386/cpuid.h>
60
61static int rdseed_step(uint64_t *seed)
62{
63 uint8_t ok;
64
65 asm volatile ("rdseed %0; setc %1" : "=r" (*seed), "=qm" (ok));
66
67 return (int) ok;
68}
69
70static int rdseed_retry(uint64_t *seed, size_t nretries)
71{
72 size_t i;
73
74 for (i = 0; i < nretries; i += 1) {
75 if (rdseed_step(seed)) {
76 return 1;
77 } else {
78 asm volatile ("pause");
79 }
80 }
81
82 return 0;
83}
84
85static size_t rdseed_seed(void *buf, size_t nwords)
86{
87 uint64_t *buf_words;
88 size_t i;
89
90 if (nwords > 8) {
91 nwords = 8;
92 }
93
94 buf_words = buf;
95 for (i = 0; i < nwords; i += 1) {
96 if (!rdseed_retry(buf_words + i, 10)) {
97 return i;
98 }
99 }
100
101 return nwords;
102}
103
104static int rdrand_step(uint64_t *rand)
105{
106 uint8_t ok;
107
108 asm volatile ("rdrand %0; setc %1" : "=r" (*rand), "=qm" (ok));
109
110 return (int) ok;
111}
112
113static int rdrand_retry(uint64_t *rand, size_t nretries)
114{
115 size_t i;
116
117 for (i = 0; i < nretries; i += 1) {
118 if (rdrand_step(rand)) {
119 return 1;
120 }
121 }
122
123 return 0;
124}
125
126static size_t rdrand_seed(void *buf, size_t nwords)
127{
128 size_t i;
129 uint64_t w;
130 uint8_t hash[CCSHA256_OUTPUT_SIZE];
131 const struct ccdigest_info *di = &ccsha256_ltc_di;
132
133 ccdigest_di_decl(di, ctx);
134 ccdigest_init(di, ctx);
135
136 for (i = 0; i < 1023; i += 1) {
137 if (!rdrand_retry(&w, 10)) {
138 nwords = 0;
139 goto out;
140 }
141 ccdigest_update(di, ctx, sizeof w, &w);
142 }
143
144 ccdigest_final(di, ctx, hash);
145
146 if (nwords > 2) {
147 nwords = 2;
148 }
149
150 memcpy(buf, hash, nwords * sizeof (uint64_t));
151
152out:
153 ccdigest_di_clear(di, ctx);
154 bzero(hash, sizeof hash);
155 bzero(&w, sizeof w);
156
157 return nwords;
158}
159
160static void intel_entropysource(void *buf, size_t *nbytes)
161{
162 size_t nwords;
163
164 /* only handle complete words */
165 assert(*nbytes % sizeof (uint64_t) == 0);
166
167 nwords = (*nbytes) / sizeof (uint64_t);
168 if (cpuid_leaf7_features() & CPUID_LEAF7_FEATURE_RDSEED) {
169 nwords = rdseed_seed(buf, nwords);
170 *nbytes = nwords * sizeof (uint64_t);
171 } else if (cpuid_features() & CPUID_FEATURE_RDRAND) {
172 nwords = rdrand_seed(buf, nwords);
173 *nbytes = nwords * sizeof (uint64_t);
174 } else {
175 *nbytes = 0;
176 }
177}
178
179#endif
180
181typedef void (*entropysource)(void *buf, size_t *nbytes);
182
183static const entropysource entropysources[] = {
184 entropy_buffer_read,
185#if defined(__x86_64__)
186 intel_entropysource,
187#endif
188};
189
190static const size_t nsources = sizeof entropysources / sizeof entropysources[0];
191
192static size_t entropy_readall(void *buf, size_t nbytes_persource)
193{
194 uint8_t *buf_bytes = buf;
195 size_t i;
196 size_t nbytes_total = 0;
197
198 for (i = 0; i < nsources; i += 1) {
199 size_t nbytes = nbytes_persource;
200 entropysources[i](buf_bytes, &nbytes);
201 bzero(buf_bytes + nbytes, nbytes_persource - nbytes);
202 nbytes_total += nbytes;
203 buf_bytes += nbytes_persource;
204 }
205
206 return nbytes_total;
207}
208
209static struct {
210 lck_grp_t *group;
211 lck_attr_t *attrs;
212 lck_grp_attr_t *group_attrs;
213 lck_mtx_t *mutex;
214} lock;
fe8ab488
A
215
216typedef struct prngContext {
5ba3f43e
A
217 struct ccdrbg_info *infop;
218 struct ccdrbg_state *statep;
219 uint64_t bytes_generated;
220 uint64_t bytes_reseeded;
fe8ab488
A
221} *prngContextp;
222
223ccdrbg_factory_t prng_ccdrbg_factory = NULL;
224
5ba3f43e
A
225entropy_data_t EntropyData = {
226 .index_ptr = EntropyData.buffer
227};
fe8ab488 228
5ba3f43e
A
229static struct {
230 uint8_t seed[nsources][EARLY_RANDOM_SEED_SIZE];
231 size_t seedset;
232 uint8_t master_drbg_state[EARLY_RANDOM_STATE_STATIC_SIZE];
233 struct ccdrbg_state *drbg_states[MAX_CPUS];
234 struct ccdrbg_info drbg_info;
235 const struct ccdrbg_nisthmac_custom drbg_custom;
236} erandom = {
237 .drbg_custom = {
238 .di = &ccsha1_eay_di,
239 .strictFIPS = 0,
240 }
fe8ab488
A
241};
242
5ba3f43e 243static void read_erandom(void *buf, uint32_t nbytes);
fe8ab488
A
244
245void
5ba3f43e 246entropy_buffer_read(void *buffer, size_t *count)
fe8ab488 247{
5ba3f43e
A
248 boolean_t current_state;
249 unsigned int i, j;
fe8ab488 250
5ba3f43e 251 if (!erandom.seedset) {
fe8ab488
A
252 panic("early_random was never invoked");
253 }
254
5ba3f43e
A
255 if (*count > ENTROPY_BUFFER_BYTE_SIZE) {
256 *count = ENTROPY_BUFFER_BYTE_SIZE;
257 }
fe8ab488
A
258
259 current_state = ml_set_interrupts_enabled(FALSE);
fe8ab488 260
5ba3f43e 261 memcpy(buffer, EntropyData.buffer, *count);
fe8ab488 262
5ba3f43e 263 /* Consider removing this mixing step rdar://problem/31668239 */
fe8ab488
A
264 for (i = 0, j = (ENTROPY_BUFFER_SIZE - 1); i < ENTROPY_BUFFER_SIZE; j = i, i++)
265 EntropyData.buffer[i] = EntropyData.buffer[i] ^ EntropyData.buffer[j];
266
fe8ab488
A
267 (void) ml_set_interrupts_enabled(current_state);
268
269#if DEVELOPMENT || DEBUG
5ba3f43e 270 uint32_t *word = buffer;
fe8ab488
A
271 /* Good for both 32-bit and 64-bit kernels. */
272 for (i = 0; i < ENTROPY_BUFFER_SIZE; i += 4)
5ba3f43e 273 /*
fe8ab488
A
274 * We use "EARLY" here so that we can grab early entropy on
275 * ARM, where tracing is not started until after PRNG is
276 * initialized.
277 */
278 KERNEL_DEBUG_EARLY(ENTROPY_READ(i/4),
279 word[i+0], word[i+1], word[i+2], word[i+3]);
280#endif
281}
282
283/*
284 * Return a uniformly distributed 64-bit random number.
285 *
286 * This interface should have minimal dependencies on kernel
287 * services, and thus be available very early in the life
288 * of the kernel.
289 * This provides cryptographically secure randomness.
290 * Each processor has its own generator instance.
291 * It is seeded (lazily) with entropy provided by the Booter.
5ba3f43e 292 *
fe8ab488
A
293 * For <rdar://problem/17292592> the algorithm switched from LCG to
294 * NIST HMAC DBRG as follows:
295 * - When first called (on OSX this is very early while page tables are being
296 * built) early_random() calls ccdrbg_factory_hmac() to set-up a ccdbrg info
297 * structure.
298 * - The boot processor's ccdrbg state structure is a statically allocated area
299 * which is then initialized by calling the ccdbrg_init method.
300 * The initial entropy is 16 bytes of boot entropy.
301 * The nonce is the first 8 bytes of entropy xor'ed with a timestamp
302 * from ml_get_timebase().
5ba3f43e 303 * The personalization data provided is null.
fe8ab488
A
304 * - The first 64-bit random value is returned on the boot processor from
305 * an invocation of the ccdbrg_generate method.
306 * - Non-boot processor's DRBG state structures are allocated dynamically
307 * from prng_init(). Each is initialized with the same 16 bytes of entropy
308 * but with a different timestamped nonce and cpu number as personalization.
309 * - Subsequent calls to early_random() pass to read_erandom() to generate
310 * an 8-byte random value. read_erandom() ensures that pre-emption is
311 * disabled and selects the DBRG state from the current processor.
312 * The ccdbrg_generate method is called for the required random output.
5ba3f43e 313 * If this method returns CCDRBG_STATUS_NEED_RESEED, the erandom.seed buffer
fe8ab488
A
314 * is re-filled with kernel-harvested entropy and the ccdbrg_reseed method is
315 * called with this new entropy. The kernel panics if a reseed fails.
316 */
317uint64_t
318early_random(void)
319{
320 uint32_t cnt = 0;
321 uint64_t result;
322 uint64_t nonce;
323 int rc;
3e170ce0 324 int ps;
5ba3f43e 325 struct ccdrbg_state *state;
fe8ab488 326
5ba3f43e
A
327 if (!erandom.seedset) {
328 erandom.seedset = 1;
fe8ab488
A
329 cnt = PE_get_random_seed((unsigned char *) EntropyData.buffer,
330 sizeof(EntropyData.buffer));
331
332 if (cnt < sizeof(EntropyData.buffer)) {
333 /*
334 * Insufficient entropy is fatal. We must fill the
335 * entire entropy buffer during initializaton.
336 */
337 panic("EntropyData needed %lu bytes, but got %u.\n",
338 sizeof(EntropyData.buffer), cnt);
339 }
340
5ba3f43e 341 entropy_readall(&erandom.seed, EARLY_RANDOM_SEED_SIZE);
fe8ab488
A
342
343 /* Init DRBG for NIST HMAC */
5ba3f43e
A
344 ccdrbg_factory_nisthmac(&erandom.drbg_info, &erandom.drbg_custom);
345 assert(erandom.drbg_info.size <= sizeof(erandom.master_drbg_state));
346 state = (struct ccdrbg_state *) erandom.master_drbg_state;
347 erandom.drbg_states[master_cpu] = state;
fe8ab488
A
348
349 /*
3e170ce0
A
350 * Init our DBRG from the boot entropy and a timestamp as nonce
351 * and the cpu number as personalization.
fe8ab488 352 */
5ba3f43e 353 assert(sizeof(erandom.seed) > sizeof(nonce));
3e170ce0
A
354 nonce = ml_get_timebase();
355 ps = 0; /* boot cpu */
5ba3f43e
A
356 rc = ccdrbg_init(&erandom.drbg_info, state,
357 sizeof(erandom.seed), erandom.seed,
fe8ab488 358 sizeof(nonce), &nonce,
3e170ce0
A
359 sizeof(ps), &ps);
360 cc_clear(sizeof(nonce), &nonce);
361 if (rc != CCDRBG_STATUS_OK)
362 panic("ccdrbg_init() returned %d", rc);
fe8ab488
A
363
364 /* Generate output */
5ba3f43e
A
365 rc = ccdrbg_generate(&erandom.drbg_info, state,
366 sizeof(result), &result,
367 0, NULL);
3e170ce0
A
368 if (rc != CCDRBG_STATUS_OK)
369 panic("ccdrbg_generate() returned %d", rc);
fe8ab488
A
370
371 return result;
372 };
373
374 read_erandom(&result, sizeof(result));
375
376 return result;
377}
378
3e170ce0 379static void
fe8ab488
A
380read_erandom(void *buffer, u_int numBytes)
381{
382 int cpu;
383 int rc;
5ba3f43e
A
384 size_t nbytes;
385 struct ccdrbg_state *state;
fe8ab488
A
386
387 mp_disable_preemption();
388 cpu = cpu_number();
5ba3f43e 389 state = erandom.drbg_states[cpu];
fe8ab488 390 assert(state);
5ba3f43e 391 for (;;) {
fe8ab488 392 /* Generate output */
5ba3f43e
A
393 rc = ccdrbg_generate(&erandom.drbg_info, state,
394 numBytes, buffer,
395 0, NULL);
fe8ab488
A
396 if (rc == CCDRBG_STATUS_OK)
397 break;
398 if (rc == CCDRBG_STATUS_NEED_RESEED) {
399 /* It's time to reseed. Get more entropy */
5ba3f43e
A
400 nbytes = entropy_readall(erandom.seed, EARLY_RANDOM_SEED_SIZE);
401 assert(nbytes >= EARLY_RANDOM_SEED_SIZE);
402 rc = ccdrbg_reseed(&erandom.drbg_info, state,
403 sizeof(erandom.seed), erandom.seed,
fe8ab488 404 0, NULL);
5ba3f43e 405 cc_clear(sizeof(erandom.seed), erandom.seed);
fe8ab488
A
406 if (rc == CCDRBG_STATUS_OK)
407 continue;
408 panic("read_erandom reseed error %d\n", rc);
409 }
410 panic("read_erandom ccdrbg error %d\n", rc);
411 }
412 mp_enable_preemption();
413}
414
415void
416read_frandom(void *buffer, u_int numBytes)
417{
5ba3f43e
A
418 uint8_t *buffer_bytes = buffer;
419 int nbytes;
fe8ab488
A
420
421 /*
422 * Split up into requests for blocks smaller than
423 * than the DBRG request limit. iThis limit is private but
424 * for NISTHMAC it's known to be greater then 4096.
425 */
426 while (numBytes) {
427 nbytes = MIN(numBytes, PAGE_SIZE);
5ba3f43e
A
428 read_erandom(buffer_bytes, nbytes);
429 buffer_bytes += nbytes;
fe8ab488
A
430 numBytes -= nbytes;
431 }
432}
433
434/*
435 * Register a DRBG factory routine to e used in constructing the kernel PRNG.
436 * XXX to be called from the corecrypto kext.
437 */
438void
439prng_factory_register(ccdrbg_factory_t factory)
440{
441 prng_ccdrbg_factory = factory;
442 thread_wakeup((event_t) &prng_ccdrbg_factory);
443}
444
445void
446prng_cpu_init(int cpu)
447{
448 uint64_t nonce;
449 int rc;
5ba3f43e 450 struct ccdrbg_state *state;
fe8ab488
A
451 prngContextp pp;
452
453 /*
454 * Allocate state and initialize DBRG state for early_random()
455 * for this processor, if necessary.
456 */
5ba3f43e 457 if (erandom.drbg_states[cpu] == NULL) {
fe8ab488 458
5ba3f43e 459 state = kalloc(erandom.drbg_info.size);
fe8ab488
A
460 if (state == NULL) {
461 panic("prng_init kalloc failed\n");
462 }
5ba3f43e 463 erandom.drbg_states[cpu] = state;
fe8ab488
A
464
465 /*
3e170ce0
A
466 * Init our DBRG from boot entropy, nonce as timestamp
467 * and use the cpu number as the personalization parameter.
fe8ab488 468 */
3e170ce0 469 nonce = ml_get_timebase();
5ba3f43e
A
470 rc = ccdrbg_init(&erandom.drbg_info, state,
471 sizeof(erandom.seed), erandom.seed,
fe8ab488
A
472 sizeof(nonce), &nonce,
473 sizeof(cpu), &cpu);
3e170ce0
A
474 cc_clear(sizeof(nonce), &nonce);
475 if (rc != CCDRBG_STATUS_OK)
476 panic("ccdrbg_init() returned %d", rc);
fe8ab488
A
477 }
478
479 /* Non-boot cpus use the master cpu's global context */
480 if (cpu != master_cpu) {
481 cpu_datap(cpu)->cpu_prng = master_prng_context();
482 return;
483 }
484
5ba3f43e 485 assert(lock.mutex == NULL); /* Once only, please */
fe8ab488
A
486
487 /* make a mutex to control access */
5ba3f43e
A
488 lock.group_attrs = lck_grp_attr_alloc_init();
489 lock.group = lck_grp_alloc_init("random", lock.group_attrs);
490 lock.attrs = lck_attr_alloc_init();
491 lock.mutex = lck_mtx_alloc_init(lock.group, lock.attrs);
fe8ab488
A
492
493 pp = kalloc(sizeof(*pp));
494 if (pp == NULL)
495 panic("Unable to allocate prng context");
496 pp->bytes_generated = 0;
497 pp->bytes_reseeded = 0;
498 pp->infop = NULL;
499
500 /* XXX Temporary registration */
501 prng_factory_register(ccdrbg_factory_yarrow);
502
503 master_prng_context() = pp;
504}
505
5ba3f43e 506static struct ccdrbg_info *
fe8ab488
A
507prng_infop(prngContextp pp)
508{
5ba3f43e
A
509 uint8_t buf[nsources][ENTROPY_BUFFER_BYTE_SIZE];
510 size_t nbytes;
511
512 lck_mtx_assert(lock.mutex, LCK_MTX_ASSERT_OWNED);
fe8ab488
A
513
514 /* Usual case: the info is all set */
515 if (pp->infop)
516 return pp->infop;
517
518 /*
519 * Possibly wait for the CCDRBG factory routune to be registered
520 * by corecypto. But panic after waiting for more than 10 seconds.
521 */
522 while (prng_ccdrbg_factory == NULL ) {
523 wait_result_t wait_result;
524 assert_wait_timeout((event_t) &prng_ccdrbg_factory, TRUE,
5ba3f43e
A
525 10, NSEC_PER_USEC);
526 lck_mtx_unlock(lock.mutex);
fe8ab488
A
527 wait_result = thread_block(THREAD_CONTINUE_NULL);
528 if (wait_result == THREAD_TIMED_OUT)
529 panic("prng_ccdrbg_factory registration timeout");
5ba3f43e 530 lck_mtx_lock(lock.mutex);
fe8ab488
A
531 }
532 /* Check we didn't lose the set-up race */
533 if (pp->infop)
534 return pp->infop;
535
5ba3f43e 536 pp->infop = (struct ccdrbg_info *) kalloc(sizeof(struct ccdrbg_info));
fe8ab488
A
537 if (pp->infop == NULL)
538 panic("Unable to allocate prng info");
539
540 prng_ccdrbg_factory(pp->infop, NULL);
541
542 pp->statep = kalloc(pp->infop->size);
543 if (pp->statep == NULL)
544 panic("Unable to allocate prng state");
545
5ba3f43e 546 nbytes = entropy_readall(buf, ENTROPY_BUFFER_BYTE_SIZE);
fe8ab488
A
547
548 (void) ccdrbg_init(pp->infop, pp->statep,
5ba3f43e 549 nbytes, buf,
fe8ab488
A
550 0, NULL,
551 0, NULL);
5ba3f43e 552 cc_clear(sizeof (buf), buf);
fe8ab488
A
553 return pp->infop;
554}
555
556static void
557Reseed(prngContextp pp)
558{
5ba3f43e
A
559 uint8_t buf[nsources][ENTROPY_BUFFER_BYTE_SIZE];
560 size_t nbytes;
561
562 nbytes = entropy_readall(buf, ENTROPY_BUFFER_BYTE_SIZE);
fe8ab488
A
563
564 PRNG_CCDRBG((void) ccdrbg_reseed(pp->infop, pp->statep,
5ba3f43e 565 nbytes, buf,
fe8ab488
A
566 0, NULL));
567
5ba3f43e 568 cc_clear(sizeof (buf), buf);
fe8ab488
A
569 pp->bytes_reseeded = pp->bytes_generated;
570}
571
572
573/* export good random numbers to the rest of the kernel */
574void
575read_random(void* buffer, u_int numbytes)
576{
5ba3f43e
A
577 prngContextp pp;
578 struct ccdrbg_info *infop;
579 int ccdrbg_err;
fe8ab488 580
5ba3f43e 581 lck_mtx_lock(lock.mutex);
fe8ab488
A
582
583 pp = current_prng_context();
584 infop = prng_infop(pp);
585
586 /*
587 * Call DRBG, reseeding and retrying if requested.
588 */
5ba3f43e 589 for (;;) {
fe8ab488
A
590 PRNG_CCDRBG(
591 ccdrbg_err = ccdrbg_generate(infop, pp->statep,
5ba3f43e
A
592 numbytes, buffer,
593 0, NULL));
fe8ab488
A
594 if (ccdrbg_err == CCDRBG_STATUS_OK)
595 break;
596 if (ccdrbg_err == CCDRBG_STATUS_NEED_RESEED) {
597 Reseed(pp);
598 continue;
599 }
600 panic("read_random ccdrbg error %d\n", ccdrbg_err);
601 }
602
603 pp->bytes_generated += numbytes;
5ba3f43e 604 lck_mtx_unlock(lock.mutex);
fe8ab488
A
605}
606
607int
608write_random(void* buffer, u_int numbytes)
609{
610#if 0
611 int retval = 0;
612 prngContextp pp;
613
5ba3f43e 614 lck_mtx_lock(lock.mutex);
fe8ab488
A
615
616 pp = current_prng_context();
617
618 if (ccdrbg_reseed(prng_infop(pp), pp->statep,
619 bytesToInput, rdBuffer, 0, NULL) != 0)
620 retval = EIO;
621
5ba3f43e 622 lck_mtx_unlock(lock.mutex);
fe8ab488
A
623 return retval;
624#else
5ba3f43e
A
625#pragma unused(buffer, numbytes)
626 return 0;
fe8ab488
A
627#endif
628}