xref: /xnu-8796.101.5/EXTERNAL_HEADERS/corecrypto/cckprng.h (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
1 /* Copyright (c) (2018-2021) 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 <stdbool.h>
16 
17 #include <corecrypto/cc.h>
18 #include "ccrng_fortuna.h"
19 #include "ccrng_crypto.h"
20 #include <corecrypto/ccrng_schedule.h>
21 #include <corecrypto/ccentropy.h>
22 #include <corecrypto/ccdrbg.h>
23 #include "cc_lock.h"
24 
25 // This is a Fortuna-inspired PRNG. While it differs from Fortuna in
26 // many minor details, the biggest difference is its support for
27 // multiple independent output generators. This is to make it suitable
28 // for use in concurrent environments.
29 //
30 // This PRNG targets a 256-bit security level.
31 //
32 // First, the user should call cckprng_init. The user must specify the
33 // maximum number of output generators that might be
34 // needed. (Typically, users should align this argument with the
35 // number of available CPUs.)
36 //
37 // The user must also provide a read-only handle to an entropy
38 // source. This is a fixed-size buffer that will receive entropy
39 // updates out of band from the PRNG (e.g. in an interrupt
40 // handler). The PRNG will consume entropy from this buffer according
41 // to an internal schedule driven by calls to cckprng_refresh (see
42 // below).
43 //
44 // The user should call cckprng_initgen for as many output generators
45 // as are needed. The numeric argument is an identifier to be reused
46 // during calls to cckprng_generate (see below) and must be less than
47 // the maximum number of generators specified to cckprng_init.
48 //
49 // After initialization, the user is free to call cckprng_generate to
50 // generate random bytes. The user must specify the generator in this
51 // call using a numeric identifier passed in the call to
52 // cckprng_initgen.
53 //
54 // Output generation is limited to 256 bytes per request. Users should
55 // make multiple requests if more output is needed.
56 //
57 // The user is expected to call cckprng_refresh regularly. This
58 // function consumes entropy and mixes it into the output generators
59 // according to an internal schedule.
60 //
61 // This implementation is thread-safe. Internally, a set of mutexes
62 // guard access to internal state. Most functions rely on a single
63 // mutex to protect shared state. The main exception is the
64 // cckprng_generate function, which uses a per-generator mutex to
65 // allow concurrent output generation on different threads.
66 //
67 // Another important exception is cckprng_refresh. While this function
68 // relies on the shared mutex, it returns immediately if it cannot
69 // acquire it.
70 //
71 // The PRNG also supports user-initiated reseeds. This is to support a
72 // user-writable random device.
73 //
74 // This PRNG supports reseeds concurrent with output generation,
75 // i.e. it is safe to call cckprng_reseed or cckprng_refresh while
76 // another thread is calling cckprng_generate.
77 
78 #define CCKPRNG_SEED_NBYTES 32
79 
80 // A function pointer to fill an entropy buffer. It should return some
81 // estimate of entropy (e.g. the number of timing samples resident in
82 // the buffer). The implementation may return zero if no entropy is
83 // available. The implementation should return negative in case of an
84 // error (e.g. a failure in continuous health tests).
85 //
86 // The caller should set entropy_nbytes to the maximum size of the
87 // input buffer, and the implementation should set it to the number of
88 // bytes it has initialized. The third argument is arbitrary state the
89 // implementation provides and receives back on each call.
90 typedef ccrng_fortuna_getentropy cckprng_getentropy;
91 
92 #define CCKPRNG_ENTROPY_SIZE 64
93 #define CCKPRNG_DRBG_STATE_MAX_SIZE ((size_t)1280)
94 #define CCKPRNG_CACHED_BUF_SIZE ((size_t)256)
95 #define CCKPRNG_MAX_REQUEST_SIZE ((size_t)4096)
96 
97 struct cckprng_ctx {
98     // A flag set every time Fortuna reseeds itself
99     ccrng_schedule_atomic_flag_ctx_t schedule_ctx;
100 
101     ccentropy_rng_ctx_t entropy_ctx;
102 
103     cc_lock_ctx_t lock_ctx;
104 
105     struct ccdrbg_info drbg_info;
106     uint8_t drbg_state[CCKPRNG_DRBG_STATE_MAX_SIZE];
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