Open-Source Wikis

/

OpenSSL

/

Subsystems

/

Random

openssl/openssl

Random

Active contributors: Pauli, Tomas Mraz, slontis, Bob Beck

Purpose

OpenSSL builds a hierarchy of NIST SP 800-90A DRBGs (CTR, HMAC, HASH) seeded from an OS-provided entropy source (or a CPU jitter source on FIPS builds). The hierarchy gives every libctx and every thread its own DRBG instance while sharing a small number of seed sources.

The user-facing API is the legacy RAND_* family (RAND_bytes, RAND_priv_bytes, RAND_status, …) plus the modern EVP_RAND / EVP_RAND_CTX from EVP. Both ultimately call into the same provider implementations.

Directory layout

crypto/rand/
├── rand_lib.c            -- the public RAND_* API and the per-libctx DRBG hierarchy
├── rand_local.h
├── rand_pool.c           -- entropy pool helper
├── rand_unix.c           -- Linux/macOS/BSD entropy collector (getrandom, /dev/urandom, ...)
├── rand_win.c            -- Windows entropy collector
├── rand_vms.c            -- VMS entropy collector
├── rand_vxworks.c        -- VxWorks entropy collector
├── rand_uefi.c           -- UEFI entropy collector
├── rand_egd.c            -- EGD-style entropy daemon support
├── rand_meth.c, randfile.c, rand_deprecated.c, rand_err.c
├── rand_seed.c           -- the OS-independent "seed source" interface
└── prov_seed.c           -- the seed source exposed back to providers via the OSSL_OP_RAND interface

providers/implementations/rands/
├── drbg.c                -- the DRBG state machine common to all three variants
├── drbg_local.h
├── drbg_ctr.c            -- AES-CTR-DRBG (NIST SP 800-90A)
├── drbg_hash.c           -- HASH-DRBG (NIST SP 800-90A)
├── drbg_hmac.c           -- HMAC-DRBG (NIST SP 800-90A)
├── seeding/              -- platform-specific entropy gathering helpers (used by both rand and FIPS)
├── seed_src.c            -- the SEED-SRC pseudo-RAND used by the DRBGs to draw from the OS entropy
├── seed_src_jitter.c     -- the jitter entropy variant (FIPS jitter mode)
├── crngt.c               -- the continuous RNG self-test
└── test_rng.c            -- the deterministic test-only RAND used in unit tests

DRBG hierarchy

graph TD
    OS[OS entropy<br/>getrandom / RDRAND fallback / /dev/urandom / ...] -->|seeds| Primary
    Primary[Primary DRBG<br/>per OSSL_LIB_CTX] -->|reseeds| Public
    Primary -->|reseeds| Private
    Public[Public DRBG<br/>per thread] -->|RAND_bytes| App
    Private[Private DRBG<br/>per thread] -->|RAND_priv_bytes| App

For each OSSL_LIB_CTX:

  • One primary DRBG draws entropy from the OS seed source.
  • Each thread has its own public and private DRBG that periodically reseed from the primary.
  • RAND_bytes consumes the public DRBG; RAND_priv_bytes consumes the private DRBG (used when generating long-lived secrets like RSA private keys, so a forensics-style compromise of one stream doesn't leak the other).

The reseed schedule is controlled by OSSL_DRBG_PARAM_RESEED_* parameters (interval, time, requests) — see include/openssl/core_names.h.in.

Selecting the DRBG type

By default the primary uses CTR-DRBG over AES-256 (also denoted CTR-DRBG-AES256). It is the fastest of the three on x86 with AES-NI. To pick a different one:

EVP_set_default_properties(libctx, "");
RAND_set_DRBG_type(libctx, "HASH-DRBG", NULL, NULL, NULL);

Or per-libctx via openssl.cnf (RANDFILE / [rand] section).

Compile-time flag OPENSSL_DEFAULT_RAND_TYPE controls the build's preferred primary.

Entropy sources

crypto/rand/rand_unix.c (and the per-OS counterparts) try a sequence of entropy mechanisms:

  1. getrandom(GRND_NONBLOCK) (Linux, FreeBSD ≥ 12, OpenBSD ≥ 5.6, …).
  2. getentropy() (macOS, OpenBSD).
  3. /dev/urandom.
  4. CPU instructions (RDRAND/RDSEED via crypto/cpuid.c and the asm helpers).
  5. EGD-style daemons (rand_egd.c).

The collector pushes raw bytes into a pool managed by rand_pool.c, then condenses them into a seed for the primary DRBG.

Continuous self-test

The Continuous RNG Test (CRNGT, crngt.c) verifies that consecutive raw entropy draws are not equal — defense against a stuck source. It runs on every block of entropy drawn from the seed source and is mandatory for FIPS.

FIPS mode

When the FIPS provider is loaded, it has its own DRBG hierarchy inside its private libctx (a "child" libctx — see subsystems/core-and-libctx). The same DRBG state machine in providers/implementations/rands/drbg.c is reused. Two FIPS-relevant entropy options:

  • External entropy (default): the FIPS module uses a host-provided entropy source via OSSL_FUNC_RAND_GET_SEED.
  • Jitter entropy (with enable-fips-jitter, 3.5+): the module ships its own jitter source. This makes the module non-compliant unless an ESV is independently completed; see README-FIPS.md.

Test RAND

test_rng.c is a deterministic RAND that the test suite installs to make crypto tests reproducible. OPENSSL_TEST_RAND_SEED=42 make test seeds it from the env var.

Integration points

  • Every RAND_bytes / RAND_priv_bytes call routes through the per-libctx DRBG hierarchy.
  • Asymmetric key generation uses RAND_priv_bytes. Symmetric IVs use RAND_bytes.
  • TLS 1.3 / QUIC generate random data via the same hierarchy; EVP_RAND_CTX directly when very large or non-default amounts are needed.
  • Providers call back into core via OSSL_FUNC_get_seed / OSSL_FUNC_clear_seed when they need entropy (this is how the FIPS provider gets its seed).

Entry points for modification

  • New entropy source: add a backend in crypto/rand/rand_<plat>.c and route it via crypto/rand/rand_lib.c. Be careful with reentrancy — the seed path runs at first-use of any DRBG.
  • New DRBG variant: extend providers/implementations/rands/drbg_*.c, register it in the provider table.
  • Reseed policy: per-instance OSSL_DRBG_PARAM_* parameters. Defaults are in drbg_local.h.

Documentation

  • doc/man7/RAND.pod, doc/man3/RAND_bytes.pod, RAND_set_DRBG_type.pod, EVP_RAND.pod.
  • doc/man3/RAND_load_file.pod — file-based seeding.
  • doc/man7/EVP_RAND-CTR-DRBG.pod, EVP_RAND-HASH-DRBG.pod, EVP_RAND-HMAC-DRBG.pod, EVP_RAND-JITTER.pod, EVP_RAND-SEED-SRC.pod.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Random – OpenSSL wiki | Factory