| 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 | |