EVP_RAND(3ossl)

๐Ÿ“ฆ version 3.5.0, in opensuse-leap 16.0

๐ŸŒธ NAME ๐ŸŒธ

okay bestie, so you know how your computer needs randomness โ€” like, actual good randomness โ€” for literally everything crypto? โœจ This is the OpenSSL 3 way to get it. It's the EVP RAND routines ๐ŸŽฒ๐Ÿ’–, from the 3ossl manual (that's OpenSSL's own man section, iykyk).

This page is giving main character energy and honestly it's a whole cast. Here's everyone ๐Ÿ‘‘:

  • The two leads: EVP_RAND and EVP_RAND_CTX โ€” the object and the context. You'll be seeing a lot of them ๐Ÿซถ
  • Getting one / letting one go: EVP_RAND_fetch, EVP_RAND_up_ref, EVP_RAND_free
  • Context life: EVP_RAND_CTX_new, EVP_RAND_CTX_free, EVP_RAND_CTX_up_ref
  • The actual RNG things, the plot: EVP_RAND_instantiate, EVP_RAND_uninstantiate, EVP_RAND_generate, EVP_RAND_reseed, EVP_RAND_nonce, EVP_RAND_enable_locking, EVP_RAND_verify_zeroization, EVP_RAND_get_strength, EVP_RAND_get_state
  • The identity check squad: EVP_RAND_get0_provider, EVP_RAND_CTX_get0_rand, EVP_RAND_is_a, EVP_RAND_get0_name, EVP_RAND_names_do_all, EVP_RAND_get0_description
  • Params, params, params (there are so many ๐Ÿ˜ญ): EVP_RAND_CTX_get_params, EVP_RAND_CTX_set_params, EVP_RAND_do_all_provided, EVP_RAND_get_params
  • And the "what can I even touch?" ones: EVP_RAND_gettable_ctx_params, EVP_RAND_settable_ctx_params, EVP_RAND_CTX_gettable_params, EVP_RAND_CTX_settable_params, EVP_RAND_gettable_params
  • The state machine besties: EVP_RAND_STATE_UNINITIALISED, EVP_RAND_STATE_READY, EVP_RAND_STATE_ERROR

That's a lot of names, I know. Breathe. It's literally all one topic โ€” the EVP layer's front door to random number generators ๐Ÿ’…


โœจ SYNOPSIS โœจ

okay so first things first, you gotta include the header, no cap:

#include <openssl/evp.h>

Then the two opaque types. These are opaque bestie, meaning you don't poke at their insides โ€” you treat them like a cute little black box and use the functions ๐ŸŽ:

typedef struct evp_rand_st EVP_RAND;
typedef struct evp_rand_ctx_st EVP_RAND_CTX;

Now the fetch/lifecycle girlies โ€” this is how you grab an RNG and how you say goodbye ๐Ÿ‘‹:

EVP_RAND *EVP_RAND_fetch(OSSL_LIB_CTX *libctx, const char *algorithm,
                       const char *properties);
int EVP_RAND_up_ref(EVP_RAND *rand);
void EVP_RAND_free(EVP_RAND *rand);
EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent);
void EVP_RAND_CTX_free(EVP_RAND_CTX *ctx);
int EVP_RAND_CTX_up_ref(EVP_RAND_CTX *ctx);
EVP_RAND *EVP_RAND_CTX_get0_rand(EVP_RAND_CTX *ctx);

Params time ๐Ÿ’… get and set, on both the object and the context:

int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[]);
int EVP_RAND_CTX_get_params(EVP_RAND_CTX *ctx, OSSL_PARAM params[]);
int EVP_RAND_CTX_set_params(EVP_RAND_CTX *ctx, const OSSL_PARAM params[]);

And the "what params exist though?" discovery functions โ€” very "let me check your vibe" of them ๐Ÿฆ‹:

const OSSL_PARAM *EVP_RAND_gettable_params(const EVP_RAND *rand);
const OSSL_PARAM *EVP_RAND_gettable_ctx_params(const EVP_RAND *rand);
const OSSL_PARAM *EVP_RAND_settable_ctx_params(const EVP_RAND *rand);
const OSSL_PARAM *EVP_RAND_CTX_gettable_params(EVP_RAND_CTX *ctx);
const OSSL_PARAM *EVP_RAND_CTX_settable_params(EVP_RAND_CTX *ctx);

Identity, names, provider โ€” the whole "who are you and who's your manager" section ๐Ÿ”:

const char *EVP_RAND_get0_name(const EVP_RAND *rand);
const char *EVP_RAND_get0_description(const EVP_RAND *rand);
int EVP_RAND_is_a(const EVP_RAND *rand, const char *name);
const OSSL_PROVIDER *EVP_RAND_get0_provider(const EVP_RAND *rand);
void EVP_RAND_do_all_provided(OSSL_LIB_CTX *libctx,
                              void (*fn)(EVP_RAND *rand, void *arg),
                              void *arg);
int EVP_RAND_names_do_all(const EVP_RAND *rand,
                          void (*fn)(const char *name, void *data),
                          void *data);

okay now the actually doing stuff section ๐Ÿ˜ค the RNG operations themselves:

int EVP_RAND_instantiate(EVP_RAND_CTX *ctx, unsigned int strength,
                         int prediction_resistance,
                         const unsigned char *pstr, size_t pstr_len,
                         const OSSL_PARAM params[]);
int EVP_RAND_uninstantiate(EVP_RAND_CTX *ctx);
int EVP_RAND_generate(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen,
                      unsigned int strength, int prediction_resistance,
                      const unsigned char *addin, size_t addin_len);
int EVP_RAND_reseed(EVP_RAND_CTX *ctx, int prediction_resistance,
                    const unsigned char *ent, size_t ent_len,
                    const unsigned char *addin, size_t addin_len);
int EVP_RAND_nonce(EVP_RAND_CTX *ctx, unsigned char *out, size_t outlen);
int EVP_RAND_enable_locking(EVP_RAND_CTX *ctx);
int EVP_RAND_verify_zeroization(EVP_RAND_CTX *ctx);
unsigned int EVP_RAND_get_strength(EVP_RAND_CTX *ctx);
int EVP_RAND_get_state(EVP_RAND_CTX *ctx);

and last but definitely not least, the state machine constants ๐Ÿ’… every RNG context is living in exactly one of these three moods:

#define EVP_RAND_STATE_UNINITIALISED    0
#define EVP_RAND_STATE_READY            1
#define EVP_RAND_STATE_ERROR            2
  • EVP_RAND_STATE_UNINITIALISED โ†’ value 0, it's brand new, nothing's happened yet ๐Ÿผ
  • EVP_RAND_STATE_READY โ†’ value 1, it's ready, slay ๐Ÿ’…
  • EVP_RAND_STATE_ERROR โ†’ value 2, something went wrong, we don't love that ๐Ÿ˜ญ
ngl that's a big synopsis. But every single one of those functions gets its moment, so don't skip ahead thinking "eh I'll figure it out" โ€” you won't, bestie, there are like forty of them ๐Ÿ’€

๐Ÿ’œ DESCRIPTION ๐Ÿ’œ

okay so real talk: the EVP RAND routines are like, a high-level interface to random number generators, both deterministic and not. ๐ŸŽฒ But listen โ€” if all you want is random bytes, you literally do not need any of this. Just call RAND_bytes() or RAND_priv_bytes() and go live your life. โœจ It's only when you want to do more that you should be using these calls instead of the older RAND and RAND_DRBG functions. Like, the old ones are giving "my mom's generation of crypto API", no shade.

So here's the flow, bestie: first you create an EVP_RAND_CTX for whatever algorithm you need using EVP_RAND_CTX_new(). Then you feed inputs to the algorithm โ€” either by passing them straight into the EVP_RAND_instantiate() call, or by calling EVP_RAND_CTX_set_params() before you call EVP_RAND_instantiate(). And finally?? You call EVP_RAND_generate() to actually produce your cryptographically secure random bytes. Periodt. ๐Ÿ”ฅ


๐Ÿฆ‹ Types ๐Ÿฆ‹

  • EVP_RAND โ€” a type that holds the implementation of a RAND. That's it, that's the whole vibe. ๐Ÿ’…
  • EVP_RAND_CTX โ€” a context type that holds the algorithm inputs. EVP_RAND_CTX structures are reference counted, so they're out here having main character energy with their own little refcounts. ๐Ÿ‘‘

๐ŸŒธ Algorithm implementation fetching ๐ŸŒธ

  • EVP_RAND_fetch() โ€” fetches an implementation of a RAND algorithm, given a library context libctx and a set of properties. Peep "ALGORITHM FETCHING" in crypto(7) for the full lore. ๐Ÿ“–
The returned value must eventually be freed with EVP_RAND_free(3). Don't forget, or you're leaking, and that's not the slay you think it is. ๐Ÿ’€
  • EVP_RAND_up_ref() โ€” increments the reference count of an already fetched RAND. Gimme one more, bestie. ๐Ÿซถ
  • EVP_RAND_free() โ€” frees a fetched algorithm. And NULL is a valid parameter here, in which case this function is a total no-op. Iconic, honestly.

๐ŸŽ€ Context manipulation functions ๐ŸŽ€

  • EVP_RAND_CTX_new() โ€” creates a new context for the RAND implementation rand. If it's not NULL, parent specifies the seed source for this implementation. Ngl, not all random number generators need a seed source specified. But if a parent is required and you pass a NULL parent, it'll go utilise the operating system entropy sources instead. And like โ€” it's recommended that you minimise the number of random number generators that rely on the operating system for their randomness, because it's often scarce. ๐Ÿ˜ญ so be mindful!
  • EVP_RAND_CTX_free() โ€” frees up the context ctx. If ctx is NULL, nothing is done. Zero drama, love that for us.
  • EVP_RAND_CTX_get0_rand() โ€” returns the EVP_RAND associated with the context ctx. โœจ

๐Ÿ”ฅ Random Number Generator Functions ๐Ÿ”ฅ

  • EVP_RAND_instantiate() โ€” processes any parameters in params and then instantiates the RAND ctx with a minimum security strength of strength and personalisation string pstr of length pstr_len. If prediction_resistance is specified, fresh entropy from a live source will be sought. This call operates as per NIST SP 800-90A and SP 800-90C. ๐Ÿงš
  • EVP_RAND_uninstantiate() โ€” uninstantiates the RAND ctx as per NIST SP 800-90A and SP 800-90C. After this call, the RAND cannot be used to generate bytes. It can only be freed or instantiated again. It's giving "we're on a break", not "we're done". ๐Ÿ™ˆ
  • EVP_RAND_generate() โ€” produces random bytes from the RAND ctx with the additional input addin of length addin_len. The bytes produced will meet the security strength. If prediction_resistance is specified, fresh entropy from a live source will be sought. This call operates as per NIST SP 800-90A and SP 800-90C. ๐ŸŽฒ
  • EVP_RAND_reseed() โ€” reseeds the RAND with new entropy. Entropy ent of length ent_len bytes can be supplied, as can additional input addin of length addin_len bytes. In the FIPS provider, both are treated as additional input as per NIST SP-800-90Ar1, Sections 9.1 and 9.2. Additional seed material is also drawn from the RAND's parent or the operating system. If prediction_resistance is specified, fresh entropy from a live source will be sought. This call operates as per NIST SP 800-90A and SP 800-90C. ๐ŸŒˆ
  • EVP_RAND_nonce() โ€” creates a nonce in out of maximum length outlen bytes from the RAND ctx. The function returns the length of the generated nonce. And if out is NULL, the length is still returned but no generation takes place โ€” which is lowkey genius, because it lets a caller dynamically allocate a buffer of the appropriate size. ๐Ÿ’ก
  • EVP_RAND_enable_locking() โ€” enables locking for the RAND ctx and all of its parents. After this, ctx will operate in a thread safe manner, albeit more slowly. Also heads up: this function is not itself thread safe if called with the same ctx from multiple threads. ๐Ÿ‘€ Typically locking should be enabled before a ctx is shared across multiple threads, so like, do it early, bestie.
  • EVP_RAND_get_params() โ€” retrieves details about the implementation rand. The set of parameters given with params determine exactly what parameters should be retrieved. Note that a parameter that is unknown in the underlying context is simply ignored. ๐Ÿ™…
  • EVP_RAND_CTX_get_params() โ€” retrieves chosen parameters, given the context ctx and its underlying context. The set of parameters given with params determine exactly what parameters should be retrieved. Note that a parameter that is unknown in the underlying context is simply ignored. Same rule, different function. ๐Ÿ’…
  • EVP_RAND_CTX_set_params() โ€” passes chosen parameters to the underlying context, given a context ctx. The set of parameters given with params determine exactly what parameters are passed down. Note that a parameter that is unknown in the underlying context is simply ignored. Also, what happens when a needed parameter isn't passed down is defined by the implementation โ€” so like, that part's on them, not us. ๐Ÿคท
  • EVP_RAND_gettable_params() โ€” returns an OSSL_PARAM(3) array that describes the retrievable and settable parameters. EVP_RAND_gettable_params() returns parameters that can be used with EVP_RAND_get_params(). ๐Ÿ“‹
  • EVP_RAND_gettable_ctx_params() and EVP_RAND_CTX_gettable_params() โ€” return constant OSSL_PARAM(3) arrays that describe the retrievable parameters that can be used with EVP_RAND_CTX_get_params(). EVP_RAND_gettable_ctx_params() returns the parameters that can be retrieved from the algorithm, whereas EVP_RAND_CTX_gettable_params() returns the parameters that can be retrieved in the context's current state. Two siblings, slightly different vibes. โœจ
  • EVP_RAND_settable_ctx_params() and EVP_RAND_CTX_settable_params() โ€” return constant OSSL_PARAM(3) arrays that describe the settable parameters that can be used with EVP_RAND_CTX_set_params(). EVP_RAND_settable_ctx_params() returns the parameters that can be retrieved from the algorithm, whereas EVP_RAND_CTX_settable_params() returns the parameters that can be retrieved in the context's current state. (Yeah, the wording's the same as above โ€” not me, that's just how it is. ๐Ÿ™ˆ)

โญ Information functions โญ

  • EVP_RAND_get_strength() โ€” returns the security strength of the RAND ctx. ๐Ÿ’ช
  • EVP_RAND_get_state() โ€” returns the current state of the RAND ctx. States defined by the OpenSSL RNGs are:
    • EVP_RAND_STATE_UNINITIALISED: this RNG is currently uninitialised. The instantiate call will change this to the ready state. ๐ŸŒฑ
    • EVP_RAND_STATE_READY: this RNG is currently ready to generate output. โšก
    • EVP_RAND_STATE_ERROR: this RNG is in an error state. ๐Ÿ’€
  • EVP_RAND_is_a() โ€” returns 1 if rand is an implementation of an algorithm that's identifiable with name, otherwise 0. Simple as.
  • EVP_RAND_get0_provider() โ€” returns the provider that holds the implementation of the given rand. ๐Ÿ 
  • EVP_RAND_do_all_provided() โ€” traverses all RAND implemented by all activated providers in the given library context libctx, and for each of the implementations, calls the given function fn with the implementation method and the given arg as argument. It's a whole tour. ๐ŸšŒ
  • EVP_RAND_get0_name() โ€” returns the canonical name of rand. ๐Ÿ’–
  • EVP_RAND_names_do_all() โ€” traverses all names for rand, and calls fn with each name and data. Aliases, everywhere.
  • EVP_RAND_get0_description() โ€” returns a description of the rand, meant for display and human consumption. The description is at the discretion of the rand implementation. So like, whatever they feel like writing. ๐Ÿ˜Œ
  • EVP_RAND_verify_zeroization() โ€” confirms if the internal DRBG state is currently zeroed. This is used by the FIPS provider to support the mandatory self tests. ๐Ÿงช

๐ŸŒˆ PARAMETERS ๐ŸŒˆ

The standard parameter names are, in no particular order, bestie โ€” here we go:

  • "state" (OSSL_RAND_PARAM_STATE) <integer> โ€” returns the state of the random number generator. ๐Ÿ”
  • "strength" (OSSL_RAND_PARAM_STRENGTH) <unsigned integer> โ€” returns the bit strength of the random number generator. ๐Ÿ’ช
  • "fips-indicator" (OSSL_RAND_PARAM_FIPS_APPROVED_INDICATOR) <integer> โ€” a getter that returns 1 if the operation is FIPS approved, or 0 otherwise. This option is used by the OpenSSL FIPS provider and is not supported by all EVP_RAND sources. โš ๏ธ not universal, so check before you assume!

For rands that are also deterministic random bit generators (DRBGs), these additional parameters are recognised. Not all parameters are relevant to, or are understood by all DRBG rands, just so you know. ๐Ÿซถ

  • "reseed_requests" (OSSL_DRBG_PARAM_RESEED_REQUESTS) <unsigned integer> โ€” reads or set the number of generate requests before reseeding the associated RAND ctx. ๐Ÿ”
  • "reseed_time_interval" (OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL) <integer> โ€” reads or set the number of elapsed seconds before reseeding the associated RAND ctx. โฐ
  • "max_request" (OSSL_RAND_PARAM_MAX_REQUEST) <unsigned integer> โ€” specifies the maximum number of bytes that can be generated in a single call to OSSL_FUNC_rand_generate. ๐Ÿ“
  • "min_entropylen" (OSSL_DRBG_PARAM_MIN_ENTROPYLEN) <unsigned integer>
  • "max_entropylen" (OSSL_DRBG_PARAM_MAX_ENTROPYLEN) <unsigned integer> โ€” specify the minimum and maximum number of bytes of random material that can be used to seed the DRBG. ๐ŸŒฑ
  • "min_noncelen" (OSSL_DRBG_PARAM_MIN_NONCELEN) <unsigned integer>
  • "max_noncelen" (OSSL_DRBG_PARAM_MAX_NONCELEN) <unsigned integer> โ€” specify the minimum and maximum number of bytes of nonce that can be used to seed the DRBG. ๐ŸŽซ
  • "max_perslen" (OSSL_DRBG_PARAM_MAX_PERSLEN) <unsigned integer>
  • "max_adinlen" (OSSL_DRBG_PARAM_MAX_ADINLEN) <unsigned integer> โ€” specify the minimum and maximum number of bytes of personalisation string that can be used with the DRBG. ๐ŸŽ€
  • "reseed_counter" (OSSL_DRBG_PARAM_RESEED_COUNTER) <unsigned integer> โ€” specifies the number of times the DRBG has been seeded or reseeded. ๐Ÿงฎ
  • "properties" (OSSL_RAND_PARAM_PROPERTIES) <UTF8 string>
  • "mac" (OSSL_RAND_PARAM_MAC) <UTF8 string>
  • "digest" (OSSL_RAND_PARAM_DIGEST) <UTF8 string>
  • "cipher" (OSSL_RAND_PARAM_CIPHER) <UTF8 string> โ€” for RAND implementations that use an underlying computation MAC, digest or cipher, these parameters set what the algorithm should be. โœจ

The value is always the name of the intended algorithm, or the properties in the case of OSSL_RAND_PARAM_PROPERTIES. ๐Ÿ’…

๐ŸŒธ NOTES ๐ŸŒธ

okay so bestie, listen up, because this part is lowkey important ๐Ÿ’…

  • Using a nonzero value for the prediction_resistance argument to EVP_RAND_instantiate(), EVP_RAND_generate() or EVP_RAND_reseed()? Use it sparingly, fr fr. In the default setup, this will cause all public and private DRBGs to be reseeded on next use. And since, by default, public and private DRBGs are allocated on a per thread basis, this can result in significant overhead for highly multi-threaded applications ๐Ÿ˜ญ like, imagine the whole group chat reseeding at once.
  • For normal use-cases, the default "reseed_requests" and "reseed_time_interval" thresholds ensure sufficient prediction resistance over time, and you can totally reduce those values if you think they're too high. โœจ
  • Explicitly requesting prediction resistance is intended for more special use-cases โ€” like generating long-term secrets. ๐Ÿ‘‘ iykyk.

Also: an EVP_RAND_CTX needs to have locking enabled if it acts as the parent of more than one child and the children can be accessed concurrently. This must be done by explicitly calling EVP_RAND_enable_locking(). ๐Ÿซถ no shortcuts, bestie.

The RAND life-cycle is described in life_cycle-rand(7). In the future, the transitions described there will be enforced. When this is done, it will not be considered a breaking change to the API. ๐Ÿ™ˆ

๐Ÿฆ‹ RETURN VALUES ๐Ÿฆ‹

okay bestie, here's the vibe check on what everything gives back ๐Ÿ’–

  • EVP_RAND_fetch() returns a pointer to a newly fetched EVP_RAND, or NULL if allocation failed.
  • EVP_RAND_get0_provider() returns a pointer to the provider for the RAND, or NULL on error.
  • EVP_RAND_CTX_get0_rand() returns a pointer to the EVP_RAND associated with the context.
  • EVP_RAND_get0_name() returns the name of the random number generation algorithm. โœจ
  • EVP_RAND_up_ref() returns 1 on success, 0 on error.
  • EVP_RAND_names_do_all() returns 1 if the callback was called for all names. A return value of 0 means that the callback was not called for any names.
  • EVP_RAND_CTX_new() returns either the newly allocated EVP_RAND_CTX structure or NULL if an error occurred.
  • EVP_RAND_CTX_free() does not return a value. (it's giving "no thoughts, just vibes" ๐Ÿ’€)
  • EVP_RAND_CTX_up_ref() returns 1 on success, 0 on error.
  • EVP_RAND_nonce() returns the length of the nonce.
  • EVP_RAND_get_strength() returns the strength of the random number generator in bits. ๐Ÿ’ช
  • EVP_RAND_gettable_params(), EVP_RAND_gettable_ctx_params() and EVP_RAND_settable_ctx_params() return an array of OSSL_PARAMs.
  • EVP_RAND_verify_zeroization() returns 1 if the internal DRBG state is currently zeroed, and 0 if not.
  • The remaining functions return 1 for success and 0 or a negative value for failure.

๐ŸŒˆ SEE ALSO ๐ŸŒˆ

go read these next, bestie, they all ate ๐Ÿ‘‘

๐Ÿ’œ HISTORY ๐Ÿ’œ

story time โœจ

  • EVP_RAND_CTX_up_ref() was added in OpenSSL 3.1.
  • The remaining functions were added in OpenSSL 3.0.

Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>. ๐Ÿซถ


and that's a wrap on the whole page, bestie!! ๐ŸŽ€ the source is OpenSSL 3.5.0, dated 2026-09-25, and it's the EVP_RAND(3ossl) page ๐Ÿ’– slay, you read the whole thing, so proud of you fr fr ๐ŸŒธ๐Ÿฆ‹โœจ

๐Ÿ“ฆ where this page comes from