VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.0/providers/implementations/rands/drbg_ctr.c@ 100947

Last change on this file since 100947 was 99366, checked in by vboxsync, 22 months ago

openssl-3.1.0: Applied and adjusted our OpenSSL changes to 3.0.7. bugref:10418

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette