X-Git-Url: https://www.bearssl.org/gitweb//home/git/?p=BearSSL;a=blobdiff_plain;f=inc%2Fbearssl_rand.h;h=2cc9ace382116ed194ee16781b4041d93fc260c7;hp=0c3bc4deea7a19899d3c3f109bdd285edab2863a;hb=5f045c759957fdff8c85716e6af99e10901fdac0;hpb=3210f38e0491b39aec1ef419cb4114e9483089fb diff --git a/inc/bearssl_rand.h b/inc/bearssl_rand.h index 0c3bc4d..2cc9ace 100644 --- a/inc/bearssl_rand.h +++ b/inc/bearssl_rand.h @@ -28,117 +28,220 @@ #include #include -/* - * Pseudo-Random Generators - * ------------------------ +/** \file bearssl_rand.h + * + * # Pseudo-Random Generators * * A PRNG is a state-based engine that outputs pseudo-random bytes on * demand. It is initialized with an initial seed, and additional seed - * bytes can be added afterwards. Bytes produced depend on the seeds - * and also on the exact sequence of calls (including sizes requested - * for each call). - * - * An object-oriented API is defined, with rules similar to that of - * hash functions. The context structure for a PRNG must start with - * a pointer to the vtable. The vtable contains the following fields: - * - * context_size size of the context structure for this PRNG - * init initialize context with an initial seed - * generate produce some pseudo-random bytes - * update insert some additional seed - * - * Note that the init() method may accept additional parameters, provided - * as a 'const void *' pointer at API level. These additional parameters - * depend on the implemented PRNG. + * bytes can be added afterwards. Bytes produced depend on the seeds and + * also on the exact sequence of calls (including sizes requested for + * each call). + * + * + * ## Procedural and OOP API + * + * For the PRNG of name "`xxx`", two API are provided. The _procedural_ + * API defined a context structure `br_xxx_context` and three functions: + * + * - `br_xxx_init()` + * + * Initialise the context with an initial seed. + * + * - `br_xxx_generate()` + * + * Produce some pseudo-random bytes. + * + * - `br_xxx_update()` + * + * Inject some additional seed. + * + * The initialisation function sets the first context field (`vtable`) + * to a pointer to the vtable that supports the OOP API. The OOP API + * provides access to the same functions through function pointers, + * named `init()`, `generate()` and `update()`. + * + * Note that the context initialisation method may accept additional + * parameters, provided as a 'const void *' pointer at API level. These + * additional parameters depend on the implemented PRNG. + * + * + * ## HMAC_DRBG + * + * HMAC_DRBG is defined in [NIST SP 800-90A Revision + * 1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf). + * It uses HMAC repeatedly, over some configurable underlying hash + * function. In BearSSL, it is implemented under the "`hmac_drbg`" name. + * The "extra parameters" pointer for context initialisation should be + * set to a pointer to the vtable for the underlying hash function (e.g. + * pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256). + * + * According to the NIST standard, each request shall produce up to + * 219 bits (i.e. 64 kB of data); moreover, the context shall + * be reseeded at least once every 248 requests. This + * implementation does not maintain the reseed counter (the threshold is + * too high to be reached in practice) and does not object to producing + * more than 64 kB in a single request; thus, the code cannot fail, + * which corresponds to the fact that the API has no room for error + * codes. However, this implies that requesting more than 64 kB in one + * `generate()` request, or making more than 248 requests + * without reseeding, is formally out of NIST specification. There is + * no currently known security penalty for exceeding the NIST limits, + * and, in any case, HMAC_DRBG usage in implementing SSL/TLS always + * stays much below these thresholds. */ +/** + * \brief Class type for PRNG implementations. + * + * A `br_prng_class` instance references the methods implementing a PRNG. + * Constant instances of this structure are defined for each implemented + * PRNG. Such instances are also called "vtables". + */ typedef struct br_prng_class_ br_prng_class; struct br_prng_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate for + * running this PRNG. + */ size_t context_size; + + /** + * \brief Initialisation method. + * + * The context to initialise is provided as a pointer to its + * first field (the vtable pointer); this function sets that + * first field to a pointer to the vtable. + * + * The extra parameters depend on the implementation; each + * implementation defines what kind of extra parameters it + * expects (if any). + * + * Requirements on the initial seed depend on the implemented + * PRNG. + * + * \param ctx PRNG context to initialise. + * \param params extra parameters for the PRNG. + * \param seed initial seed. + * \param seed_len initial seed length (in bytes). + */ void (*init)(const br_prng_class **ctx, const void *params, const void *seed, size_t seed_len); + + /** + * \brief Random bytes generation. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. + * + * \param ctx PRNG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ void (*generate)(const br_prng_class **ctx, void *out, size_t len); + + /** + * \brief Inject additional seed bytes. + * + * The provided seed bytes are added into the PRNG internal + * entropy pool. + * + * \param ctx PRNG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ void (*update)(const br_prng_class **ctx, const void *seed, size_t seed_len); }; -/* - * HMAC_DRBG is a pseudo-random number generator based on HMAC (with - * an underlying hash function). HMAC_DRBG is specified in NIST Special - * Publication 800-90A. It works as a stateful machine: - * -- It has an internal state. - * -- The state can be updated with additional "entropy" (some bytes - * provided from the outside). - * -- Each request is for some bits (up to some limit). For each request, - * an internal "reseed counter" is incremented. - * -- When the reseed counter reaches a given threshold, a reseed is - * necessary. - * - * Standard limits are quite high: each request can produce up to 2^19 - * bits (i.e. 64 kB of data), and the threshold for the reseed counter - * is 2^48. In practice, we cannot really reach that reseed counter, so - * the implementation simply omits the counter. Similarly, we consider - * that it is up to callers NOT to ask for more than 64 kB of randomness - * in one go. Under these conditions, this implementation cannot fail, - * and thus functions need not return any status code. - * - * (Asking for more than 64 kB of data in one generate() call won't make - * the implementation fail, and, as far as we know, it will not induce - * any actual weakness; this is "merely" out of the formal usage range - * defined for HMAC_DRBG.) - * - * A dedicated context structure (caller allocated, as usual) contains - * the current PRNG state. - * - * For the OOP interface, the "additional parameters" are a pointer to - * the class of the hash function to use. +/** + * \brief Context for HMAC_DRBG. + * + * The context contents are opaque, except the first field, which + * supports OOP. */ - typedef struct { + /** + * \brief Pointer to the vtable. + * + * This field is set with the initialisation method/function. + */ const br_prng_class *vtable; +#ifndef BR_DOXYGEN_IGNORE unsigned char K[64]; unsigned char V[64]; const br_hash_class *digest_class; +#endif } br_hmac_drbg_context; +/** + * \brief Statically allocated, constant vtable for HMAC_DRBG. + */ extern const br_prng_class br_hmac_drbg_vtable; -/* - * Initialize a HMAC_DRBG instance, with the provided initial seed (of - * 'len' bytes). The 'seed' used here is what is called, in SP 800-90A - * terminology, the concatenation of the "seed", "nonce" and - * "personalization string", in that order. - * - * Formally, the underlying digest can only be SHA-1 or one of the SHA-2 - * functions. This implementation also works with any other implemented - * hash function (e.g. MD5), but such usage is non-standard and not - * recommended. +/** + * \brief HMAC_DRBG initialisation. + * + * The context to initialise is provided as a pointer to its first field + * (the vtable pointer); this function sets that first field to a + * pointer to the vtable. + * + * The `seed` value is what is called, in NIST terminology, the + * concatenation of the "seed", "nonce" and "personalization string", in + * that order. + * + * The `digest_class` parameter defines the underlying hash function. + * Formally, the NIST standard specifies that the hash function shall + * be only SHA-1 or one of the SHA-2 functions. This implementation also + * works with any other implemented hash function (such as MD5), but + * this is non-standard and therefore not recommended. + * + * \param ctx HMAC_DRBG context to initialise. + * \param digest_class vtable for the underlying hash function. + * \param seed initial seed. + * \param seed_len initial seed length (in bytes). */ void br_hmac_drbg_init(br_hmac_drbg_context *ctx, - const br_hash_class *digest_class, const void *seed, size_t len); + const br_hash_class *digest_class, const void *seed, size_t seed_len); -/* - * Obtain some pseudorandom bits from HMAC_DRBG. The provided context - * is updated. The output bits are written in 'out' ('len' bytes). The - * size of the requested chunk of pseudorandom bits MUST NOT exceed - * 64 kB (the function won't fail if more bytes are requested, but - * the usage will be outside of the HMAC_DRBG specification limits). +/** + * \brief Random bytes generation with HMAC_DRBG. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. Formally, requesting + * more than 65536 bytes in one request falls out of specification + * limits (but it won't fail). + * + * \param ctx HMAC_DRBG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. */ void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len); -/* - * Update an HMAC_DRBG instance with some new entropy. The extra 'seed' - * complements the current state but does not completely replace any - * previous seed. The process is such that pushing new entropy, even of - * questionable quality, will not make the output "less random" in any - * practical way. +/** + * \brief Inject additional seed bytes in HMAC_DRBG. + * + * The provided seed bytes are added into the HMAC_DRBG internal + * entropy pool. The process does not _replace_ existing entropy, + * thus pushing non-random bytes (i.e. bytes which are known to the + * attackers) does not degrade the overall quality of generated bytes. + * + * \param ctx HMAC_DRBG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). */ void br_hmac_drbg_update(br_hmac_drbg_context *ctx, - const void *seed, size_t len); + const void *seed, size_t seed_len); -/* - * Get the hash function implementation used by a given instance of +/** + * \brief Get the hash function implementation used by a given instance of * HMAC_DRBG. + * + * This calls MUST NOT be performed on a context which was not + * previously initialised. + * + * \param ctx HMAC_DRBG context. + * \return the hash function vtable. */ static inline const br_hash_class * br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx)