1 /* Copyright (c) (2018,2019) Apple Inc. All rights reserved.
3 * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which
4 * is contained in the License.txt file distributed with corecrypto) and only to
5 * people who accept that license. IMPORTANT: Any license rights granted to you by
6 * Apple Inc. (if any) are limited to internal use within your organization only on
7 * devices and computers you own or control, for the sole purpose of verifying the
8 * security characteristics and correct functioning of the Apple Software. You may
9 * not, directly or indirectly, redistribute the Apple Software or any portions thereof.
12 #ifndef _CORECRYPTO_CCKPRNG_H_
13 #define _CORECRYPTO_CCKPRNG_H_
17 #include <corecrypto/cc.h>
19 // This is a Fortuna-inspired PRNG. While it differs from Fortuna in
20 // many minor details, the biggest difference is its support for
21 // multiple independent output generators. This is to make it suitable
22 // for use in concurrent environments.
24 // This PRNG targets a 256-bit security level.
26 // First, the user should call cckprng_init. The user must specify the
27 // maximum number of output generators that might be
28 // needed. (Typically, users should align this argument with the
29 // number of available CPUs.)
31 // The user must also provide a read-only handle to an entropy
32 // source. This is a fixed-size buffer that will receive entropy
33 // updates out of band from the PRNG (e.g. in an interrupt
34 // handler). The PRNG will consume entropy from this buffer according
35 // to an internal schedule driven by calls to cckprng_refresh (see
38 // The user should call cckprng_initgen for as many output generators
39 // as are needed. The numeric argument is an identifier to be reused
40 // during calls to cckprng_generate (see below) and must be less than
41 // the maximum number of generators specified to cckprng_init.
43 // After initialization, the user is free to call cckprng_generate to
44 // generate random bytes. The user must specify the generator in this
45 // call using a numeric identifier passed in the call to
48 // Output generation is limited to 256 bytes per request. Users should
49 // make multiple requests if more output is needed.
51 // The user is expected to call cckprng_refresh regularly. This
52 // function consumes entropy and mixes it into the output generators
53 // according to an internal schedule.
55 // This implementation is thread-safe. Internally, a set of mutexes
56 // guard access to internal state. Most functions rely on a single
57 // mutex to protect shared state. The main exception is the
58 // cckprng_generate function, which uses a per-generator mutex to
59 // allow concurrent output generation on different threads.
61 // Another important exception is cckprng_refresh. While this function
62 // relies on the shared mutex, it returns immediately if it cannot
65 // The PRNG also supports user-initiated reseeds. This is to support a
66 // user-writable random device.
68 // This PRNG supports reseeds concurrent with output generation,
69 // i.e. it is safe to call cckprng_reseed or cckprng_refresh while
70 // another thread is calling cckprng_generate.
72 #define CCKPRNG_NPOOLS 32
73 #define CCKPRNG_SEED_NBYTES 32
74 #define CCKPRNG_POOL_NBYTES 32
75 #define CCKPRNG_KEY_NBYTES 32
77 struct cckprng_gen_diag
{
78 // The number of times this generator has been rekeyed from the master seed
81 // The number of requests this generator has fulfilled
84 // The total number of bytes this generator has generated over all requests
87 // The maximum number of bytes this generator has generated in any one request
88 uint64_t out_nbytes_req_max
;
90 // The total number of bytes this generator has generated since the last rekey
91 uint64_t out_nbytes_key
;
93 // The maximum total number of bytes this generator has generated between two rekeys
94 uint64_t out_nbytes_key_max
;
97 struct cckprng_pool_diag
{
98 // The number of samples currently resident in the pool
101 // The number of times this pool has been drained in a reseed
104 // The maximum number of samples this pool has held at any one time
105 uint64_t nsamples_max
;
108 struct cckprng_diag
{
109 // The number of reseeds via user input (e.g. by writing to /dev/random)
110 uint64_t userreseed_nreseeds
;
112 // The number of reseeds via the scheduler
113 uint64_t schedreseed_nreseeds
;
115 // The maximum number of samples included in any one scheduler reseed
116 uint64_t schedreseed_nsamples_max
;
118 // The maximum number of samples included in any one entropy input
119 uint64_t addentropy_nsamples_max
;
121 // Diagnostics corresponding to individual output generators
123 CC_ALIGNED(8) struct cckprng_gen_diag
*gens
;
125 // Diagnostics corresponding to internal entropy pools
126 struct cckprng_pool_diag pools
[CCKPRNG_NPOOLS
];
131 #include <kern/locks.h>
133 typedef lck_grp_t
*cckprng_lock_group
;
134 typedef lck_mtx_t
*cckprng_lock_mutex
;
136 struct cckprng_lock_ctx
{
137 cckprng_lock_group group
;
138 cckprng_lock_mutex mutex
;
141 #elif CC_ANDROID || CC_LINUX
145 typedef pthread_mutex_t cckprng_lock_mutex
;
147 struct cckprng_lock_ctx
{
148 cckprng_lock_mutex mutex
;
155 typedef os_unfair_lock cckprng_lock_mutex
;
157 struct cckprng_lock_ctx
{
158 cckprng_lock_mutex mutex
;
163 struct cckprng_key_ctx
{
164 uint8_t data
[CCKPRNG_KEY_NBYTES
];
167 struct cckprng_gen_ctx
{
168 // We maintain two keys (one live and one idle) to allow
169 // concurrent generation and reseeding
170 struct cckprng_key_ctx keys
[2];
171 _Atomic
unsigned swap
;
172 unsigned key_live_idx
;
173 unsigned key_idle_idx
;
175 // A counter used in CTR mode
178 // Whether the generator has been initialized
181 // A mutex governing this generator's state (but note the idle key
182 // context is under control of the PRNG's shared mutex)
184 cckprng_lock_mutex mutex
;
188 struct cckprng_pool_ctx
{
189 uint8_t data
[CCKPRNG_POOL_NBYTES
];
192 // This is a handle to an "entropy buffer" to be managed externally
193 // (i.e. in xnu). This is a non-cryptographic
194 // accumulator. Practically, the buffer is filled with timestamps
195 // collected during interrupts. The existing state of the buffer is
196 // rotated and new timestamps are added in. A counter of raw timing
197 // samples is also managed externally. The buffer and the counter are
198 // both subject to data races, which we tolerate.
200 struct cckprng_entropybuf
{
202 // A read-only handle to an "entropy buffer" (a non-cryptographic accumulator) to be managed externally
205 // The size of the entropy buffer
208 // A read-only handle to a count of raw samples in the buffer
209 const uint32_t *nsamples
;
211 // The count of raw samples in the buffer at time of last read
212 uint32_t nsamples_last
;
215 struct cckprng_sched_ctx
{
216 // A counter governing the set of entropy pools to drain
217 uint64_t reseed_sched
;
219 // An index used to add entropy to pools in a round-robin style
224 // The master secret of the PRNG
225 struct cckprng_key_ctx key
;
227 // A counter used in CTR mode (with the master secret)
230 // State used to schedule entropy consumption and reseeds
231 struct cckprng_sched_ctx sched
;
233 // A mutex governing access to shared state
234 struct cckprng_lock_ctx lock
;
236 // The maximum number of generators that may be allocated
239 // The actual number of generators that have been initialized
242 // An array of output generators (allocated dynamically) of length max_ngens
243 struct cckprng_gen_ctx
*gens
;
245 // A set of entropy pools
246 struct cckprng_pool_ctx pools
[CCKPRNG_NPOOLS
];
248 // A handle to an entropy source managed externally
249 struct cckprng_entropybuf entropybuf
;
251 // Diagnostics for the PRNG
252 struct cckprng_diag diag
;
255 // This collection of function pointers is just a convenience for
256 // registering the PRNG with xnu
257 struct cckprng_funcs
{
258 void (*init
)(struct cckprng_ctx
*ctx
,
260 size_t entropybuf_nbytes
,
261 const void *entropybuf
,
262 const uint32_t *entropybuf_nsamples
,
267 void (*initgen
)(struct cckprng_ctx
*ctx
, unsigned gen_idx
);
268 void (*reseed
)(struct cckprng_ctx
*ctx
, size_t nbytes
, const void *seed
);
269 void (*refresh
)(struct cckprng_ctx
*ctx
);
270 void (*generate
)(struct cckprng_ctx
*ctx
, unsigned gen_idx
, size_t nbytes
, void *out
);
274 @function cckprng_init
275 @abstract Initialize a kernel PRNG context.
277 @param ctx Context for this instance
278 @param max_ngens Maximum count of generators that may be allocated
279 @param entropybuf_nbytes Length of the entropy buffer in bytes
280 @param entropybuf Read-only pointer to a long-lived entropy buffer
281 @param entropybuf_nsamples Read-only pointer to a counter of samples in the entropy buffer
282 @param seed_nbytes Length of the seed in bytes
283 @param seed Pointer to a high-entropy seed
284 @param nonce_nbytes Length of the nonce in bytes
285 @param seed Pointer to a single-use nonce
287 @discussion @p max_ngens should be set based on an upper bound of CPUs available on the device. The entropy buffer should be managed outside the PRNG and updated continuously (e.g. by an interrupt handler). The count of samples in the entropy buffer needn't be better than a rough estimate.
289 void cckprng_init(struct cckprng_ctx
*ctx
,
291 size_t entropybuf_nbytes
,
292 const void *entropybuf
,
293 const uint32_t *entropybuf_nsamples
,
300 @function cckprng_initgen
301 @abstract Initialize an output generator.
303 @param ctx Context for this instance
304 @param gen_idx Index of the generator
306 @discussion @p gen_idx must be less than @p max_ngens provided to @cckprng_init and must be unique within the lifetime of a PRNG context. This function will abort if these contracts are violated.
308 void cckprng_initgen(struct cckprng_ctx
*ctx
, unsigned gen_idx
);
311 @function cckprng_reseed
312 @abstract Reseed a kernel PRNG context with a user-supplied seed.
314 @param ctx Context for this instance
315 @param nbytes Length of the seed in bytes
316 @param seed Pointer to a high-entropy seed
318 @discussion It is safe to expose this function to attacker-controlled requests (e.g. writes to /dev/random).
320 void cckprng_reseed(struct cckprng_ctx
*ctx
, size_t nbytes
, const void *seed
);
323 @function cckprng_refresh
324 @abstract Consume entropy and reseed according to an internal schedule.
326 @param ctx Context for this instance
328 @discussion This function should be called on a regular basis. (For example, it is reasonable to call this inline before a call to @p cckprng_generate.) This function will not necessarily consume entropy or reseed the internal state on any given invocation. To force an immediate reseed, call @p cckprng_reseed.
330 void cckprng_refresh(struct cckprng_ctx
*ctx
);
332 #define CCKPRNG_GENERATE_MAX_NBYTES 256
335 @function cckprng_generate
336 @abstract Generate random values for use in applications.
338 @param ctx Context for this instance
339 @param gen_idx Index of the output generator
340 @param nbytes Length of the desired output in bytes
341 @param out Pointer to the output buffer
343 @discussion @p gen_idx must be a previous argument to @p cckprng_initgen. @p nbytes must be less than or equal to @p CCKPRNG_GENERATE_MAX_NBYTES. (Callers may invoke this function in a loop to generate larger outputs.) This function will abort if these contracts are violated.
345 void cckprng_generate(struct cckprng_ctx
*ctx
, unsigned gen_idx
, size_t nbytes
, void *out
);
347 #endif /* _CORECRYPTO_CCKPRNG_H_ */