1 | /*
|
---|
2 | * Copyright 2011-2023 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 <string.h>
|
---|
11 | #include <openssl/crypto.h>
|
---|
12 | #include <openssl/err.h>
|
---|
13 | #include <openssl/rand.h>
|
---|
14 | #include <openssl/evp.h>
|
---|
15 | #include "crypto/rand.h"
|
---|
16 | #include <openssl/proverr.h>
|
---|
17 | #include "drbg_local.h"
|
---|
18 | #include "internal/thread_once.h"
|
---|
19 | #include "crypto/cryptlib.h"
|
---|
20 | #include "prov/seeding.h"
|
---|
21 | #include "crypto/rand_pool.h"
|
---|
22 | #include "prov/provider_ctx.h"
|
---|
23 | #include "prov/providercommon.h"
|
---|
24 | #include "prov/fipscommon.h"
|
---|
25 | #include "crypto/context.h"
|
---|
26 |
|
---|
27 | /*
|
---|
28 | * Support framework for NIST SP 800-90A DRBG
|
---|
29 | *
|
---|
30 | * See manual page PROV_DRBG(7) for a general overview.
|
---|
31 | *
|
---|
32 | * The OpenSSL model is to have new and free functions, and that new
|
---|
33 | * does all initialization. That is not the NIST model, which has
|
---|
34 | * instantiation and un-instantiate, and re-use within a new/free
|
---|
35 | * lifecycle. (No doubt this comes from the desire to support hardware
|
---|
36 | * DRBG, where allocation of resources on something like an HSM is
|
---|
37 | * a much bigger deal than just re-setting an allocated resource.)
|
---|
38 | */
|
---|
39 |
|
---|
40 | /* NIST SP 800-90A DRBG recommends the use of a personalization string. */
|
---|
41 | static const char ossl_pers_string[] = DRBG_DEFAULT_PERS_STRING;
|
---|
42 |
|
---|
43 | static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,
|
---|
44 | int function);
|
---|
45 |
|
---|
46 | static int rand_drbg_restart(PROV_DRBG *drbg);
|
---|
47 |
|
---|
48 | int ossl_drbg_lock(void *vctx)
|
---|
49 | {
|
---|
50 | PROV_DRBG *drbg = vctx;
|
---|
51 |
|
---|
52 | if (drbg == NULL || drbg->lock == NULL)
|
---|
53 | return 1;
|
---|
54 | return CRYPTO_THREAD_write_lock(drbg->lock);
|
---|
55 | }
|
---|
56 |
|
---|
57 | void ossl_drbg_unlock(void *vctx)
|
---|
58 | {
|
---|
59 | PROV_DRBG *drbg = vctx;
|
---|
60 |
|
---|
61 | if (drbg != NULL && drbg->lock != NULL)
|
---|
62 | CRYPTO_THREAD_unlock(drbg->lock);
|
---|
63 | }
|
---|
64 |
|
---|
65 | static int ossl_drbg_lock_parent(PROV_DRBG *drbg)
|
---|
66 | {
|
---|
67 | void *parent = drbg->parent;
|
---|
68 |
|
---|
69 | if (parent != NULL
|
---|
70 | && drbg->parent_lock != NULL
|
---|
71 | && !drbg->parent_lock(parent)) {
|
---|
72 | ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);
|
---|
73 | return 0;
|
---|
74 | }
|
---|
75 | return 1;
|
---|
76 | }
|
---|
77 |
|
---|
78 | static void ossl_drbg_unlock_parent(PROV_DRBG *drbg)
|
---|
79 | {
|
---|
80 | void *parent = drbg->parent;
|
---|
81 |
|
---|
82 | if (parent != NULL && drbg->parent_unlock != NULL)
|
---|
83 | drbg->parent_unlock(parent);
|
---|
84 | }
|
---|
85 |
|
---|
86 | static int get_parent_strength(PROV_DRBG *drbg, unsigned int *str)
|
---|
87 | {
|
---|
88 | OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
---|
89 | void *parent = drbg->parent;
|
---|
90 | int res;
|
---|
91 |
|
---|
92 | if (drbg->parent_get_ctx_params == NULL) {
|
---|
93 | ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH);
|
---|
94 | return 0;
|
---|
95 | }
|
---|
96 |
|
---|
97 | *params = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, str);
|
---|
98 | if (!ossl_drbg_lock_parent(drbg)) {
|
---|
99 | ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT);
|
---|
100 | return 0;
|
---|
101 | }
|
---|
102 | res = drbg->parent_get_ctx_params(parent, params);
|
---|
103 | ossl_drbg_unlock_parent(drbg);
|
---|
104 | if (!res) {
|
---|
105 | ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PARENT_STRENGTH);
|
---|
106 | return 0;
|
---|
107 | }
|
---|
108 | return 1;
|
---|
109 | }
|
---|
110 |
|
---|
111 | static unsigned int get_parent_reseed_count(PROV_DRBG *drbg)
|
---|
112 | {
|
---|
113 | OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
---|
114 | void *parent = drbg->parent;
|
---|
115 | unsigned int r = 0;
|
---|
116 |
|
---|
117 | *params = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_COUNTER, &r);
|
---|
118 | if (!ossl_drbg_lock_parent(drbg)) {
|
---|
119 | ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOCK_PARENT);
|
---|
120 | goto err;
|
---|
121 | }
|
---|
122 | if (!drbg->parent_get_ctx_params(parent, params))
|
---|
123 | r = 0;
|
---|
124 | ossl_drbg_unlock_parent(drbg);
|
---|
125 | return r;
|
---|
126 |
|
---|
127 | err:
|
---|
128 | r = tsan_load(&drbg->reseed_counter) - 2;
|
---|
129 | if (r == 0)
|
---|
130 | r = UINT_MAX;
|
---|
131 | return r;
|
---|
132 | }
|
---|
133 |
|
---|
134 | /*
|
---|
135 | * Implements the get_entropy() callback
|
---|
136 | *
|
---|
137 | * If the DRBG has a parent, then the required amount of entropy input
|
---|
138 | * is fetched using the parent's ossl_prov_drbg_generate().
|
---|
139 | *
|
---|
140 | * Otherwise, the entropy is polled from the system entropy sources
|
---|
141 | * using ossl_pool_acquire_entropy().
|
---|
142 | *
|
---|
143 | * If a random pool has been added to the DRBG using RAND_add(), then
|
---|
144 | * its entropy will be used up first.
|
---|
145 | */
|
---|
146 | size_t ossl_drbg_get_seed(void *vdrbg, unsigned char **pout,
|
---|
147 | int entropy, size_t min_len,
|
---|
148 | size_t max_len, int prediction_resistance,
|
---|
149 | const unsigned char *adin, size_t adin_len)
|
---|
150 | {
|
---|
151 | PROV_DRBG *drbg = (PROV_DRBG *)vdrbg;
|
---|
152 | size_t bytes_needed;
|
---|
153 | unsigned char *buffer;
|
---|
154 |
|
---|
155 | /* Figure out how many bytes we need */
|
---|
156 | bytes_needed = entropy >= 0 ? (entropy + 7) / 8 : 0;
|
---|
157 | if (bytes_needed < min_len)
|
---|
158 | bytes_needed = min_len;
|
---|
159 | if (bytes_needed > max_len)
|
---|
160 | bytes_needed = max_len;
|
---|
161 |
|
---|
162 | /* Allocate storage */
|
---|
163 | buffer = OPENSSL_secure_malloc(bytes_needed);
|
---|
164 | if (buffer == NULL) {
|
---|
165 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
---|
166 | return 0;
|
---|
167 | }
|
---|
168 |
|
---|
169 | /*
|
---|
170 | * Get random data. Include our DRBG address as
|
---|
171 | * additional input, in order to provide a distinction between
|
---|
172 | * different DRBG child instances.
|
---|
173 | *
|
---|
174 | * Note: using the sizeof() operator on a pointer triggers
|
---|
175 | * a warning in some static code analyzers, but it's
|
---|
176 | * intentional and correct here.
|
---|
177 | */
|
---|
178 | if (!ossl_prov_drbg_generate(drbg, buffer, bytes_needed,
|
---|
179 | drbg->strength, prediction_resistance,
|
---|
180 | (unsigned char *)&drbg, sizeof(drbg))) {
|
---|
181 | OPENSSL_secure_clear_free(buffer, bytes_needed);
|
---|
182 | ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);
|
---|
183 | return 0;
|
---|
184 | }
|
---|
185 | *pout = buffer;
|
---|
186 | return bytes_needed;
|
---|
187 | }
|
---|
188 |
|
---|
189 | /* Implements the cleanup_entropy() callback */
|
---|
190 | void ossl_drbg_clear_seed(ossl_unused void *vdrbg,
|
---|
191 | unsigned char *out, size_t outlen)
|
---|
192 | {
|
---|
193 | OPENSSL_secure_clear_free(out, outlen);
|
---|
194 | }
|
---|
195 |
|
---|
196 | static size_t get_entropy(PROV_DRBG *drbg, unsigned char **pout, int entropy,
|
---|
197 | size_t min_len, size_t max_len,
|
---|
198 | int prediction_resistance)
|
---|
199 | {
|
---|
200 | size_t bytes;
|
---|
201 | unsigned int p_str;
|
---|
202 |
|
---|
203 | if (drbg->parent == NULL)
|
---|
204 | #ifdef FIPS_MODULE
|
---|
205 | return ossl_crngt_get_entropy(drbg, pout, entropy, min_len, max_len,
|
---|
206 | prediction_resistance);
|
---|
207 | #else
|
---|
208 | return ossl_prov_get_entropy(drbg->provctx, pout, entropy, min_len,
|
---|
209 | max_len);
|
---|
210 | #endif
|
---|
211 |
|
---|
212 | if (drbg->parent_get_seed == NULL) {
|
---|
213 | ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_CANNOT_SUPPLY_ENTROPY_SEED);
|
---|
214 | return 0;
|
---|
215 | }
|
---|
216 | if (!get_parent_strength(drbg, &p_str))
|
---|
217 | return 0;
|
---|
218 | if (drbg->strength > p_str) {
|
---|
219 | /*
|
---|
220 | * We currently don't support the algorithm from NIST SP 800-90C
|
---|
221 | * 10.1.2 to use a weaker DRBG as source
|
---|
222 | */
|
---|
223 | ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);
|
---|
224 | return 0;
|
---|
225 | }
|
---|
226 |
|
---|
227 | /*
|
---|
228 | * Our lock is already held, but we need to lock our parent before
|
---|
229 | * generating bits from it. Note: taking the lock will be a no-op
|
---|
230 | * if locking is not required (while drbg->parent->lock == NULL).
|
---|
231 | */
|
---|
232 | if (!ossl_drbg_lock_parent(drbg))
|
---|
233 | return 0;
|
---|
234 | /*
|
---|
235 | * Get random data from parent. Include our DRBG address as
|
---|
236 | * additional input, in order to provide a distinction between
|
---|
237 | * different DRBG child instances.
|
---|
238 | *
|
---|
239 | * Note: using the sizeof() operator on a pointer triggers
|
---|
240 | * a warning in some static code analyzers, but it's
|
---|
241 | * intentional and correct here.
|
---|
242 | */
|
---|
243 | bytes = drbg->parent_get_seed(drbg->parent, pout, drbg->strength,
|
---|
244 | min_len, max_len, prediction_resistance,
|
---|
245 | (unsigned char *)&drbg, sizeof(drbg));
|
---|
246 | ossl_drbg_unlock_parent(drbg);
|
---|
247 | return bytes;
|
---|
248 | }
|
---|
249 |
|
---|
250 | static void cleanup_entropy(PROV_DRBG *drbg, unsigned char *out, size_t outlen)
|
---|
251 | {
|
---|
252 | if (drbg->parent == NULL) {
|
---|
253 | #ifdef FIPS_MODULE
|
---|
254 | ossl_crngt_cleanup_entropy(drbg, out, outlen);
|
---|
255 | #else
|
---|
256 | ossl_prov_cleanup_entropy(drbg->provctx, out, outlen);
|
---|
257 | #endif
|
---|
258 | } else if (drbg->parent_clear_seed != NULL) {
|
---|
259 | if (!ossl_drbg_lock_parent(drbg))
|
---|
260 | return;
|
---|
261 | drbg->parent_clear_seed(drbg->parent, out, outlen);
|
---|
262 | ossl_drbg_unlock_parent(drbg);
|
---|
263 | }
|
---|
264 | }
|
---|
265 |
|
---|
266 | #ifndef PROV_RAND_GET_RANDOM_NONCE
|
---|
267 | typedef struct prov_drbg_nonce_global_st {
|
---|
268 | CRYPTO_RWLOCK *rand_nonce_lock;
|
---|
269 | int rand_nonce_count;
|
---|
270 | } PROV_DRBG_NONCE_GLOBAL;
|
---|
271 |
|
---|
272 | /*
|
---|
273 | * drbg_ossl_ctx_new() calls drgb_setup() which calls rand_drbg_get_nonce()
|
---|
274 | * which needs to get the rand_nonce_lock out of the OSSL_LIB_CTX...but since
|
---|
275 | * drbg_ossl_ctx_new() hasn't finished running yet we need the rand_nonce_lock
|
---|
276 | * to be in a different global data object. Otherwise we will go into an
|
---|
277 | * infinite recursion loop.
|
---|
278 | */
|
---|
279 | void *ossl_prov_drbg_nonce_ctx_new(OSSL_LIB_CTX *libctx)
|
---|
280 | {
|
---|
281 | PROV_DRBG_NONCE_GLOBAL *dngbl = OPENSSL_zalloc(sizeof(*dngbl));
|
---|
282 |
|
---|
283 | if (dngbl == NULL)
|
---|
284 | return NULL;
|
---|
285 |
|
---|
286 | dngbl->rand_nonce_lock = CRYPTO_THREAD_lock_new();
|
---|
287 | if (dngbl->rand_nonce_lock == NULL) {
|
---|
288 | OPENSSL_free(dngbl);
|
---|
289 | return NULL;
|
---|
290 | }
|
---|
291 |
|
---|
292 | return dngbl;
|
---|
293 | }
|
---|
294 |
|
---|
295 | void ossl_prov_drbg_nonce_ctx_free(void *vdngbl)
|
---|
296 | {
|
---|
297 | PROV_DRBG_NONCE_GLOBAL *dngbl = vdngbl;
|
---|
298 |
|
---|
299 | if (dngbl == NULL)
|
---|
300 | return;
|
---|
301 |
|
---|
302 | CRYPTO_THREAD_lock_free(dngbl->rand_nonce_lock);
|
---|
303 |
|
---|
304 | OPENSSL_free(dngbl);
|
---|
305 | }
|
---|
306 |
|
---|
307 | /* Get a nonce from the operating system */
|
---|
308 | static size_t prov_drbg_get_nonce(PROV_DRBG *drbg, unsigned char **pout,
|
---|
309 | size_t min_len, size_t max_len)
|
---|
310 | {
|
---|
311 | size_t ret = 0, n;
|
---|
312 | unsigned char *buf = NULL;
|
---|
313 | OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx);
|
---|
314 | PROV_DRBG_NONCE_GLOBAL *dngbl
|
---|
315 | = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_NONCE_INDEX);
|
---|
316 | struct {
|
---|
317 | void *drbg;
|
---|
318 | int count;
|
---|
319 | } data;
|
---|
320 |
|
---|
321 | if (dngbl == NULL)
|
---|
322 | return 0;
|
---|
323 |
|
---|
324 | if (drbg->parent != NULL && drbg->parent_nonce != NULL) {
|
---|
325 | n = drbg->parent_nonce(drbg->parent, NULL, 0, drbg->min_noncelen,
|
---|
326 | drbg->max_noncelen);
|
---|
327 | if (n > 0 && (buf = OPENSSL_malloc(n)) != NULL) {
|
---|
328 | ret = drbg->parent_nonce(drbg->parent, buf, 0,
|
---|
329 | drbg->min_noncelen, drbg->max_noncelen);
|
---|
330 | if (ret == n) {
|
---|
331 | *pout = buf;
|
---|
332 | return ret;
|
---|
333 | }
|
---|
334 | OPENSSL_free(buf);
|
---|
335 | }
|
---|
336 | }
|
---|
337 |
|
---|
338 | /* Use the built in nonce source plus some of our specifics */
|
---|
339 | memset(&data, 0, sizeof(data));
|
---|
340 | data.drbg = drbg;
|
---|
341 | CRYPTO_atomic_add(&dngbl->rand_nonce_count, 1, &data.count,
|
---|
342 | dngbl->rand_nonce_lock);
|
---|
343 | return ossl_prov_get_nonce(drbg->provctx, pout, min_len, max_len,
|
---|
344 | &data, sizeof(data));
|
---|
345 | }
|
---|
346 | #endif /* PROV_RAND_GET_RANDOM_NONCE */
|
---|
347 |
|
---|
348 | /*
|
---|
349 | * Instantiate |drbg|, after it has been initialized. Use |pers| and
|
---|
350 | * |perslen| as prediction-resistance input.
|
---|
351 | *
|
---|
352 | * Requires that drbg->lock is already locked for write, if non-null.
|
---|
353 | *
|
---|
354 | * Returns 1 on success, 0 on failure.
|
---|
355 | */
|
---|
356 | int ossl_prov_drbg_instantiate(PROV_DRBG *drbg, unsigned int strength,
|
---|
357 | int prediction_resistance,
|
---|
358 | const unsigned char *pers, size_t perslen)
|
---|
359 | {
|
---|
360 | unsigned char *nonce = NULL, *entropy = NULL;
|
---|
361 | size_t noncelen = 0, entropylen = 0;
|
---|
362 | size_t min_entropy, min_entropylen, max_entropylen;
|
---|
363 |
|
---|
364 | if (strength > drbg->strength) {
|
---|
365 | ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);
|
---|
366 | goto end;
|
---|
367 | }
|
---|
368 | min_entropy = drbg->strength;
|
---|
369 | min_entropylen = drbg->min_entropylen;
|
---|
370 | max_entropylen = drbg->max_entropylen;
|
---|
371 |
|
---|
372 | if (pers == NULL) {
|
---|
373 | pers = (const unsigned char *)ossl_pers_string;
|
---|
374 | perslen = sizeof(ossl_pers_string);
|
---|
375 | }
|
---|
376 | if (perslen > drbg->max_perslen) {
|
---|
377 | ERR_raise(ERR_LIB_PROV, PROV_R_PERSONALISATION_STRING_TOO_LONG);
|
---|
378 | goto end;
|
---|
379 | }
|
---|
380 |
|
---|
381 | if (drbg->state != EVP_RAND_STATE_UNINITIALISED) {
|
---|
382 | if (drbg->state == EVP_RAND_STATE_ERROR)
|
---|
383 | ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
|
---|
384 | else
|
---|
385 | ERR_raise(ERR_LIB_PROV, PROV_R_ALREADY_INSTANTIATED);
|
---|
386 | goto end;
|
---|
387 | }
|
---|
388 |
|
---|
389 | drbg->state = EVP_RAND_STATE_ERROR;
|
---|
390 |
|
---|
391 | if (drbg->min_noncelen > 0) {
|
---|
392 | if (drbg->parent_nonce != NULL) {
|
---|
393 | noncelen = drbg->parent_nonce(drbg->parent, NULL, drbg->strength,
|
---|
394 | drbg->min_noncelen,
|
---|
395 | drbg->max_noncelen);
|
---|
396 | if (noncelen == 0) {
|
---|
397 | ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
|
---|
398 | goto end;
|
---|
399 | }
|
---|
400 | nonce = OPENSSL_malloc(noncelen);
|
---|
401 | if (nonce == NULL) {
|
---|
402 | ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
|
---|
403 | goto end;
|
---|
404 | }
|
---|
405 | if (noncelen != drbg->parent_nonce(drbg->parent, nonce,
|
---|
406 | drbg->strength,
|
---|
407 | drbg->min_noncelen,
|
---|
408 | drbg->max_noncelen)) {
|
---|
409 | ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
|
---|
410 | goto end;
|
---|
411 | }
|
---|
412 | #ifndef PROV_RAND_GET_RANDOM_NONCE
|
---|
413 | } else if (drbg->parent != NULL) {
|
---|
414 | #endif
|
---|
415 | /*
|
---|
416 | * NIST SP800-90Ar1 section 9.1 says you can combine getting
|
---|
417 | * the entropy and nonce in 1 call by increasing the entropy
|
---|
418 | * with 50% and increasing the minimum length to accommodate
|
---|
419 | * the length of the nonce. We do this in case a nonce is
|
---|
420 | * required and there is no parental nonce capability.
|
---|
421 | */
|
---|
422 | min_entropy += drbg->strength / 2;
|
---|
423 | min_entropylen += drbg->min_noncelen;
|
---|
424 | max_entropylen += drbg->max_noncelen;
|
---|
425 | }
|
---|
426 | #ifndef PROV_RAND_GET_RANDOM_NONCE
|
---|
427 | else { /* parent == NULL */
|
---|
428 | noncelen = prov_drbg_get_nonce(drbg, &nonce, drbg->min_noncelen,
|
---|
429 | drbg->max_noncelen);
|
---|
430 | if (noncelen < drbg->min_noncelen
|
---|
431 | || noncelen > drbg->max_noncelen) {
|
---|
432 | ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_NONCE);
|
---|
433 | goto end;
|
---|
434 | }
|
---|
435 | }
|
---|
436 | #endif
|
---|
437 | }
|
---|
438 |
|
---|
439 | drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);
|
---|
440 | if (drbg->reseed_next_counter) {
|
---|
441 | drbg->reseed_next_counter++;
|
---|
442 | if (!drbg->reseed_next_counter)
|
---|
443 | drbg->reseed_next_counter = 1;
|
---|
444 | }
|
---|
445 |
|
---|
446 | entropylen = get_entropy(drbg, &entropy, min_entropy,
|
---|
447 | min_entropylen, max_entropylen,
|
---|
448 | prediction_resistance);
|
---|
449 | if (entropylen < min_entropylen
|
---|
450 | || entropylen > max_entropylen) {
|
---|
451 | ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);
|
---|
452 | goto end;
|
---|
453 | }
|
---|
454 |
|
---|
455 | if (!drbg->instantiate(drbg, entropy, entropylen, nonce, noncelen,
|
---|
456 | pers, perslen)) {
|
---|
457 | cleanup_entropy(drbg, entropy, entropylen);
|
---|
458 | ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_INSTANTIATING_DRBG);
|
---|
459 | goto end;
|
---|
460 | }
|
---|
461 | cleanup_entropy(drbg, entropy, entropylen);
|
---|
462 |
|
---|
463 | drbg->state = EVP_RAND_STATE_READY;
|
---|
464 | drbg->generate_counter = 1;
|
---|
465 | drbg->reseed_time = time(NULL);
|
---|
466 | tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);
|
---|
467 |
|
---|
468 | end:
|
---|
469 | if (nonce != NULL)
|
---|
470 | ossl_prov_cleanup_nonce(drbg->provctx, nonce, noncelen);
|
---|
471 | if (drbg->state == EVP_RAND_STATE_READY)
|
---|
472 | return 1;
|
---|
473 | return 0;
|
---|
474 | }
|
---|
475 |
|
---|
476 | /*
|
---|
477 | * Uninstantiate |drbg|. Must be instantiated before it can be used.
|
---|
478 | *
|
---|
479 | * Requires that drbg->lock is already locked for write, if non-null.
|
---|
480 | *
|
---|
481 | * Returns 1 on success, 0 on failure.
|
---|
482 | */
|
---|
483 | int ossl_prov_drbg_uninstantiate(PROV_DRBG *drbg)
|
---|
484 | {
|
---|
485 | drbg->state = EVP_RAND_STATE_UNINITIALISED;
|
---|
486 | return 1;
|
---|
487 | }
|
---|
488 |
|
---|
489 | /*
|
---|
490 | * Reseed |drbg|, mixing in the specified data
|
---|
491 | *
|
---|
492 | * Requires that drbg->lock is already locked for write, if non-null.
|
---|
493 | *
|
---|
494 | * Returns 1 on success, 0 on failure.
|
---|
495 | */
|
---|
496 | int ossl_prov_drbg_reseed(PROV_DRBG *drbg, int prediction_resistance,
|
---|
497 | const unsigned char *ent, size_t ent_len,
|
---|
498 | const unsigned char *adin, size_t adinlen)
|
---|
499 | {
|
---|
500 | unsigned char *entropy = NULL;
|
---|
501 | size_t entropylen = 0;
|
---|
502 |
|
---|
503 | if (!ossl_prov_is_running())
|
---|
504 | return 0;
|
---|
505 |
|
---|
506 | if (drbg->state != EVP_RAND_STATE_READY) {
|
---|
507 | /* try to recover from previous errors */
|
---|
508 | rand_drbg_restart(drbg);
|
---|
509 |
|
---|
510 | if (drbg->state == EVP_RAND_STATE_ERROR) {
|
---|
511 | ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
|
---|
512 | return 0;
|
---|
513 | }
|
---|
514 | if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {
|
---|
515 | ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);
|
---|
516 | return 0;
|
---|
517 | }
|
---|
518 | }
|
---|
519 |
|
---|
520 | if (ent != NULL) {
|
---|
521 | if (ent_len < drbg->min_entropylen) {
|
---|
522 | ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_OUT_OF_RANGE);
|
---|
523 | drbg->state = EVP_RAND_STATE_ERROR;
|
---|
524 | return 0;
|
---|
525 | }
|
---|
526 | if (ent_len > drbg->max_entropylen) {
|
---|
527 | ERR_raise(ERR_LIB_RAND, RAND_R_ENTROPY_INPUT_TOO_LONG);
|
---|
528 | drbg->state = EVP_RAND_STATE_ERROR;
|
---|
529 | return 0;
|
---|
530 | }
|
---|
531 | }
|
---|
532 |
|
---|
533 | if (adin == NULL) {
|
---|
534 | adinlen = 0;
|
---|
535 | } else if (adinlen > drbg->max_adinlen) {
|
---|
536 | ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);
|
---|
537 | return 0;
|
---|
538 | }
|
---|
539 |
|
---|
540 | drbg->state = EVP_RAND_STATE_ERROR;
|
---|
541 |
|
---|
542 | drbg->reseed_next_counter = tsan_load(&drbg->reseed_counter);
|
---|
543 | if (drbg->reseed_next_counter) {
|
---|
544 | drbg->reseed_next_counter++;
|
---|
545 | if (!drbg->reseed_next_counter)
|
---|
546 | drbg->reseed_next_counter = 1;
|
---|
547 | }
|
---|
548 |
|
---|
549 | if (ent != NULL) {
|
---|
550 | #ifdef FIPS_MODULE
|
---|
551 | /*
|
---|
552 | * NIST SP-800-90A mandates that entropy *shall not* be provided
|
---|
553 | * by the consuming application. Instead the data is added as additional
|
---|
554 | * input.
|
---|
555 | *
|
---|
556 | * (NIST SP-800-90Ar1, Sections 9.1 and 9.2)
|
---|
557 | */
|
---|
558 | if (!drbg->reseed(drbg, NULL, 0, ent, ent_len)) {
|
---|
559 | ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);
|
---|
560 | return 0;
|
---|
561 | }
|
---|
562 | #else
|
---|
563 | if (!drbg->reseed(drbg, ent, ent_len, adin, adinlen)) {
|
---|
564 | ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_RESEED);
|
---|
565 | return 0;
|
---|
566 | }
|
---|
567 | /* There isn't much point adding the same additional input twice */
|
---|
568 | adin = NULL;
|
---|
569 | adinlen = 0;
|
---|
570 | #endif
|
---|
571 | }
|
---|
572 |
|
---|
573 | /* Reseed using our sources in addition */
|
---|
574 | entropylen = get_entropy(drbg, &entropy, drbg->strength,
|
---|
575 | drbg->min_entropylen, drbg->max_entropylen,
|
---|
576 | prediction_resistance);
|
---|
577 | if (entropylen < drbg->min_entropylen
|
---|
578 | || entropylen > drbg->max_entropylen) {
|
---|
579 | ERR_raise(ERR_LIB_PROV, PROV_R_ERROR_RETRIEVING_ENTROPY);
|
---|
580 | goto end;
|
---|
581 | }
|
---|
582 |
|
---|
583 | if (!drbg->reseed(drbg, entropy, entropylen, adin, adinlen))
|
---|
584 | goto end;
|
---|
585 |
|
---|
586 | drbg->state = EVP_RAND_STATE_READY;
|
---|
587 | drbg->generate_counter = 1;
|
---|
588 | drbg->reseed_time = time(NULL);
|
---|
589 | tsan_store(&drbg->reseed_counter, drbg->reseed_next_counter);
|
---|
590 | if (drbg->parent != NULL)
|
---|
591 | drbg->parent_reseed_counter = get_parent_reseed_count(drbg);
|
---|
592 |
|
---|
593 | end:
|
---|
594 | cleanup_entropy(drbg, entropy, entropylen);
|
---|
595 | if (drbg->state == EVP_RAND_STATE_READY)
|
---|
596 | return 1;
|
---|
597 | return 0;
|
---|
598 | }
|
---|
599 |
|
---|
600 | /*
|
---|
601 | * Generate |outlen| bytes into the buffer at |out|. Reseed if we need
|
---|
602 | * to or if |prediction_resistance| is set. Additional input can be
|
---|
603 | * sent in |adin| and |adinlen|.
|
---|
604 | *
|
---|
605 | * Requires that drbg->lock is already locked for write, if non-null.
|
---|
606 | *
|
---|
607 | * Returns 1 on success, 0 on failure.
|
---|
608 | *
|
---|
609 | */
|
---|
610 | int ossl_prov_drbg_generate(PROV_DRBG *drbg, unsigned char *out, size_t outlen,
|
---|
611 | unsigned int strength, int prediction_resistance,
|
---|
612 | const unsigned char *adin, size_t adinlen)
|
---|
613 | {
|
---|
614 | int fork_id;
|
---|
615 | int reseed_required = 0;
|
---|
616 |
|
---|
617 | if (!ossl_prov_is_running())
|
---|
618 | return 0;
|
---|
619 |
|
---|
620 | if (drbg->state != EVP_RAND_STATE_READY) {
|
---|
621 | /* try to recover from previous errors */
|
---|
622 | rand_drbg_restart(drbg);
|
---|
623 |
|
---|
624 | if (drbg->state == EVP_RAND_STATE_ERROR) {
|
---|
625 | ERR_raise(ERR_LIB_PROV, PROV_R_IN_ERROR_STATE);
|
---|
626 | return 0;
|
---|
627 | }
|
---|
628 | if (drbg->state == EVP_RAND_STATE_UNINITIALISED) {
|
---|
629 | ERR_raise(ERR_LIB_PROV, PROV_R_NOT_INSTANTIATED);
|
---|
630 | return 0;
|
---|
631 | }
|
---|
632 | }
|
---|
633 | if (strength > drbg->strength) {
|
---|
634 | ERR_raise(ERR_LIB_PROV, PROV_R_INSUFFICIENT_DRBG_STRENGTH);
|
---|
635 | return 0;
|
---|
636 | }
|
---|
637 |
|
---|
638 | if (outlen > drbg->max_request) {
|
---|
639 | ERR_raise(ERR_LIB_PROV, PROV_R_REQUEST_TOO_LARGE_FOR_DRBG);
|
---|
640 | return 0;
|
---|
641 | }
|
---|
642 | if (adinlen > drbg->max_adinlen) {
|
---|
643 | ERR_raise(ERR_LIB_PROV, PROV_R_ADDITIONAL_INPUT_TOO_LONG);
|
---|
644 | return 0;
|
---|
645 | }
|
---|
646 |
|
---|
647 | fork_id = openssl_get_fork_id();
|
---|
648 |
|
---|
649 | if (drbg->fork_id != fork_id) {
|
---|
650 | drbg->fork_id = fork_id;
|
---|
651 | reseed_required = 1;
|
---|
652 | }
|
---|
653 |
|
---|
654 | if (drbg->reseed_interval > 0) {
|
---|
655 | if (drbg->generate_counter >= drbg->reseed_interval)
|
---|
656 | reseed_required = 1;
|
---|
657 | }
|
---|
658 | if (drbg->reseed_time_interval > 0) {
|
---|
659 | time_t now = time(NULL);
|
---|
660 | if (now < drbg->reseed_time
|
---|
661 | || now - drbg->reseed_time >= drbg->reseed_time_interval)
|
---|
662 | reseed_required = 1;
|
---|
663 | }
|
---|
664 | if (drbg->parent != NULL
|
---|
665 | && get_parent_reseed_count(drbg) != drbg->parent_reseed_counter)
|
---|
666 | reseed_required = 1;
|
---|
667 |
|
---|
668 | if (reseed_required || prediction_resistance) {
|
---|
669 | if (!ossl_prov_drbg_reseed(drbg, prediction_resistance, NULL, 0,
|
---|
670 | adin, adinlen)) {
|
---|
671 | ERR_raise(ERR_LIB_PROV, PROV_R_RESEED_ERROR);
|
---|
672 | return 0;
|
---|
673 | }
|
---|
674 | adin = NULL;
|
---|
675 | adinlen = 0;
|
---|
676 | }
|
---|
677 |
|
---|
678 | if (!drbg->generate(drbg, out, outlen, adin, adinlen)) {
|
---|
679 | drbg->state = EVP_RAND_STATE_ERROR;
|
---|
680 | ERR_raise(ERR_LIB_PROV, PROV_R_GENERATE_ERROR);
|
---|
681 | return 0;
|
---|
682 | }
|
---|
683 |
|
---|
684 | drbg->generate_counter++;
|
---|
685 |
|
---|
686 | return 1;
|
---|
687 | }
|
---|
688 |
|
---|
689 | /*
|
---|
690 | * Restart |drbg|, using the specified entropy or additional input
|
---|
691 | *
|
---|
692 | * Tries its best to get the drbg instantiated by all means,
|
---|
693 | * regardless of its current state.
|
---|
694 | *
|
---|
695 | * Optionally, a |buffer| of |len| random bytes can be passed,
|
---|
696 | * which is assumed to contain at least |entropy| bits of entropy.
|
---|
697 | *
|
---|
698 | * If |entropy| > 0, the buffer content is used as entropy input.
|
---|
699 | *
|
---|
700 | * If |entropy| == 0, the buffer content is used as additional input
|
---|
701 | *
|
---|
702 | * Returns 1 on success, 0 on failure.
|
---|
703 | *
|
---|
704 | * This function is used internally only.
|
---|
705 | */
|
---|
706 | static int rand_drbg_restart(PROV_DRBG *drbg)
|
---|
707 | {
|
---|
708 | /* repair error state */
|
---|
709 | if (drbg->state == EVP_RAND_STATE_ERROR)
|
---|
710 | drbg->uninstantiate(drbg);
|
---|
711 |
|
---|
712 | /* repair uninitialized state */
|
---|
713 | if (drbg->state == EVP_RAND_STATE_UNINITIALISED)
|
---|
714 | /* reinstantiate drbg */
|
---|
715 | ossl_prov_drbg_instantiate(drbg, drbg->strength, 0, NULL, 0);
|
---|
716 |
|
---|
717 | return drbg->state == EVP_RAND_STATE_READY;
|
---|
718 | }
|
---|
719 |
|
---|
720 | /* Provider support from here down */
|
---|
721 | static const OSSL_DISPATCH *find_call(const OSSL_DISPATCH *dispatch,
|
---|
722 | int function)
|
---|
723 | {
|
---|
724 | if (dispatch != NULL)
|
---|
725 | while (dispatch->function_id != 0) {
|
---|
726 | if (dispatch->function_id == function)
|
---|
727 | return dispatch;
|
---|
728 | dispatch++;
|
---|
729 | }
|
---|
730 | return NULL;
|
---|
731 | }
|
---|
732 |
|
---|
733 | int ossl_drbg_enable_locking(void *vctx)
|
---|
734 | {
|
---|
735 | PROV_DRBG *drbg = vctx;
|
---|
736 |
|
---|
737 | if (drbg != NULL && drbg->lock == NULL) {
|
---|
738 | if (drbg->parent_enable_locking != NULL)
|
---|
739 | if (!drbg->parent_enable_locking(drbg->parent)) {
|
---|
740 | ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_LOCKING_NOT_ENABLED);
|
---|
741 | return 0;
|
---|
742 | }
|
---|
743 | drbg->lock = CRYPTO_THREAD_lock_new();
|
---|
744 | if (drbg->lock == NULL) {
|
---|
745 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_CREATE_LOCK);
|
---|
746 | return 0;
|
---|
747 | }
|
---|
748 | }
|
---|
749 | return 1;
|
---|
750 | }
|
---|
751 |
|
---|
752 | /*
|
---|
753 | * Allocate memory and initialize a new DRBG. The DRBG is allocated on
|
---|
754 | * the secure heap if |secure| is nonzero and the secure heap is enabled.
|
---|
755 | * The |parent|, if not NULL, will be used as random source for reseeding.
|
---|
756 | * This also requires the parent's provider context and the parent's lock.
|
---|
757 | *
|
---|
758 | * Returns a pointer to the new DRBG instance on success, NULL on failure.
|
---|
759 | */
|
---|
760 | PROV_DRBG *ossl_rand_drbg_new
|
---|
761 | (void *provctx, void *parent, const OSSL_DISPATCH *p_dispatch,
|
---|
762 | int (*dnew)(PROV_DRBG *ctx),
|
---|
763 | int (*instantiate)(PROV_DRBG *drbg,
|
---|
764 | const unsigned char *entropy, size_t entropylen,
|
---|
765 | const unsigned char *nonce, size_t noncelen,
|
---|
766 | const unsigned char *pers, size_t perslen),
|
---|
767 | int (*uninstantiate)(PROV_DRBG *ctx),
|
---|
768 | int (*reseed)(PROV_DRBG *drbg, const unsigned char *ent, size_t ent_len,
|
---|
769 | const unsigned char *adin, size_t adin_len),
|
---|
770 | int (*generate)(PROV_DRBG *, unsigned char *out, size_t outlen,
|
---|
771 | const unsigned char *adin, size_t adin_len))
|
---|
772 | {
|
---|
773 | PROV_DRBG *drbg;
|
---|
774 | unsigned int p_str;
|
---|
775 | const OSSL_DISPATCH *pfunc;
|
---|
776 |
|
---|
777 | if (!ossl_prov_is_running())
|
---|
778 | return NULL;
|
---|
779 |
|
---|
780 | drbg = OPENSSL_zalloc(sizeof(*drbg));
|
---|
781 | if (drbg == NULL) {
|
---|
782 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
---|
783 | return NULL;
|
---|
784 | }
|
---|
785 |
|
---|
786 | drbg->provctx = provctx;
|
---|
787 | drbg->instantiate = instantiate;
|
---|
788 | drbg->uninstantiate = uninstantiate;
|
---|
789 | drbg->reseed = reseed;
|
---|
790 | drbg->generate = generate;
|
---|
791 | drbg->fork_id = openssl_get_fork_id();
|
---|
792 |
|
---|
793 | /* Extract parent's functions */
|
---|
794 | drbg->parent = parent;
|
---|
795 | if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_ENABLE_LOCKING)) != NULL)
|
---|
796 | drbg->parent_enable_locking = OSSL_FUNC_rand_enable_locking(pfunc);
|
---|
797 | if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_LOCK)) != NULL)
|
---|
798 | drbg->parent_lock = OSSL_FUNC_rand_lock(pfunc);
|
---|
799 | if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_UNLOCK)) != NULL)
|
---|
800 | drbg->parent_unlock = OSSL_FUNC_rand_unlock(pfunc);
|
---|
801 | if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_CTX_PARAMS)) != NULL)
|
---|
802 | drbg->parent_get_ctx_params = OSSL_FUNC_rand_get_ctx_params(pfunc);
|
---|
803 | if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_NONCE)) != NULL)
|
---|
804 | drbg->parent_nonce = OSSL_FUNC_rand_nonce(pfunc);
|
---|
805 | if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_GET_SEED)) != NULL)
|
---|
806 | drbg->parent_get_seed = OSSL_FUNC_rand_get_seed(pfunc);
|
---|
807 | if ((pfunc = find_call(p_dispatch, OSSL_FUNC_RAND_CLEAR_SEED)) != NULL)
|
---|
808 | drbg->parent_clear_seed = OSSL_FUNC_rand_clear_seed(pfunc);
|
---|
809 |
|
---|
810 | /* Set some default maximums up */
|
---|
811 | drbg->max_entropylen = DRBG_MAX_LENGTH;
|
---|
812 | drbg->max_noncelen = DRBG_MAX_LENGTH;
|
---|
813 | drbg->max_perslen = DRBG_MAX_LENGTH;
|
---|
814 | drbg->max_adinlen = DRBG_MAX_LENGTH;
|
---|
815 | drbg->generate_counter = 1;
|
---|
816 | drbg->reseed_counter = 1;
|
---|
817 | drbg->reseed_interval = RESEED_INTERVAL;
|
---|
818 | drbg->reseed_time_interval = TIME_INTERVAL;
|
---|
819 |
|
---|
820 | if (!dnew(drbg))
|
---|
821 | goto err;
|
---|
822 |
|
---|
823 | if (parent != NULL) {
|
---|
824 | if (!get_parent_strength(drbg, &p_str))
|
---|
825 | goto err;
|
---|
826 | if (drbg->strength > p_str) {
|
---|
827 | /*
|
---|
828 | * We currently don't support the algorithm from NIST SP 800-90C
|
---|
829 | * 10.1.2 to use a weaker DRBG as source
|
---|
830 | */
|
---|
831 | ERR_raise(ERR_LIB_PROV, PROV_R_PARENT_STRENGTH_TOO_WEAK);
|
---|
832 | goto err;
|
---|
833 | }
|
---|
834 | }
|
---|
835 | #ifdef TSAN_REQUIRES_LOCKING
|
---|
836 | if (!ossl_drbg_enable_locking(drbg))
|
---|
837 | goto err;
|
---|
838 | #endif
|
---|
839 | return drbg;
|
---|
840 |
|
---|
841 | err:
|
---|
842 | ossl_rand_drbg_free(drbg);
|
---|
843 | return NULL;
|
---|
844 | }
|
---|
845 |
|
---|
846 | void ossl_rand_drbg_free(PROV_DRBG *drbg)
|
---|
847 | {
|
---|
848 | if (drbg == NULL)
|
---|
849 | return;
|
---|
850 |
|
---|
851 | CRYPTO_THREAD_lock_free(drbg->lock);
|
---|
852 | OPENSSL_free(drbg);
|
---|
853 | }
|
---|
854 |
|
---|
855 | int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[])
|
---|
856 | {
|
---|
857 | OSSL_PARAM *p;
|
---|
858 |
|
---|
859 | p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
|
---|
860 | if (p != NULL && !OSSL_PARAM_set_int(p, drbg->state))
|
---|
861 | return 0;
|
---|
862 |
|
---|
863 | p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
|
---|
864 | if (p != NULL && !OSSL_PARAM_set_int(p, drbg->strength))
|
---|
865 | return 0;
|
---|
866 |
|
---|
867 | p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
|
---|
868 | if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_request))
|
---|
869 | return 0;
|
---|
870 |
|
---|
871 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_ENTROPYLEN);
|
---|
872 | if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_entropylen))
|
---|
873 | return 0;
|
---|
874 |
|
---|
875 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ENTROPYLEN);
|
---|
876 | if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_entropylen))
|
---|
877 | return 0;
|
---|
878 |
|
---|
879 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MIN_NONCELEN);
|
---|
880 | if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->min_noncelen))
|
---|
881 | return 0;
|
---|
882 |
|
---|
883 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_NONCELEN);
|
---|
884 | if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_noncelen))
|
---|
885 | return 0;
|
---|
886 |
|
---|
887 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_PERSLEN);
|
---|
888 | if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_perslen))
|
---|
889 | return 0;
|
---|
890 |
|
---|
891 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_MAX_ADINLEN);
|
---|
892 | if (p != NULL && !OSSL_PARAM_set_size_t(p, drbg->max_adinlen))
|
---|
893 | return 0;
|
---|
894 |
|
---|
895 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);
|
---|
896 | if (p != NULL && !OSSL_PARAM_set_uint(p, drbg->reseed_interval))
|
---|
897 | return 0;
|
---|
898 |
|
---|
899 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME);
|
---|
900 | if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time))
|
---|
901 | return 0;
|
---|
902 |
|
---|
903 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);
|
---|
904 | if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time_interval))
|
---|
905 | return 0;
|
---|
906 |
|
---|
907 | p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_COUNTER);
|
---|
908 | if (p != NULL
|
---|
909 | && !OSSL_PARAM_set_uint(p, tsan_load(&drbg->reseed_counter)))
|
---|
910 | return 0;
|
---|
911 | return 1;
|
---|
912 | }
|
---|
913 |
|
---|
914 | int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[])
|
---|
915 | {
|
---|
916 | const OSSL_PARAM *p;
|
---|
917 |
|
---|
918 | if (params == NULL)
|
---|
919 | return 1;
|
---|
920 |
|
---|
921 | p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_REQUESTS);
|
---|
922 | if (p != NULL && !OSSL_PARAM_get_uint(p, &drbg->reseed_interval))
|
---|
923 | return 0;
|
---|
924 |
|
---|
925 | p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL);
|
---|
926 | if (p != NULL && !OSSL_PARAM_get_time_t(p, &drbg->reseed_time_interval))
|
---|
927 | return 0;
|
---|
928 | return 1;
|
---|
929 | }
|
---|
930 |
|
---|
931 | /* Confirm digest is allowed to be used with a DRBG */
|
---|
932 | int ossl_drbg_verify_digest(ossl_unused OSSL_LIB_CTX *libctx, const EVP_MD *md)
|
---|
933 | {
|
---|
934 | #ifdef FIPS_MODULE
|
---|
935 | /* FIPS 140-3 IG D.R limited DRBG digests to a specific set */
|
---|
936 | static const char *const allowed_digests[] = {
|
---|
937 | "SHA1", /* SHA 1 allowed */
|
---|
938 | "SHA2-256", "SHA2-512", /* non-truncated SHA2 allowed */
|
---|
939 | "SHA3-256", "SHA3-512", /* non-truncated SHA3 allowed */
|
---|
940 | };
|
---|
941 | size_t i;
|
---|
942 |
|
---|
943 | if (FIPS_restricted_drbg_digests_enabled(libctx)) {
|
---|
944 | for (i = 0; i < OSSL_NELEM(allowed_digests); i++)
|
---|
945 | if (EVP_MD_is_a(md, allowed_digests[i]))
|
---|
946 | return 1;
|
---|
947 | ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
|
---|
948 | return 0;
|
---|
949 | }
|
---|
950 | #endif
|
---|
951 | /* Outside of FIPS, any digests that are not XOF are allowed */
|
---|
952 | if ((EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0) {
|
---|
953 | ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
|
---|
954 | return 0;
|
---|
955 | }
|
---|
956 | return 1;
|
---|
957 | }
|
---|