]> git.saurik.com Git - apple/xnu.git/blame_incremental - EXTERNAL_HEADERS/corecrypto/cckprng.h
xnu-6153.11.26.tar.gz
[apple/xnu.git] / EXTERNAL_HEADERS / corecrypto / cckprng.h
... / ...
CommitLineData
1/*
2 * cckprng.h
3 * corecrypto
4 *
5 * Created on 12/7/2017
6 *
7 * Copyright (c) 2017 Apple Inc. All rights reserved.
8 *
9 */
10
11#ifndef _CORECRYPTO_CCKPRNG_H_
12#define _CORECRYPTO_CCKPRNG_H_
13
14#include <stdbool.h>
15
16#include <corecrypto/cc.h>
17
18#define CCKPRNG_YARROW 0
19
20#if CCKPRNG_YARROW
21
22typedef struct PRNG *PrngRef;
23
24struct cckprng_ctx {
25 PrngRef prng;
26 uint64_t bytes_since_entropy;
27 uint64_t bytes_generated;
28};
29
30#define CCKPRNG_ENTROPY_INTERVAL (1 << 14)
31#define CCKPRNG_RESEED_NTICKS 50
32
33typedef struct cckprng_ctx *cckprng_ctx_t;
34
35#else
36
37// This is a Fortuna-inspired PRNG. While it differs from Fortuna in
38// many minor details, the biggest difference is its support for
39// multiple independent output generators. This is to make it suitable
40// for use in concurrent environments.
41//
42// This PRNG targets a 256-bit security level.
43//
44// First, the user should call cckprng_init. The user must specify the
45// maximum number of output generators that might be
46// needed. (Typically, users should align this argument with the
47// number of available CPUs.)
48//
49// The user must also provide a read-only handle to an entropy
50// source. This is a fixed-size buffer that will receive entropy
51// updates out of band from the PRNG (e.g. in an interrupt
52// handler). The PRNG will consume entropy from this buffer according
53// to an internal schedule driven by calls to cckprng_refresh (see
54// below).
55//
56// The user should call cckprng_initgen for as many output generators
57// as are needed. The numeric argument is an identifier to be reused
58// during calls to cckprng_generate (see below) and must be less than
59// the maximum number of generators specified to cckprng_init.
60//
61// After initialization, the user is free to call cckprng_generate to
62// generate random bytes. The user must specify the generator in this
63// call using a numeric identifier passed in the call to
64// cckprng_initgen.
65//
66// Output generation is limited to 256 bytes per request. Users should
67// make multiple requests if more output is needed.
68//
69// The user is expected to call cckprng_refresh regularly. This
70// function consumes entropy and mixes it into the output generators
71// according to an internal schedule.
72//
73// This implementation is thread-safe. Internally, a set of mutexes
74// guard access to internal state. Most functions rely on a single
75// mutex to protect shared state. The main exception is the
76// cckprng_generate function, which uses a per-generator mutex to
77// allow concurrent output generation on different threads.
78//
79// Another important exception is cckprng_refresh. While this function
80// relies on the shared mutex, it returns immediately if it cannot
81// acquire it.
82//
83// The PRNG also supports user-initiated reseeds. This is to support a
84// user-writable random device.
85//
86// This PRNG supports reseeds concurrent with output generation,
87// i.e. it is safe to call cckprng_reseed or cckprng_refresh while
88// another thread is calling cckprng_generate.
89
90#define CCKPRNG_NPOOLS 32
91#define CCKPRNG_SEED_NBYTES 32
92#define CCKPRNG_POOL_NBYTES 32
93#define CCKPRNG_KEY_NBYTES 32
94
95struct cckprng_gen_diag {
96 // The number of times this generator has been rekeyed from the master seed
97 uint64_t nrekeys;
98
99 // The number of requests this generator has fulfilled
100 uint64_t out_nreqs;
101
102 // The total number of bytes this generator has generated over all requests
103 uint64_t out_nbytes;
104
105 // The maximum number of bytes this generator has generated in any one request
106 uint64_t out_nbytes_req_max;
107
108 // The total number of bytes this generator has generated since the last rekey
109 uint64_t out_nbytes_key;
110
111 // The maximum total number of bytes this generator has generated between two rekeys
112 uint64_t out_nbytes_key_max;
113};
114
115struct cckprng_pool_diag {
116 // The number of samples currently resident in the pool
117 uint64_t nsamples;
118
119 // The number of times this pool has been drained in a reseed
120 uint64_t ndrains;
121
122 // The maximum number of samples this pool has held at any one time
123 uint64_t nsamples_max;
124};
125
126struct cckprng_diag {
127 // The number of reseeds via user input (e.g. by writing to /dev/random)
128 uint64_t userreseed_nreseeds;
129
130 // The number of reseeds via the scheduler
131 uint64_t schedreseed_nreseeds;
132
133 // The maximum number of samples included in any one scheduler reseed
134 uint64_t schedreseed_nsamples_max;
135
136 // The maximum number of samples included in any one entropy input
137 uint64_t addentropy_nsamples_max;
138
139 // Diagnostics corresponding to individual output generators
140 unsigned ngens;
141 struct cckprng_gen_diag *gens;
142
143 // Diagnostics corresponding to internal entropy pools
144 struct cckprng_pool_diag pools[CCKPRNG_NPOOLS];
145};
146
147#if CC_KERNEL
148
149#include <kern/locks.h>
150
151typedef lck_grp_t *cckprng_lock_group;
152typedef lck_mtx_t *cckprng_lock_mutex;
153
154struct cckprng_lock_ctx {
155 cckprng_lock_group group;
156 cckprng_lock_mutex mutex;
157};
158
159#else
160
161#include <os/lock.h>
162
163typedef os_unfair_lock cckprng_lock_mutex;
164
165struct cckprng_lock_ctx {
166 cckprng_lock_mutex mutex;
167};
168
169#endif
170
171struct cckprng_key_ctx {
172 uint8_t data[CCKPRNG_KEY_NBYTES];
173};
174
175struct cckprng_gen_ctx {
176 // We maintain two keys (one live and one idle) to allow
177 // concurrent generation and reseeding
178 struct cckprng_key_ctx keys[2];
179 _Atomic unsigned swap;
180 unsigned key_live_idx;
181 unsigned key_idle_idx;
182
183 // A counter used in CTR mode
184 uint8_t ctr[16];
185
186 // Whether the generator has been initialized
187 bool init;
188
189 // A mutex governing this generator's state (but note the idle key
190 // context is under control of the PRNG's shared mutex)
191 struct {
192 cckprng_lock_mutex mutex;
193 } lock;
194};
195
196struct cckprng_pool_ctx {
197 uint8_t data[CCKPRNG_POOL_NBYTES];
198};
199
200// This is a handle to an "entropy buffer" to be managed externally
201// (i.e. in xnu). This is a non-cryptographic
202// accumulator. Practically, the buffer is filled with timestamps
203// collected during interrupts. The existing state of the buffer is
204// rotated and new timestamps are added in. A counter of raw timing
205// samples is also managed externally. The buffer and the counter are
206// both subject to data races, which we tolerate.
207
208struct cckprng_entropybuf {
209
210 // A read-only handle to an "entropy buffer" (a non-cryptographic accumulator) to be managed externally
211 const void *buf;
212
213 // The size of the entropy buffer
214 size_t nbytes;
215
216 // A read-only handle to a count of raw samples in the buffer
217 const uint32_t *nsamples;
218
219 // The count of raw samples in the buffer at time of last read
220 uint32_t nsamples_last;
221};
222
223struct cckprng_sched_ctx {
224 // A counter governing the set of entropy pools to drain
225 uint64_t reseed_sched;
226
227 // A timestamp from the last reseed
228 uint64_t reseed_last;
229
230 // An index used to add entropy to pools in a round-robin style
231 unsigned pool_idx;
232};
233
234struct cckprng_ctx {
235
236 // The master secret of the PRNG
237 uint8_t seed[CCKPRNG_SEED_NBYTES];
238
239 // State used to schedule entropy consumption and reseeds
240 struct cckprng_sched_ctx sched;
241
242 // A mutex governing access to shared state
243 struct cckprng_lock_ctx lock;
244
245 // The maximum number of generators that may be allocated
246 unsigned max_ngens;
247
248 // An array of output generators (allocated dynamically) of length max_ngens
249 struct cckprng_gen_ctx *gens;
250
251 // A set of entropy pools
252 struct cckprng_pool_ctx pools[CCKPRNG_NPOOLS];
253
254 // A handle to an entropy source managed externally
255 struct cckprng_entropybuf entropybuf;
256
257 // Diagnostics for the PRNG
258 struct cckprng_diag diag;
259};
260
261// This collection of function pointers is just a convenience for
262// registering the PRNG with xnu
263struct cckprng_funcs {
264 void (*init)(struct cckprng_ctx *ctx,
265 unsigned max_ngens,
266 size_t entropybuf_nbytes,
267 const void *entropybuf,
268 const uint32_t *entropybuf_nsamples,
269 size_t seed_nbytes,
270 const void *seed,
271 size_t nonce_nbytes,
272 const void *nonce);
273 void (*initgen)(struct cckprng_ctx *ctx, unsigned gen_idx);
274 void (*reseed)(struct cckprng_ctx *ctx, size_t nbytes, const void *seed);
275 void (*refresh)(struct cckprng_ctx *ctx);
276 void (*generate)(struct cckprng_ctx *ctx, unsigned gen_idx, size_t nbytes, void *out);
277};
278
279#endif
280
281/*
282 @function cckprng_init
283 @abstract Initialize a kernel PRNG context.
284
285 @param ctx Context for this instance
286 @param max_ngens Maximum count of generators that may be allocated
287 @param entropybuf_nbytes Length of the entropy buffer in bytes
288 @param entropybuf Read-only pointer to a long-lived entropy buffer
289 @param entropybuf_nsamples Read-only pointer to a counter of samples in the entropy buffer
290 @param seed_nbytes Length of the seed in bytes
291 @param seed Pointer to a high-entropy seed
292 @param nonce_nbytes Length of the nonce in bytes
293 @param seed Pointer to a single-use nonce
294
295 @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.
296*/
297void cckprng_init(struct cckprng_ctx *ctx,
298 unsigned max_ngens,
299 size_t entropybuf_nbytes,
300 const void *entropybuf,
301 const uint32_t *entropybuf_nsamples,
302 size_t seed_nbytes,
303 const void *seed,
304 size_t nonce_nbytes,
305 const void *nonce);
306
307/*
308 @function cckprng_initgen
309 @abstract Initialize an output generator.
310
311 @param ctx Context for this instance
312 @param gen_idx Index of the generator
313
314 @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.
315*/
316void cckprng_initgen(struct cckprng_ctx *ctx, unsigned gen_idx);
317
318/*
319 @function cckprng_reseed
320 @abstract Reseed a kernel PRNG context with a user-supplied seed.
321
322 @param ctx Context for this instance
323 @param nbytes Length of the seed in bytes
324 @param seed Pointer to a high-entropy seed
325
326 @discussion It is safe to expose this function to attacker-controlled requests (e.g. writes to /dev/random).
327*/
328void cckprng_reseed(struct cckprng_ctx *ctx, size_t nbytes, const void *seed);
329
330/*
331 @function cckprng_refresh
332 @abstract Consume entropy and reseed according to an internal schedule.
333
334 @param ctx Context for this instance
335
336 @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.
337*/
338void cckprng_refresh(struct cckprng_ctx *ctx);
339
340#define CCKPRNG_GENERATE_MAX_NBYTES 256
341
342/*
343 @function cckprng_generate
344 @abstract Generate random values for use in applications.
345
346 @param ctx Context for this instance
347 @param gen_idx Index of the output generator
348 @param nbytes Length of the desired output in bytes
349 @param out Pointer to the output buffer
350
351 @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.
352*/
353void cckprng_generate(struct cckprng_ctx *ctx, unsigned gen_idx, size_t nbytes, void *out);
354
355#endif /* _CORECRYPTO_CCKPRNG_H_ */