]>
Commit | Line | Data |
---|---|---|
12fb8c3d | 1 | /* |
a28d06f3 | 2 | * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. |
12fb8c3d | 3 | * |
0db63de9 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
12fb8c3d RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include <stdlib.h> | |
11 | #include <string.h> | |
12 | #include <openssl/crypto.h> | |
13 | #include <openssl/err.h> | |
14 | #include <openssl/rand.h> | |
f000e828 | 15 | #include <openssl/aes.h> |
2741128e | 16 | #include <openssl/proverr.h> |
d5f9166b | 17 | #include "internal/e_os.h" /* strcasecmp */ |
28bdbe1a | 18 | #include "crypto/modes.h" |
12fb8c3d | 19 | #include "internal/thread_once.h" |
f000e828 | 20 | #include "prov/implementations.h" |
b98d550d | 21 | #include "prov/providercommon.h" |
f000e828 | 22 | #include "prov/provider_ctx.h" |
f000e828 P |
23 | #include "drbg_local.h" |
24 | ||
363b1e5d DMSP |
25 | static OSSL_FUNC_rand_newctx_fn drbg_ctr_new_wrapper; |
26 | static OSSL_FUNC_rand_freectx_fn drbg_ctr_free; | |
27 | static OSSL_FUNC_rand_instantiate_fn drbg_ctr_instantiate_wrapper; | |
28 | static OSSL_FUNC_rand_uninstantiate_fn drbg_ctr_uninstantiate_wrapper; | |
29 | static OSSL_FUNC_rand_generate_fn drbg_ctr_generate_wrapper; | |
30 | static OSSL_FUNC_rand_reseed_fn drbg_ctr_reseed_wrapper; | |
31 | static OSSL_FUNC_rand_settable_ctx_params_fn drbg_ctr_settable_ctx_params; | |
32 | static OSSL_FUNC_rand_set_ctx_params_fn drbg_ctr_set_ctx_params; | |
33 | static OSSL_FUNC_rand_gettable_ctx_params_fn drbg_ctr_gettable_ctx_params; | |
34 | static OSSL_FUNC_rand_get_ctx_params_fn drbg_ctr_get_ctx_params; | |
35 | static OSSL_FUNC_rand_verify_zeroization_fn drbg_ctr_verify_zeroization; | |
f000e828 P |
36 | |
37 | /* | |
38 | * The state of a DRBG AES-CTR. | |
39 | */ | |
40 | typedef struct rand_drbg_ctr_st { | |
41 | EVP_CIPHER_CTX *ctx_ecb; | |
42 | EVP_CIPHER_CTX *ctx_ctr; | |
43 | EVP_CIPHER_CTX *ctx_df; | |
44 | EVP_CIPHER *cipher_ecb; | |
45 | EVP_CIPHER *cipher_ctr; | |
46 | size_t keylen; | |
47 | int use_df; | |
48 | unsigned char K[32]; | |
49 | unsigned char V[16]; | |
50 | /* Temporary block storage used by ctr_df */ | |
51 | unsigned char bltmp[16]; | |
52 | size_t bltmp_pos; | |
53 | unsigned char KX[48]; | |
54 | } PROV_DRBG_CTR; | |
8bf36651 | 55 | |
12fb8c3d | 56 | /* |
75e2c877 | 57 | * Implementation of NIST SP 800-90A CTR DRBG. |
12fb8c3d | 58 | */ |
f000e828 | 59 | static void inc_128(PROV_DRBG_CTR *ctr) |
12fb8c3d | 60 | { |
069165d1 PS |
61 | unsigned char *p = &ctr->V[0]; |
62 | u32 n = 16, c = 1; | |
63 | ||
64 | do { | |
65 | --n; | |
66 | c += p[n]; | |
67 | p[n] = (u8)c; | |
68 | c >>= 8; | |
69 | } while (n); | |
12fb8c3d RS |
70 | } |
71 | ||
f000e828 | 72 | static void ctr_XOR(PROV_DRBG_CTR *ctr, const unsigned char *in, size_t inlen) |
12fb8c3d RS |
73 | { |
74 | size_t i, n; | |
75 | ||
76 | if (in == NULL || inlen == 0) | |
77 | return; | |
78 | ||
79 | /* | |
80 | * Any zero padding will have no effect on the result as we | |
81 | * are XORing. So just process however much input we have. | |
82 | */ | |
75e2c877 | 83 | n = inlen < ctr->keylen ? inlen : ctr->keylen; |
12fb8c3d | 84 | for (i = 0; i < n; i++) |
75e2c877 RS |
85 | ctr->K[i] ^= in[i]; |
86 | if (inlen <= ctr->keylen) | |
12fb8c3d RS |
87 | return; |
88 | ||
75e2c877 | 89 | n = inlen - ctr->keylen; |
12fb8c3d RS |
90 | if (n > 16) { |
91 | /* Should never happen */ | |
92 | n = 16; | |
93 | } | |
b8a437ff | 94 | for (i = 0; i < n; i++) |
75e2c877 | 95 | ctr->V[i] ^= in[i + ctr->keylen]; |
12fb8c3d RS |
96 | } |
97 | ||
98 | /* | |
99 | * Process a complete block using BCC algorithm of SP 800-90A 10.3.3 | |
100 | */ | |
f000e828 | 101 | __owur static int ctr_BCC_block(PROV_DRBG_CTR *ctr, unsigned char *out, |
28bdbe1a | 102 | const unsigned char *in, int len) |
12fb8c3d | 103 | { |
dbdcc04f | 104 | int i, outlen = AES_BLOCK_SIZE; |
12fb8c3d | 105 | |
28bdbe1a | 106 | for (i = 0; i < len; i++) |
12fb8c3d | 107 | out[i] ^= in[i]; |
dbdcc04f | 108 | |
28bdbe1a PS |
109 | if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, len) |
110 | || outlen != len) | |
dbdcc04f KR |
111 | return 0; |
112 | return 1; | |
12fb8c3d RS |
113 | } |
114 | ||
115 | ||
116 | /* | |
117 | * Handle several BCC operations for as much data as we need for K and X | |
118 | */ | |
f000e828 | 119 | __owur static int ctr_BCC_blocks(PROV_DRBG_CTR *ctr, const unsigned char *in) |
12fb8c3d | 120 | { |
28bdbe1a PS |
121 | unsigned char in_tmp[48]; |
122 | unsigned char num_of_blk = 2; | |
123 | ||
124 | memcpy(in_tmp, in, 16); | |
125 | memcpy(in_tmp + 16, in, 16); | |
126 | if (ctr->keylen != 16) { | |
127 | memcpy(in_tmp + 32, in, 16); | |
128 | num_of_blk = 3; | |
129 | } | |
130 | return ctr_BCC_block(ctr, ctr->KX, in_tmp, AES_BLOCK_SIZE * num_of_blk); | |
12fb8c3d RS |
131 | } |
132 | ||
133 | /* | |
134 | * Initialise BCC blocks: these have the value 0,1,2 in leftmost positions: | |
135 | * see 10.3.1 stage 7. | |
136 | */ | |
f000e828 | 137 | __owur static int ctr_BCC_init(PROV_DRBG_CTR *ctr) |
12fb8c3d | 138 | { |
28bdbe1a PS |
139 | unsigned char bltmp[48] = {0}; |
140 | unsigned char num_of_blk; | |
141 | ||
75e2c877 | 142 | memset(ctr->KX, 0, 48); |
28bdbe1a PS |
143 | num_of_blk = ctr->keylen == 16 ? 2 : 3; |
144 | bltmp[(AES_BLOCK_SIZE * 1) + 3] = 1; | |
145 | bltmp[(AES_BLOCK_SIZE * 2) + 3] = 2; | |
146 | return ctr_BCC_block(ctr, ctr->KX, bltmp, num_of_blk * AES_BLOCK_SIZE); | |
12fb8c3d RS |
147 | } |
148 | ||
149 | /* | |
150 | * Process several blocks into BCC algorithm, some possibly partial | |
151 | */ | |
f000e828 | 152 | __owur static int ctr_BCC_update(PROV_DRBG_CTR *ctr, |
dbdcc04f | 153 | const unsigned char *in, size_t inlen) |
12fb8c3d RS |
154 | { |
155 | if (in == NULL || inlen == 0) | |
dbdcc04f | 156 | return 1; |
12fb8c3d RS |
157 | |
158 | /* If we have partial block handle it first */ | |
75e2c877 RS |
159 | if (ctr->bltmp_pos) { |
160 | size_t left = 16 - ctr->bltmp_pos; | |
12fb8c3d RS |
161 | |
162 | /* If we now have a complete block process it */ | |
163 | if (inlen >= left) { | |
75e2c877 | 164 | memcpy(ctr->bltmp + ctr->bltmp_pos, in, left); |
dbdcc04f KR |
165 | if (!ctr_BCC_blocks(ctr, ctr->bltmp)) |
166 | return 0; | |
75e2c877 | 167 | ctr->bltmp_pos = 0; |
12fb8c3d RS |
168 | inlen -= left; |
169 | in += left; | |
170 | } | |
171 | } | |
172 | ||
173 | /* Process zero or more complete blocks */ | |
174 | for (; inlen >= 16; in += 16, inlen -= 16) { | |
dbdcc04f KR |
175 | if (!ctr_BCC_blocks(ctr, in)) |
176 | return 0; | |
12fb8c3d RS |
177 | } |
178 | ||
179 | /* Copy any remaining partial block to the temporary buffer */ | |
180 | if (inlen > 0) { | |
75e2c877 RS |
181 | memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen); |
182 | ctr->bltmp_pos += inlen; | |
12fb8c3d | 183 | } |
dbdcc04f | 184 | return 1; |
12fb8c3d RS |
185 | } |
186 | ||
f000e828 | 187 | __owur static int ctr_BCC_final(PROV_DRBG_CTR *ctr) |
12fb8c3d | 188 | { |
75e2c877 RS |
189 | if (ctr->bltmp_pos) { |
190 | memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos); | |
dbdcc04f KR |
191 | if (!ctr_BCC_blocks(ctr, ctr->bltmp)) |
192 | return 0; | |
12fb8c3d | 193 | } |
dbdcc04f | 194 | return 1; |
12fb8c3d RS |
195 | } |
196 | ||
f000e828 | 197 | __owur static int ctr_df(PROV_DRBG_CTR *ctr, |
dbdcc04f KR |
198 | const unsigned char *in1, size_t in1len, |
199 | const unsigned char *in2, size_t in2len, | |
200 | const unsigned char *in3, size_t in3len) | |
12fb8c3d RS |
201 | { |
202 | static unsigned char c80 = 0x80; | |
203 | size_t inlen; | |
75e2c877 | 204 | unsigned char *p = ctr->bltmp; |
dbdcc04f | 205 | int outlen = AES_BLOCK_SIZE; |
12fb8c3d | 206 | |
dbdcc04f KR |
207 | if (!ctr_BCC_init(ctr)) |
208 | return 0; | |
12fb8c3d RS |
209 | if (in1 == NULL) |
210 | in1len = 0; | |
211 | if (in2 == NULL) | |
212 | in2len = 0; | |
213 | if (in3 == NULL) | |
214 | in3len = 0; | |
215 | inlen = in1len + in2len + in3len; | |
216 | /* Initialise L||N in temporary block */ | |
217 | *p++ = (inlen >> 24) & 0xff; | |
218 | *p++ = (inlen >> 16) & 0xff; | |
219 | *p++ = (inlen >> 8) & 0xff; | |
220 | *p++ = inlen & 0xff; | |
221 | ||
222 | /* NB keylen is at most 32 bytes */ | |
223 | *p++ = 0; | |
224 | *p++ = 0; | |
225 | *p++ = 0; | |
75e2c877 RS |
226 | *p = (unsigned char)((ctr->keylen + 16) & 0xff); |
227 | ctr->bltmp_pos = 8; | |
dbdcc04f KR |
228 | if (!ctr_BCC_update(ctr, in1, in1len) |
229 | || !ctr_BCC_update(ctr, in2, in2len) | |
230 | || !ctr_BCC_update(ctr, in3, in3len) | |
231 | || !ctr_BCC_update(ctr, &c80, 1) | |
232 | || !ctr_BCC_final(ctr)) | |
233 | return 0; | |
12fb8c3d | 234 | /* Set up key K */ |
28bdbe1a | 235 | if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->KX, NULL, -1)) |
dbdcc04f | 236 | return 0; |
12fb8c3d | 237 | /* X follows key K */ |
28bdbe1a | 238 | if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX, &outlen, ctr->KX + ctr->keylen, |
dbdcc04f KR |
239 | AES_BLOCK_SIZE) |
240 | || outlen != AES_BLOCK_SIZE) | |
241 | return 0; | |
28bdbe1a | 242 | if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 16, &outlen, ctr->KX, |
dbdcc04f KR |
243 | AES_BLOCK_SIZE) |
244 | || outlen != AES_BLOCK_SIZE) | |
245 | return 0; | |
75e2c877 | 246 | if (ctr->keylen != 16) |
28bdbe1a PS |
247 | if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 32, &outlen, |
248 | ctr->KX + 16, AES_BLOCK_SIZE) | |
dbdcc04f KR |
249 | || outlen != AES_BLOCK_SIZE) |
250 | return 0; | |
251 | return 1; | |
12fb8c3d RS |
252 | } |
253 | ||
254 | /* | |
255 | * NB the no-df Update in SP800-90A specifies a constant input length | |
256 | * of seedlen, however other uses of this algorithm pad the input with | |
257 | * zeroes if necessary and have up to two parameters XORed together, | |
75e2c877 | 258 | * so we handle both cases in this function instead. |
12fb8c3d | 259 | */ |
f000e828 | 260 | __owur static int ctr_update(PROV_DRBG *drbg, |
dbdcc04f KR |
261 | const unsigned char *in1, size_t in1len, |
262 | const unsigned char *in2, size_t in2len, | |
263 | const unsigned char *nonce, size_t noncelen) | |
12fb8c3d | 264 | { |
f000e828 | 265 | PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data; |
dbdcc04f | 266 | int outlen = AES_BLOCK_SIZE; |
28bdbe1a PS |
267 | unsigned char V_tmp[48], out[48]; |
268 | unsigned char len; | |
12fb8c3d | 269 | |
dbdcc04f | 270 | /* correct key is already set up. */ |
28bdbe1a | 271 | memcpy(V_tmp, ctr->V, 16); |
75e2c877 | 272 | inc_128(ctr); |
28bdbe1a PS |
273 | memcpy(V_tmp + 16, ctr->V, 16); |
274 | if (ctr->keylen == 16) { | |
275 | len = 32; | |
276 | } else { | |
75e2c877 | 277 | inc_128(ctr); |
28bdbe1a PS |
278 | memcpy(V_tmp + 32, ctr->V, 16); |
279 | len = 48; | |
12fb8c3d | 280 | } |
28bdbe1a PS |
281 | if (!EVP_CipherUpdate(ctr->ctx_ecb, out, &outlen, V_tmp, len) |
282 | || outlen != len) | |
dbdcc04f | 283 | return 0; |
28bdbe1a PS |
284 | memcpy(ctr->K, out, ctr->keylen); |
285 | memcpy(ctr->V, out + ctr->keylen, 16); | |
12fb8c3d | 286 | |
f000e828 | 287 | if (ctr->use_df) { |
12fb8c3d RS |
288 | /* If no input reuse existing derived value */ |
289 | if (in1 != NULL || nonce != NULL || in2 != NULL) | |
dbdcc04f KR |
290 | if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len)) |
291 | return 0; | |
12fb8c3d RS |
292 | /* If this a reuse input in1len != 0 */ |
293 | if (in1len) | |
75e2c877 | 294 | ctr_XOR(ctr, ctr->KX, drbg->seedlen); |
12fb8c3d | 295 | } else { |
75e2c877 RS |
296 | ctr_XOR(ctr, in1, in1len); |
297 | ctr_XOR(ctr, in2, in2len); | |
12fb8c3d RS |
298 | } |
299 | ||
28bdbe1a PS |
300 | if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1) |
301 | || !EVP_CipherInit_ex(ctr->ctx_ctr, NULL, NULL, ctr->K, NULL, -1)) | |
dbdcc04f KR |
302 | return 0; |
303 | return 1; | |
12fb8c3d RS |
304 | } |
305 | ||
f000e828 P |
306 | static int drbg_ctr_instantiate(PROV_DRBG *drbg, |
307 | const unsigned char *entropy, size_t entropylen, | |
308 | const unsigned char *nonce, size_t noncelen, | |
309 | const unsigned char *pers, size_t perslen) | |
12fb8c3d | 310 | { |
f000e828 | 311 | PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data; |
12fb8c3d | 312 | |
aa048aef | 313 | if (entropy == NULL) |
4c78ba59 DSH |
314 | return 0; |
315 | ||
75e2c877 RS |
316 | memset(ctr->K, 0, sizeof(ctr->K)); |
317 | memset(ctr->V, 0, sizeof(ctr->V)); | |
28bdbe1a | 318 | if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1)) |
dbdcc04f | 319 | return 0; |
28bdbe1a PS |
320 | |
321 | inc_128(ctr); | |
dbdcc04f KR |
322 | if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen)) |
323 | return 0; | |
12fb8c3d RS |
324 | return 1; |
325 | } | |
326 | ||
f000e828 P |
327 | static int drbg_ctr_instantiate_wrapper(void *vdrbg, unsigned int strength, |
328 | int prediction_resistance, | |
329 | const unsigned char *pstr, | |
b98d550d P |
330 | size_t pstr_len, |
331 | const OSSL_PARAM params[]) | |
f000e828 P |
332 | { |
333 | PROV_DRBG *drbg = (PROV_DRBG *)vdrbg; | |
334 | ||
b98d550d P |
335 | if (!ossl_prov_is_running() || !drbg_ctr_set_ctx_params(drbg, params)) |
336 | return 0; | |
7d6766cb P |
337 | return ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance, |
338 | pstr, pstr_len); | |
f000e828 P |
339 | } |
340 | ||
341 | static int drbg_ctr_reseed(PROV_DRBG *drbg, | |
342 | const unsigned char *entropy, size_t entropylen, | |
343 | const unsigned char *adin, size_t adinlen) | |
12fb8c3d | 344 | { |
f000e828 | 345 | PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data; |
28bdbe1a | 346 | |
aa048aef | 347 | if (entropy == NULL) |
4c78ba59 | 348 | return 0; |
28bdbe1a PS |
349 | |
350 | inc_128(ctr); | |
dbdcc04f KR |
351 | if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0)) |
352 | return 0; | |
12fb8c3d RS |
353 | return 1; |
354 | } | |
355 | ||
f000e828 P |
356 | static int drbg_ctr_reseed_wrapper(void *vdrbg, int prediction_resistance, |
357 | const unsigned char *ent, size_t ent_len, | |
358 | const unsigned char *adin, size_t adin_len) | |
359 | { | |
360 | PROV_DRBG *drbg = (PROV_DRBG *)vdrbg; | |
361 | ||
7d6766cb P |
362 | return ossl_prov_drbg_reseed(drbg, prediction_resistance, ent, ent_len, |
363 | adin, adin_len); | |
f000e828 P |
364 | } |
365 | ||
28bdbe1a PS |
366 | static void ctr96_inc(unsigned char *counter) |
367 | { | |
368 | u32 n = 12, c = 1; | |
369 | ||
370 | do { | |
371 | --n; | |
372 | c += counter[n]; | |
373 | counter[n] = (u8)c; | |
374 | c >>= 8; | |
375 | } while (n); | |
376 | } | |
377 | ||
f000e828 P |
378 | static int drbg_ctr_generate(PROV_DRBG *drbg, |
379 | unsigned char *out, size_t outlen, | |
380 | const unsigned char *adin, size_t adinlen) | |
12fb8c3d | 381 | { |
f000e828 | 382 | PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data; |
28bdbe1a PS |
383 | unsigned int ctr32, blocks; |
384 | int outl, buflen; | |
12fb8c3d RS |
385 | |
386 | if (adin != NULL && adinlen != 0) { | |
28bdbe1a PS |
387 | inc_128(ctr); |
388 | ||
dbdcc04f KR |
389 | if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0)) |
390 | return 0; | |
12fb8c3d | 391 | /* This means we reuse derived value */ |
f000e828 | 392 | if (ctr->use_df) { |
12fb8c3d RS |
393 | adin = NULL; |
394 | adinlen = 1; | |
395 | } | |
396 | } else { | |
397 | adinlen = 0; | |
398 | } | |
399 | ||
28bdbe1a | 400 | inc_128(ctr); |
dbdcc04f | 401 | |
28bdbe1a | 402 | if (outlen == 0) { |
75e2c877 | 403 | inc_128(ctr); |
28bdbe1a PS |
404 | |
405 | if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0)) | |
dbdcc04f | 406 | return 0; |
28bdbe1a | 407 | return 1; |
12fb8c3d RS |
408 | } |
409 | ||
28bdbe1a PS |
410 | memset(out, 0, outlen); |
411 | ||
412 | do { | |
413 | if (!EVP_CipherInit_ex(ctr->ctx_ctr, | |
414 | NULL, NULL, NULL, ctr->V, -1)) | |
415 | return 0; | |
416 | ||
417 | /*- | |
418 | * outlen has type size_t while EVP_CipherUpdate takes an | |
419 | * int argument and thus cannot be guaranteed to process more | |
420 | * than 2^31-1 bytes at a time. We process such huge generate | |
421 | * requests in 2^30 byte chunks, which is the greatest multiple | |
422 | * of AES block size lower than or equal to 2^31-1. | |
423 | */ | |
424 | buflen = outlen > (1U << 30) ? (1U << 30) : outlen; | |
425 | blocks = (buflen + 15) / 16; | |
426 | ||
427 | ctr32 = GETU32(ctr->V + 12) + blocks; | |
428 | if (ctr32 < blocks) { | |
429 | /* 32-bit counter overflow into V. */ | |
42fa3e66 BE |
430 | if (ctr32 != 0) { |
431 | blocks -= ctr32; | |
432 | buflen = blocks * 16; | |
433 | ctr32 = 0; | |
434 | } | |
28bdbe1a PS |
435 | ctr96_inc(ctr->V); |
436 | } | |
437 | PUTU32(ctr->V + 12, ctr32); | |
438 | ||
439 | if (!EVP_CipherUpdate(ctr->ctx_ctr, out, &outl, out, buflen) | |
440 | || outl != buflen) | |
441 | return 0; | |
442 | ||
443 | out += buflen; | |
444 | outlen -= buflen; | |
445 | } while (outlen); | |
446 | ||
dbdcc04f KR |
447 | if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0)) |
448 | return 0; | |
12fb8c3d RS |
449 | return 1; |
450 | } | |
451 | ||
f000e828 P |
452 | static int drbg_ctr_generate_wrapper |
453 | (void *vdrbg, unsigned char *out, size_t outlen, | |
454 | unsigned int strength, int prediction_resistance, | |
455 | const unsigned char *adin, size_t adin_len) | |
12fb8c3d | 456 | { |
f000e828 P |
457 | PROV_DRBG *drbg = (PROV_DRBG *)vdrbg; |
458 | ||
7d6766cb P |
459 | return ossl_prov_drbg_generate(drbg, out, outlen, strength, |
460 | prediction_resistance, adin, adin_len); | |
12fb8c3d RS |
461 | } |
462 | ||
f000e828 P |
463 | static int drbg_ctr_uninstantiate(PROV_DRBG *drbg) |
464 | { | |
465 | PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data; | |
466 | ||
467 | OPENSSL_cleanse(ctr->K, sizeof(ctr->K)); | |
468 | OPENSSL_cleanse(ctr->V, sizeof(ctr->V)); | |
469 | OPENSSL_cleanse(ctr->bltmp, sizeof(ctr->bltmp)); | |
470 | OPENSSL_cleanse(ctr->KX, sizeof(ctr->KX)); | |
471 | ctr->bltmp_pos = 0; | |
7d6766cb | 472 | return ossl_prov_drbg_uninstantiate(drbg); |
f000e828 | 473 | } |
8212d505 | 474 | |
f000e828 | 475 | static int drbg_ctr_uninstantiate_wrapper(void *vdrbg) |
12fb8c3d | 476 | { |
f000e828 P |
477 | return drbg_ctr_uninstantiate((PROV_DRBG *)vdrbg); |
478 | } | |
12fb8c3d | 479 | |
f000e828 P |
480 | static int drbg_ctr_verify_zeroization(void *vdrbg) |
481 | { | |
482 | PROV_DRBG *drbg = (PROV_DRBG *)vdrbg; | |
483 | PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data; | |
484 | ||
485 | PROV_DRBG_VERYIFY_ZEROIZATION(ctr->K); | |
486 | PROV_DRBG_VERYIFY_ZEROIZATION(ctr->V); | |
487 | PROV_DRBG_VERYIFY_ZEROIZATION(ctr->bltmp); | |
488 | PROV_DRBG_VERYIFY_ZEROIZATION(ctr->KX); | |
489 | if (ctr->bltmp_pos != 0) | |
efb8128a | 490 | return 0; |
f000e828 P |
491 | return 1; |
492 | } | |
493 | ||
494 | static int drbg_ctr_init_lengths(PROV_DRBG *drbg) | |
495 | { | |
496 | PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data; | |
497 | int res = 1; | |
498 | ||
f000e828 P |
499 | /* Maximum number of bits per request = 2^19 = 2^16 bytes */ |
500 | drbg->max_request = 1 << 16; | |
501 | if (ctr->use_df) { | |
502 | drbg->min_entropylen = 0; | |
503 | drbg->max_entropylen = DRBG_MAX_LENGTH; | |
504 | drbg->min_noncelen = 0; | |
505 | drbg->max_noncelen = DRBG_MAX_LENGTH; | |
506 | drbg->max_perslen = DRBG_MAX_LENGTH; | |
507 | drbg->max_adinlen = DRBG_MAX_LENGTH; | |
57ca171a | 508 | |
f000e828 P |
509 | if (ctr->keylen > 0) { |
510 | drbg->min_entropylen = ctr->keylen; | |
511 | drbg->min_noncelen = drbg->min_entropylen / 2; | |
512 | } | |
513 | } else { | |
514 | const size_t len = ctr->keylen > 0 ? drbg->seedlen : DRBG_MAX_LENGTH; | |
515 | ||
516 | drbg->min_entropylen = len; | |
517 | drbg->max_entropylen = len; | |
518 | /* Nonce not used */ | |
519 | drbg->min_noncelen = 0; | |
520 | drbg->max_noncelen = 0; | |
521 | drbg->max_perslen = len; | |
522 | drbg->max_adinlen = len; | |
523 | } | |
524 | return res; | |
525 | } | |
526 | ||
527 | static int drbg_ctr_init(PROV_DRBG *drbg) | |
528 | { | |
529 | PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data; | |
2f142901 | 530 | size_t keylen; |
8212d505 | 531 | |
2f142901 P |
532 | if (ctr->cipher_ctr == NULL) { |
533 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER); | |
534 | return 0; | |
535 | } | |
ed576acd | 536 | ctr->keylen = keylen = EVP_CIPHER_get_key_length(ctr->cipher_ctr); |
28bdbe1a PS |
537 | if (ctr->ctx_ecb == NULL) |
538 | ctr->ctx_ecb = EVP_CIPHER_CTX_new(); | |
539 | if (ctr->ctx_ctr == NULL) | |
540 | ctr->ctx_ctr = EVP_CIPHER_CTX_new(); | |
f000e828 P |
541 | if (ctr->ctx_ecb == NULL || ctr->ctx_ctr == NULL) { |
542 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
543 | goto err; | |
544 | } | |
545 | ||
2f142901 P |
546 | if (!EVP_CipherInit_ex(ctr->ctx_ecb, |
547 | ctr->cipher_ecb, NULL, NULL, NULL, 1) | |
548 | || !EVP_CipherInit_ex(ctr->ctx_ctr, | |
549 | ctr->cipher_ctr, NULL, NULL, NULL, 1)) { | |
550 | ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_INITIALISE_CIPHERS); | |
551 | goto err; | |
552 | } | |
f000e828 | 553 | |
2f142901 P |
554 | drbg->strength = keylen * 8; |
555 | drbg->seedlen = keylen + 16; | |
f000e828 | 556 | |
2f142901 P |
557 | if (ctr->use_df) { |
558 | /* df initialisation */ | |
559 | static const unsigned char df_key[32] = { | |
560 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | |
561 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | |
562 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | |
563 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f | |
564 | }; | |
565 | ||
566 | if (ctr->ctx_df == NULL) | |
567 | ctr->ctx_df = EVP_CIPHER_CTX_new(); | |
568 | if (ctr->ctx_df == NULL) { | |
569 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
570 | goto err; | |
571 | } | |
572 | /* Set key schedule for df_key */ | |
573 | if (!EVP_CipherInit_ex(ctr->ctx_df, | |
574 | ctr->cipher_ecb, NULL, df_key, NULL, 1)) { | |
575 | ERR_raise(ERR_LIB_PROV, PROV_R_DERIVATION_FUNCTION_INIT_FAILED); | |
576 | goto err; | |
f000e828 P |
577 | } |
578 | } | |
579 | return drbg_ctr_init_lengths(drbg); | |
580 | ||
581 | err: | |
582 | EVP_CIPHER_CTX_free(ctr->ctx_ecb); | |
583 | EVP_CIPHER_CTX_free(ctr->ctx_ctr); | |
584 | ctr->ctx_ecb = ctr->ctx_ctr = NULL; | |
585 | return 0; | |
586 | } | |
587 | ||
588 | static int drbg_ctr_new(PROV_DRBG *drbg) | |
589 | { | |
590 | PROV_DRBG_CTR *ctr; | |
591 | ||
592 | ctr = OPENSSL_secure_zalloc(sizeof(*ctr)); | |
593 | if (ctr == NULL) { | |
594 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
dbdcc04f | 595 | return 0; |
f000e828 P |
596 | } |
597 | ||
598 | ctr->use_df = 1; | |
599 | drbg->data = ctr; | |
600 | return drbg_ctr_init_lengths(drbg); | |
601 | } | |
602 | ||
603 | static void *drbg_ctr_new_wrapper(void *provctx, void *parent, | |
604 | const OSSL_DISPATCH *parent_dispatch) | |
605 | { | |
1dc188ba | 606 | return ossl_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_ctr_new, |
f000e828 P |
607 | &drbg_ctr_instantiate, &drbg_ctr_uninstantiate, |
608 | &drbg_ctr_reseed, &drbg_ctr_generate); | |
609 | } | |
610 | ||
611 | static void drbg_ctr_free(void *vdrbg) | |
612 | { | |
613 | PROV_DRBG *drbg = (PROV_DRBG *)vdrbg; | |
614 | PROV_DRBG_CTR *ctr; | |
615 | ||
616 | if (drbg != NULL && (ctr = (PROV_DRBG_CTR *)drbg->data) != NULL) { | |
617 | EVP_CIPHER_CTX_free(ctr->ctx_ecb); | |
618 | EVP_CIPHER_CTX_free(ctr->ctx_ctr); | |
619 | EVP_CIPHER_CTX_free(ctr->ctx_df); | |
620 | EVP_CIPHER_free(ctr->cipher_ecb); | |
621 | EVP_CIPHER_free(ctr->cipher_ctr); | |
622 | ||
623 | OPENSSL_secure_clear_free(ctr, sizeof(*ctr)); | |
624 | } | |
1dc188ba | 625 | ossl_rand_drbg_free(drbg); |
f000e828 P |
626 | } |
627 | ||
628 | static int drbg_ctr_get_ctx_params(void *vdrbg, OSSL_PARAM params[]) | |
629 | { | |
630 | PROV_DRBG *drbg = (PROV_DRBG *)vdrbg; | |
0ed26fb6 P |
631 | PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data; |
632 | OSSL_PARAM *p; | |
633 | ||
634 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_USE_DF); | |
635 | if (p != NULL && !OSSL_PARAM_set_int(p, ctr->use_df)) | |
636 | return 0; | |
637 | ||
638 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_CIPHER); | |
639 | if (p != NULL) { | |
640 | if (ctr->cipher_ctr == NULL | |
ed576acd TM |
641 | || !OSSL_PARAM_set_utf8_string(p, |
642 | EVP_CIPHER_get0_name(ctr->cipher_ctr))) | |
0ed26fb6 P |
643 | return 0; |
644 | } | |
f000e828 | 645 | |
b24d6c33 | 646 | return ossl_drbg_get_ctx_params(drbg, params); |
f000e828 P |
647 | } |
648 | ||
a3f091fd P |
649 | static const OSSL_PARAM *drbg_ctr_gettable_ctx_params(ossl_unused void *vctx, |
650 | ossl_unused void *provctx) | |
f000e828 P |
651 | { |
652 | static const OSSL_PARAM known_gettable_ctx_params[] = { | |
0ed26fb6 P |
653 | OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0), |
654 | OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL), | |
82a7b2fb | 655 | OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON, |
f000e828 P |
656 | OSSL_PARAM_END |
657 | }; | |
658 | return known_gettable_ctx_params; | |
659 | } | |
660 | ||
661 | static int drbg_ctr_set_ctx_params(void *vctx, const OSSL_PARAM params[]) | |
662 | { | |
663 | PROV_DRBG *ctx = (PROV_DRBG *)vctx; | |
664 | PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)ctx->data; | |
a829b735 | 665 | OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); |
f000e828 P |
666 | const OSSL_PARAM *p; |
667 | char *ecb; | |
668 | const char *propquery = NULL; | |
669 | int i, cipher_init = 0; | |
670 | ||
671 | if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_USE_DF)) != NULL | |
672 | && OSSL_PARAM_get_int(p, &i)) { | |
673 | /* FIPS errors out in the drbg_ctr_init() call later */ | |
674 | ctr->use_df = i != 0; | |
675 | cipher_init = 1; | |
676 | } | |
677 | ||
678 | if ((p = OSSL_PARAM_locate_const(params, | |
679 | OSSL_DRBG_PARAM_PROPERTIES)) != NULL) { | |
680 | if (p->data_type != OSSL_PARAM_UTF8_STRING) | |
681 | return 0; | |
682 | propquery = (const char *)p->data; | |
683 | } | |
684 | ||
685 | if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_CIPHER)) != NULL) { | |
686 | const char *base = (const char *)p->data; | |
3262300a RL |
687 | size_t ctr_str_len = sizeof("CTR") - 1; |
688 | size_t ecb_str_len = sizeof("ECB") - 1; | |
28bdbe1a | 689 | |
f000e828 | 690 | if (p->data_type != OSSL_PARAM_UTF8_STRING |
3262300a | 691 | || p->data_size < ctr_str_len) |
dbdcc04f | 692 | return 0; |
3262300a | 693 | if (strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) { |
f000e828 P |
694 | ERR_raise(ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER); |
695 | return 0; | |
696 | } | |
3262300a | 697 | if ((ecb = OPENSSL_strndup(base, p->data_size)) == NULL) { |
f000e828 | 698 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
dbdcc04f | 699 | return 0; |
f000e828 | 700 | } |
3262300a | 701 | strcpy(ecb + p->data_size - ecb_str_len, "ECB"); |
f000e828 P |
702 | EVP_CIPHER_free(ctr->cipher_ecb); |
703 | EVP_CIPHER_free(ctr->cipher_ctr); | |
704 | ctr->cipher_ctr = EVP_CIPHER_fetch(libctx, base, propquery); | |
705 | ctr->cipher_ecb = EVP_CIPHER_fetch(libctx, ecb, propquery); | |
706 | OPENSSL_free(ecb); | |
707 | if (ctr->cipher_ctr == NULL || ctr->cipher_ecb == NULL) { | |
708 | ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_FIND_CIPHERS); | |
709 | return 0; | |
710 | } | |
711 | cipher_init = 1; | |
712 | } | |
75e2c877 | 713 | |
f000e828 | 714 | if (cipher_init && !drbg_ctr_init(ctx)) |
6c7d80ab | 715 | return 0; |
12fb8c3d | 716 | |
b24d6c33 | 717 | return ossl_drbg_set_ctx_params(ctx, params); |
f000e828 | 718 | } |
4917e911 | 719 | |
a3f091fd P |
720 | static const OSSL_PARAM *drbg_ctr_settable_ctx_params(ossl_unused void *vctx, |
721 | ossl_unused void *provctx) | |
f000e828 P |
722 | { |
723 | static const OSSL_PARAM known_settable_ctx_params[] = { | |
724 | OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0), | |
725 | OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0), | |
f000e828 | 726 | OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL), |
82a7b2fb | 727 | OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON, |
f000e828 P |
728 | OSSL_PARAM_END |
729 | }; | |
730 | return known_settable_ctx_params; | |
12fb8c3d | 731 | } |
f000e828 | 732 | |
1be63951 | 733 | const OSSL_DISPATCH ossl_drbg_ctr_functions[] = { |
f000e828 P |
734 | { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_ctr_new_wrapper }, |
735 | { OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_ctr_free }, | |
736 | { OSSL_FUNC_RAND_INSTANTIATE, | |
737 | (void(*)(void))drbg_ctr_instantiate_wrapper }, | |
738 | { OSSL_FUNC_RAND_UNINSTANTIATE, | |
739 | (void(*)(void))drbg_ctr_uninstantiate_wrapper }, | |
740 | { OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_ctr_generate_wrapper }, | |
741 | { OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_ctr_reseed_wrapper }, | |
b24d6c33 P |
742 | { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))ossl_drbg_enable_locking }, |
743 | { OSSL_FUNC_RAND_LOCK, (void(*)(void))ossl_drbg_lock }, | |
744 | { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))ossl_drbg_unlock }, | |
f000e828 P |
745 | { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS, |
746 | (void(*)(void))drbg_ctr_settable_ctx_params }, | |
747 | { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_ctr_set_ctx_params }, | |
748 | { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS, | |
749 | (void(*)(void))drbg_ctr_gettable_ctx_params }, | |
750 | { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_ctr_get_ctx_params }, | |
f000e828 P |
751 | { OSSL_FUNC_RAND_VERIFY_ZEROIZATION, |
752 | (void(*)(void))drbg_ctr_verify_zeroization }, | |
335e85f5 P |
753 | { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed }, |
754 | { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed }, | |
f000e828 P |
755 | { 0, NULL } |
756 | }; |