]> git.ipfire.org Git - thirdparty/openssl.git/blame - providers/implementations/rands/drbg_ctr.c
Replaced '{ 0, NULL }' with OSSL_DISPATCH_END in OSSL_DISPATCH arrays
[thirdparty/openssl.git] / providers / implementations / rands / drbg_ctr.c
CommitLineData
12fb8c3d 1/*
fecb3aae 2 * Copyright 2011-2022 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>
28bdbe1a 17#include "crypto/modes.h"
12fb8c3d 18#include "internal/thread_once.h"
f000e828 19#include "prov/implementations.h"
b98d550d 20#include "prov/providercommon.h"
f000e828 21#include "prov/provider_ctx.h"
f000e828
P
22#include "drbg_local.h"
23
363b1e5d
DMSP
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;
f000e828
P
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;
8bf36651 54
12fb8c3d 55/*
75e2c877 56 * Implementation of NIST SP 800-90A CTR DRBG.
12fb8c3d 57 */
f000e828 58static void inc_128(PROV_DRBG_CTR *ctr)
12fb8c3d 59{
069165d1
PS
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);
12fb8c3d
RS
69}
70
f000e828 71static void ctr_XOR(PROV_DRBG_CTR *ctr, const unsigned char *in, size_t inlen)
12fb8c3d
RS
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 */
75e2c877 82 n = inlen < ctr->keylen ? inlen : ctr->keylen;
12fb8c3d 83 for (i = 0; i < n; i++)
75e2c877
RS
84 ctr->K[i] ^= in[i];
85 if (inlen <= ctr->keylen)
12fb8c3d
RS
86 return;
87
75e2c877 88 n = inlen - ctr->keylen;
12fb8c3d
RS
89 if (n > 16) {
90 /* Should never happen */
91 n = 16;
92 }
b8a437ff 93 for (i = 0; i < n; i++)
75e2c877 94 ctr->V[i] ^= in[i + ctr->keylen];
12fb8c3d
RS
95}
96
97/*
98 * Process a complete block using BCC algorithm of SP 800-90A 10.3.3
99 */
f000e828 100__owur static int ctr_BCC_block(PROV_DRBG_CTR *ctr, unsigned char *out,
28bdbe1a 101 const unsigned char *in, int len)
12fb8c3d 102{
dbdcc04f 103 int i, outlen = AES_BLOCK_SIZE;
12fb8c3d 104
28bdbe1a 105 for (i = 0; i < len; i++)
12fb8c3d 106 out[i] ^= in[i];
dbdcc04f 107
28bdbe1a
PS
108 if (!EVP_CipherUpdate(ctr->ctx_df, out, &outlen, out, len)
109 || outlen != len)
dbdcc04f
KR
110 return 0;
111 return 1;
12fb8c3d
RS
112}
113
114
115/*
116 * Handle several BCC operations for as much data as we need for K and X
117 */
f000e828 118__owur static int ctr_BCC_blocks(PROV_DRBG_CTR *ctr, const unsigned char *in)
12fb8c3d 119{
28bdbe1a
PS
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);
12fb8c3d
RS
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 */
f000e828 136__owur static int ctr_BCC_init(PROV_DRBG_CTR *ctr)
12fb8c3d 137{
28bdbe1a
PS
138 unsigned char bltmp[48] = {0};
139 unsigned char num_of_blk;
140
75e2c877 141 memset(ctr->KX, 0, 48);
28bdbe1a
PS
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);
12fb8c3d
RS
146}
147
148/*
149 * Process several blocks into BCC algorithm, some possibly partial
150 */
f000e828 151__owur static int ctr_BCC_update(PROV_DRBG_CTR *ctr,
dbdcc04f 152 const unsigned char *in, size_t inlen)
12fb8c3d
RS
153{
154 if (in == NULL || inlen == 0)
dbdcc04f 155 return 1;
12fb8c3d
RS
156
157 /* If we have partial block handle it first */
75e2c877
RS
158 if (ctr->bltmp_pos) {
159 size_t left = 16 - ctr->bltmp_pos;
12fb8c3d
RS
160
161 /* If we now have a complete block process it */
162 if (inlen >= left) {
75e2c877 163 memcpy(ctr->bltmp + ctr->bltmp_pos, in, left);
dbdcc04f
KR
164 if (!ctr_BCC_blocks(ctr, ctr->bltmp))
165 return 0;
75e2c877 166 ctr->bltmp_pos = 0;
12fb8c3d
RS
167 inlen -= left;
168 in += left;
169 }
170 }
171
172 /* Process zero or more complete blocks */
173 for (; inlen >= 16; in += 16, inlen -= 16) {
dbdcc04f
KR
174 if (!ctr_BCC_blocks(ctr, in))
175 return 0;
12fb8c3d
RS
176 }
177
178 /* Copy any remaining partial block to the temporary buffer */
179 if (inlen > 0) {
75e2c877
RS
180 memcpy(ctr->bltmp + ctr->bltmp_pos, in, inlen);
181 ctr->bltmp_pos += inlen;
12fb8c3d 182 }
dbdcc04f 183 return 1;
12fb8c3d
RS
184}
185
f000e828 186__owur static int ctr_BCC_final(PROV_DRBG_CTR *ctr)
12fb8c3d 187{
75e2c877
RS
188 if (ctr->bltmp_pos) {
189 memset(ctr->bltmp + ctr->bltmp_pos, 0, 16 - ctr->bltmp_pos);
dbdcc04f
KR
190 if (!ctr_BCC_blocks(ctr, ctr->bltmp))
191 return 0;
12fb8c3d 192 }
dbdcc04f 193 return 1;
12fb8c3d
RS
194}
195
f000e828 196__owur static int ctr_df(PROV_DRBG_CTR *ctr,
dbdcc04f
KR
197 const unsigned char *in1, size_t in1len,
198 const unsigned char *in2, size_t in2len,
199 const unsigned char *in3, size_t in3len)
12fb8c3d
RS
200{
201 static unsigned char c80 = 0x80;
202 size_t inlen;
75e2c877 203 unsigned char *p = ctr->bltmp;
dbdcc04f 204 int outlen = AES_BLOCK_SIZE;
12fb8c3d 205
dbdcc04f
KR
206 if (!ctr_BCC_init(ctr))
207 return 0;
12fb8c3d
RS
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;
75e2c877
RS
225 *p = (unsigned char)((ctr->keylen + 16) & 0xff);
226 ctr->bltmp_pos = 8;
dbdcc04f
KR
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;
12fb8c3d 233 /* Set up key K */
28bdbe1a 234 if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->KX, NULL, -1))
dbdcc04f 235 return 0;
12fb8c3d 236 /* X follows key K */
28bdbe1a 237 if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX, &outlen, ctr->KX + ctr->keylen,
dbdcc04f
KR
238 AES_BLOCK_SIZE)
239 || outlen != AES_BLOCK_SIZE)
240 return 0;
28bdbe1a 241 if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 16, &outlen, ctr->KX,
dbdcc04f
KR
242 AES_BLOCK_SIZE)
243 || outlen != AES_BLOCK_SIZE)
244 return 0;
75e2c877 245 if (ctr->keylen != 16)
28bdbe1a
PS
246 if (!EVP_CipherUpdate(ctr->ctx_ecb, ctr->KX + 32, &outlen,
247 ctr->KX + 16, AES_BLOCK_SIZE)
dbdcc04f
KR
248 || outlen != AES_BLOCK_SIZE)
249 return 0;
250 return 1;
12fb8c3d
RS
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,
75e2c877 257 * so we handle both cases in this function instead.
12fb8c3d 258 */
f000e828 259__owur static int ctr_update(PROV_DRBG *drbg,
dbdcc04f
KR
260 const unsigned char *in1, size_t in1len,
261 const unsigned char *in2, size_t in2len,
262 const unsigned char *nonce, size_t noncelen)
12fb8c3d 263{
f000e828 264 PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
dbdcc04f 265 int outlen = AES_BLOCK_SIZE;
28bdbe1a
PS
266 unsigned char V_tmp[48], out[48];
267 unsigned char len;
12fb8c3d 268
dbdcc04f 269 /* correct key is already set up. */
28bdbe1a 270 memcpy(V_tmp, ctr->V, 16);
75e2c877 271 inc_128(ctr);
28bdbe1a
PS
272 memcpy(V_tmp + 16, ctr->V, 16);
273 if (ctr->keylen == 16) {
274 len = 32;
275 } else {
75e2c877 276 inc_128(ctr);
28bdbe1a
PS
277 memcpy(V_tmp + 32, ctr->V, 16);
278 len = 48;
12fb8c3d 279 }
28bdbe1a
PS
280 if (!EVP_CipherUpdate(ctr->ctx_ecb, out, &outlen, V_tmp, len)
281 || outlen != len)
dbdcc04f 282 return 0;
28bdbe1a
PS
283 memcpy(ctr->K, out, ctr->keylen);
284 memcpy(ctr->V, out + ctr->keylen, 16);
12fb8c3d 285
f000e828 286 if (ctr->use_df) {
12fb8c3d
RS
287 /* If no input reuse existing derived value */
288 if (in1 != NULL || nonce != NULL || in2 != NULL)
dbdcc04f
KR
289 if (!ctr_df(ctr, in1, in1len, nonce, noncelen, in2, in2len))
290 return 0;
12fb8c3d
RS
291 /* If this a reuse input in1len != 0 */
292 if (in1len)
75e2c877 293 ctr_XOR(ctr, ctr->KX, drbg->seedlen);
12fb8c3d 294 } else {
75e2c877
RS
295 ctr_XOR(ctr, in1, in1len);
296 ctr_XOR(ctr, in2, in2len);
12fb8c3d
RS
297 }
298
28bdbe1a
PS
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))
dbdcc04f
KR
301 return 0;
302 return 1;
12fb8c3d
RS
303}
304
f000e828
P
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)
12fb8c3d 309{
f000e828 310 PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
12fb8c3d 311
aa048aef 312 if (entropy == NULL)
4c78ba59
DSH
313 return 0;
314
75e2c877
RS
315 memset(ctr->K, 0, sizeof(ctr->K));
316 memset(ctr->V, 0, sizeof(ctr->V));
28bdbe1a 317 if (!EVP_CipherInit_ex(ctr->ctx_ecb, NULL, NULL, ctr->K, NULL, -1))
dbdcc04f 318 return 0;
28bdbe1a
PS
319
320 inc_128(ctr);
dbdcc04f
KR
321 if (!ctr_update(drbg, entropy, entropylen, pers, perslen, nonce, noncelen))
322 return 0;
12fb8c3d
RS
323 return 1;
324}
325
f000e828
P
326static int drbg_ctr_instantiate_wrapper(void *vdrbg, unsigned int strength,
327 int prediction_resistance,
328 const unsigned char *pstr,
b98d550d
P
329 size_t pstr_len,
330 const OSSL_PARAM params[])
f000e828
P
331{
332 PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
333
b98d550d
P
334 if (!ossl_prov_is_running() || !drbg_ctr_set_ctx_params(drbg, params))
335 return 0;
7d6766cb
P
336 return ossl_prov_drbg_instantiate(drbg, strength, prediction_resistance,
337 pstr, pstr_len);
f000e828
P
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)
12fb8c3d 343{
f000e828 344 PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
28bdbe1a 345
aa048aef 346 if (entropy == NULL)
4c78ba59 347 return 0;
28bdbe1a
PS
348
349 inc_128(ctr);
dbdcc04f
KR
350 if (!ctr_update(drbg, entropy, entropylen, adin, adinlen, NULL, 0))
351 return 0;
12fb8c3d
RS
352 return 1;
353}
354
f000e828
P
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
7d6766cb
P
361 return ossl_prov_drbg_reseed(drbg, prediction_resistance, ent, ent_len,
362 adin, adin_len);
f000e828
P
363}
364
28bdbe1a
PS
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
f000e828
P
377static int drbg_ctr_generate(PROV_DRBG *drbg,
378 unsigned char *out, size_t outlen,
379 const unsigned char *adin, size_t adinlen)
12fb8c3d 380{
f000e828 381 PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
28bdbe1a
PS
382 unsigned int ctr32, blocks;
383 int outl, buflen;
12fb8c3d
RS
384
385 if (adin != NULL && adinlen != 0) {
28bdbe1a
PS
386 inc_128(ctr);
387
dbdcc04f
KR
388 if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
389 return 0;
12fb8c3d 390 /* This means we reuse derived value */
f000e828 391 if (ctr->use_df) {
12fb8c3d
RS
392 adin = NULL;
393 adinlen = 1;
394 }
395 } else {
396 adinlen = 0;
397 }
398
28bdbe1a 399 inc_128(ctr);
dbdcc04f 400
28bdbe1a 401 if (outlen == 0) {
75e2c877 402 inc_128(ctr);
28bdbe1a
PS
403
404 if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
dbdcc04f 405 return 0;
28bdbe1a 406 return 1;
12fb8c3d
RS
407 }
408
28bdbe1a
PS
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. */
42fa3e66
BE
429 if (ctr32 != 0) {
430 blocks -= ctr32;
431 buflen = blocks * 16;
432 ctr32 = 0;
433 }
28bdbe1a
PS
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
dbdcc04f
KR
446 if (!ctr_update(drbg, adin, adinlen, NULL, 0, NULL, 0))
447 return 0;
12fb8c3d
RS
448 return 1;
449}
450
f000e828
P
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)
12fb8c3d 455{
f000e828
P
456 PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
457
7d6766cb
P
458 return ossl_prov_drbg_generate(drbg, out, outlen, strength,
459 prediction_resistance, adin, adin_len);
12fb8c3d
RS
460}
461
f000e828
P
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;
7d6766cb 471 return ossl_prov_drbg_uninstantiate(drbg);
f000e828 472}
8212d505 473
f000e828 474static int drbg_ctr_uninstantiate_wrapper(void *vdrbg)
12fb8c3d 475{
f000e828
P
476 return drbg_ctr_uninstantiate((PROV_DRBG *)vdrbg);
477}
12fb8c3d 478
f000e828
P
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)
efb8128a 489 return 0;
f000e828
P
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
f000e828
P
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;
57ca171a 507
f000e828
P
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;
2f142901 529 size_t keylen;
8212d505 530
2f142901
P
531 if (ctr->cipher_ctr == NULL) {
532 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CIPHER);
533 return 0;
534 }
ed576acd 535 ctr->keylen = keylen = EVP_CIPHER_get_key_length(ctr->cipher_ctr);
28bdbe1a
PS
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();
f000e828 540 if (ctr->ctx_ecb == NULL || ctr->ctx_ctr == NULL) {
e077455e 541 ERR_raise(ERR_LIB_PROV, ERR_R_EVP_LIB);
f000e828
P
542 goto err;
543 }
544
2f142901
P
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 }
f000e828 552
2f142901
P
553 drbg->strength = keylen * 8;
554 drbg->seedlen = keylen + 16;
f000e828 555
2f142901
P
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) {
e077455e 568 ERR_raise(ERR_LIB_PROV, ERR_R_EVP_LIB);
2f142901
P
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;
f000e828
P
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));
e077455e 592 if (ctr == NULL)
dbdcc04f 593 return 0;
f000e828
P
594
595 ctr->use_df = 1;
596 drbg->data = ctr;
597 return drbg_ctr_init_lengths(drbg);
598}
599
600static void *drbg_ctr_new_wrapper(void *provctx, void *parent,
601 const OSSL_DISPATCH *parent_dispatch)
602{
1dc188ba 603 return ossl_rand_drbg_new(provctx, parent, parent_dispatch, &drbg_ctr_new,
f000e828
P
604 &drbg_ctr_instantiate, &drbg_ctr_uninstantiate,
605 &drbg_ctr_reseed, &drbg_ctr_generate);
606}
607
608static void drbg_ctr_free(void *vdrbg)
609{
610 PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
611 PROV_DRBG_CTR *ctr;
612
613 if (drbg != NULL && (ctr = (PROV_DRBG_CTR *)drbg->data) != NULL) {
614 EVP_CIPHER_CTX_free(ctr->ctx_ecb);
615 EVP_CIPHER_CTX_free(ctr->ctx_ctr);
616 EVP_CIPHER_CTX_free(ctr->ctx_df);
617 EVP_CIPHER_free(ctr->cipher_ecb);
618 EVP_CIPHER_free(ctr->cipher_ctr);
619
620 OPENSSL_secure_clear_free(ctr, sizeof(*ctr));
621 }
1dc188ba 622 ossl_rand_drbg_free(drbg);
f000e828
P
623}
624
625static int drbg_ctr_get_ctx_params(void *vdrbg, OSSL_PARAM params[])
626{
627 PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
0ed26fb6
P
628 PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)drbg->data;
629 OSSL_PARAM *p;
630
631 p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_USE_DF);
632 if (p != NULL && !OSSL_PARAM_set_int(p, ctr->use_df))
633 return 0;
634
635 p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_CIPHER);
636 if (p != NULL) {
637 if (ctr->cipher_ctr == NULL
ed576acd
TM
638 || !OSSL_PARAM_set_utf8_string(p,
639 EVP_CIPHER_get0_name(ctr->cipher_ctr)))
0ed26fb6
P
640 return 0;
641 }
f000e828 642
b24d6c33 643 return ossl_drbg_get_ctx_params(drbg, params);
f000e828
P
644}
645
a3f091fd
P
646static const OSSL_PARAM *drbg_ctr_gettable_ctx_params(ossl_unused void *vctx,
647 ossl_unused void *provctx)
f000e828
P
648{
649 static const OSSL_PARAM known_gettable_ctx_params[] = {
0ed26fb6
P
650 OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0),
651 OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL),
82a7b2fb 652 OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON,
f000e828
P
653 OSSL_PARAM_END
654 };
655 return known_gettable_ctx_params;
656}
657
658static int drbg_ctr_set_ctx_params(void *vctx, const OSSL_PARAM params[])
659{
660 PROV_DRBG *ctx = (PROV_DRBG *)vctx;
661 PROV_DRBG_CTR *ctr = (PROV_DRBG_CTR *)ctx->data;
a829b735 662 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
f000e828
P
663 const OSSL_PARAM *p;
664 char *ecb;
665 const char *propquery = NULL;
666 int i, cipher_init = 0;
667
668 if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_USE_DF)) != NULL
669 && OSSL_PARAM_get_int(p, &i)) {
670 /* FIPS errors out in the drbg_ctr_init() call later */
671 ctr->use_df = i != 0;
672 cipher_init = 1;
673 }
674
675 if ((p = OSSL_PARAM_locate_const(params,
676 OSSL_DRBG_PARAM_PROPERTIES)) != NULL) {
677 if (p->data_type != OSSL_PARAM_UTF8_STRING)
678 return 0;
679 propquery = (const char *)p->data;
680 }
681
682 if ((p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_CIPHER)) != NULL) {
683 const char *base = (const char *)p->data;
3262300a
RL
684 size_t ctr_str_len = sizeof("CTR") - 1;
685 size_t ecb_str_len = sizeof("ECB") - 1;
28bdbe1a 686
f000e828 687 if (p->data_type != OSSL_PARAM_UTF8_STRING
3262300a 688 || p->data_size < ctr_str_len)
dbdcc04f 689 return 0;
fba140c7 690 if (OPENSSL_strcasecmp("CTR", base + p->data_size - ctr_str_len) != 0) {
f000e828
P
691 ERR_raise(ERR_LIB_PROV, PROV_R_REQUIRE_CTR_MODE_CIPHER);
692 return 0;
693 }
e077455e 694 if ((ecb = OPENSSL_strndup(base, p->data_size)) == NULL)
dbdcc04f 695 return 0;
3262300a 696 strcpy(ecb + p->data_size - ecb_str_len, "ECB");
f000e828
P
697 EVP_CIPHER_free(ctr->cipher_ecb);
698 EVP_CIPHER_free(ctr->cipher_ctr);
699 ctr->cipher_ctr = EVP_CIPHER_fetch(libctx, base, propquery);
700 ctr->cipher_ecb = EVP_CIPHER_fetch(libctx, ecb, propquery);
701 OPENSSL_free(ecb);
702 if (ctr->cipher_ctr == NULL || ctr->cipher_ecb == NULL) {
703 ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_FIND_CIPHERS);
704 return 0;
705 }
706 cipher_init = 1;
707 }
75e2c877 708
f000e828 709 if (cipher_init && !drbg_ctr_init(ctx))
6c7d80ab 710 return 0;
12fb8c3d 711
b24d6c33 712 return ossl_drbg_set_ctx_params(ctx, params);
f000e828 713}
4917e911 714
a3f091fd
P
715static const OSSL_PARAM *drbg_ctr_settable_ctx_params(ossl_unused void *vctx,
716 ossl_unused void *provctx)
f000e828
P
717{
718 static const OSSL_PARAM known_settable_ctx_params[] = {
719 OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0),
720 OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0),
f000e828 721 OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL),
82a7b2fb 722 OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON,
f000e828
P
723 OSSL_PARAM_END
724 };
725 return known_settable_ctx_params;
12fb8c3d 726}
f000e828 727
1be63951 728const OSSL_DISPATCH ossl_drbg_ctr_functions[] = {
f000e828
P
729 { OSSL_FUNC_RAND_NEWCTX, (void(*)(void))drbg_ctr_new_wrapper },
730 { OSSL_FUNC_RAND_FREECTX, (void(*)(void))drbg_ctr_free },
731 { OSSL_FUNC_RAND_INSTANTIATE,
732 (void(*)(void))drbg_ctr_instantiate_wrapper },
733 { OSSL_FUNC_RAND_UNINSTANTIATE,
734 (void(*)(void))drbg_ctr_uninstantiate_wrapper },
735 { OSSL_FUNC_RAND_GENERATE, (void(*)(void))drbg_ctr_generate_wrapper },
736 { OSSL_FUNC_RAND_RESEED, (void(*)(void))drbg_ctr_reseed_wrapper },
b24d6c33
P
737 { OSSL_FUNC_RAND_ENABLE_LOCKING, (void(*)(void))ossl_drbg_enable_locking },
738 { OSSL_FUNC_RAND_LOCK, (void(*)(void))ossl_drbg_lock },
739 { OSSL_FUNC_RAND_UNLOCK, (void(*)(void))ossl_drbg_unlock },
f000e828
P
740 { OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS,
741 (void(*)(void))drbg_ctr_settable_ctx_params },
742 { OSSL_FUNC_RAND_SET_CTX_PARAMS, (void(*)(void))drbg_ctr_set_ctx_params },
743 { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
744 (void(*)(void))drbg_ctr_gettable_ctx_params },
745 { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))drbg_ctr_get_ctx_params },
f000e828
P
746 { OSSL_FUNC_RAND_VERIFY_ZEROIZATION,
747 (void(*)(void))drbg_ctr_verify_zeroization },
335e85f5
P
748 { OSSL_FUNC_RAND_GET_SEED, (void(*)(void))ossl_drbg_get_seed },
749 { OSSL_FUNC_RAND_CLEAR_SEED, (void(*)(void))ossl_drbg_clear_seed },
1e6bd31e 750 OSSL_DISPATCH_END
f000e828 751};