Branch data Line data Source code
1 : : /*
2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License").
5 : : * You may not use this file except in compliance with the License.
6 : : * A copy of the License is located at
7 : : *
8 : : * http://aws.amazon.com/apache2.0
9 : : *
10 : : * or in the "license" file accompanying this file. This file is distributed
11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 : : * express or implied. See the License for the specific language governing
13 : : * permissions and limitations under the License.
14 : : */
15 : :
16 : : #include "crypto/s2n_drbg.h"
17 : :
18 : : #include <openssl/evp.h>
19 : : #include <sys/param.h>
20 : :
21 : : #include "crypto/s2n_openssl.h"
22 : : #include "utils/s2n_blob.h"
23 : : #include "utils/s2n_random.h"
24 : : #include "utils/s2n_safety.h"
25 : :
26 : : static bool ignore_prediction_resistance_for_testing = false;
27 : :
28 : : #define s2n_drbg_key_size(drgb) EVP_CIPHER_CTX_key_length((drbg)->ctx)
29 : : #define s2n_drbg_seed_size(drgb) (S2N_DRBG_BLOCK_SIZE + s2n_drbg_key_size(drgb))
30 : :
31 : : /* This function is the same as s2n_increment_sequence_number
32 : : but it does not check for overflow, since overflow is
33 : : acceptable in DRBG */
34 : : S2N_RESULT s2n_increment_drbg_counter(struct s2n_blob *counter)
35 : 148222744 : {
36 [ + + ]: 148804007 : for (uint32_t i = (uint32_t) counter->size; i > 0; i--) {
37 : 148804007 : counter->data[i - 1] += 1;
38 [ + + ]: 148804007 : if (counter->data[i - 1]) {
39 : 148222982 : break;
40 : 148222982 : }
41 : :
42 : : /* seq[i] wrapped, so let it carry */
43 : 148804007 : }
44 : 148222744 : return S2N_RESULT_OK;
45 : 148222744 : }
46 : :
47 : : static S2N_RESULT s2n_drbg_block_encrypt(EVP_CIPHER_CTX *ctx, uint8_t in[S2N_DRBG_BLOCK_SIZE], uint8_t out[S2N_DRBG_BLOCK_SIZE])
48 : 148222970 : {
49 [ - + ][ # # ]: 148222970 : RESULT_ENSURE_REF(ctx);
50 : :
51 : : /* len is set by EVP_EncryptUpdate and checked post operation */
52 : 148222970 : int len = S2N_DRBG_BLOCK_SIZE;
53 [ - + ][ # # ]: 148222970 : RESULT_GUARD_OSSL(EVP_EncryptUpdate(ctx, out, &len, in, S2N_DRBG_BLOCK_SIZE), S2N_ERR_DRBG);
54 [ - + ][ # # ]: 148222970 : RESULT_ENSURE_EQ(len, S2N_DRBG_BLOCK_SIZE);
55 : :
56 : 148222970 : return S2N_RESULT_OK;
57 : 148222970 : }
58 : :
59 : : static S2N_RESULT s2n_drbg_bits(struct s2n_drbg *drbg, struct s2n_blob *out)
60 : 6272843 : {
61 [ - + ][ # # ]: 6272843 : RESULT_ENSURE_REF(drbg);
62 [ - + ][ # # ]: 6272843 : RESULT_ENSURE_REF(drbg->ctx);
63 [ # # ][ - + ]: 6272843 : RESULT_ENSURE_REF(out);
64 : :
65 : 6272843 : struct s2n_blob value = { 0 };
66 [ - + ]: 6272843 : RESULT_GUARD_POSIX(s2n_blob_init(&value, drbg->v, sizeof(drbg->v)));
67 : 6272843 : uint32_t block_aligned_size = out->size - (out->size % S2N_DRBG_BLOCK_SIZE);
68 : :
69 : : /* Per NIST SP800-90A 10.2.1.2: */
70 [ + + ]: 153669227 : for (size_t i = 0; i < block_aligned_size; i += S2N_DRBG_BLOCK_SIZE) {
71 [ - + ]: 147396384 : RESULT_GUARD(s2n_increment_drbg_counter(&value));
72 [ - + ]: 147396384 : RESULT_GUARD(s2n_drbg_block_encrypt(drbg->ctx, drbg->v, out->data + i));
73 : 147396384 : drbg->bytes_used += S2N_DRBG_BLOCK_SIZE;
74 : 147396384 : }
75 : :
76 [ + + ]: 6272843 : if (out->size <= block_aligned_size) {
77 : 5446596 : return S2N_RESULT_OK;
78 : 5446596 : }
79 : :
80 : 826247 : uint8_t spare_block[S2N_DRBG_BLOCK_SIZE];
81 [ - + ]: 826247 : RESULT_GUARD(s2n_increment_drbg_counter(&value));
82 [ - + ]: 826247 : RESULT_GUARD(s2n_drbg_block_encrypt(drbg->ctx, drbg->v, spare_block));
83 : 826247 : drbg->bytes_used += S2N_DRBG_BLOCK_SIZE;
84 : :
85 [ - + ][ # # ]: 826247 : RESULT_CHECKED_MEMCPY(out->data + block_aligned_size, spare_block, out->size - block_aligned_size);
[ + + ]
86 : :
87 : 826247 : return S2N_RESULT_OK;
88 : 826247 : }
89 : :
90 : : static S2N_RESULT s2n_drbg_update(struct s2n_drbg *drbg, struct s2n_blob *provided_data)
91 : 4014527 : {
92 [ - + ][ # # ]: 4014527 : RESULT_ENSURE_REF(drbg);
93 [ # # ][ - + ]: 4014527 : RESULT_ENSURE_REF(drbg->ctx);
94 [ - + ][ # # ]: 4014527 : RESULT_ENSURE_REF(provided_data);
95 : :
96 [ - + ][ # # ]: 8029054 : RESULT_STACK_BLOB(temp_blob, s2n_drbg_seed_size(drgb), S2N_DRBG_MAX_SEED_SIZE);
[ - + ]
97 : :
98 [ - + ][ # # ]: 4014527 : RESULT_ENSURE_EQ(provided_data->size, (uint32_t) s2n_drbg_seed_size(drbg));
99 : :
100 [ - + ]: 4014527 : RESULT_GUARD(s2n_drbg_bits(drbg, &temp_blob));
101 : :
102 : : /* XOR in the provided data */
103 [ + + ]: 158064012 : for (uint32_t i = 0; i < provided_data->size; i++) {
104 : 154049485 : temp_blob.data[i] ^= provided_data->data[i];
105 : 154049485 : }
106 : :
107 : : /* Update the key and value */
108 [ - + ][ # # ]: 4014527 : RESULT_GUARD_OSSL(EVP_EncryptInit_ex(drbg->ctx, NULL, NULL, temp_blob.data, NULL), S2N_ERR_DRBG);
109 : :
110 [ - + ][ # # ]: 4014527 : RESULT_CHECKED_MEMCPY(drbg->v, temp_blob.data + s2n_drbg_key_size(drbg), S2N_DRBG_BLOCK_SIZE);
[ + + ]
111 : :
112 : 4014527 : return S2N_RESULT_OK;
113 : 4014527 : }
114 : :
115 : : static S2N_RESULT s2n_drbg_mix_in_entropy(struct s2n_drbg *drbg, struct s2n_blob *entropy, struct s2n_blob *ps)
116 : 1756272 : {
117 [ - + ][ # # ]: 1756272 : RESULT_ENSURE_REF(drbg);
118 [ - + ][ # # ]: 1756272 : RESULT_ENSURE_REF(drbg->ctx);
119 [ - + ][ # # ]: 1756272 : RESULT_ENSURE_REF(entropy);
120 : :
121 [ - + ][ # # ]: 1756272 : RESULT_ENSURE_GTE(entropy->size, ps->size);
122 : :
123 [ + + ]: 69031392 : for (uint32_t i = 0; i < ps->size; i++) {
124 : 67275120 : entropy->data[i] ^= ps->data[i];
125 : 67275120 : }
126 : :
127 [ - + ]: 1756272 : RESULT_GUARD(s2n_drbg_update(drbg, entropy));
128 : :
129 : 1756272 : return S2N_RESULT_OK;
130 : 1756272 : }
131 : :
132 : : static S2N_RESULT s2n_drbg_seed(struct s2n_drbg *drbg, struct s2n_blob *ps)
133 : 6818 : {
134 [ - + ][ - + ]: 6818 : RESULT_STACK_BLOB(blob, s2n_drbg_seed_size(drbg), S2N_DRBG_MAX_SEED_SIZE);
[ # # ]
135 : :
136 [ - + ]: 6818 : RESULT_GUARD(s2n_get_seed_entropy(&blob));
137 [ - + ]: 6818 : RESULT_GUARD(s2n_drbg_mix_in_entropy(drbg, &blob, ps));
138 : :
139 : 6818 : drbg->bytes_used = 0;
140 : :
141 : 6818 : return S2N_RESULT_OK;
142 : 6818 : }
143 : :
144 : : static S2N_RESULT s2n_drbg_mix(struct s2n_drbg *drbg, struct s2n_blob *ps)
145 : 2258186 : {
146 [ + + ]: 2258186 : if (s2n_unlikely(ignore_prediction_resistance_for_testing)) {
147 [ - + ][ # # ]: 508778 : RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
148 : 508778 : return S2N_RESULT_OK;
149 : 508778 : }
150 : :
151 [ - + ][ # # ]: 3498816 : RESULT_STACK_BLOB(blob, s2n_drbg_seed_size(drbg), S2N_DRBG_MAX_SEED_SIZE);
[ - + ]
152 : :
153 [ - + ]: 1749408 : RESULT_GUARD(s2n_get_mix_entropy(&blob));
154 [ - + ]: 1749408 : RESULT_GUARD(s2n_drbg_mix_in_entropy(drbg, &blob, ps));
155 : :
156 : 1749408 : drbg->mixes += 1;
157 : :
158 : 1749408 : return S2N_RESULT_OK;
159 : 1749408 : }
160 : :
161 : : S2N_RESULT s2n_drbg_instantiate(struct s2n_drbg *drbg, struct s2n_blob *personalization_string, const s2n_drbg_mode mode)
162 : 6846 : {
163 [ - + ][ # # ]: 6846 : RESULT_ENSURE_REF(drbg);
164 [ - + ][ # # ]: 6846 : RESULT_ENSURE_REF(personalization_string);
165 : :
166 : 6846 : drbg->ctx = EVP_CIPHER_CTX_new();
167 [ - + ]: 6846 : RESULT_GUARD_PTR(drbg->ctx);
168 : :
169 [ - + ][ # # ]: 6846 : RESULT_EVP_CTX_INIT(drbg->ctx);
170 : :
171 : 6846 : switch (mode) {
172 [ + + ]: 3467 : case S2N_AES_128_CTR_NO_DF_PR:
173 [ # # ][ - + ]: 3467 : RESULT_GUARD_OSSL(EVP_EncryptInit_ex(drbg->ctx, EVP_aes_128_ecb(), NULL, NULL, NULL), S2N_ERR_DRBG);
174 : 3467 : break;
175 [ + + ]: 3467 : case S2N_AES_256_CTR_NO_DF_PR:
176 [ # # ][ - + ]: 3309 : RESULT_GUARD_OSSL(EVP_EncryptInit_ex(drbg->ctx, EVP_aes_256_ecb(), NULL, NULL, NULL), S2N_ERR_DRBG);
177 : 3309 : break;
178 [ - + ]: 3309 : default:
179 [ # # ]: 0 : RESULT_BAIL(S2N_ERR_DRBG);
180 : 6846 : }
181 : :
182 [ - + ][ # # ]: 6797 : RESULT_ENSURE_LTE(s2n_drbg_key_size(drbg), S2N_DRBG_MAX_KEY_SIZE);
183 [ - + ][ # # ]: 6797 : RESULT_ENSURE_LTE(s2n_drbg_seed_size(drbg), S2N_DRBG_MAX_SEED_SIZE);
184 : :
185 : 6797 : static const uint8_t zero_key[S2N_DRBG_MAX_KEY_SIZE] = { 0 };
186 : :
187 : : /* Start off with zeroed data, per 10.2.1.3.1 item 4 and 5 */
188 : 6797 : memset(drbg->v, 0, sizeof(drbg->v));
189 [ - + ][ # # ]: 6797 : RESULT_GUARD_OSSL(EVP_EncryptInit_ex(drbg->ctx, NULL, NULL, zero_key, NULL), S2N_ERR_DRBG);
190 : :
191 : : /* Copy the personalization string */
192 [ - + ][ # # ]: 13594 : RESULT_STACK_BLOB(ps, s2n_drbg_seed_size(drbg), S2N_DRBG_MAX_SEED_SIZE);
[ - + ]
193 [ - + ]: 6797 : RESULT_GUARD_POSIX(s2n_blob_zero(&ps));
194 : :
195 [ # # ][ - + ]: 6797 : RESULT_CHECKED_MEMCPY(ps.data, personalization_string->data, MIN(ps.size, personalization_string->size));
[ + + ][ + + ]
196 : :
197 : : /* Seed the DRBG */
198 [ - + ]: 6797 : RESULT_GUARD(s2n_drbg_seed(drbg, &ps));
199 : :
200 : 6797 : return S2N_RESULT_OK;
201 : 6797 : }
202 : :
203 : : S2N_RESULT s2n_drbg_generate(struct s2n_drbg *drbg, struct s2n_blob *blob)
204 : 2258257 : {
205 [ - + ][ # # ]: 2258257 : RESULT_ENSURE_REF(drbg);
206 [ - + ][ # # ]: 2258257 : RESULT_ENSURE_REF(drbg->ctx);
207 : :
208 [ - + ][ # # ]: 4516514 : RESULT_STACK_BLOB(zeros, s2n_drbg_seed_size(drbg), S2N_DRBG_MAX_SEED_SIZE);
[ - + ]
209 : :
210 [ # # ][ - + ]: 2258257 : RESULT_ENSURE(blob->size <= S2N_DRBG_GENERATE_LIMIT, S2N_ERR_DRBG_REQUEST_SIZE);
211 : :
212 : : /* Mix in additional entropy for every randomness generation call. This
213 : : * defense mechanism is referred to as "prediction resistance".
214 : : * If we ever relax this defense, we must:
215 : : * 1. Implement reseeding according to limit specified in
216 : : * NIST SP800-90A 10.2.1 Table 3.
217 : : * 2. Re-consider whether the current fork detection strategy is still
218 : : * sufficient.
219 : : */
220 [ - + ]: 2258257 : RESULT_GUARD(s2n_drbg_mix(drbg, &zeros));
221 [ - + ]: 2258257 : RESULT_GUARD(s2n_drbg_bits(drbg, blob));
222 [ - + ]: 2258257 : RESULT_GUARD(s2n_drbg_update(drbg, &zeros));
223 : :
224 : 2258257 : return S2N_RESULT_OK;
225 : 2258257 : }
226 : :
227 : : S2N_RESULT s2n_drbg_wipe(struct s2n_drbg *drbg)
228 : 7369 : {
229 [ - + ][ # # ]: 7369 : RESULT_ENSURE_REF(drbg);
230 : :
231 [ + + ]: 7369 : if (drbg->ctx) {
232 [ - + ][ # # ]: 6717 : RESULT_GUARD_OSSL(EVP_CIPHER_CTX_cleanup(drbg->ctx), S2N_ERR_DRBG);
233 : :
234 : 6717 : EVP_CIPHER_CTX_free(drbg->ctx);
235 : 6717 : drbg->ctx = NULL;
236 : 6717 : }
237 : :
238 : 7369 : *drbg = (struct s2n_drbg){ 0 };
239 : 7369 : return S2N_RESULT_OK;
240 : 7369 : }
241 : :
242 : : S2N_RESULT s2n_drbg_bytes_used(struct s2n_drbg *drbg, uint64_t *bytes_used)
243 : 226 : {
244 [ - + ][ # # ]: 226 : RESULT_ENSURE_REF(drbg);
245 [ # # ][ - + ]: 226 : RESULT_ENSURE_REF(bytes_used);
246 : :
247 : 226 : *bytes_used = drbg->bytes_used;
248 : 226 : return S2N_RESULT_OK;
249 : 226 : }
250 : :
251 : : S2N_RESULT s2n_ignore_prediction_resistance_for_testing(bool ignore_bool)
252 : 106 : {
253 [ - + ][ # # ]: 106 : RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
254 : :
255 : 106 : ignore_prediction_resistance_for_testing = ignore_bool;
256 : :
257 : 106 : return S2N_RESULT_OK;
258 : 106 : }
|