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_CCRNG_FORTUNA_H_ 13 #define _CORECRYPTO_CCRNG_FORTUNA_H_ 14 15 #include <corecrypto/cc.h> 16 #include <corecrypto/ccrng.h> 17 #include "cc_lock.h" 18 19 // This is a Fortuna-inspired PRNG. While it differs from Fortuna in 20 // many minor details, the biggest difference is its support for 21 // multiple independent output generators. This is to make it suitable 22 // for use in concurrent environments. 23 // 24 // This PRNG targets a 256-bit security level. 25 // 26 // First, the user should call ccrng_fortuna_init. The user must 27 // specify the maximum number of output generators that might be 28 // needed. (Typically, users should align this argument with the 29 // number of available CPUs.) 30 // 31 // The user must also provide a read-only handle to an entropy 32 // source. This is a fixed-size buffer that will receive entropy 33 // updates out of band from the PRNG (e.g. in an interrupt 34 // handler). The PRNG will consume entropy from this buffer according 35 // to an internal schedule driven by calls to ccrng_fortuna_refresh 36 // (see below). 37 // 38 // The user should call ccrng_fortuna_initgen for as many output 39 // generators as are needed. The numeric argument is an identifier to 40 // be reused during calls to ccrng_fortuna_generate (see below) and 41 // must be less than the maximum number of generators specified to 42 // ccrng_fortuna_init. 43 // 44 // After initialization, the user is free to call 45 // ccrng_fortuna_generate to generate random bytes. The user must 46 // specify the generator in this call using a numeric identifier 47 // passed in the call to ccrng_fortuna_initgen. 48 // 49 // Output generation is limited to 256 bytes per request. Users should 50 // make multiple requests if more output is needed. 51 // 52 // The user is expected to call ccrng_fortuna_refresh regularly. This 53 // function consumes entropy and mixes it into the output generators 54 // according to an internal schedule. 55 // 56 // This implementation is thread-safe. Internally, a set of mutexes 57 // guard access to internal state. Most functions rely on a single 58 // mutex to protect shared state. The main exception is the 59 // ccrng_fortuna_generate function, which uses a per-generator mutex 60 // to allow concurrent output generation on different threads. 61 // 62 // Another important exception is ccrng_fortuna_refresh. While this 63 // function relies on the shared mutex, it returns immediately if it 64 // cannot acquire it. 65 // 66 // The PRNG also supports user-initiated reseeds. This is to support a 67 // user-writable random device. 68 // 69 // This PRNG supports reseeds concurrent with output generation, 70 // i.e. it is safe to call ccrng_fortuna_reseed or 71 // ccrng_fortuna_refresh while another thread is calling 72 // ccrng_fortuna_generate. 73 74 #define CCRNG_FORTUNA_NPOOLS 32 75 #define CCRNG_FORTUNA_SEED_NBYTES 32 76 #define CCRNG_FORTUNA_POOL_NBYTES 32 77 #define CCRNG_FORTUNA_KEY_NBYTES 32 78 79 struct ccrng_fortuna_pool_ctx { 80 uint8_t data[CCRNG_FORTUNA_POOL_NBYTES]; 81 82 // The number of samples currently resident in the pool 83 uint64_t nsamples; 84 85 // The number of times this pool has been drained in a reseed 86 uint64_t ndrains; 87 88 // The maximum number of samples this pool has held at any one time 89 uint64_t nsamples_max; 90 }; 91 92 struct ccrng_fortuna_sched_ctx { 93 // A counter governing the set of entropy pools to drain 94 uint64_t reseed_sched; 95 96 // An index used to add entropy to pools in a round-robin style 97 unsigned pool_idx; 98 }; 99 100 // A function pointer to fill an entropy buffer. It should return some 101 // estimate of entropy (e.g. the number of timing samples resident in 102 // the buffer). The implementation may return zero if no entropy is 103 // available. The implementation should return negative in case of an 104 // error (e.g. a failure in continuous health tests). 105 // 106 // The caller should set entropy_nbytes to the maximum size of the 107 // input buffer, and the implementation should set it to the number of 108 // bytes it has initialized. The third argument is arbitrary state the 109 // implementation provides and receives back on each call. 110 typedef int32_t (*ccrng_fortuna_getentropy)(size_t *entropy_nbytes, 111 void *entropy, 112 void *arg); 113 114 struct ccrng_fortuna_ctx { 115 CCRNG_STATE_COMMON 116 117 // The root secret of the PRNG 118 uint8_t key[CCRNG_FORTUNA_KEY_NBYTES]; 119 120 // A counter used in CTR mode (with the root secret) 121 uint8_t ctr[16]; 122 123 // State used to schedule entropy consumption and reseeds 124 struct ccrng_fortuna_sched_ctx sched; 125 126 // A mutex governing access to shared state 127 cc_lock_ctx_t lock; 128 129 // A set of entropy pools 130 struct ccrng_fortuna_pool_ctx pools[CCRNG_FORTUNA_NPOOLS]; 131 132 // A function pointer to get entropy 133 CC_SPTR(ccrng_fortuna_ctx, ccrng_fortuna_getentropy) getentropy; 134 135 // An arbitrary piece of state to be provided to the entropy function 136 void *getentropy_arg; 137 138 // A flag describing whether the instance has been seeded with 139 // sufficient entropy. This flag is set when a set of pools 140 // containing a minimum threshold of entropy inputs is 141 // drained. The PRNG will not generate output until this flag is 142 // set. This flag is reset if the entropy source signals a 143 // failure. 144 bool seeded; 145 146 // The number of scheduled reseeds 147 uint64_t nreseeds; 148 149 // The maximum number of samples included in any one scheduler reseed 150 uint64_t schedreseed_nsamples_max; 151 152 // The maximum number of samples included in any one entropy input 153 uint64_t addentropy_nsamples_max; 154 }; 155 156 /* 157 @function ccrng_fortuna_init 158 @abstract Initialize a kernel PRNG context. 159 160 @param ctx Context for this instance 161 @param getentropy A function pointer to fill an entropy buffer 162 @param getentropy_arg State provided to the entropy function 163 164 @discussion @p max_ngens should be set based on an upper bound of CPUs available on the device. See the @p ccrng_fortuna_getentropy type definition for discussion on its semantics. 165 */ 166 void ccrng_fortuna_init(struct ccrng_fortuna_ctx *ctx, 167 ccrng_fortuna_getentropy getentropy, 168 void *getentropy_arg); 169 170 /* 171 @function ccrng_fortuna_refresh 172 @abstract Consume entropy and reseed according to an internal schedule. 173 174 @param ctx Context for this instance 175 176 @return True if a reseed occurred, false otherwise. 177 178 @discussion This function should be called on a regular basis. (For example, it is reasonable to call this inline before a call to @p ccrng_fortuna_generate.) This function will not necessarily consume entropy or reseed the internal state on any given invocation. To force an immediate reseed, call @p ccrng_fortuna_reseed. 179 */ 180 bool ccrng_fortuna_refresh(struct ccrng_fortuna_ctx *ctx); 181 182 #define CCRNG_FORTUNA_GENERATE_MAX_NBYTES 256 183 184 /* 185 @function ccrng_fortuna_generate 186 @abstract Generate random values for use in applications. 187 188 @param ctx Context for this instance 189 @param nbytes Length of the desired output in bytes 190 @param out Pointer to the output buffer 191 192 @return 0 on success, negative otherwise. 193 194 @discussion @p gen_idx must be a previous argument to @p ccrng_fortuna_initgen. @p nbytes must be less than or equal to @p CCRNG_FORTUNA_GENERATE_MAX_NBYTES. (Callers may invoke this function in a loop to generate larger outputs.) This function will abort if these contracts are violated. 195 */ 196 int ccrng_fortuna_generate(struct ccrng_fortuna_ctx *ctx, size_t nbytes, void *out); 197 198 #endif /* _CORECRYPTO_CCRNG_FORTUNA_H_ */ 199