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