From: Thomas Pornin Date: Sat, 19 Nov 2016 18:05:08 +0000 (+0100) Subject: More Doxygen-compatible documentation. Also unified two identical structures. X-Git-Tag: v0.4~53 X-Git-Url: https://bearssl.org/gitweb//home/git/?a=commitdiff_plain;h=e683ebfe1962ef5b00a972761984674528922a4a;p=BearSSL More Doxygen-compatible documentation. Also unified two identical structures. --- diff --git a/Doxyfile b/Doxyfile index 57b5325..0fa968a 100644 --- a/Doxyfile +++ b/Doxyfile @@ -771,7 +771,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = inc/bearssl_hash.h +INPUT = inc/bearssl.h inc/bearssl_hash.h inc/bearssl_hmac.h inc/bearssl_prf.h inc/bearssl_rand.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -946,7 +946,7 @@ INLINE_SOURCES = NO # Fortran comments will always remain visible. # The default value is: YES. -STRIP_CODE_COMMENTS = YES +STRIP_CODE_COMMENTS = NO # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. @@ -1840,7 +1840,7 @@ RTF_SOURCE_CODE = NO # classes and files. # The default value is: NO. -GENERATE_MAN = YES +GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of diff --git a/inc/bearssl.h b/inc/bearssl.h index c11080e..6258e92 100644 --- a/inc/bearssl.h +++ b/inc/bearssl.h @@ -28,6 +28,90 @@ #include #include +/** \mainpage BearSSL API + * + * # API Layout + * + * The functions and structures defined by the BearSSL API are located + * in various header files: + * + * | Header file | Elements | + * | :-------------- | :------------------------------------------------ | + * | bearssl_hash.h | Hash functions | + * | bearssl_hmac.h | HMAC | + * | bearssl_rand.h | Pseudorandom byte generators | + * | bearssl_prf.h | PRF implementations (for SSL/TLS) | + * | bearssl_block.h | Symmetric encryption | + * | bearssl_rsa.h | RSA encryption and signatures | + * | bearssl_ec.h | Elliptic curves support (including ECDSA) | + * | bearssl_ssl.h | SSL/TLS engine interface | + * | bearssl_x509.h | X.509 certificate decoding and validation | + * | bearssl_pem.h | Base64/PEM decoding support functions | + * + * Applications using BearSSL are supposed to simply include `bearssl.h` + * as follows: + * + * #include + * + * The `bearssl.h` file itself includes all the other header files. It is + * possible to include specific header files, but it has no practical + * advantage for the application. The API is separated into separate + * header files only for documentation convenience. + * + * + * # Conventions + * + * ## MUST and SHALL + * + * In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology + * is used. Failure to meet requirements expressed with a "MUST" or + * "SHALL" implies undefined behaviour, which means that segmentation + * faults, buffer overflows, and other similar adverse events, may occur. + * + * In general, BearSSL is not very forgiving of programming errors, and + * does not include much failsafes or error reporting when the problem + * does not arise from external transient conditions, and can be fixed + * only in the application code. This is done so in order to make the + * total code footprint ligther. + * + * + * ## Memory Allocation + * + * BearSSL does not perform dynamic memory allocation. This implies that + * for any functionality that requires a non-transient state, the caller + * is responsible for allocating the relevant context structure. Such + * allocation can be done in any appropriate area, including static data + * segments, the heap, and the stack, provided that proper alignment is + * respected. The header files define these context structures + * (including size and contents), so the C compiler should handle + * alignment automatically. + * + * Since there is no dynamic resource allocation, there is also nothing to + * release. When the calling code is done with a BearSSL feature, it + * may simple release the context structures it allocated itself, with + * no "close function" to call. If the context structures were allocated + * on the stack (as local variables), then even that release operation is + * implicit. + * + * + * ## Structure Contents + * + * Except when explicitly indicated, structure contents are opaque: they + * are included in the header files so that calling code may know the + * structure sizes and alignment requirements, but callers SHALL NOT + * access individual fields directly. For fields that are supposed to + * be read from or written to, the API defines accessor functions (the + * simplest of these accessor functions are defined as `static inline` + * functions, and the C compiler will optimise them away). + * + * + * # API Usage + * + * BearSSL usage for running a SSL/TLS client or server is described + * on the [BearSSL Web site](https://www.bearssl.org/api1.html). The + * BearSSL source archive also comes with sample code. + */ + #include "bearssl_hash.h" #include "bearssl_hmac.h" #include "bearssl_rand.h" diff --git a/inc/bearssl_hash.h b/inc/bearssl_hash.h index dbcc74c..e58a54f 100644 --- a/inc/bearssl_hash.h +++ b/inc/bearssl_hash.h @@ -35,99 +35,132 @@ * * This file documents the API for hash functions. * - * Implemented hash functions are MD5, SHA-1, SHA-224, SHA-256, SHA-384 - * and SHA-512; these are the _standard hash functions_ (as specified in - * TLS). Also provided are MD5+SHA-1 (an aggregate hash function that - * computes both MD5 and SHA-1 on its input, and provides a 36-byte - * output), a multi-hasher system that computes some or all of the - * standard hash functions on the same input, and some GHASH - * implementations (GHASH is the sort-of keyed hash function used in GCM - * encryption mode). - * - * For each standard hash function (and also MD5+SHA-1), two similar API - * are provided: one consists in direct, named function calls, while the - * other uses function pointers through a vtable. The vtable incarnates - * object-oriented programming. An introduction on the OOP concept used - * here can be read on the BearSSL Web site:
- *    [https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html) - */ - -/* - * Hash Functions - * -------------- - * - * For hash function 'xxx', the following elements are defined: - * - * br_xxx_vtable - * An externally defined instance of br_hash_class. - * - * br_xxx_SIZE - * A macro that evaluates to the output size (in bytes) of the - * hash function. - * - * br_xxx_ID - * A macro that evaluates to a symbolic identifier for the hash - * function. Such identifiers are used with HMAC and signature - * algorithm implementations. - * NOTE: the numerical value of these identifiers MUST match the - * constants for hash function identification in TLS 1.2 (see RFC - * 5246, section 7.4.1.4.1). These are values 1 to 6, for MD5, - * SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512, respectively. - * - * br_xxx_context - * Context for an ongoing computation. It is allocated by the - * caller, and a pointer to it is passed to all functions. A - * context contains no interior pointer, so it can be moved around - * and cloned (with a simple memcpy() or equivalent) in order to - * capture the function state at some point. Computations that use - * distinct context structures are independent of each other. The - * first field of br_xxx_context is always a pointer to the - * br_xxx_vtable structure; br_xxx_init() sets that pointer. - * - * br_xxx_init(br_xxx_context *ctx) - * Initialize the provided context. Previous contents of the structure - * are ignored. This calls resets the context to the start of a new - * hash computation. - * - * br_xxx_update(br_xxx_context *ctx, const void *data, size_t len) - * Add some more bytes to the hash computation represented by the - * provided context. - * - * br_xxx_out(const br_xxx_context *ctx, void *out) - * Complete the hash computation and write the result in the provided - * buffer. The output buffer MUST be large enough to accomodate the - * result. The context is NOT modified by this operation, so this - * function can be used to get a "partial hash" while still keeping - * the possibility of adding more bytes to the input. - * - * br_xxx_state(const br_xxx_context *ctx, void *out) - * Get a copy of the "current state" for the computation so far. For - * MD functions (MD5, SHA-1, SHA-2 family), this is the running state - * resulting from the processing of the last complete input block. - * Returned value is the current input length (in bytes). - * - * br_xxx_set_state(br_xxx_context *ctx, const void *stb, uint64_t count) - * Set the internal state to the provided values. The 'stb' and 'count' - * values shall match that which was obtained from br_xxx_state(). This - * restores the hash state only if the state values were at an - * appropriate block boundary. This does NOT set the 'vtable' pointer - * in the context. + * + * ## Procedural API + * + * For each implemented hash function, of name "`xxx`", the following + * elements are defined: + * + * - `br_xxx_vtable` + * + * An externally defined instance of `br_hash_class`. + * + * - `br_xxx_SIZE` + * + * A macro that evaluates to the output size (in bytes) of the + * hash function. + * + * - `br_xxx_ID` + * + * A macro that evaluates to a symbolic identifier for the hash + * function. Such identifiers are used with HMAC and signature + * algorithm implementations. + * + * NOTE: for the "standard" hash functions defined in [the TLS + * standard](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1), + * the symbolic identifiers match the constants used in TLS, i.e. + * 1 to 6 for MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512, + * respectively. + * + * - `br_xxx_context` + * + * Context for an ongoing computation. It is allocated by the + * caller, and a pointer to it is passed to all functions. A + * context contains no interior pointer, so it can be moved around + * and cloned (with a simple `memcpy()` or equivalent) in order to + * capture the function state at some point. Computations that use + * distinct context structures are independent of each other. The + * first field of `br_xxx_context` is always a pointer to the + * `br_xxx_vtable` structure; `br_xxx_init()` sets that pointer. + * + * - `br_xxx_init(br_xxx_context *ctx)` + * + * Initialise the provided context. Previous contents of the structure + * are ignored. This calls resets the context to the start of a new + * hash computation; it also sets the first field of the context + * structure (called `vtable`) to a pointer to the statically + * allocated constant `br_xxx_vtable` structure. + * + * - `br_xxx_update(br_xxx_context *ctx, const void *data, size_t len)` + * + * Add some more bytes to the hash computation represented by the + * provided context. + * + * - `br_xxx_out(const br_xxx_context *ctx, void *out)` + * + * Complete the hash computation and write the result in the provided + * buffer. The output buffer MUST be large enough to accomodate the + * result. The context is NOT modified by this operation, so this + * function can be used to get a "partial hash" while still keeping + * the possibility of adding more bytes to the input. + * + * - `br_xxx_state(const br_xxx_context *ctx, void *out)` + * + * Get a copy of the "current state" for the computation so far. For + * MD functions (MD5, SHA-1, SHA-2 family), this is the running state + * resulting from the processing of the last complete input block. + * Returned value is the current input length (in bytes). + * + * - `br_xxx_set_state(br_xxx_context *ctx, const void *stb, uint64_t count)` + * + * Set the internal state to the provided values. The 'stb' and + * 'count' values shall match that which was obtained from + * `br_xxx_state()`. This restores the hash state only if the state + * values were at an appropriate block boundary. This does NOT set + * the `vtable` pointer in the context. * * Context structures can be discarded without any explicit deallocation. * Hash function implementations are purely software and don't reserve * any resources outside of the context structure itself. * - * Implemented hash functions are: * - * Function Name Output length State length + * ## Object-Oriented API + * + * For each hash function that follows the procedural API described + * above, an object-oriented API is also provided. In that API, function + * pointers from the vtable (`br_xxx_vtable`) are used. The vtable + * incarnates object-oriented programming. An introduction on the OOP + * concept used here can be read on the BearSSL Web site:
+ *    [https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html) + * + * The vtable offers functions called `init()`, `update()`, `out()`, + * `set()` and `set_state()`, which are in fact the functions from + * the procedural API. That vtable also contains two informative fields: + * + * - `context_size` + * + * The size of the context structure (`br_xxx_context`), in bytes. + * This can be used by generic implementations to perform dynamic + * context allocation. + * + * - `desc` + * + * A "descriptor" field that encodes some information on the hash + * function: symbolic identifier, output size, state size, + * internal block size, details on the padding. + * + * Users of this object-oriented API (in particular generic HMAC + * implementations) may make the following assumptions: + * + * - Hash output size is no more than 64 bytes. + * - Hash internal state size is no more than 64 bytes. + * - Internal block size is a power of two, no less than 16 and no more + * than 256. * - * MD5 md5 16 16 - * SHA-1 sha1 20 20 - * SHA-224 sha224 28 32 - * SHA-256 sha256 32 32 - * SHA-384 sha384 48 64 - * SHA-512 sha512 64 64 - * MD5+SHA-1 md5sha1 36 36 + * + * ## Implemented Hash Functions + * + * Implemented hash functions are: + * + * | Function | Name | Output length | State length | + * | :-------- | :------ | :-----------: | :----------: | + * | MD5 | md5 | 16 | 16 | + * | SHA-1 | sha1 | 20 | 20 | + * | SHA-224 | sha224 | 28 | 32 | + * | SHA-256 | sha256 | 32 | 32 | + * | SHA-384 | sha384 | 48 | 64 | + * | SHA-512 | sha512 | 64 | 64 | + * | MD5+SHA-1 | md5sha1 | 36 | 36 | * * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the * same input; in the implementation, the internal data buffer is @@ -136,38 +169,39 @@ * 1.1.) * * - * An object-oriented API is also available: the first field of the - * context is a pointer to a br_hash_class structure, that has the - * following contents: + * ## Multi-Hasher + * + * An aggregate hasher is provided, that can compute several standard + * hash functions in parallel. It uses `br_multihash_context` and a + * procedural API. It is configured with the implementations (the vtables) + * that it should use; it will then compute all these hash functions in + * parallel, on the same input. It is meant to be used in cases when the + * hash of an object will be used, but the exact hash function is not + * known yet (typically, streamed processing on X.509 certificates). + * + * Only the standard hash functions (MD5, SHA-1, SHA-224, SHA-256, SHA-384 + * and SHA-512) are supported by the multi-hasher. + * * - * context_size total size of the required context structure - * desc descriptor (see below) - * init context initialization or reset (function pointer) - * update process some more bytes (function pointer) - * out get hash output so far (function pointer) - * state get copy of internal state (function pointer) - * set_state reset the internal state (function pointer) + * ## GHASH * - * The descriptor is a combination of the following elements: - * bits 0 to 7 hash algorithm identifier - * bits 8 to 14 hash output size (in bytes) - * bits 15 to 22 hash internal state size (in bytes) - * bits 23 to 26 log (base 2) of hash internal block size (in bytes) - * bit 28 1 if using MD padding, 0 otherwise - * bit 29 1 if MD padding uses a 128-bit bit length, 0 otherwise - * bit 30 1 if MD padding is big-endian, 0 otherwise + * GHASH is not a generic hash function; it is a _universal_ hash function, + * which, as the name does not say, means that it CANNOT be used in most + * places where a hash function is needed. GHASH is used within the GCM + * encryption mode, to provide the checked integrity functionality. * - * For function 'xxx', the br_xxx_init() function sets the first field - * to a pointer to the relevant br_hash_class instance (i.e. - * br_xxx_vtable). + * A GHASH implementation is basically a function that uses the type defined + * in this file under the name `br_ghash`: * - * Users of this object-oriented API may make the following assumptions: - * Hash output size is no more than 64 bytes. - * Hash internal state size is no more than 64 bytes. - * Internal block size is a power of two, no less than 2^4 and no more - * than 2^8. - * For functions that do not have an internal block size that is a - * power of 2, the relevant element is 0. + * typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); + * + * The `y` pointer refers to a 16-byte value which is used as input, and + * receives the output of the GHASH invocation. `h` is a 16-byte secret + * value (that serves as key). `data` and `len` define the input data. + * + * Three GHASH implementations are provided, all constant-time, based on + * the use of integer multiplications with appropriate masking to cancel + * carry propagation. */ /** @@ -517,23 +551,6 @@ uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); */ void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); -/* obsolete -#define br_sha1_ID 2 -#define br_sha1_SIZE 20 -extern const br_hash_class br_sha1_vtable; -typedef struct { - const br_hash_class *vtable; - unsigned char buf[64]; - uint64_t count; - uint32_t val[5]; -} br_sha1_context; -void br_sha1_init(br_sha1_context *ctx); -void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len); -void br_sha1_out(const br_sha1_context *ctx, void *out); -uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); -void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); -*/ - /** * \brief Symbolic identifier for SHA-224. */ @@ -630,24 +647,6 @@ uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); void br_sha224_set_state(br_sha224_context *ctx, const void *stb, uint64_t count); -/* obsolete -#define br_sha224_ID 3 -#define br_sha224_SIZE 28 -extern const br_hash_class br_sha224_vtable; -typedef struct { - const br_hash_class *vtable; - unsigned char buf[64]; - uint64_t count; - uint32_t val[8]; -} br_sha224_context; -void br_sha224_init(br_sha224_context *ctx); -void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len); -void br_sha224_out(const br_sha224_context *ctx, void *out); -uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); -void br_sha224_set_state(br_sha224_context *ctx, - const void *stb, uint64_t count); -*/ - /** * \brief Symbolic identifier for SHA-256. */ @@ -755,18 +754,6 @@ void br_sha256_set_state(br_sha256_context *ctx, #define br_sha256_set_state br_sha224_set_state #endif -/* obsolete -#define br_sha256_ID 4 -#define br_sha256_SIZE 32 -extern const br_hash_class br_sha256_vtable; -typedef br_sha224_context br_sha256_context; -void br_sha256_init(br_sha256_context *ctx); -#define br_sha256_update br_sha224_update -void br_sha256_out(const br_sha256_context *ctx, void *out); -#define br_sha256_state br_sha224_state -#define br_sha256_set_state br_sha224_set_state -*/ - /** * \brief Symbolic identifier for SHA-384. */ @@ -863,24 +850,6 @@ uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); void br_sha384_set_state(br_sha384_context *ctx, const void *stb, uint64_t count); -/* obsolete -#define br_sha384_ID 5 -#define br_sha384_SIZE 48 -extern const br_hash_class br_sha384_vtable; -typedef struct { - const br_hash_class *vtable; - unsigned char buf[128]; - uint64_t count; - uint64_t val[8]; -} br_sha384_context; -void br_sha384_init(br_sha384_context *ctx); -void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len); -void br_sha384_out(const br_sha384_context *ctx, void *out); -uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); -void br_sha384_set_state(br_sha384_context *ctx, - const void *stb, uint64_t count); -*/ - /** * \brief Symbolic identifier for SHA-512. */ @@ -908,9 +877,6 @@ typedef struct { * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; - unsigned char buf[128]; - uint64_t count; - uint64_t val[8]; } br_sha512_context; #else typedef br_sha384_context br_sha512_context; @@ -991,18 +957,6 @@ void br_sha512_set_state(br_sha512_context *ctx, #define br_sha512_set_state br_sha384_set_state #endif -/* obsolete -#define br_sha512_ID 6 -#define br_sha512_SIZE 64 -extern const br_hash_class br_sha512_vtable; -typedef br_sha384_context br_sha512_context; -void br_sha512_init(br_sha512_context *ctx); -#define br_sha512_update br_sha384_update -void br_sha512_out(const br_sha512_context *ctx, void *out); -#define br_sha512_state br_sha384_state -#define br_sha512_set_state br_sha384_set_state -*/ - /* * "md5sha1" is a special hash function that computes both MD5 and SHA-1 * on the same input, and produces a 36-byte output (MD5 and SHA-1 diff --git a/inc/bearssl_hmac.h b/inc/bearssl_hmac.h index d65653a..71e9451 100644 --- a/inc/bearssl_hmac.h +++ b/inc/bearssl_hmac.h @@ -30,9 +30,9 @@ #include "bearssl_hash.h" -/* - * HMAC - * ---- +/** \file bearssl_hmac.h + * + * # HMAC * * HMAC is initialized with a key and an underlying hash function; it * then fills a "key context". That context contains the processed @@ -44,94 +44,143 @@ * * IMPORTANT: HMAC shall be used only with functions that have the * following properties: - * hash output size does not exceed 64 bytes - * hash internal state size does not exceed 64 bytes - * internal block length is a power of 2 between 16 and 256 bytes + * + * - hash output size does not exceed 64 bytes; + * - hash internal state size does not exceed 64 bytes; + * - internal block length is a power of 2 between 16 and 256 bytes. */ -/* - * Key context. +/** + * \brief HMAC key context. + * + * The HMAC key context is initialised with a hash function implementation + * and a secret key. Contents are opaque (callers should not access them + * directly). The caller is responsible for allocating the context where + * appropriate. Context initialisation and usage incurs no dynamic + * allocation, so there is no release function. */ typedef struct { +#ifndef BR_DOXYGEN_IGNORE const br_hash_class *dig_vtable; unsigned char ksi[64], kso[64]; +#endif } br_hmac_key_context; -/* - * Initialize the key context with the provided key, using the hash function - * identified by digest_class. +/** + * \brief HMAC key context initialisation. + * + * Initialise the key context with the provided key, using the hash function + * identified by `digest_vtable`. This supports arbitrary key lengths. + * + * \param kc HMAC key context to initialise. + * \param digest_vtable pointer to the hash function implementation vtable. + * \param key pointer to the HMAC secret key. + * \param key_len HMAC secret key length (in bytes). */ void br_hmac_key_init(br_hmac_key_context *kc, - const br_hash_class *digest_class, const void *key, size_t key_len); - -/* - * A helper structure that is big enough to accommodate all context - * structures for all hash functions for which HMAC is supported. - */ -typedef union { - const br_hash_class *vtable; - br_md5_context md5; - br_sha1_context sha1; - br_sha224_context sha224; - br_sha256_context sha256; - br_sha384_context sha384; - br_sha512_context sha512; -} br_hmac_allhash_context; + const br_hash_class *digest_vtable, const void *key, size_t key_len); -/* - * Context for an HMAC computation. +/** + * \brief HMAC computation context. + * + * The HMAC computation context maintains the state for a single HMAC + * computation. It is modified as input bytes are injected. The context + * is caller-allocated and has no release function since it does not + * dynamically allocate external resources. Its contents are opaque. */ typedef struct { - br_hmac_allhash_context dig; +#ifndef BR_DOXYGEN_IGNORE + br_hash_compat_context dig; unsigned char kso[64]; size_t out_len; +#endif } br_hmac_context; -/* - * Initialize a HMAC context with a key context. The key context is +/** + * \brief HMAC computation initialisation. + * + * Initialise a HMAC context with a key context. The key context is * unmodified. Relevant data from the key context is immediately copied; * the key context can thus be independently reused, modified or released * without impacting this HMAC computation. * * An explicit output length can be specified; the actual output length * will be the minimum of that value and the natural HMAC output length. - * If out_len is 0, then the natural HMAC output length is selected. + * If `out_len` is 0, then the natural HMAC output length is selected. The + * "natural output length" is the output length of the underlying hash + * function. + * + * \param ctx HMAC context to initialise. + * \param kc HMAC key context (already initialised with the key). + * \param out_len HMAC output length (0 to select "natural length"). */ void br_hmac_init(br_hmac_context *ctx, const br_hmac_key_context *kc, size_t out_len); -/* - * Get the MAC output size. The context must have been initialized. +/** + * \brief Get the HMAC output size. + * + * The HMAC output size is the number of bytes that will actually be + * produced with `br_hmac_out()` with the provided context. This function + * MUST NOT be called on a non-initialised HMAC computation context. + * The returned value is the minimum of the HMAC natural length (output + * size of the underlying hash function) and the `out_len` parameter which + * was used with the last `br_hmac_init()` call on that context (if the + * initialisation `out_len` parameter was 0, then this function will + * return the HMAC natural length). + * + * \param ctx the (already initialised) HMAC computation context. + * \return the HMAC actual output size. */ -#define br_hmac_size(ctx) ((ctx)->out_len) +static inline size_t +br_hmac_size(br_hmac_context *ctx) +{ + return ctx->out_len; +} -/* - * Process some more bytes. +/** + * \brief Inject some bytes in HMAC. + * + * The provided `len` bytes are injected as extra input in the HMAC + * computation incarnated by the `ctx` HMAC context. It is acceptable + * that `len` is zero, in which case `data` is ignored (and may be + * `NULL`) and this function does nothing. */ void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len); -/* - * Compute the HMAC output. The destination buffer MUST be large enough - * to accomodate the result. The context is NOT modified; further bytes - * may be processed. Thus, "partial HMAC" values can be efficiently - * obtained. +/** + * \brief Compute the HMAC output. + * + * The destination buffer MUST be large enough to accomodate the result; + * its length is at most the "natural length" of HMAC (i.e. the output + * length of the underlying hash function). The context is NOT modified; + * further bytes may be processed. Thus, "partial HMAC" values can be + * efficiently obtained. * * Returned value is the output length (in bytes). + * + * \param ctx HMAC computation context. + * \param out destination buffer for the HMAC output. + * \return the produced value length (in bytes). */ size_t br_hmac_out(const br_hmac_context *ctx, void *out); -/* - * Compute the HMAC output in constant time. Some extra input bytes are - * processed, then the output is computed. The extra input consists in - * the 'len' bytes pointed to by 'data'. The 'len' parameter must lie - * between 'min_len' and 'max_len' (inclusive); max_len bytes are - * actually read from 'data'. Computing time (and memory access pattern) - * will not depend upon the data bytes or the value of 'len'. - * - * The output is written in the 'out' buffer, that MUST be large enough +/** + * \brief Constant-time HMAC computation. + * + * This function compute the HMAC output in constant time. Some extra + * input bytes are processed, then the output is computed. The extra + * input consists in the `len` bytes pointed to by `data`. The `len` + * parameter must lie between `min_len` and `max_len` (inclusive); + * `max_len` bytes are actually read from `data`. Computing time (and + * memory access pattern) will not depend upon the data byte contents or + * the value of `len`. + * + * The output is written in the `out` buffer, that MUST be large enough * to receive it. * - * The difference max_len-min_len MUST be less than 2^30. + * The difference `max_len - min_len` MUST be less than 230 + * (i.e. about one gigabyte). * * This function computes the output properly only if the underlying * hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256, @@ -139,7 +188,13 @@ size_t br_hmac_out(const br_hmac_context *ctx, void *out); * * The provided context is NOT modified. * - * Returned value is the MAC length (in bytes). + * \param ctx the (already initialised) HMAC computation context. + * \param data the extra input bytes. + * \param len the extra input length (in bytes). + * \param min_len minimum extra input length (in bytes). + * \param max_len maximum extra input length (in bytes). + * \param out destination buffer for the HMAC output. + * \return the produced value length (in bytes). */ size_t br_hmac_outCT(const br_hmac_context *ctx, const void *data, size_t len, size_t min_len, size_t max_len, diff --git a/inc/bearssl_prf.h b/inc/bearssl_prf.h index 779a75b..1ad4a04 100644 --- a/inc/bearssl_prf.h +++ b/inc/bearssl_prf.h @@ -28,36 +28,88 @@ #include #include -/* - * The TLS PRF - * ----------- +/** \file bearssl_prf.h + * + * # The TLS PRF + * + * The "PRF" is the pseudorandom function used internally during the + * SSL/TLS handshake, notably to expand negociated shared secrets into + * the symmetric encryption keys that will be used to process the + * application data. * * TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This - * is implemented by the br_tls10_prf() function. + * is implemented by the `br_tls10_prf()` function. * * TLS 1.2 redefines the PRF, using an explicit hash function. The - * br_tls12_sha256_prf() and br_tls12_sha384_prf() functions apply that - * PRF with, respectively, SHA-256 and SHA-384. + * `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that + * PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites + * rely on the SHA-256 based PRF, but some use SHA-384. * * The PRF always uses as input three parameters: a "secret" (some * bytes), a "label" (ASCII string), and a "seed" (again some bytes). * An arbitrary output length can be produced. */ +/** \brief PRF implementation for TLS 1.0 and 1.1. + * + * This PRF is the one specified by TLS 1.0 and 1.1. It internally uses + * MD5 and SHA-1. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed seed for this computation (usually non-secret). + * \param seed_len length of "seed" (in bytes). + */ void br_tls10_prf(void *dst, size_t len, const void *secret, size_t secret_len, const char *label, const void *seed, size_t seed_len); +/** \brief PRF implementation for TLS 1.2, with SHA-256. + * + * This PRF is the one specified by TLS 1.2, when the underlying hash + * function is SHA-256. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed seed for this computation (usually non-secret). + * \param seed_len length of "seed" (in bytes). + */ void br_tls12_sha256_prf(void *dst, size_t len, const void *secret, size_t secret_len, const char *label, const void *seed, size_t seed_len); +/** \brief PRF implementation for TLS 1.2, with SHA-384. + * + * This PRF is the one specified by TLS 1.2, when the underlying hash + * function is SHA-384. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed seed for this computation (usually non-secret). + * \param seed_len length of "seed" (in bytes). + */ void br_tls12_sha384_prf(void *dst, size_t len, const void *secret, size_t secret_len, const char *label, const void *seed, size_t seed_len); -/* - * A convenient type name for a PRF implementation. +/** \brief A convenient type name for a PRF implementation. + * + * \param dst destination buffer. + * \param len output length (in bytes). + * \param secret secret value (key) for this computation. + * \param secret_len length of "secret" (in bytes). + * \param label PRF label (zero-terminated ASCII string). + * \param seed seed for this computation (usually non-secret). + * \param seed_len length of "seed" (in bytes). */ typedef void (*br_tls_prf_impl)(void *dst, size_t len, const void *secret, size_t secret_len, 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) diff --git a/src/mac/hmac.c b/src/mac/hmac.c index 765e454..b438798 100644 --- a/src/mac/hmac.c +++ b/src/mac/hmac.c @@ -57,7 +57,7 @@ void br_hmac_key_init(br_hmac_key_context *kc, const br_hash_class *dig, const void *key, size_t key_len) { - br_hmac_allhash_context hc; + br_hash_compat_context hc; unsigned char kbuf[64]; kc->dig_vtable = dig; @@ -105,7 +105,7 @@ size_t br_hmac_out(const br_hmac_context *ctx, void *out) { const br_hash_class *dig; - br_hmac_allhash_context hc; + br_hash_compat_context hc; unsigned char tmp[64]; size_t blen, hlen; diff --git a/src/mac/hmac_ct.c b/src/mac/hmac_ct.c index d3ab425..3237885 100644 --- a/src/mac/hmac_ct.c +++ b/src/mac/hmac_ct.c @@ -63,7 +63,7 @@ br_hmac_outCT(const br_hmac_context *ctx, */ const br_hash_class *dig; - br_hmac_allhash_context hc; + br_hash_compat_context hc; int be; uint32_t po, bs; uint32_t kr, km, kl, kz, u;