CPRNG(9) Kernel Developer's Manual CPRNG(9)

NAME

cprng, cprng_strong_create, cprng_strong_destroy, cprng_strong, cprng_strong32, cprng_strong64, cprng_fast, cprng_fast32, cprng_fast64, — cryptographic pseudorandom number generators

SYNOPSIS

#include <sys/cprng.h>

cprng_strong_t *
cprng_strong_create(const char *name, int ipl, int flags);

void
cprng_strong_destroy(cprng_strong_t *cprng);

size_t
cprng_strong(cprng_strong_t *cprng, void *buf, size_t len, int flags);

uint32_t
cprng_strong32(void);

uint64_t
cprng_strong64(void);

size_t
cprng_fast(void *buf, size_t len);

uint32_t
cprng_fast32(void);

uint32_t
cprng_fast64(void);

#define CPRNG_MAX_LEN   524288

DESCRIPTION

The cprng family of functions provide cryptographic pseudorandom number generators automatically seeded from the kernel entropy pool. They replace the arc4random(9) and rnd_extract_data(9) functions for this purpose. The NetBSD kernel no longer supports direct reading from the kernel entropy pool; all access is mediated by the cprng functions.

The “strong” family of functions use cryptographically strong pseudorandom number generators suitable for keying crypto systems and similar purposes. Calls to rnd_extract_data(9) should be replaced by calls to cprng_strong().

The “fast” family of functions use cryptographically weaker pseudorandom number generators suitable for initialization vectors, nonces in certain protocols, and other similar purposes, using a faster but less secure stream-cipher-based generator. Calls to arc4random(9) should be replaced by calls to cprng_fast32(), and calls to arc4randbytes(9) should be replaced by calls to cprng_fast().

A single instance of the fast generator serves the entire kernel. A well-known instance of the strong generator, kern_cprng, may be used by any in-kernel caller, but separately seeded instances of the strong generator can also be created by calling cprng_strong_create().

FUNCTIONS

cprng_strong_create(name, ipl, flags)
Create an instance of the cprng_strong generator. This generator implements the NIST SP 800-90 CTR_DRBG with AES128 as the block transform.

The name argument is used to “personalize” the CTR_DRBG according to the standard, so that its initial state will depend both on seed material from the entropy pool and also on the personalization string (name).

The ipl argument specifies the interrupt priority level for the mutex which will serialize access to the new instance of the generator (see spl(9)), and must be no higher than IPL_VM.

The flags argument controls the behavior of the generator:

CPRNG_INIT_ANY
Suppress a warning message to the console if, during cprng_strong_create(), only partial entropy for the generator is available from the entropy pool.
CPRNG_REKEY_ANY
Suppress a warning message to the console if, during cprng_strong() after the generator has been exhausted and must be reseeded, only partial entropy for the generator is available from the entropy pool.
CPRNG_USE_CV
Make cprng_strong() sleep if the generator has not been seeded with full entropy until full entropy is available. Otherwise, cprng_strong() will never sleep when passed this generator.
CPRNG_HARD
Limit the number of bits of output from the generator before reseeding to the number of bits in its seed, so that it approximates the information-theoretic entropy of its seed. Otherwise, the generator may provide many more bits of output than it was seeded with.

Creation will succeed even if full entropy for the generator is not available. In this case, the first request to read from the generator may cause reseeding.

cprng_strong_create() may sleep to allocate memory.

cprng_strong_destroy(cprng)
Destroy cprng.

cprng_strong_destroy() may sleep.

cprng_strong(cprng, buf, len, flags)
Fill memory location buf with up to len bytes from the generator cprng, and return the number of bytes. len must be at most CPRNG_MAX_LEN.

If cprng was created with the CPRNG_USE_CV flag and has been exhausted, then cprng_strong() may sleep until full entropy can be obtained from the entropy pool to reseed it. However, if flags includes the FNONBLOCK flag, then cprng_strong() will immediately return zero in this case instead.

If cprng was created with the CPRNG_HARD flag, then cprng_strong() will return at most as many bytes as are left from its seed size since the last reseeding.

If cprng was created with neither the CPRNG_USE_CV flag nor the CPRNG_HARD flag, then cprng_strong() is guaranteed to return as many bytes as requested, up to CPRNG_MAX_LEN, without sleeping.

cprng_strong32()
Generate 32 bits using the kern_cprng strong generator.

cprng_strong32() does not sleep.

cprng_strong64()
Generate 64 bits using the kern_cprng strong generator.

cprng_strong64() does not sleep.

cprng_fast(buf, len)
Fill memory location buf with len bytes from the fast generator.

cprng_fast() does not sleep.

cprng_fast32()
Generate 32 bits using the fast generator.

cprng_fast32() does not sleep.

cprng_fast64()
Generate 64 bits using the fast generator.

cprng_fast64() does not sleep.

CODE REFERENCES

The cprng API is implemented by sys/kern/subr_cprng.c and sys/sys/cprng.h. The “strong” generator uses the CTR_DRBG implementation in sys/crypto/nist_ctr_drbg. The “fast” generator uses the arc4random implementation in sys/lib/libkern/arc4random.c.

SEE ALSO

condvar(9), rnd(9), spl(9)

Elaine Barker and John Kelsey, Recommendation for Random Number Generation Using Deterministic Random Bit Generators (Revised), National Institute of Standards and Technology, 2011, NIST Special Publication 800-90A, Rev 1.

HISTORY

The cprng family of functions first appeared in NetBSD 6.0.
July 18, 2013 NetBSD 6.99