]> git.ipfire.org Git - thirdparty/openssl.git/blob - providers/implementations/rands/drbg_ctr.c
dbe57b0d2898df28da08d81901ec3ee225b98c68
[thirdparty/openssl.git] / providers / implementations / rands / drbg_ctr.c
1 /*
2 * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
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>
15 #include <openssl/aes.h>
16 #include <openssl/proverr.h>
17 #include "e_os.h" /* strcasecmp */
18 #include "crypto/modes.h"
19 #include "internal/thread_once.h"
20 #include "prov/implementations.h"
21 #include "prov/providercommon.h"
22 #include "prov/provider_ctx.h"
23 #include "drbg_local.h"
24
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;
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;
55
56 /*
57 * Implementation of NIST SP 800-90A CTR DRBG.
58 */
59 static void inc_128(PROV_DRBG_CTR *ctr)
60 {
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);
70 }
71
72 static void ctr_XOR(PROV_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
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 */
83 n = inlen < ctr->keylen ? inlen : ctr->keylen;
84 for (i = 0; i < n; i++)
85 ctr->K[i] ^= in[i];
86 if (inlen <= ctr->keylen)
87 return;
88
89 n = inlen - ctr->keylen;
90 if (n > 16) {
91 /* Should never happen */
92 n = 16;
93 }
94 for (i = 0; i < n; i++)
95 ctr->V[i] ^= in[i + ctr->keylen];
96 }
97
98 /*
99 * Process a complete block using BCC algorithm of SP 800-90A 10.3.3
100 */
101 __owur static int ctr_BCC_block(PROV_DRBG_CTR *ctr, unsigned char *out,
102 const unsigned char *in, int len)
103 {
104 int i, outlen = AES_BLOCK_SIZE;
105
106 for (i = 0; i < len; i++)
107 out[i] ^= in[i];
108
109 if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, len)
110 || outlen != len)
111 return 0;
112 return 1;
113 }
114
115
116 /*
117 * Handle several BCC operations for as much data as we need for K and X
118 */
119 __owur static int ctr_BCC_blocks(PROV_DRBG_CTR *ctr, const unsigned char *in)
120 {
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);
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 */
137 __owur static int ctr_BCC_init(PROV_DRBG_CTR *ctr)
138 {
139 unsigned char bltmp[48] = {0};
140 unsigned char num_of_blk;
141
142 memset(ctr->KX, 0, 48);
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);
147 }
148
149 /*
150 * Process several blocks into BCC algorithm, some possibly partial
151 */
152 __owur static int ctr_BCC_update(PROV_DRBG_CTR *ctr,
153 const unsigned char *in, size_t inlen)
154 {
155 if (in == NULL || inlen == 0)
156 return 1;
157
158 /* If we have partial block handle it first */
159 if (ctr->bltmp_pos) {
160 size_t left = 16 - ctr->bltmp_pos;
161
162 /* If we now have a complete block process it */
163 if (inlen >= left) {
164 memcpy(ctr->bltmp + ctr->bltmp_pos, in, left);
165 if (!ctr_BCC_blocks(ctr, ctr->bltmp))
166 return 0;
167 ctr->bltmp_pos = 0;
168 inlen -= left;
169 in += left;
170 }
171 }
172
173 /* Process zero or more complete blocks */
174 for (; inlen >= 16; in += 16, inlen -= 16) {
175 if (!ctr_BCC_blocks(ctr, in))
176 return 0;
177 }
178
179 /* Copy any remaining partial block to the temporary buffer */
180 if (inlen > 0) {
181 memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen);
182 ctr->bltmp_pos += inlen;
183 }
184 return 1;
185 }
186
187 __owur static int ctr_BCC_final(PROV_DRBG_CTR *ctr)
188 {
189 if (ctr->bltmp_pos) {
190 memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos);
191 if (!ctr_BCC_blocks(ctr, ctr->bltmp))
192 return 0;
193 }
194 return 1;
195 }
196
197 __owur static int ctr_df(PROV_DRBG_CTR *ctr,
198 const unsigned char *in1, size_t in1len,
199 const unsigned char *in2, size_t in2len,
200 const unsigned char *in3, size_t in3len)
201 {
202 static unsigned char c80 = 0x80;
203 size_t inlen;
204 unsigned char *p = ctr->bltmp;
205 int outlen = AES_BLOCK_SIZE;
206
207 if (!ctr_BCC_init(ctr))
208 return 0;
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;
226 *p = (unsigned char)((ctr->keylen + 16) & 0xff);
227 ctr->bltmp_pos = 8;
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;
234 /* Set up key K */
235 if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->KX, NULL, -1))
236 return 0;
237 /* X follows key K */
238 if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX, &outlen, ctr->KX + ctr->keylen,
239 AES_BLOCK_SIZE)
240 || outlen != AES_BLOCK_SIZE)
241 return 0;
242 if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 16, &outlen, ctr->KX,
243 AES_BLOCK_SIZE)
244 || outlen != AES_BLOCK_SIZE)
245 return 0;
246 if (ctr->keylen != 16)
247 if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 32, &outlen,
248 ctr->KX + 16, AES_BLOCK_SIZE)
249 || outlen != AES_BLOCK_SIZE)
250 return 0;
251 return 1;
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,
258 * so we handle both cases in this function instead.
259 */
260 __owur static int ctr_update(PROV_DRBG *drbg,
261 const unsigned char *in1, size_t in1len,
262 const unsigned char *in2, size_t in2len,
263 const unsigned char *nonce, size_t noncelen)
264 {
265 PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
266 int outlen = AES_BLOCK_SIZE;
267 unsigned char V_tmp[48], out[48];
268 unsigned char len;
269
270 /* correct key is already set up. */
271 memcpy(V_tmp, ctr->V, 16);
272 inc_128(ctr);
273 memcpy(V_tmp + 16, ctr->V, 16);
274 if (ctr->keylen == 16) {
275 len = 32;
276 } else {
277 inc_128(ctr);
278 memcpy(V_tmp + 32, ctr->V, 16);
279 len = 48;
280 }
281 if (!EVP_CipherUpdate(ctr->ctx_ecb, out, &outlen, V_tmp, len)
282 || outlen != len)
283 return 0;
284 memcpy(ctr->K, out, ctr->keylen);
285 memcpy(ctr->V, out + ctr->keylen, 16);
286
287 if (ctr->use_df) {
288 /* If no input reuse existing derived value */
289 if (in1 != NULL || nonce != NULL || in2 != NULL)
290 if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len))
291 return 0;
292 /* If this a reuse input in1len != 0 */
293 if (in1len)
294 ctr_XOR(ctr, ctr->KX, drbg->seedlen);
295 } else {
296 ctr_XOR(ctr, in1, in1len);
297 ctr_XOR(ctr, in2, in2len);
298 }
299
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))
302 return 0;
303 return 1;
304 }
305
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)
310 {
311 PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
312
313 if (entropy == NULL)
314 return 0;
315
316 memset(ctr->K, 0, sizeof(ctr->K));
317 memset(ctr->V, 0, sizeof(ctr->V));
318 if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1))
319 return 0;
320
321 inc_128(ctr);
322 if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen))
323 return 0;
324 return 1;
325 }
326
327 static int drbg_ctr_instantiate_wrapper(void *vdrbg, unsigned int strength,
328 int prediction_resistance,
329 const unsigned char *pstr,
330 size_t pstr_len,
331 const OSSL_PARAM params[])
332 {
333 PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
334
335 if (!ossl_prov_is_running() || !drbg_ctr_set_ctx_params(drbg, params))
336 return 0;
337 return ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance,
338 pstr, pstr_len);
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)
344 {
345 PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
346
347 if (entropy == NULL)
348 return 0;
349
350 inc_128(ctr);
351 if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0))
352 return 0;
353 return 1;
354 }
355
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
362 return ossl_prov_drbg_reseed(drbg, prediction_resistance, ent, ent_len,
363 adin, adin_len);
364 }
365
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
378 static int drbg_ctr_generate(PROV_DRBG *drbg,
379 unsigned char *out, size_t outlen,
380 const unsigned char *adin, size_t adinlen)
381 {
382 PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
383 unsigned int ctr32, blocks;
384 int outl, buflen;
385
386 if (adin != NULL && adinlen != 0) {
387 inc_128(ctr);
388
389 if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
390 return 0;
391 /* This means we reuse derived value */
392 if (ctr->use_df) {
393 adin = NULL;
394 adinlen = 1;
395 }
396 } else {
397 adinlen = 0;
398 }
399
400 inc_128(ctr);
401
402 if (outlen == 0) {
403 inc_128(ctr);
404
405 if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
406 return 0;
407 return 1;
408 }
409
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. */
430 if (ctr32 != 0) {
431 blocks -= ctr32;
432 buflen = blocks * 16;
433 ctr32 = 0;
434 }
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
447 if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
448 return 0;
449 return 1;
450 }
451
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)
456 {
457 PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
458
459 return ossl_prov_drbg_generate(drbg, out, outlen, strength,
460 prediction_resistance, adin, adin_len);
461 }
462
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;
472 return ossl_prov_drbg_uninstantiate(drbg);
473 }
474
475 static int drbg_ctr_uninstantiate_wrapper(void *vdrbg)
476 {
477 return drbg_ctr_uninstantiate((PROV_DRBG *)vdrbg);
478 }
479
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)
490 return 0;
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
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;
508
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;
530 size_t keylen;
531
532 if (ctr->cipher_ctr == NULL) {
533 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER);
534 return 0;
535 }
536 ctr->keylen = keylen = EVP_CIPHER_get_key_length(ctr->cipher_ctr);
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();
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
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 }
553
554 drbg->strength = keylen * 8;
555 drbg->seedlen = keylen + 16;
556
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;
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);
595 return 0;
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 {
606 return ossl_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_ctr_new,
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 }
625 ossl_rand_drbg_free(drbg);
626 }
627
628 static int drbg_ctr_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
629 {
630 PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
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
641 || !OSSL_PARAM_set_utf8_string(p,
642 EVP_CIPHER_get0_name(ctr->cipher_ctr)))
643 return 0;
644 }
645
646 return ossl_drbg_get_ctx_params(drbg, params);
647 }
648
649 static const OSSL_PARAM *drbg_ctr_gettable_ctx_params(ossl_unused void *vctx,
650 ossl_unused void *provctx)
651 {
652 static const OSSL_PARAM known_gettable_ctx_params[] = {
653 OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0),
654 OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL),
655 OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON,
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;
665 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
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;
687 size_t ctr_str_len = sizeof("CTR") - 1;
688 size_t ecb_str_len = sizeof("ECB") - 1;
689
690 if (p->data_type != OSSL_PARAM_UTF8_STRING
691 || p->data_size < ctr_str_len)
692 return 0;
693 if (strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) {
694 ERR_raise(ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER);
695 return 0;
696 }
697 if ((ecb = OPENSSL_strndup(base, p->data_size)) == NULL) {
698 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
699 return 0;
700 }
701 strcpy(ecb + p->data_size - ecb_str_len, "ECB");
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 }
713
714 if (cipher_init && !drbg_ctr_init(ctx))
715 return 0;
716
717 return ossl_drbg_set_ctx_params(ctx, params);
718 }
719
720 static const OSSL_PARAM *drbg_ctr_settable_ctx_params(ossl_unused void *vctx,
721 ossl_unused void *provctx)
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),
726 OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL),
727 OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON,
728 OSSL_PARAM_END
729 };
730 return known_settable_ctx_params;
731 }
732
733 const OSSL_DISPATCH ossl_drbg_ctr_functions[] = {
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 },
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 },
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 },
751 { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
752 (void(*)(void))drbg_ctr_verify_zeroization },
753 { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
754 { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
755 { 0, NULL }
756 };