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.
171 ccdrbg_state_t
*state
;
173 if (!erandom_seed_set
) {
174 simple_lock_init(&entropy_lock
,0);
175 erandom_seed_set
= TRUE
;
176 cnt
= PE_get_random_seed((unsigned char *) EntropyData
.buffer
,
177 sizeof(EntropyData
.buffer
));
179 if (cnt
< sizeof(EntropyData
.buffer
)) {
181 * Insufficient entropy is fatal. We must fill the
182 * entire entropy buffer during initializaton.
184 panic("EntropyData needed %lu bytes, but got %u.\n",
185 sizeof(EntropyData
.buffer
), cnt
);
189 * Use some of the supplied entropy as a basis for early_random;
190 * reuse is ugly, but simplifies things. Ideally, we would guard
191 * early random values well enough that it isn't safe to attack
192 * them, but this cannot be guaranteed; thus, initial entropy
193 * can be considered 8 bytes weaker for a given boot if any
194 * early random values are conclusively determined.
196 * early_random_seed could be larger than EntopyData.buffer...
199 bcopy(EntropyData
.buffer
, &erandom_seed
, sizeof(erandom_seed
));
201 /* Init DRBG for NIST HMAC */
202 ccdrbg_factory_nisthmac(&erandom_info
, &erandom_custom
);
203 assert(erandom_info
.size
<= sizeof(master_erandom_state
));
204 state
= (ccdrbg_state_t
*) master_erandom_state
;
205 erandom_state
[0] = state
;
208 * Init our DBRG from the boot entropy and a nonce composed of
209 * a timestamp swizzled with the first 8 bytes of this entropy.
211 assert(sizeof(erandom_seed
) > sizeof(nonce
));
212 bcopy(erandom_seed
, &nonce
, sizeof(nonce
));
213 nonce
^= ml_get_timebase();
214 rc
= ccdrbg_init(&erandom_info
, state
,
215 sizeof(erandom_seed
), erandom_seed
,
216 sizeof(nonce
), &nonce
,
218 assert(rc
== CCDRBG_STATUS_OK
);
220 /* Generate output */
221 rc
= ccdrbg_generate(&erandom_info
, state
,
222 sizeof(result
), &result
,
224 assert(rc
== CCDRBG_STATUS_OK
);
229 read_erandom(&result
, sizeof(result
));
235 read_erandom(void *buffer
, u_int numBytes
)
240 ccdrbg_state_t
*state
;
242 mp_disable_preemption();
244 state
= erandom_state
[cpu
];
247 /* Generate output */
248 rc
= ccdrbg_generate(&erandom_info
, state
,
251 if (rc
== CCDRBG_STATUS_OK
)
253 if (rc
== CCDRBG_STATUS_NEED_RESEED
) {
254 /* It's time to reseed. Get more entropy */
255 cnt
= sizeof(erandom_seed
);
256 entropy_buffer_read(erandom_seed
, &cnt
);
257 assert(cnt
== sizeof(erandom_seed
));
258 rc
= ccdrbg_reseed(&erandom_info
, state
,
259 sizeof(erandom_seed
), erandom_seed
,
261 if (rc
== CCDRBG_STATUS_OK
)
263 panic("read_erandom reseed error %d\n", rc
);
265 panic("read_erandom ccdrbg error %d\n", rc
);
267 mp_enable_preemption();
271 read_frandom(void *buffer
, u_int numBytes
)
273 char *cp
= (char *) buffer
;
277 * Split up into requests for blocks smaller than
278 * than the DBRG request limit. iThis limit is private but
279 * for NISTHMAC it's known to be greater then 4096.
282 nbytes
= MIN(numBytes
, PAGE_SIZE
);
283 read_erandom(cp
, nbytes
);
290 * Register a DRBG factory routine to e used in constructing the kernel PRNG.
291 * XXX to be called from the corecrypto kext.
294 prng_factory_register(ccdrbg_factory_t factory
)
296 prng_ccdrbg_factory
= factory
;
297 thread_wakeup((event_t
) &prng_ccdrbg_factory
);
301 prng_cpu_init(int cpu
)
305 ccdrbg_state_t
*state
;
309 * Allocate state and initialize DBRG state for early_random()
310 * for this processor, if necessary.
312 if (erandom_state
[cpu
] == NULL
) {
314 state
= kalloc(erandom_info
.size
);
316 panic("prng_init kalloc failed\n");
318 erandom_state
[cpu
] = state
;
321 * Init our DBRG from boot entropy, nonce as timestamp xor'ed
322 * with the first 8 bytes of entropy, and use the cpu number
323 * as the personalization parameter.
325 bcopy(erandom_seed
, &nonce
, sizeof(nonce
));
326 nonce
^= ml_get_timebase();
327 rc
= ccdrbg_init(&erandom_info
, state
,
328 sizeof(erandom_seed
), erandom_seed
,
329 sizeof(nonce
), &nonce
,
331 assert(rc
== CCDRBG_STATUS_OK
);
334 /* Non-boot cpus use the master cpu's global context */
335 if (cpu
!= master_cpu
) {
336 cpu_datap(cpu
)->cpu_prng
= master_prng_context();
340 assert(gPRNGMutex
== NULL
); /* Once only, please */
342 /* make a mutex to control access */
343 gPRNGGrpAttr
= lck_grp_attr_alloc_init();
344 gPRNGGrp
= lck_grp_alloc_init("random", gPRNGGrpAttr
);
345 gPRNGAttr
= lck_attr_alloc_init();
346 gPRNGMutex
= lck_mtx_alloc_init(gPRNGGrp
, gPRNGAttr
);
348 pp
= kalloc(sizeof(*pp
));
350 panic("Unable to allocate prng context");
351 pp
->bytes_generated
= 0;
352 pp
->bytes_reseeded
= 0;
355 /* XXX Temporary registration */
356 prng_factory_register(ccdrbg_factory_yarrow
);
358 master_prng_context() = pp
;
361 static ccdrbg_info_t
*
362 prng_infop(prngContextp pp
)
364 lck_mtx_assert(gPRNGMutex
, LCK_MTX_ASSERT_OWNED
);
366 /* Usual case: the info is all set */
371 * Possibly wait for the CCDRBG factory routune to be registered
372 * by corecypto. But panic after waiting for more than 10 seconds.
374 while (prng_ccdrbg_factory
== NULL
) {
375 wait_result_t wait_result
;
376 assert_wait_timeout((event_t
) &prng_ccdrbg_factory
, TRUE
,
378 lck_mtx_unlock(gPRNGMutex
);
379 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
380 if (wait_result
== THREAD_TIMED_OUT
)
381 panic("prng_ccdrbg_factory registration timeout");
382 lck_mtx_lock(gPRNGMutex
);
384 /* Check we didn't lose the set-up race */
388 pp
->infop
= (ccdrbg_info_t
*) kalloc(sizeof(ccdrbg_info_t
));
389 if (pp
->infop
== NULL
)
390 panic("Unable to allocate prng info");
392 prng_ccdrbg_factory(pp
->infop
, NULL
);
394 pp
->statep
= kalloc(pp
->infop
->size
);
395 if (pp
->statep
== NULL
)
396 panic("Unable to allocate prng state");
398 char rdBuffer
[ENTROPY_BUFFER_BYTE_SIZE
];
399 unsigned int bytesToInput
= sizeof(rdBuffer
);
401 entropy_buffer_read(rdBuffer
, &bytesToInput
);
403 (void) ccdrbg_init(pp
->infop
, pp
->statep
,
404 bytesToInput
, rdBuffer
,
411 Reseed(prngContextp pp
)
413 char rdBuffer
[ENTROPY_BUFFER_BYTE_SIZE
];
414 unsigned int bytesToInput
= sizeof(rdBuffer
);
416 entropy_buffer_read(rdBuffer
, &bytesToInput
);
418 PRNG_CCDRBG((void) ccdrbg_reseed(pp
->infop
, pp
->statep
,
419 bytesToInput
, rdBuffer
,
422 pp
->bytes_reseeded
= pp
->bytes_generated
;
426 /* export good random numbers to the rest of the kernel */
428 read_random(void* buffer
, u_int numbytes
)
431 ccdrbg_info_t
*infop
;
434 lck_mtx_lock(gPRNGMutex
);
436 pp
= current_prng_context();
437 infop
= prng_infop(pp
);
440 * Call DRBG, reseeding and retrying if requested.
444 ccdrbg_err
= ccdrbg_generate(infop
, pp
->statep
,
447 if (ccdrbg_err
== CCDRBG_STATUS_OK
)
449 if (ccdrbg_err
== CCDRBG_STATUS_NEED_RESEED
) {
453 panic("read_random ccdrbg error %d\n", ccdrbg_err
);
456 pp
->bytes_generated
+= numbytes
;
457 lck_mtx_unlock(gPRNGMutex
);
461 write_random(void* buffer
, u_int numbytes
)
467 lck_mtx_lock(gPRNGMutex
);
469 pp
= current_prng_context();
471 if (ccdrbg_reseed(prng_infop(pp
), pp
->statep
,
472 bytesToInput
, rdBuffer
, 0, NULL
) != 0)
475 lck_mtx_unlock(gPRNGMutex
);
478 #pragma unused(buffer, numbytes)