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. |
88 | typedef 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 | |
95 | struct 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 |
117 | struct 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 | */ |
154 | void 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 | */ |
177 | void 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 | */ |
195 | void 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 | */ |
207 | void 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 | */ |
217 | void 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 | */ |
232 | void cckprng_generate(struct cckprng_ctx *ctx, unsigned gen_idx, size_t nbytes, void *out); |
233 | |
234 | #endif /* _CORECRYPTO_CCKPRNG_H_ */ |
235 | |