| 1 | /* Copyright (c) (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_CCENTROPY_H_ | 
| 13 | #define _CORECRYPTO_CCENTROPY_H_ | 
| 14 |  | 
| 15 | #include <corecrypto/cc.h> | 
| 16 | #include <corecrypto/ccdigest.h> | 
| 17 |  | 
| 18 | // An interface to provide high-entropy seeds to RNGs. | 
| 19 |  | 
| 20 | typedef struct ccentropy_ctx ccentropy_ctx_t; | 
| 21 |  | 
| 22 | typedef int (*ccentropy_get_seed_fn_t)(ccentropy_ctx_t *ctx, | 
| 23 |                                        size_t seed_nbytes, | 
| 24 |                                        void *seed); | 
| 25 |  | 
| 26 | typedef int (*ccentropy_add_entropy_fn_t)(ccentropy_ctx_t *ctx, | 
| 27 |                                           uint32_t entropy_nsamples, | 
| 28 |                                           size_t entropy_nbytes, | 
| 29 |                                           const void *entropy); | 
| 30 |  | 
| 31 | // A descriptor for an entropy implementation. | 
| 32 | typedef struct ccentropy_info { | 
| 33 |     // This is a required function. Implementations should populate | 
| 34 |     // the seed with a full-entropy output. If they are temporarily | 
| 35 |     // unable due to insufficient entropy, they should return | 
| 36 |     // CCERR_OUT_OF_ENTROPY. If they are permanently unable they | 
| 37 |     // should return some other error (or abort). | 
| 38 |     ccentropy_get_seed_fn_t get_seed; | 
| 39 |  | 
| 40 |     // This is an optional function. The caller will provide a set of | 
| 41 |     // (potentially low-quality) entropy samples, and the | 
| 42 |     // implementation should mix these into its internal | 
| 43 |     // state. Implementations are free to omit this function if it | 
| 44 |     // does not make sense (e.g. see ccentropy_rng below). | 
| 45 |     ccentropy_add_entropy_fn_t add_entropy; | 
| 46 | } ccentropy_info_t; | 
| 47 |  | 
| 48 | // Common state for entropy implementations. | 
| 49 | struct ccentropy_ctx { | 
| 50 |     // A pointer to the descriptor. | 
| 51 |     const ccentropy_info_t *info; | 
| 52 | }; | 
| 53 |  | 
| 54 | /*! | 
| 55 |   @function ccentropy_get_seed | 
| 56 |   @abstract Get a high-entropy seed. | 
| 57 |  | 
| 58 |   @param ctx The entropy context. | 
| 59 |   @param seed_nbytes The size of the seed requested. | 
| 60 |   @param seed A buffer to receive the seed. | 
| 61 |  | 
| 62 |   @return CCERR_OK on success; CCERR_OUT_OF_ENTROPY if entropy is | 
| 63 |   temporarily unavailable; some implementation-defined error (or | 
| 64 |   abort) otherwise. | 
| 65 | */ | 
| 66 | int ccentropy_get_seed(ccentropy_ctx_t *ctx, | 
| 67 |                        size_t seed_nbytes, | 
| 68 |                        void *seed); | 
| 69 |  | 
| 70 | /*! | 
| 71 |   @function ccentropy_add_entropy | 
| 72 |   @abstract Add fresh entropy samples to the context. | 
| 73 |  | 
| 74 |   @param ctx The entropy context. | 
| 75 |   @param entropy_nsamples The count of samples included in this batch. | 
| 76 |   @param entropy_nbytes The size of the entropy payload in bytes. | 
| 77 |   @param entropy A buffer containing the fresh entropy samples. | 
| 78 |  | 
| 79 |   @return CCERR_OK on success; CCERR_NOT_SUPPORTED if this operation | 
| 80 |   is not supported for the implementation; some implementation-defined | 
| 81 |   error (or abort) otherwise. | 
| 82 |  | 
| 83 |   @discussion This operation is optional and will not be supported by | 
| 84 |   all implementations. | 
| 85 | */ | 
| 86 | int ccentropy_add_entropy(ccentropy_ctx_t *ctx, | 
| 87 |                           uint32_t entropy_nsamples, | 
| 88 |                           size_t entropy_nbytes, | 
| 89 |                           const void *entropy); | 
| 90 |  | 
| 91 | // A simple wrapper around a ccrng instance. This implementation does | 
| 92 | // not support the add_entropy interface. | 
| 93 | typedef struct ccentropy_rng_ctx { | 
| 94 |     ccentropy_ctx_t entropy_ctx; | 
| 95 |     struct ccrng_state *rng_ctx; | 
| 96 |     size_t seed_max_nbytes; | 
| 97 | } ccentropy_rng_ctx_t; | 
| 98 |  | 
| 99 | /*! | 
| 100 |   @function ccentropy_rng_init | 
| 101 |   @abstract Wrap a ccrng instance in the ccentropy interface. | 
| 102 |  | 
| 103 |   @param ctx The entropy context. | 
| 104 |   @param rng_ctx The RNG to wrap. | 
| 105 |   @param seed_max_nbytes The maximum seed size that this RNG can provide. | 
| 106 |  | 
| 107 |   @return CCERR_OK on success. | 
| 108 |  | 
| 109 |   @discussion seed_max_nbytes should correspond to the security level | 
| 110 |   of the underlying RNG. | 
| 111 | */ | 
| 112 | int ccentropy_rng_init(ccentropy_rng_ctx_t *ctx, | 
| 113 |                        struct ccrng_state *rng_ctx, | 
| 114 |                        size_t seed_max_nbytes); | 
| 115 |  | 
| 116 | // An entropy conditioner based on digest functions. We assume a fixed | 
| 117 | // per-sample entropy estimate measured in millibits | 
| 118 | // (i.e. mbits). This estimate should be determined via offline | 
| 119 | // analysis. | 
| 120 | typedef struct ccentropy_digest_ctx { | 
| 121 |     ccentropy_ctx_t entropy_ctx; | 
| 122 |     const struct ccdigest_info *digest_info; | 
| 123 |     ccdigest_ctx_decl(MAX_DIGEST_STATE_SIZE, | 
| 124 |                       MAX_DIGEST_BLOCK_SIZE, | 
| 125 |                       digest_ctx); | 
| 126 |     uint32_t entropy_mbits_per_sample; | 
| 127 |     uint32_t entropy_mbits; | 
| 128 | } ccentropy_digest_ctx_t; | 
| 129 |  | 
| 130 | #define CCENTROPY_MBITS_PER_BYTE ((uint32_t)(8000)) | 
| 131 |  | 
| 132 | /*! | 
| 133 |   @function ccentropy_digest_init | 
| 134 |   @abstract Initialize a digest-based entropy conditioner. | 
| 135 |  | 
| 136 |   @param ctx The entropy context. | 
| 137 |   @param digest_info A descriptor for the digest. | 
| 138 |   @param entropy_mbits_per_sample An estimate of per-sample entropy measured in millibits. | 
| 139 |  | 
| 140 |   @return CCERR_OK on success. | 
| 141 |  | 
| 142 |   @discussion The estimated entropy per sample should be determined | 
| 143 |   via offline analysis. | 
| 144 | */ | 
| 145 | int ccentropy_digest_init(struct ccentropy_digest_ctx *ctx, | 
| 146 |                           const struct ccdigest_info *digest_info, | 
| 147 |                           uint32_t entropy_mbits_per_sample); | 
| 148 |  | 
| 149 | #endif /* _CORECRYPTO_CCENTROPY_H_ */ | 
| 150 |  |