1/* Copyright (c) (2018-2022) Apple Inc. All rights reserved.
2 *
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.
10 */
11
12#ifndef _CORECRYPTO_CCKPRNG_H_
13#define _CORECRYPTO_CCKPRNG_H_
14
15#include <corecrypto/cc.h>
16#include "ccrng_fortuna.h"
17#include "ccrng_crypto.h"
18#include <corecrypto/ccrng_schedule.h>
19#include <corecrypto/ccentropy.h>
20#include <corecrypto/ccdrbg.h>
21#include "cc_lock.h"
22
23// This is a Fortuna-inspired PRNG. While it differs from Fortuna in
24// many minor details, the biggest difference is its support for
25// multiple independent output generators. This is to make it suitable
26// for use in concurrent environments.
27//
28// This PRNG targets a 256-bit security level.
29//
30// First, the user should call cckprng_init. The user must specify the
31// maximum number of output generators that might be
32// needed. (Typically, users should align this argument with the
33// number of available CPUs.)
34//
35// The user must also provide a read-only handle to an entropy
36// source. This is a fixed-size buffer that will receive entropy
37// updates out of band from the PRNG (e.g. in an interrupt
38// handler). The PRNG will consume entropy from this buffer according
39// to an internal schedule driven by calls to cckprng_refresh (see
40// below).
41//
42// The user should call cckprng_initgen for as many output generators
43// as are needed. The numeric argument is an identifier to be reused
44// during calls to cckprng_generate (see below) and must be less than
45// the maximum number of generators specified to cckprng_init.
46//
47// After initialization, the user is free to call cckprng_generate to
48// generate random bytes. The user must specify the generator in this
49// call using a numeric identifier passed in the call to
50// cckprng_initgen.
51//
52// Output generation is limited to 256 bytes per request. Users should
53// make multiple requests if more output is needed.
54//
55// The user is expected to call cckprng_refresh regularly. This
56// function consumes entropy and mixes it into the output generators
57// according to an internal schedule.
58//
59// This implementation is thread-safe. Internally, a set of mutexes
60// guard access to internal state. Most functions rely on a single
61// mutex to protect shared state. The main exception is the
62// cckprng_generate function, which uses a per-generator mutex to
63// allow concurrent output generation on different threads.
64//
65// Another important exception is cckprng_refresh. While this function
66// relies on the shared mutex, it returns immediately if it cannot
67// acquire it.
68//
69// The PRNG also supports user-initiated reseeds. This is to support a
70// user-writable random device.
71//
72// This PRNG supports reseeds concurrent with output generation,
73// i.e. it is safe to call cckprng_reseed or cckprng_refresh while
74// another thread is calling cckprng_generate.
75
76#define CCKPRNG_SEED_NBYTES 32
77
78// A function pointer to fill an entropy buffer. It should return some
79// estimate of entropy (e.g. the number of timing samples resident in
80// the buffer). The implementation may return zero if no entropy is
81// available. The implementation should return negative in case of an
82// error (e.g. a failure in continuous health tests).
83//
84// The caller should set entropy_nbytes to the maximum size of the
85// input buffer, and the implementation should set it to the number of
86// bytes it has initialized. The third argument is arbitrary state the
87// implementation provides and receives back on each call.
88typedef ccrng_fortuna_getentropy cckprng_getentropy;
89
90#define CCKPRNG_ENTROPY_SIZE 64
91#define CCKPRNG_DRBG_STATE_MAX_SIZE ((size_t)1280)
92#define CCKPRNG_CACHED_BUF_SIZE ((size_t)256)
93#define CCKPRNG_MAX_REQUEST_SIZE ((size_t)4096)
94
95struct cckprng_ctx {
96 // A flag set every time Fortuna reseeds itself
97 ccrng_schedule_atomic_flag_ctx_t schedule_ctx;
98
99 ccentropy_rng_ctx_t entropy_ctx;
100
101 cc_lock_ctx_t lock_ctx;
102
103 struct ccdrbg_info drbg_info;
104 uint8_t drbg_state[CCKPRNG_DRBG_STATE_MAX_SIZE];
105
106 ccdrbg_df_bc_ctx_t drbg_df_ctx;
107
108 uint8_t cache[CCKPRNG_CACHED_BUF_SIZE];
109
110 ccrng_crypto_ctx_t rng_ctx;
111
112 struct ccrng_fortuna_ctx fortuna_ctx;
113};
114
115// This collection of function pointers is just a convenience for
116// registering the PRNG with xnu
117struct cckprng_funcs {
118 void (*CC_SPTR(cckprng_funcs, init))(struct cckprng_ctx *ctx,
119 size_t seed_nbytes,
120 const void *seed,
121 size_t nonce_nbytes,
122 const void *nonce,
123 cckprng_getentropy getentropy,
124 void *getentropy_arg);
125 void (*CC_SPTR(cckprng_funcs, initgen))(struct cckprng_ctx *ctx, unsigned gen_idx);
126 void (*CC_SPTR(cckprng_funcs, reseed))(struct cckprng_ctx *ctx, size_t nbytes, const void *seed);
127 void (*CC_SPTR(cckprng_funcs, refresh))(struct cckprng_ctx *ctx);
128 void (*CC_SPTR(cckprng_funcs, generate))(struct cckprng_ctx *ctx, unsigned gen_idx, size_t nbytes, void *out);
129 void (*CC_SPTR(cckprng_funcs, init_with_getentropy))(struct cckprng_ctx *ctx,
130 unsigned max_ngens,
131 size_t seed_nbytes,
132 const void *seed,
133 size_t nonce_nbytes,
134 const void *nonce,
135 cckprng_getentropy getentropy,
136 void *getentropy_arg);
137};
138
139/*
140 @function cckprng_init
141 @abstract Initialize a kernel PRNG context.
142
143 @param ctx Context for this instance
144 @param seed_nbytes Length of the seed in bytes
145 @param seed Pointer to a high-entropy seed
146 @param nonce_nbytes Length of the nonce in bytes
147 @param nonce Pointer to a single-use nonce
148 @param getentropy A function pointer to fill an entropy buffer
149 @param getentropy_arg State provided to the entropy function
150
151 @discussion See the @p cckprng_getentropy type definition for discussion on its semantics.
152
153*/
154void cckprng_init(struct cckprng_ctx *ctx,
155 size_t seed_nbytes,
156 const void *seed,
157 size_t nonce_nbytes,
158 const void *nonce,
159 cckprng_getentropy getentropy,
160 void *getentropy_arg);
161
162/*
163 @function cckprng_init_with_getentropy
164 @abstract Initialize a kernel PRNG context.
165
166 @param ctx Context for this instance
167 @param max_ngens Maximum count of generators that may be allocated
168 @param seed_nbytes Length of the seed in bytes
169 @param seed Pointer to a high-entropy seed
170 @param nonce_nbytes Length of the nonce in bytes
171 @param nonce Pointer to a single-use nonce
172 @param getentropy A function pointer to fill an entropy buffer
173 @param getentropy_arg State provided to the entropy function
174
175 @discussion @p max_ngens should be set based on an upper bound of CPUs available on the device. See the @p cckprng_getentropy type definition for discussion on its semantics.
176*/
177void cckprng_init_with_getentropy(struct cckprng_ctx *ctx,
178 unsigned max_ngens,
179 size_t seed_nbytes,
180 const void *seed,
181 size_t nonce_nbytes,
182 const void *nonce,
183 cckprng_getentropy getentropy,
184 void *getentropy_arg);
185
186/*
187 @function cckprng_initgen
188 @abstract Initialize an output generator.
189
190 @param ctx Context for this instance
191 @param gen_idx Index of the generator
192
193 @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.
194*/
195void cckprng_initgen(struct cckprng_ctx *ctx, unsigned gen_idx);
196
197/*
198 @function cckprng_reseed
199 @abstract Reseed a kernel PRNG context with a user-supplied seed.
200
201 @param ctx Context for this instance
202 @param nbytes Length of the seed in bytes
203 @param seed Pointer to a high-entropy seed
204
205 @discussion It is safe to expose this function to attacker-controlled requests (e.g. writes to /dev/random).
206*/
207void cckprng_reseed(struct cckprng_ctx *ctx, size_t nbytes, const void *seed);
208
209/*
210 @function cckprng_refresh
211 @abstract Consume entropy and reseed according to an internal schedule.
212
213 @param ctx Context for this instance
214
215 @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.
216*/
217void cckprng_refresh(struct cckprng_ctx *ctx);
218
219#define CCKPRNG_GENERATE_MAX_NBYTES 256
220
221/*
222 @function cckprng_generate
223 @abstract Generate random values for use in applications.
224
225 @param ctx Context for this instance
226 @param gen_idx Index of the output generator
227 @param nbytes Length of the desired output in bytes
228 @param out Pointer to the output buffer
229
230 @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.
231*/
232void cckprng_generate(struct cckprng_ctx *ctx, unsigned gen_idx, size_t nbytes, void *out);
233
234#endif /* _CORECRYPTO_CCKPRNG_H_ */
235