Home | History | Annotate | Line # | Download | only in evp
      1 /*
      2  * Copyright 2020-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 <stdio.h>
     11 #include <stdlib.h>
     12 #include <openssl/evp.h>
     13 #include <openssl/rand.h>
     14 #include <openssl/core.h>
     15 #include <openssl/core_names.h>
     16 #include <openssl/crypto.h>
     17 #include "internal/cryptlib.h"
     18 #include "internal/numbers.h"
     19 #include "internal/provider.h"
     20 #include "internal/core.h"
     21 #include "crypto/evp.h"
     22 #include "evp_local.h"
     23 
     24 struct evp_rand_st {
     25     OSSL_PROVIDER *prov;
     26     int name_id;
     27     char *type_name;
     28     const char *description;
     29     CRYPTO_REF_COUNT refcnt;
     30 
     31     const OSSL_DISPATCH *dispatch;
     32     OSSL_FUNC_rand_newctx_fn *newctx;
     33     OSSL_FUNC_rand_freectx_fn *freectx;
     34     OSSL_FUNC_rand_instantiate_fn *instantiate;
     35     OSSL_FUNC_rand_uninstantiate_fn *uninstantiate;
     36     OSSL_FUNC_rand_generate_fn *generate;
     37     OSSL_FUNC_rand_reseed_fn *reseed;
     38     OSSL_FUNC_rand_nonce_fn *nonce;
     39     OSSL_FUNC_rand_enable_locking_fn *enable_locking;
     40     OSSL_FUNC_rand_lock_fn *lock;
     41     OSSL_FUNC_rand_unlock_fn *unlock;
     42     OSSL_FUNC_rand_gettable_params_fn *gettable_params;
     43     OSSL_FUNC_rand_gettable_ctx_params_fn *gettable_ctx_params;
     44     OSSL_FUNC_rand_settable_ctx_params_fn *settable_ctx_params;
     45     OSSL_FUNC_rand_get_params_fn *get_params;
     46     OSSL_FUNC_rand_get_ctx_params_fn *get_ctx_params;
     47     OSSL_FUNC_rand_set_ctx_params_fn *set_ctx_params;
     48     OSSL_FUNC_rand_verify_zeroization_fn *verify_zeroization;
     49     OSSL_FUNC_rand_get_seed_fn *get_seed;
     50     OSSL_FUNC_rand_clear_seed_fn *clear_seed;
     51 } /* EVP_RAND */;
     52 
     53 static int evp_rand_up_ref(void *vrand)
     54 {
     55     EVP_RAND *rand = (EVP_RAND *)vrand;
     56     int ref = 0;
     57 
     58     if (rand != NULL)
     59         return CRYPTO_UP_REF(&rand->refcnt, &ref);
     60     return 1;
     61 }
     62 
     63 static void evp_rand_free(void *vrand)
     64 {
     65     EVP_RAND *rand = (EVP_RAND *)vrand;
     66     int ref = 0;
     67 
     68     if (rand == NULL)
     69         return;
     70     CRYPTO_DOWN_REF(&rand->refcnt, &ref);
     71     if (ref > 0)
     72         return;
     73     OPENSSL_free(rand->type_name);
     74     ossl_provider_free(rand->prov);
     75     CRYPTO_FREE_REF(&rand->refcnt);
     76     OPENSSL_free(rand);
     77 }
     78 
     79 static void *evp_rand_new(void)
     80 {
     81     EVP_RAND *rand = OPENSSL_zalloc(sizeof(*rand));
     82 
     83     if (rand == NULL)
     84         return NULL;
     85 
     86     if (!CRYPTO_NEW_REF(&rand->refcnt, 1)) {
     87         OPENSSL_free(rand);
     88         return NULL;
     89     }
     90     return rand;
     91 }
     92 
     93 /* Enable locking of the underlying DRBG/RAND if available */
     94 int EVP_RAND_enable_locking(EVP_RAND_CTX *rand)
     95 {
     96     if (rand->meth->enable_locking != NULL)
     97         return rand->meth->enable_locking(rand->algctx);
     98     ERR_raise(ERR_LIB_EVP, EVP_R_LOCKING_NOT_SUPPORTED);
     99     return 0;
    100 }
    101 
    102 /* Lock the underlying DRBG/RAND if available */
    103 static int evp_rand_lock(EVP_RAND_CTX *rand)
    104 {
    105     if (rand->meth->lock != NULL)
    106         return rand->meth->lock(rand->algctx);
    107     return 1;
    108 }
    109 
    110 /* Unlock the underlying DRBG/RAND if available */
    111 static void evp_rand_unlock(EVP_RAND_CTX *rand)
    112 {
    113     if (rand->meth->unlock != NULL)
    114         rand->meth->unlock(rand->algctx);
    115 }
    116 
    117 static void *evp_rand_from_algorithm(int name_id,
    118     const OSSL_ALGORITHM *algodef,
    119     OSSL_PROVIDER *prov)
    120 {
    121     const OSSL_DISPATCH *fns = algodef->implementation;
    122     EVP_RAND *rand = NULL;
    123     int fnrandcnt = 0, fnctxcnt = 0, fnlockcnt = 0, fnenablelockcnt = 0;
    124 #ifdef FIPS_MODULE
    125     int fnzeroizecnt = 0;
    126 #endif
    127 
    128     if ((rand = evp_rand_new()) == NULL) {
    129         ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
    130         return NULL;
    131     }
    132     rand->name_id = name_id;
    133     if ((rand->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
    134         evp_rand_free(rand);
    135         return NULL;
    136     }
    137     rand->description = algodef->algorithm_description;
    138     rand->dispatch = fns;
    139     for (; fns->function_id != 0; fns++) {
    140         switch (fns->function_id) {
    141         case OSSL_FUNC_RAND_NEWCTX:
    142             if (rand->newctx != NULL)
    143                 break;
    144             rand->newctx = OSSL_FUNC_rand_newctx(fns);
    145             fnctxcnt++;
    146             break;
    147         case OSSL_FUNC_RAND_FREECTX:
    148             if (rand->freectx != NULL)
    149                 break;
    150             rand->freectx = OSSL_FUNC_rand_freectx(fns);
    151             fnctxcnt++;
    152             break;
    153         case OSSL_FUNC_RAND_INSTANTIATE:
    154             if (rand->instantiate != NULL)
    155                 break;
    156             rand->instantiate = OSSL_FUNC_rand_instantiate(fns);
    157             fnrandcnt++;
    158             break;
    159         case OSSL_FUNC_RAND_UNINSTANTIATE:
    160             if (rand->uninstantiate != NULL)
    161                 break;
    162             rand->uninstantiate = OSSL_FUNC_rand_uninstantiate(fns);
    163             fnrandcnt++;
    164             break;
    165         case OSSL_FUNC_RAND_GENERATE:
    166             if (rand->generate != NULL)
    167                 break;
    168             rand->generate = OSSL_FUNC_rand_generate(fns);
    169             fnrandcnt++;
    170             break;
    171         case OSSL_FUNC_RAND_RESEED:
    172             if (rand->reseed != NULL)
    173                 break;
    174             rand->reseed = OSSL_FUNC_rand_reseed(fns);
    175             break;
    176         case OSSL_FUNC_RAND_NONCE:
    177             if (rand->nonce != NULL)
    178                 break;
    179             rand->nonce = OSSL_FUNC_rand_nonce(fns);
    180             break;
    181         case OSSL_FUNC_RAND_ENABLE_LOCKING:
    182             if (rand->enable_locking != NULL)
    183                 break;
    184             rand->enable_locking = OSSL_FUNC_rand_enable_locking(fns);
    185             fnenablelockcnt++;
    186             break;
    187         case OSSL_FUNC_RAND_LOCK:
    188             if (rand->lock != NULL)
    189                 break;
    190             rand->lock = OSSL_FUNC_rand_lock(fns);
    191             fnlockcnt++;
    192             break;
    193         case OSSL_FUNC_RAND_UNLOCK:
    194             if (rand->unlock != NULL)
    195                 break;
    196             rand->unlock = OSSL_FUNC_rand_unlock(fns);
    197             fnlockcnt++;
    198             break;
    199         case OSSL_FUNC_RAND_GETTABLE_PARAMS:
    200             if (rand->gettable_params != NULL)
    201                 break;
    202             rand->gettable_params = OSSL_FUNC_rand_gettable_params(fns);
    203             break;
    204         case OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS:
    205             if (rand->gettable_ctx_params != NULL)
    206                 break;
    207             rand->gettable_ctx_params = OSSL_FUNC_rand_gettable_ctx_params(fns);
    208             break;
    209         case OSSL_FUNC_RAND_SETTABLE_CTX_PARAMS:
    210             if (rand->settable_ctx_params != NULL)
    211                 break;
    212             rand->settable_ctx_params = OSSL_FUNC_rand_settable_ctx_params(fns);
    213             break;
    214         case OSSL_FUNC_RAND_GET_PARAMS:
    215             if (rand->get_params != NULL)
    216                 break;
    217             rand->get_params = OSSL_FUNC_rand_get_params(fns);
    218             break;
    219         case OSSL_FUNC_RAND_GET_CTX_PARAMS:
    220             if (rand->get_ctx_params != NULL)
    221                 break;
    222             rand->get_ctx_params = OSSL_FUNC_rand_get_ctx_params(fns);
    223             fnctxcnt++;
    224             break;
    225         case OSSL_FUNC_RAND_SET_CTX_PARAMS:
    226             if (rand->set_ctx_params != NULL)
    227                 break;
    228             rand->set_ctx_params = OSSL_FUNC_rand_set_ctx_params(fns);
    229             break;
    230         case OSSL_FUNC_RAND_VERIFY_ZEROIZATION:
    231             if (rand->verify_zeroization != NULL)
    232                 break;
    233             rand->verify_zeroization = OSSL_FUNC_rand_verify_zeroization(fns);
    234 #ifdef FIPS_MODULE
    235             fnzeroizecnt++;
    236 #endif
    237             break;
    238         case OSSL_FUNC_RAND_GET_SEED:
    239             if (rand->get_seed != NULL)
    240                 break;
    241             rand->get_seed = OSSL_FUNC_rand_get_seed(fns);
    242             break;
    243         case OSSL_FUNC_RAND_CLEAR_SEED:
    244             if (rand->clear_seed != NULL)
    245                 break;
    246             rand->clear_seed = OSSL_FUNC_rand_clear_seed(fns);
    247             break;
    248         }
    249     }
    250     /*
    251      * In order to be a consistent set of functions we must have at least
    252      * a complete set of "rand" functions and a complete set of context
    253      * management functions.  In FIPS mode, we also require the zeroization
    254      * verification function.
    255      *
    256      * In addition, if locking can be enabled, we need a complete set of
    257      * locking functions.
    258      */
    259     if (fnrandcnt != 3
    260         || fnctxcnt != 3
    261         || (fnenablelockcnt != 0 && fnenablelockcnt != 1)
    262         || (fnlockcnt != 0 && fnlockcnt != 2)
    263 #ifdef FIPS_MODULE
    264         || fnzeroizecnt != 1
    265 #endif
    266     ) {
    267         evp_rand_free(rand);
    268         ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
    269         return NULL;
    270     }
    271 
    272     if (prov != NULL && !ossl_provider_up_ref(prov)) {
    273         evp_rand_free(rand);
    274         ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
    275         return NULL;
    276     }
    277     rand->prov = prov;
    278 
    279     return rand;
    280 }
    281 
    282 EVP_RAND *EVP_RAND_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
    283     const char *properties)
    284 {
    285     return evp_generic_fetch(libctx, OSSL_OP_RAND, algorithm, properties,
    286         evp_rand_from_algorithm, evp_rand_up_ref,
    287         evp_rand_free);
    288 }
    289 
    290 int EVP_RAND_up_ref(EVP_RAND *rand)
    291 {
    292     return evp_rand_up_ref(rand);
    293 }
    294 
    295 void EVP_RAND_free(EVP_RAND *rand)
    296 {
    297     evp_rand_free(rand);
    298 }
    299 
    300 int evp_rand_get_number(const EVP_RAND *rand)
    301 {
    302     return rand->name_id;
    303 }
    304 
    305 const char *EVP_RAND_get0_name(const EVP_RAND *rand)
    306 {
    307     return rand->type_name;
    308 }
    309 
    310 const char *EVP_RAND_get0_description(const EVP_RAND *rand)
    311 {
    312     return rand->description;
    313 }
    314 
    315 int EVP_RAND_is_a(const EVP_RAND *rand, const char *name)
    316 {
    317     return rand != NULL && evp_is_a(rand->prov, rand->name_id, NULL, name);
    318 }
    319 
    320 const OSSL_PROVIDER *EVP_RAND_get0_provider(const EVP_RAND *rand)
    321 {
    322     return rand->prov;
    323 }
    324 
    325 int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[])
    326 {
    327     if (rand->get_params != NULL)
    328         return rand->get_params(params);
    329     return 1;
    330 }
    331 
    332 int EVP_RAND_CTX_up_ref(EVP_RAND_CTX *ctx)
    333 {
    334     int ref = 0;
    335 
    336     return CRYPTO_UP_REF(&ctx->refcnt, &ref);
    337 }
    338 
    339 EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent)
    340 {
    341     EVP_RAND_CTX *ctx;
    342     void *parent_ctx = NULL;
    343     const OSSL_DISPATCH *parent_dispatch = NULL;
    344 
    345     if (rand == NULL) {
    346         ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM);
    347         return NULL;
    348     }
    349 
    350     ctx = OPENSSL_zalloc(sizeof(*ctx));
    351     if (ctx == NULL)
    352         return NULL;
    353     if (!CRYPTO_NEW_REF(&ctx->refcnt, 1)) {
    354         OPENSSL_free(ctx);
    355         return NULL;
    356     }
    357     if (parent != NULL) {
    358         if (!EVP_RAND_CTX_up_ref(parent)) {
    359             ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
    360             CRYPTO_FREE_REF(&ctx->refcnt);
    361             OPENSSL_free(ctx);
    362             return NULL;
    363         }
    364         parent_ctx = parent->algctx;
    365         parent_dispatch = parent->meth->dispatch;
    366     }
    367     if ((ctx->algctx = rand->newctx(ossl_provider_ctx(rand->prov), parent_ctx,
    368              parent_dispatch))
    369             == NULL
    370         || !EVP_RAND_up_ref(rand)) {
    371         ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
    372         rand->freectx(ctx->algctx);
    373         CRYPTO_FREE_REF(&ctx->refcnt);
    374         OPENSSL_free(ctx);
    375         EVP_RAND_CTX_free(parent);
    376         return NULL;
    377     }
    378     ctx->meth = rand;
    379     ctx->parent = parent;
    380     return ctx;
    381 }
    382 
    383 void EVP_RAND_CTX_free(EVP_RAND_CTX *ctx)
    384 {
    385     int ref = 0;
    386     EVP_RAND_CTX *parent;
    387 
    388     if (ctx == NULL)
    389         return;
    390 
    391     CRYPTO_DOWN_REF(&ctx->refcnt, &ref);
    392     if (ref > 0)
    393         return;
    394     parent = ctx->parent;
    395     ctx->meth->freectx(ctx->algctx);
    396     ctx->algctx = NULL;
    397     EVP_RAND_free(ctx->meth);
    398     CRYPTO_FREE_REF(&ctx->refcnt);
    399     OPENSSL_free(ctx);
    400     EVP_RAND_CTX_free(parent);
    401 }
    402 
    403 EVP_RAND *EVP_RAND_CTX_get0_rand(EVP_RAND_CTX *ctx)
    404 {
    405     return ctx->meth;
    406 }
    407 
    408 static int evp_rand_get_ctx_params_locked(EVP_RAND_CTX *ctx,
    409     OSSL_PARAM params[])
    410 {
    411     return ctx->meth->get_ctx_params(ctx->algctx, params);
    412 }
    413 
    414 int EVP_RAND_CTX_get_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[])
    415 {
    416     int res;
    417 
    418     if (!evp_rand_lock(ctx))
    419         return 0;
    420     res = evp_rand_get_ctx_params_locked(ctx, params);
    421     evp_rand_unlock(ctx);
    422     return res;
    423 }
    424 
    425 static int evp_rand_set_ctx_params_locked(EVP_RAND_CTX *ctx,
    426     const OSSL_PARAM params[])
    427 {
    428     if (ctx->meth->set_ctx_params != NULL)
    429         return ctx->meth->set_ctx_params(ctx->algctx, params);
    430     return 1;
    431 }
    432 
    433 int EVP_RAND_CTX_set_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[])
    434 {
    435     int res;
    436 
    437     if (!evp_rand_lock(ctx))
    438         return 0;
    439     res = evp_rand_set_ctx_params_locked(ctx, params);
    440     evp_rand_unlock(ctx);
    441     return res;
    442 }
    443 
    444 const OSSL_PARAM *EVP_RAND_gettable_params(const EVP_RAND *rand)
    445 {
    446     if (rand->gettable_params == NULL)
    447         return NULL;
    448     return rand->gettable_params(ossl_provider_ctx(EVP_RAND_get0_provider(rand)));
    449 }
    450 
    451 const OSSL_PARAM *EVP_RAND_gettable_ctx_params(const EVP_RAND *rand)
    452 {
    453     void *provctx;
    454 
    455     if (rand->gettable_ctx_params == NULL)
    456         return NULL;
    457     provctx = ossl_provider_ctx(EVP_RAND_get0_provider(rand));
    458     return rand->gettable_ctx_params(NULL, provctx);
    459 }
    460 
    461 const OSSL_PARAM *EVP_RAND_settable_ctx_params(const EVP_RAND *rand)
    462 {
    463     void *provctx;
    464 
    465     if (rand->settable_ctx_params == NULL)
    466         return NULL;
    467     provctx = ossl_provider_ctx(EVP_RAND_get0_provider(rand));
    468     return rand->settable_ctx_params(NULL, provctx);
    469 }
    470 
    471 const OSSL_PARAM *EVP_RAND_CTX_gettable_params(EVP_RAND_CTX *ctx)
    472 {
    473     void *provctx;
    474 
    475     if (ctx->meth->gettable_ctx_params == NULL)
    476         return NULL;
    477     provctx = ossl_provider_ctx(EVP_RAND_get0_provider(ctx->meth));
    478     return ctx->meth->gettable_ctx_params(ctx->algctx, provctx);
    479 }
    480 
    481 const OSSL_PARAM *EVP_RAND_CTX_settable_params(EVP_RAND_CTX *ctx)
    482 {
    483     void *provctx;
    484 
    485     if (ctx->meth->settable_ctx_params == NULL)
    486         return NULL;
    487     provctx = ossl_provider_ctx(EVP_RAND_get0_provider(ctx->meth));
    488     return ctx->meth->settable_ctx_params(ctx->algctx, provctx);
    489 }
    490 
    491 void EVP_RAND_do_all_provided(OSSL_LIB_CTX *libctx,
    492     void (*fn)(EVP_RAND *rand, void *arg),
    493     void *arg)
    494 {
    495     evp_generic_do_all(libctx, OSSL_OP_RAND,
    496         (void (*)(void *, void *))fn, arg,
    497         evp_rand_from_algorithm, evp_rand_up_ref,
    498         evp_rand_free);
    499 }
    500 
    501 int EVP_RAND_names_do_all(const EVP_RAND *rand,
    502     void (*fn)(const char *name, void *data),
    503     void *data)
    504 {
    505     if (rand->prov != NULL)
    506         return evp_names_do_all(rand->prov, rand->name_id, fn, data);
    507 
    508     return 1;
    509 }
    510 
    511 static int evp_rand_instantiate_locked(EVP_RAND_CTX *ctx, unsigned int strength, int prediction_resistance,
    512     const unsigned char *pstr, size_t pstr_len, const OSSL_PARAM params[])
    513 {
    514     return ctx->meth->instantiate(ctx->algctx, strength, prediction_resistance,
    515         pstr, pstr_len, params);
    516 }
    517 
    518 int EVP_RAND_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
    519     int prediction_resistance,
    520     const unsigned char *pstr, size_t pstr_len,
    521     const OSSL_PARAM params[])
    522 {
    523     int res;
    524 
    525     if (!evp_rand_lock(ctx))
    526         return 0;
    527     res = evp_rand_instantiate_locked(ctx, strength, prediction_resistance,
    528         pstr, pstr_len, params);
    529     evp_rand_unlock(ctx);
    530     return res;
    531 }
    532 
    533 static int evp_rand_uninstantiate_locked(EVP_RAND_CTX *ctx)
    534 {
    535     return ctx->meth->uninstantiate(ctx->algctx);
    536 }
    537 
    538 int EVP_RAND_uninstantiate(EVP_RAND_CTX *ctx)
    539 {
    540     int res;
    541 
    542     if (!evp_rand_lock(ctx))
    543         return 0;
    544     res = evp_rand_uninstantiate_locked(ctx);
    545     evp_rand_unlock(ctx);
    546     return res;
    547 }
    548 
    549 static int evp_rand_generate_locked(EVP_RAND_CTX *ctx, unsigned char *out,
    550     size_t outlen, unsigned int strength,
    551     int prediction_resistance,
    552     const unsigned char *addin,
    553     size_t addin_len)
    554 {
    555     size_t chunk, max_request = 0;
    556     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
    557 
    558     params[0] = OSSL_PARAM_construct_size_t(OSSL_RAND_PARAM_MAX_REQUEST,
    559         &max_request);
    560     if (!evp_rand_get_ctx_params_locked(ctx, params)
    561         || max_request == 0) {
    562         ERR_raise(ERR_LIB_EVP, EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE);
    563         return 0;
    564     }
    565     for (; outlen > 0; outlen -= chunk, out += chunk) {
    566         chunk = outlen > max_request ? max_request : outlen;
    567         if (!ctx->meth->generate(ctx->algctx, out, chunk, strength,
    568                 prediction_resistance, addin, addin_len)) {
    569             ERR_raise(ERR_LIB_EVP, EVP_R_GENERATE_ERROR);
    570             return 0;
    571         }
    572         /*
    573          * Prediction resistance is only relevant the first time around,
    574          * subsequently, the DRBG has already been properly reseeded.
    575          */
    576         prediction_resistance = 0;
    577     }
    578     return 1;
    579 }
    580 
    581 int EVP_RAND_generate(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen,
    582     unsigned int strength, int prediction_resistance,
    583     const unsigned char *addin, size_t addin_len)
    584 {
    585     int res;
    586 
    587     if (!evp_rand_lock(ctx))
    588         return 0;
    589     res = evp_rand_generate_locked(ctx, out, outlen, strength,
    590         prediction_resistance, addin, addin_len);
    591     evp_rand_unlock(ctx);
    592     return res;
    593 }
    594 
    595 static int evp_rand_reseed_locked(EVP_RAND_CTX *ctx, int prediction_resistance,
    596     const unsigned char *ent, size_t ent_len,
    597     const unsigned char *addin, size_t addin_len)
    598 {
    599     if (ctx->meth->reseed != NULL)
    600         return ctx->meth->reseed(ctx->algctx, prediction_resistance,
    601             ent, ent_len, addin, addin_len);
    602     return 1;
    603 }
    604 
    605 int EVP_RAND_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
    606     const unsigned char *ent, size_t ent_len,
    607     const unsigned char *addin, size_t addin_len)
    608 {
    609     int res;
    610 
    611     if (!evp_rand_lock(ctx))
    612         return 0;
    613     res = evp_rand_reseed_locked(ctx, prediction_resistance,
    614         ent, ent_len, addin, addin_len);
    615     evp_rand_unlock(ctx);
    616     return res;
    617 }
    618 
    619 static unsigned int evp_rand_strength_locked(EVP_RAND_CTX *ctx)
    620 {
    621     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
    622     unsigned int strength = 0;
    623 
    624     params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, &strength);
    625     if (!evp_rand_get_ctx_params_locked(ctx, params))
    626         return 0;
    627     return strength;
    628 }
    629 
    630 unsigned int EVP_RAND_get_strength(EVP_RAND_CTX *ctx)
    631 {
    632     unsigned int res;
    633 
    634     if (!evp_rand_lock(ctx))
    635         return 0;
    636     res = evp_rand_strength_locked(ctx);
    637     evp_rand_unlock(ctx);
    638     return res;
    639 }
    640 
    641 static int evp_rand_nonce_locked(EVP_RAND_CTX *ctx, unsigned char *out,
    642     size_t outlen)
    643 {
    644     unsigned int str = evp_rand_strength_locked(ctx);
    645 
    646     if (ctx->meth->nonce != NULL)
    647         return ctx->meth->nonce(ctx->algctx, out, str, outlen, outlen) > 0;
    648     return evp_rand_generate_locked(ctx, out, outlen, str, 0, NULL, 0);
    649 }
    650 
    651 int EVP_RAND_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen)
    652 {
    653     int res;
    654 
    655     if (ctx == NULL || out == NULL || outlen == 0) {
    656         ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
    657         return 0;
    658     }
    659 
    660     if (!evp_rand_lock(ctx))
    661         return 0;
    662     res = evp_rand_nonce_locked(ctx, out, outlen);
    663     evp_rand_unlock(ctx);
    664     return res;
    665 }
    666 
    667 int EVP_RAND_get_state(EVP_RAND_CTX *ctx)
    668 {
    669     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
    670     int state;
    671 
    672     params[0] = OSSL_PARAM_construct_int(OSSL_RAND_PARAM_STATE, &state);
    673     if (!EVP_RAND_CTX_get_params(ctx, params))
    674         state = EVP_RAND_STATE_ERROR;
    675     return state;
    676 }
    677 
    678 static int evp_rand_verify_zeroization_locked(EVP_RAND_CTX *ctx)
    679 {
    680     if (ctx->meth->verify_zeroization != NULL)
    681         return ctx->meth->verify_zeroization(ctx->algctx);
    682     return 0;
    683 }
    684 
    685 int EVP_RAND_verify_zeroization(EVP_RAND_CTX *ctx)
    686 {
    687     int res;
    688 
    689     if (!evp_rand_lock(ctx))
    690         return 0;
    691     res = evp_rand_verify_zeroization_locked(ctx);
    692     evp_rand_unlock(ctx);
    693     return res;
    694 }
    695 
    696 int evp_rand_can_seed(EVP_RAND_CTX *ctx)
    697 {
    698     return ctx->meth->get_seed != NULL;
    699 }
    700 
    701 static size_t evp_rand_get_seed_locked(EVP_RAND_CTX *ctx,
    702     unsigned char **buffer,
    703     int entropy,
    704     size_t min_len, size_t max_len,
    705     int prediction_resistance,
    706     const unsigned char *adin,
    707     size_t adin_len)
    708 {
    709     if (ctx->meth->get_seed != NULL)
    710         return ctx->meth->get_seed(ctx->algctx, buffer,
    711             entropy, min_len, max_len,
    712             prediction_resistance,
    713             adin, adin_len);
    714     return 0;
    715 }
    716 
    717 size_t evp_rand_get_seed(EVP_RAND_CTX *ctx,
    718     unsigned char **buffer,
    719     int entropy, size_t min_len, size_t max_len,
    720     int prediction_resistance,
    721     const unsigned char *adin, size_t adin_len)
    722 {
    723     int res;
    724 
    725     if (!evp_rand_lock(ctx))
    726         return 0;
    727     res = evp_rand_get_seed_locked(ctx,
    728         buffer,
    729         entropy, min_len, max_len,
    730         prediction_resistance,
    731         adin, adin_len);
    732     evp_rand_unlock(ctx);
    733     return res;
    734 }
    735 
    736 static void evp_rand_clear_seed_locked(EVP_RAND_CTX *ctx,
    737     unsigned char *buffer, size_t b_len)
    738 {
    739     if (ctx->meth->clear_seed != NULL)
    740         ctx->meth->clear_seed(ctx->algctx, buffer, b_len);
    741 }
    742 
    743 void evp_rand_clear_seed(EVP_RAND_CTX *ctx,
    744     unsigned char *buffer, size_t b_len)
    745 {
    746     if (!evp_rand_lock(ctx))
    747         return;
    748     evp_rand_clear_seed_locked(ctx, buffer, b_len);
    749     evp_rand_unlock(ctx);
    750 }
    751