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