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