From 006462f17efaffab0face8892e9180b3cc60eb3c Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 10 Jun 2019 12:06:03 +0200 Subject: [PATCH] Refactored TLS based on BearSSL - cleaned --- include/bearssl/bearssl.h | 170 + include/bearssl/bearssl_aead.h | 1059 ++++++ include/bearssl/bearssl_block.h | 2618 ++++++++++++++ include/bearssl/bearssl_ec.h | 967 +++++ include/bearssl/bearssl_hash.h | 1346 +++++++ include/bearssl/bearssl_hmac.h | 241 ++ include/bearssl/bearssl_kdf.h | 284 ++ include/bearssl/bearssl_pem.h | 294 ++ include/bearssl/bearssl_prf.h | 150 + include/bearssl/bearssl_rand.h | 397 +++ include/bearssl/bearssl_rsa.h | 1655 +++++++++ include/bearssl/bearssl_ssl.h | 4308 +++++++++++++++++++++++ include/bearssl/bearssl_x509.h | 1592 +++++++++ lib_bearssl/README.md | 5 +- lib_bearssl/libbearssl.a | Bin 4999318 -> 3767710 bytes platformio.ini | 2 + sonoff/StackThunk_light.cpp | 2 +- sonoff/WiFiClientSecureLightBearSSL.cpp | 62 +- sonoff/WiFiClientSecureLightBearSSL.h | 6 - sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 25 +- sonoff/sonoff.ino | 5 + sonoff/sonoff_ca.ino | 236 ++ sonoff/sonoff_letsencrypt.h | 102 - sonoff/sonoff_post.h | 25 +- sonoff/xdrv_01_webserver.ino | 5 + sonoff/xdrv_02_mqtt.ino | 214 +- 27 files changed, 15498 insertions(+), 273 deletions(-) create mode 100644 include/bearssl/bearssl.h create mode 100644 include/bearssl/bearssl_aead.h create mode 100644 include/bearssl/bearssl_block.h create mode 100644 include/bearssl/bearssl_ec.h create mode 100644 include/bearssl/bearssl_hash.h create mode 100644 include/bearssl/bearssl_hmac.h create mode 100644 include/bearssl/bearssl_kdf.h create mode 100644 include/bearssl/bearssl_pem.h create mode 100644 include/bearssl/bearssl_prf.h create mode 100644 include/bearssl/bearssl_rand.h create mode 100644 include/bearssl/bearssl_rsa.h create mode 100644 include/bearssl/bearssl_ssl.h create mode 100644 include/bearssl/bearssl_x509.h create mode 100644 sonoff/sonoff_ca.ino delete mode 100644 sonoff/sonoff_letsencrypt.h diff --git a/include/bearssl/bearssl.h b/include/bearssl/bearssl.h new file mode 100644 index 000000000..4f4797cf7 --- /dev/null +++ b/include/bearssl/bearssl.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_H__ +#define BR_BEARSSL_H__ + +#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_kdf.h | Key Derivation Functions | + * | bearssl_rand.h | Pseudorandom byte generators | + * | bearssl_prf.h | PRF implementations (for SSL/TLS) | + * | bearssl_block.h | Symmetric encryption | + * | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) | + * | 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 lighter. + * + * + * ## `NULL` values + * + * Function parameters with a pointer type shall not be `NULL` unless + * explicitly authorised by the documentation. As an exception, when + * the pointer aims at a sequence of bytes and is accompanied with + * a length parameter, and the length is zero (meaning that there is + * no byte at all to retrieve), then the pointer may be `NULL` even if + * not explicitly allowed. + * + * + * ## 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_kdf.h" +#include "bearssl_rand.h" +#include "bearssl_prf.h" +#include "bearssl_block.h" +#include "bearssl_aead.h" +#include "bearssl_rsa.h" +#include "bearssl_ec.h" +#include "bearssl_ssl.h" +#include "bearssl_x509.h" +#include "bearssl_pem.h" + +/** \brief Type for a configuration option. + * + * A "configuration option" is a value that is selected when the BearSSL + * library itself is compiled. Most options are boolean; their value is + * then either 1 (option is enabled) or 0 (option is disabled). Some + * values have other integer values. Option names correspond to macro + * names. Some of the options can be explicitly set in the internal + * `"config.h"` file. + */ +typedef struct { + /** \brief Configurable option name. */ + const char *name; + /** \brief Configurable option value. */ + long value; +} br_config_option; + +/** \brief Get configuration report. + * + * This function returns compiled configuration options, each as a + * 'long' value. Names match internal macro names, in particular those + * that can be set in the `"config.h"` inner file. For boolean options, + * the numerical value is 1 if enabled, 0 if disabled. For maximum + * key sizes, values are expressed in bits. + * + * The returned array is terminated by an entry whose `name` is `NULL`. + * + * \return the configuration report. + */ +const br_config_option *br_get_config(void); + +#endif diff --git a/include/bearssl/bearssl_aead.h b/include/bearssl/bearssl_aead.h new file mode 100644 index 000000000..8e35a1fde --- /dev/null +++ b/include/bearssl/bearssl_aead.h @@ -0,0 +1,1059 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_AEAD_H__ +#define BR_BEARSSL_AEAD_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_aead.h + * + * # Authenticated Encryption with Additional Data + * + * This file documents the API for AEAD encryption. + * + * + * ## Procedural API + * + * An AEAD algorithm processes messages and provides confidentiality + * (encryption) and checked integrity (MAC). It uses the following + * parameters: + * + * - A symmetric key. Exact size depends on the AEAD algorithm. + * + * - A nonce (IV). Size depends on the AEAD algorithm; for most + * algorithms, it is crucial for security that any given nonce + * value is never used twice for the same key and distinct + * messages. + * + * - Data to encrypt and protect. + * + * - Additional authenticated data, which is covered by the MAC but + * otherwise left untouched (i.e. not encrypted). + * + * The AEAD algorithm encrypts the data, and produces an authentication + * tag. It is assumed that the encrypted data, the tag, the additional + * authenticated data and the nonce are sent to the receiver; the + * additional data and the nonce may be implicit (e.g. using elements of + * the underlying transport protocol, such as record sequence numbers). + * The receiver will recompute the tag value and compare it with the one + * received; if they match, then the data is correct, and can be + * decrypted and used; otherwise, at least one of the elements was + * altered in transit, normally leading to wholesale rejection of the + * complete message. + * + * For each AEAD algorithm, identified by a symbolic name (hereafter + * denoted as "`xxx`"), the following functions are defined: + * + * - `br_xxx_init()` + * + * Initialise the AEAD algorithm, on a provided context structure. + * Exact parameters depend on the algorithm, and may include + * pointers to extra implementations and context structures. The + * secret key is provided at this point, either directly or + * indirectly. + * + * - `br_xxx_reset()` + * + * Start a new AEAD computation. The nonce value is provided as + * parameter to this function. + * + * - `br_xxx_aad_inject()` + * + * Inject some additional authenticated data. Additional data may + * be provided in several chunks of arbitrary length. + * + * - `br_xxx_flip()` + * + * This function MUST be called after injecting all additional + * authenticated data, and before beginning to encrypt the plaintext + * (or decrypt the ciphertext). + * + * - `br_xxx_run()` + * + * Process some plaintext (to encrypt) or ciphertext (to decrypt). + * Encryption/decryption is done in place. Data may be provided in + * several chunks of arbitrary length. + * + * - `br_xxx_get_tag()` + * + * Compute the authentication tag. All message data (encrypted or + * decrypted) must have been injected at that point. Also, this + * call may modify internal context elements, so it may be called + * only once for a given AEAD computation. + * + * - `br_xxx_check_tag()` + * + * An alternative to `br_xxx_get_tag()`, meant to be used by the + * receiver: the authentication tag is internally recomputed, and + * compared with the one provided as parameter. + * + * This API makes the following assumptions on the AEAD algorithm: + * + * - Encryption does not expand the size of the ciphertext; there is + * no padding. This is true of most modern AEAD modes such as GCM. + * + * - The additional authenticated data must be processed first, + * before the encrypted/decrypted data. + * + * - Nonce, plaintext and additional authenticated data all consist + * in an integral number of bytes. There is no provision to use + * elements whose length in bits is not a multiple of 8. + * + * Each AEAD algorithm has its own requirements and limits on the sizes + * of additional data and plaintext. This API does not provide any + * way to report invalid usage; it is up to the caller to ensure that + * the provided key, nonce, and data elements all fit the algorithm's + * requirements. + * + * + * ## Object-Oriented API + * + * Each context structure begins with a field (called `vtable`) that + * points to an instance of a structure that references the relevant + * functions through pointers. Each such structure contains the + * following: + * + * - `reset` + * + * Pointer to the reset function, that allows starting a new + * computation. + * + * - `aad_inject` + * + * Pointer to the additional authenticated data injection function. + * + * - `flip` + * + * Pointer to the function that transitions from additional data + * to main message data processing. + * + * - `get_tag` + * + * Pointer to the function that computes and returns the tag. + * + * - `check_tag` + * + * Pointer to the function that computes and verifies the tag against + * a received value. + * + * Note that there is no OOP method for context initialisation: the + * various AEAD algorithms have different requirements that would not + * map well to a single initialisation API. + * + * The OOP API is not provided for CCM, due to its specific requirements + * (length of plaintext must be known in advance). + */ + +/** + * \brief Class type of an AEAD algorithm. + */ +typedef struct br_aead_class_ br_aead_class; +struct br_aead_class_ { + + /** + * \brief Size (in bytes) of authentication tags created by + * this AEAD algorithm. + */ + size_t tag_size; + + /** + * \brief Reset an AEAD context. + * + * This function resets an already initialised AEAD context for + * a new computation run. Implementations and keys are + * conserved. This function can be called at any time; it + * cancels any ongoing AEAD computation that uses the provided + * context structure. + + * The provided IV is a _nonce_. Each AEAD algorithm has its + * own requirements on IV size and contents; for most of them, + * it is crucial to security that each nonce value is used + * only once for a given secret key. + * + * \param cc AEAD context structure. + * \param iv AEAD nonce to use. + * \param len AEAD nonce length (in bytes). + */ + void (*reset)(const br_aead_class **cc, const void *iv, size_t len); + + /** + * \brief Inject additional authenticated data. + * + * The provided data is injected into a running AEAD + * computation. Additional data must be injected _before_ the + * call to `flip()`. Additional data can be injected in several + * chunks of arbitrary length. + * + * \param cc AEAD context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ + void (*aad_inject)(const br_aead_class **cc, + const void *data, size_t len); + + /** + * \brief Finish injection of additional authenticated data. + * + * This function MUST be called before beginning the actual + * encryption or decryption (with `run()`), even if no + * additional authenticated data was injected. No additional + * authenticated data may be injected after this function call. + * + * \param cc AEAD context structure. + */ + void (*flip)(const br_aead_class **cc); + + /** + * \brief Encrypt or decrypt some data. + * + * Data encryption or decryption can be done after `flip()` has + * been called on the context. If `encrypt` is non-zero, then + * the provided data shall be plaintext, and it is encrypted in + * place. Otherwise, the data shall be ciphertext, and it is + * decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. + * + * \param cc AEAD context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ + void (*run)(const br_aead_class **cc, int encrypt, + void *data, size_t len); + + /** + * \brief Compute authentication tag. + * + * Compute the AEAD authentication tag. The tag length depends + * on the AEAD algorithm; it is written in the provided `tag` + * buffer. This call terminates the AEAD run: no data may be + * processed with that AEAD context afterwards, until `reset()` + * is called to initiate a new AEAD run. + * + * The tag value must normally be sent along with the encrypted + * data. When decrypting, the tag value must be recomputed and + * compared with the received tag: if the two tag values differ, + * then either the tag or the encrypted data was altered in + * transit. As an alternative to this function, the + * `check_tag()` function may be used to compute and check the + * tag value. + * + * Tag length depends on the AEAD algorithm. + * + * \param cc AEAD context structure. + * \param tag destination buffer for the tag. + */ + void (*get_tag)(const br_aead_class **cc, void *tag); + + /** + * \brief Compute and check authentication tag. + * + * This function is an alternative to `get_tag()`, and is + * normally used on the receiving end (i.e. when decrypting + * messages). The tag value is recomputed and compared with the + * provided tag value. If they match, 1 is returned; on + * mismatch, 0 is returned. A returned value of 0 means that the + * data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length depends on the AEAD algorithm. + * + * \param cc AEAD context structure. + * \param tag tag value to compare with. + * \return 1 on success (exact match of tag value), 0 otherwise. + */ + uint32_t (*check_tag)(const br_aead_class **cc, const void *tag); + + /** + * \brief Compute authentication tag (with truncation). + * + * This function is similar to `get_tag()`, except that the tag + * length is provided. Some AEAD algorithms allow several tag + * lengths, usually by truncating the normal tag. Shorter tags + * mechanically increase success probability of forgeries. + * The range of allowed tag lengths depends on the algorithm. + * + * \param cc AEAD context structure. + * \param tag destination buffer for the tag. + * \param len tag length (in bytes). + */ + void (*get_tag_trunc)(const br_aead_class **cc, void *tag, size_t len); + + /** + * \brief Compute and check authentication tag (with truncation). + * + * This function is similar to `check_tag()` except that it + * works over an explicit tag length. See `get_tag()` for a + * discussion of explicit tag lengths; the range of allowed tag + * lengths depends on the algorithm. + * + * \param cc AEAD context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ + uint32_t (*check_tag_trunc)(const br_aead_class **cc, + const void *tag, size_t len); +}; + +/** + * \brief Context structure for GCM. + * + * GCM is an AEAD mode that combines a block cipher in CTR mode with a + * MAC based on GHASH, to provide authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with GCM. + * + * - The nonce can have any length, from 0 up to 2^64-1 bits; however, + * 96-bit nonces (12 bytes) are recommended (nonces with a length + * distinct from 12 bytes are internally hashed, which risks reusing + * nonce value with a small but not always negligible probability). + * + * - Additional authenticated data may have length up to 2^64-1 bits. + * + * - Message length may range up to 2^39-256 bits at most. + * + * - The authentication tag has length 16 bytes. + * + * The GCM initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * GCM context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_aead_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctr_class **bctx; + br_ghash gh; + unsigned char h[16]; + unsigned char j0_1[12]; + unsigned char buf[16]; + unsigned char y[16]; + uint32_t j0_2, jc; + uint64_t count_aad, count_ctr; +#endif +} br_gcm_context; + +/** + * \brief Initialize a GCM context. + * + * A block cipher implementation, with its initialised context structure, + * is provided. The block cipher MUST use 16-byte blocks in CTR mode, + * and its secret key MUST have been already set in the provided context. + * A GHASH implementation must also be provided. The parameters are linked + * in the GCM context. + * + * After this function has been called, the `br_gcm_reset()` function must + * be called, to provide the IV for GCM computation. + * + * \param ctx GCM context structure. + * \param bctx block cipher context (already initialised with secret key). + * \param gh GHASH implementation. + */ +void br_gcm_init(br_gcm_context *ctx, + const br_block_ctr_class **bctx, br_ghash gh); + +/** + * \brief Reset a GCM context. + * + * This function resets an already initialised GCM context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing GCM computation that + * uses the provided context structure. + * + * The provided IV is a _nonce_. It is critical to GCM security that IV + * values are not repeated for the same encryption key. IV can have + * arbitrary length (up to 2^64-1 bits), but the "normal" length is + * 96 bits (12 bytes). + * + * \param ctx GCM context structure. + * \param iv GCM nonce to use. + * \param len GCM nonce length (in bytes). + */ +void br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len); + +/** + * \brief Inject additional authenticated data into GCM. + * + * The provided data is injected into a running GCM computation. Additional + * data must be injected _before_ the call to `br_gcm_flip()`. + * Additional data can be injected in several chunks of arbitrary length; + * the maximum total size of additional authenticated data is 2^64-1 + * bits. + * + * \param ctx GCM context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into GCM. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_gcm_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx GCM context structure. + */ +void br_gcm_flip(br_gcm_context *ctx); + +/** + * \brief Encrypt or decrypt some data with GCM. + * + * Data encryption or decryption can be done after `br_gcm_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. The maximum + * total length for data is 2^39-256 bits, i.e. about 65 gigabytes. + * + * \param ctx GCM context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute GCM authentication tag. + * + * Compute the GCM authentication tag. The tag is a 16-byte value which + * is written in the provided `tag` buffer. This call terminates the + * GCM run: no data may be processed with that GCM context afterwards, + * until `br_gcm_reset()` is called to initiate a new GCM run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_gcm_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx GCM context structure. + * \param tag destination buffer for the tag (16 bytes). + */ +void br_gcm_get_tag(br_gcm_context *ctx, void *tag); + +/** + * \brief Compute and check GCM authentication tag. + * + * This function is an alternative to `br_gcm_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx GCM context structure. + * \param tag tag value to compare with (16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_gcm_check_tag(br_gcm_context *ctx, const void *tag); + +/** + * \brief Compute GCM authentication tag (with truncation). + * + * This function is similar to `br_gcm_get_tag()`, except that it allows + * the tag to be truncated to a smaller length. The intended tag length + * is provided as `len` (in bytes); it MUST be no more than 16, but + * it may be smaller. Note that decreasing tag length mechanically makes + * forgeries easier; NIST SP 800-38D specifies that the tag length shall + * lie between 12 and 16 bytes (inclusive), but may be truncated down to + * 4 or 8 bytes, for specific applications that can tolerate it. It must + * also be noted that successful forgeries leak information on the + * authentication key, making subsequent forgeries easier. Therefore, + * tag truncation, and in particular truncation to sizes lower than 12 + * bytes, shall be envisioned only with great care. + * + * The tag is written in the provided `tag` buffer. This call terminates + * the GCM run: no data may be processed with that GCM context + * afterwards, until `br_gcm_reset()` is called to initiate a new GCM + * run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_gcm_check_tag_trunc()` function can be used to + * compute and check the tag value. + * + * \param ctx GCM context structure. + * \param tag destination buffer for the tag. + * \param len tag length (16 bytes or less). + */ +void br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len); + +/** + * \brief Compute and check GCM authentication tag (with truncation). + * + * This function is an alternative to `br_gcm_get_tag_trunc()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length MUST be 16 bytes or less. The normal GCM tag length is 16 + * bytes. See `br_check_tag_trunc()` for some discussion on the potential + * perils of truncating authentication tags. + * + * \param ctx GCM context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_gcm_check_tag_trunc(br_gcm_context *ctx, + const void *tag, size_t len); + +/** + * \brief Class instance for GCM. + */ +extern const br_aead_class br_gcm_vtable; + +/** + * \brief Context structure for EAX. + * + * EAX is an AEAD mode that combines a block cipher in CTR mode with + * CBC-MAC using the same block cipher and the same key, to provide + * authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with EAX + * (technically, other block sizes are defined as well, but this + * is not implemented by these functions; shorter blocks also + * imply numerous security issues). + * + * - The nonce can have any length, as long as nonce values are + * not reused (thus, if nonces are randomly selected, the nonce + * size should be such that reuse probability is negligible). + * + * - Additional authenticated data length is unlimited. + * + * - Message length is unlimited. + * + * - The authentication tag has length 16 bytes. + * + * The EAX initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * EAX context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_aead_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctrcbc_class **bctx; + unsigned char L2[16]; + unsigned char L4[16]; + unsigned char nonce[16]; + unsigned char head[16]; + unsigned char ctr[16]; + unsigned char cbcmac[16]; + unsigned char buf[16]; + size_t ptr; +#endif +} br_eax_context; + +/** + * \brief EAX captured state. + * + * Some internal values computed by EAX may be captured at various + * points, and reused for another EAX run with the same secret key, + * for lower per-message overhead. Captured values do not depend on + * the nonce. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char st[3][16]; +#endif +} br_eax_state; + +/** + * \brief Initialize an EAX context. + * + * A block cipher implementation, with its initialised context + * structure, is provided. The block cipher MUST use 16-byte blocks in + * CTR + CBC-MAC mode, and its secret key MUST have been already set in + * the provided context. The parameters are linked in the EAX context. + * + * After this function has been called, the `br_eax_reset()` function must + * be called, to provide the nonce for EAX computation. + * + * \param ctx EAX context structure. + * \param bctx block cipher context (already initialised with secret key). + */ +void br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx); + +/** + * \brief Capture pre-AAD state. + * + * This function precomputes key-dependent data, and stores it in the + * provided `st` structure. This structure should then be used with + * `br_eax_reset_pre_aad()`, or updated with `br_eax_get_aad_mac()` + * and then used with `br_eax_reset_post_aad()`. + * + * The EAX context structure is unmodified by this call. + * + * \param ctx EAX context structure. + * \param st recipient for captured state. + */ +void br_eax_capture(const br_eax_context *ctx, br_eax_state *st); + +/** + * \brief Reset an EAX context. + * + * This function resets an already initialised EAX context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing EAX computation that + * uses the provided context structure. + * + * It is critical to EAX security that nonce values are not repeated for + * the same encryption key. Nonces can have arbitrary length. If nonces + * are randomly generated, then a nonce length of at least 128 bits (16 + * bytes) is recommended, to make nonce reuse probability sufficiently + * low. + * + * \param ctx EAX context structure. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len); + +/** + * \brief Reset an EAX context with a pre-AAD captured state. + * + * This function is an alternative to `br_eax_reset()`, that reuses a + * previously captured state structure for lower per-message overhead. + * The state should have been populated with `br_eax_capture_state()` + * but not updated with `br_eax_get_aad_mac()`. + * + * After this function is called, additional authenticated data MUST + * be injected. At least one byte of additional authenticated data + * MUST be provided with `br_eax_aad_inject()`; computation result will + * be incorrect if `br_eax_flip()` is called right away. + * + * After injection of the AAD and call to `br_eax_flip()`, at least + * one message byte must be provided. Empty messages are not supported + * with this reset mode. + * + * \param ctx EAX context structure. + * \param st pre-AAD captured state. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st, + const void *nonce, size_t len); + +/** + * \brief Reset an EAX context with a post-AAD captured state. + * + * This function is an alternative to `br_eax_reset()`, that reuses a + * previously captured state structure for lower per-message overhead. + * The state should have been populated with `br_eax_capture_state()` + * and then updated with `br_eax_get_aad_mac()`. + * + * After this function is called, message data MUST be injected. The + * `br_eax_flip()` function MUST NOT be called. At least one byte of + * message data MUST be provided with `br_eax_run()`; empty messages + * are not supported with this reset mode. + * + * \param ctx EAX context structure. + * \param st post-AAD captured state. + * \param nonce EAX nonce to use. + * \param len EAX nonce length (in bytes). + */ +void br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st, + const void *nonce, size_t len); + +/** + * \brief Inject additional authenticated data into EAX. + * + * The provided data is injected into a running EAX computation. Additional + * data must be injected _before_ the call to `br_eax_flip()`. + * Additional data can be injected in several chunks of arbitrary length; + * the total amount of additional authenticated data is unlimited. + * + * \param ctx EAX context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into EAX. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_eax_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx EAX context structure. + */ +void br_eax_flip(br_eax_context *ctx); + +/** + * \brief Obtain a copy of the MAC on additional authenticated data. + * + * This function may be called only after `br_eax_flip()`; it copies the + * AAD-specific MAC value into the provided state. The MAC value depends + * on the secret key and the additional data itself, but not on the + * nonce. The updated state `st` is meant to be used as parameter for a + * further `br_eax_reset_post_aad()` call. + * + * \param ctx EAX context structure. + * \param st captured state to update. + */ +static inline void +br_eax_get_aad_mac(const br_eax_context *ctx, br_eax_state *st) +{ + memcpy(st->st[1], ctx->head, sizeof ctx->head); +} + +/** + * \brief Encrypt or decrypt some data with EAX. + * + * Data encryption or decryption can be done after `br_eax_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length. + * + * \param ctx EAX context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute EAX authentication tag. + * + * Compute the EAX authentication tag. The tag is a 16-byte value which + * is written in the provided `tag` buffer. This call terminates the + * EAX run: no data may be processed with that EAX context afterwards, + * until `br_eax_reset()` is called to initiate a new EAX run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_eax_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx EAX context structure. + * \param tag destination buffer for the tag (16 bytes). + */ +void br_eax_get_tag(br_eax_context *ctx, void *tag); + +/** + * \brief Compute and check EAX authentication tag. + * + * This function is an alternative to `br_eax_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx EAX context structure. + * \param tag tag value to compare with (16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_eax_check_tag(br_eax_context *ctx, const void *tag); + +/** + * \brief Compute EAX authentication tag (with truncation). + * + * This function is similar to `br_eax_get_tag()`, except that it allows + * the tag to be truncated to a smaller length. The intended tag length + * is provided as `len` (in bytes); it MUST be no more than 16, but + * it may be smaller. Note that decreasing tag length mechanically makes + * forgeries easier; NIST SP 800-38D specifies that the tag length shall + * lie between 12 and 16 bytes (inclusive), but may be truncated down to + * 4 or 8 bytes, for specific applications that can tolerate it. It must + * also be noted that successful forgeries leak information on the + * authentication key, making subsequent forgeries easier. Therefore, + * tag truncation, and in particular truncation to sizes lower than 12 + * bytes, shall be envisioned only with great care. + * + * The tag is written in the provided `tag` buffer. This call terminates + * the EAX run: no data may be processed with that EAX context + * afterwards, until `br_eax_reset()` is called to initiate a new EAX + * run. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_eax_check_tag_trunc()` function can be used to + * compute and check the tag value. + * + * \param ctx EAX context structure. + * \param tag destination buffer for the tag. + * \param len tag length (16 bytes or less). + */ +void br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len); + +/** + * \brief Compute and check EAX authentication tag (with truncation). + * + * This function is an alternative to `br_eax_get_tag_trunc()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * Tag length MUST be 16 bytes or less. The normal EAX tag length is 16 + * bytes. See `br_check_tag_trunc()` for some discussion on the potential + * perils of truncating authentication tags. + * + * \param ctx EAX context structure. + * \param tag tag value to compare with. + * \param len tag length (in bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_eax_check_tag_trunc(br_eax_context *ctx, + const void *tag, size_t len); + +/** + * \brief Class instance for EAX. + */ +extern const br_aead_class br_eax_vtable; + +/** + * \brief Context structure for CCM. + * + * CCM is an AEAD mode that combines a block cipher in CTR mode with + * CBC-MAC using the same block cipher and the same key, to provide + * authenticated encryption: + * + * - Any block cipher with 16-byte blocks can be used with CCM + * (technically, other block sizes are defined as well, but this + * is not implemented by these functions; shorter blocks also + * imply numerous security issues). + * + * - The authentication tag length, and plaintext length, MUST be + * known when starting processing data. Plaintext and ciphertext + * can still be provided by chunks, but the total size must match + * the value provided upon initialisation. + * + * - The nonce length is constrained between 7 and 13 bytes (inclusive). + * Furthermore, the plaintext length, when encoded, must fit over + * 15-nonceLen bytes; thus, if the nonce has length 13 bytes, then + * the plaintext length cannot exceed 65535 bytes. + * + * - Additional authenticated data length is practically unlimited + * (formal limit is at 2^64 bytes). + * + * - The authentication tag has length 4 to 16 bytes (even values only). + * + * The CCM initialisation function receives as parameter an + * _initialised_ block cipher implementation context, with the secret + * key already set. A pointer to that context will be kept within the + * CCM context structure. It is up to the caller to allocate and + * initialise that block cipher context. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + const br_block_ctrcbc_class **bctx; + unsigned char ctr[16]; + unsigned char cbcmac[16]; + unsigned char tagmask[16]; + unsigned char buf[16]; + size_t ptr; + size_t tag_len; +#endif +} br_ccm_context; + +/** + * \brief Initialize a CCM context. + * + * A block cipher implementation, with its initialised context + * structure, is provided. The block cipher MUST use 16-byte blocks in + * CTR + CBC-MAC mode, and its secret key MUST have been already set in + * the provided context. The parameters are linked in the CCM context. + * + * After this function has been called, the `br_ccm_reset()` function must + * be called, to provide the nonce for CCM computation. + * + * \param ctx CCM context structure. + * \param bctx block cipher context (already initialised with secret key). + */ +void br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx); + +/** + * \brief Reset a CCM context. + * + * This function resets an already initialised CCM context for a new + * computation run. Implementations and keys are conserved. This function + * can be called at any time; it cancels any ongoing CCM computation that + * uses the provided context structure. + * + * The `aad_len` parameter contains the total length, in bytes, of the + * additional authenticated data. It may be zero. That length MUST be + * exact. + * + * The `data_len` parameter contains the total length, in bytes, of the + * data that will be injected (plaintext or ciphertext). That length MUST + * be exact. Moreover, that length MUST be less than 2^(8*(15-nonce_len)). + * + * The nonce length (`nonce_len`), in bytes, must be in the 7..13 range + * (inclusive). + * + * The tag length (`tag_len`), in bytes, must be in the 4..16 range, and + * be an even integer. Short tags mechanically allow for higher forgery + * probabilities; hence, tag sizes smaller than 12 bytes shall be used only + * with care. + * + * It is critical to CCM security that nonce values are not repeated for + * the same encryption key. Random generation of nonces is not generally + * recommended, due to the relatively small maximum nonce value. + * + * Returned value is 1 on success, 0 on error. An error is reported if + * the tag or nonce length is out of range, or if the + * plaintext/ciphertext length cannot be encoded with the specified + * nonce length. + * + * \param ctx CCM context structure. + * \param nonce CCM nonce to use. + * \param nonce_len CCM nonce length (in bytes, 7 to 13). + * \param aad_len additional authenticated data length (in bytes). + * \param data_len plaintext/ciphertext length (in bytes). + * \param tag_len tag length (in bytes). + * \return 1 on success, 0 on error. + */ +int br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, + uint64_t aad_len, uint64_t data_len, size_t tag_len); + +/** + * \brief Inject additional authenticated data into CCM. + * + * The provided data is injected into a running CCM computation. Additional + * data must be injected _before_ the call to `br_ccm_flip()`. + * Additional data can be injected in several chunks of arbitrary length, + * but the total amount MUST exactly match the value which was provided + * to `br_ccm_reset()`. + * + * \param ctx CCM context structure. + * \param data pointer to additional authenticated data. + * \param len length of additional authenticated data (in bytes). + */ +void br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len); + +/** + * \brief Finish injection of additional authenticated data into CCM. + * + * This function MUST be called before beginning the actual encryption + * or decryption (with `br_ccm_run()`), even if no additional authenticated + * data was injected. No additional authenticated data may be injected + * after this function call. + * + * \param ctx CCM context structure. + */ +void br_ccm_flip(br_ccm_context *ctx); + +/** + * \brief Encrypt or decrypt some data with CCM. + * + * Data encryption or decryption can be done after `br_ccm_flip()` + * has been called on the context. If `encrypt` is non-zero, then the + * provided data shall be plaintext, and it is encrypted in place. + * Otherwise, the data shall be ciphertext, and it is decrypted in place. + * + * Data may be provided in several chunks of arbitrary length, provided + * that the total length exactly matches the length provided to the + * `br_ccm_reset()` call. + * + * \param ctx CCM context structure. + * \param encrypt non-zero for encryption, zero for decryption. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +void br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len); + +/** + * \brief Compute CCM authentication tag. + * + * Compute the CCM authentication tag. This call terminates the CCM + * run: all data must have been injected with `br_ccm_run()` (in zero, + * one or more successive calls). After this function has been called, + * no more data can br processed; a `br_ccm_reset()` call is required + * to start a new message. + * + * The tag length was provided upon context initialisation (last call + * to `br_ccm_reset()`); it is returned by this function. + * + * The tag value must normally be sent along with the encrypted data. + * When decrypting, the tag value must be recomputed and compared with + * the received tag: if the two tag values differ, then either the tag + * or the encrypted data was altered in transit. As an alternative to + * this function, the `br_ccm_check_tag()` function can be used to + * compute and check the tag value. + * + * \param ctx CCM context structure. + * \param tag destination buffer for the tag (up to 16 bytes). + * \return the tag length (in bytes). + */ +size_t br_ccm_get_tag(br_ccm_context *ctx, void *tag); + +/** + * \brief Compute and check CCM authentication tag. + * + * This function is an alternative to `br_ccm_get_tag()`, normally used + * on the receiving end (i.e. when decrypting value). The tag value is + * recomputed and compared with the provided tag value. If they match, 1 + * is returned; on mismatch, 0 is returned. A returned value of 0 means + * that the data or the tag was altered in transit, normally leading to + * wholesale rejection of the complete message. + * + * \param ctx CCM context structure. + * \param tag tag value to compare with (up to 16 bytes). + * \return 1 on success (exact match of tag value), 0 otherwise. + */ +uint32_t br_ccm_check_tag(br_ccm_context *ctx, const void *tag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_block.h b/include/bearssl/bearssl_block.h new file mode 100644 index 000000000..683a4906d --- /dev/null +++ b/include/bearssl/bearssl_block.h @@ -0,0 +1,2618 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_BLOCK_H__ +#define BR_BEARSSL_BLOCK_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_block.h + * + * # Block Ciphers and Symmetric Ciphers + * + * This file documents the API for block ciphers and other symmetric + * ciphers. + * + * + * ## Procedural API + * + * For a block cipher implementation, up to three separate sets of + * functions are provided, for CBC encryption, CBC decryption, and CTR + * encryption/decryption. Each set has its own context structure, + * initialised with the encryption key. + * + * For CBC encryption and decryption, the data to encrypt or decrypt is + * referenced as a sequence of blocks. The implementations assume that + * there is no partial block; no padding is applied or removed. The + * caller is responsible for handling any kind of padding. + * + * Function for CTR encryption are defined only for block ciphers with + * blocks of 16 bytes or more (i.e. AES, but not DES/3DES). + * + * Each implemented block cipher is identified by an "internal name" + * from which are derived the names of structures and functions that + * implement the cipher. For the block cipher of internal name "`xxx`", + * the following are defined: + * + * - `br_xxx_BLOCK_SIZE` + * + * A macro that evaluates to the block size (in bytes) of the + * cipher. For all implemented block ciphers, this value is a + * power of two. + * + * - `br_xxx_cbcenc_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CBC encryption. The + * structure first field is called `vtable` and points to the + * appropriate OOP structure. + * + * - `br_xxx_cbcenc_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CBC encryption are computed and + * written in the provided context structure. The key length MUST be + * adequate for the implemented block cipher. This function also sets + * the `vtable` field. + * + * - `br_xxx_cbcenc_run(const br_xxx_cbcenc_keys *ctx, void *iv, void *data, size_t len)` + * + * Perform CBC encryption of `len` bytes, in place. The encrypted data + * replaces the cleartext. `len` MUST be a multiple of the block length + * (if it is not, the function may loop forever or overflow a buffer). + * The IV is provided with the `iv` pointer; it is also updated with + * a copy of the last encrypted block. + * + * - `br_xxx_cbcdec_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CBC decryption. The + * structure first field is called `vtable` and points to the + * appropriate OOP structure. + * + * - `br_xxx_cbcdec_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CBC decryption are computed and + * written in the provided context structure. The key length MUST be + * adequate for the implemented block cipher. This function also sets + * the `vtable` field. + * + * - `br_xxx_cbcdec_run(const br_xxx_cbcdec_keys *ctx, void *iv, void *data, size_t num_blocks)` + * + * Perform CBC decryption of `len` bytes, in place. The decrypted data + * replaces the ciphertext. `len` MUST be a multiple of the block length + * (if it is not, the function may loop forever or overflow a buffer). + * The IV is provided with the `iv` pointer; it is also updated with + * a copy of the last _encrypted_ block. + * + * - `br_xxx_ctr_keys` + * + * Context structure that contains the subkeys resulting from the key + * expansion. These subkeys are appropriate for CTR encryption and + * decryption. The structure first field is called `vtable` and + * points to the appropriate OOP structure. + * + * - `br_xxx_ctr_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for CTR encryption and decryption + * are computed and written in the provided context structure. The + * key length MUST be adequate for the implemented block cipher. This + * function also sets the `vtable` field. + * + * - `br_xxx_ctr_run(const br_xxx_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len)` (returns `uint32_t`) + * + * Perform CTR encryption/decryption of some data. Processing is done + * "in place" (the output data replaces the input data). This function + * implements the "standard incrementing function" from NIST SP800-38A, + * annex B: the IV length shall be 4 bytes less than the block size + * (i.e. 12 bytes for AES) and the counter is the 32-bit value starting + * with `cc`. The data length (`len`) is not necessarily a multiple of + * the block size. The new counter value is returned, which supports + * chunked processing, provided that each chunk length (except possibly + * the last one) is a multiple of the block size. + * + * - `br_xxx_ctrcbc_keys` + * + * Context structure that contains the subkeys resulting from the + * key expansion. These subkeys are appropriate for doing combined + * CTR encryption/decryption and CBC-MAC, as used in the CCM and EAX + * authenticated encryption modes. The structure first field is + * called `vtable` and points to the appropriate OOP structure. + * + * - `br_xxx_ctrcbc_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)` + * + * Perform key expansion: subkeys for combined CTR + * encryption/decryption and CBC-MAC are computed and written in the + * provided context structure. The key length MUST be adequate for + * the implemented block cipher. This function also sets the + * `vtable` field. + * + * - `br_xxx_ctrcbc_encrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)` + * + * Perform CTR encryption of some data, and CBC-MAC. Processing is + * done "in place" (the output data replaces the input data). This + * function applies CTR encryption on the data, using a full + * block-size counter (i.e. for 128-bit blocks, the counter is + * incremented as a 128-bit value). The 'ctr' array contains the + * initial value for the counter (used in the first block) and it is + * updated with the new value after data processing. The 'cbcmac' + * value shall point to a block-sized value which is used as IV for + * CBC-MAC, computed over the encrypted data (output of CTR + * encryption); the resulting CBC-MAC is written over 'cbcmac' on + * output. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_decrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)` + * + * Perform CTR decryption of some data, and CBC-MAC. Processing is + * done "in place" (the output data replaces the input data). This + * function applies CTR decryption on the data, using a full + * block-size counter (i.e. for 128-bit blocks, the counter is + * incremented as a 128-bit value). The 'ctr' array contains the + * initial value for the counter (used in the first block) and it is + * updated with the new value after data processing. The 'cbcmac' + * value shall point to a block-sized value which is used as IV for + * CBC-MAC, computed over the encrypted data (input of CTR + * encryption); the resulting CBC-MAC is written over 'cbcmac' on + * output. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_ctr(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *data, size_t len)` + * + * Perform CTR encryption or decryption of the provided data. The + * data is processed "in place" (the output data replaces the input + * data). A full block-sized counter is applied (i.e. for 128-bit + * blocks, the counter is incremented as a 128-bit value). The 'ctr' + * array contains the initial value for the counter (used in the + * first block), and it is updated with the new value after data + * processing. + * + * The data length MUST be a multiple of the block size. + * + * - `br_xxx_ctrcbc_mac(const br_xxx_ctrcbc_keys *ctx, void *cbcmac, const void *data, size_t len)` + * + * Compute CBC-MAC over the provided data. The IV for CBC-MAC is + * provided as 'cbcmac'; the output is written over the same array. + * The data itself is untouched. The data length MUST be a multiple + * of the block size. + * + * + * It shall be noted that the key expansion functions return `void`. If + * the provided key length is not allowed, then there will be no error + * reporting; implementations need not validate the key length, thus an + * invalid key length may result in undefined behaviour (e.g. buffer + * overflow). + * + * Subkey structures contain no interior pointer, and no external + * resources are allocated upon key expansion. They can thus be + * discarded without any explicit deallocation. + * + * + * ## Object-Oriented API + * + * Each context structure begins with a field (called `vtable`) that + * points to an instance of a structure that references the relevant + * functions through pointers. Each such structure contains the + * following: + * + * - `context_size` + * + * The size (in bytes) of the context structure for subkeys. + * + * - `block_size` + * + * The cipher block size (in bytes). + * + * - `log_block_size` + * + * The base-2 logarithm of cipher block size (e.g. 4 for blocks + * of 16 bytes). + * + * - `init` + * + * Pointer to the key expansion function. + * + * - `run` + * + * Pointer to the encryption/decryption function. + * + * For combined CTR/CBC-MAC encryption, the `vtable` has a slightly + * different structure: + * + * - `context_size` + * + * The size (in bytes) of the context structure for subkeys. + * + * - `block_size` + * + * The cipher block size (in bytes). + * + * - `log_block_size` + * + * The base-2 logarithm of cipher block size (e.g. 4 for blocks + * of 16 bytes). + * + * - `init` + * + * Pointer to the key expansion function. + * + * - `encrypt` + * + * Pointer to the CTR encryption + CBC-MAC function. + * + * - `decrypt` + * + * Pointer to the CTR decryption + CBC-MAC function. + * + * - `ctr` + * + * Pointer to the CTR encryption/decryption function. + * + * - `mac` + * + * Pointer to the CBC-MAC function. + * + * For block cipher "`xxx`", static, constant instances of these + * structures are defined, under the names: + * + * - `br_xxx_cbcenc_vtable` + * - `br_xxx_cbcdec_vtable` + * - `br_xxx_ctr_vtable` + * - `br_xxx_ctrcbc_vtable` + * + * + * ## Implemented Block Ciphers + * + * Provided implementations are: + * + * | Name | Function | Block Size (bytes) | Key lengths (bytes) | + * | :-------- | :------- | :----------------: | :-----------------: | + * | aes_big | AES | 16 | 16, 24 and 32 | + * | aes_small | AES | 16 | 16, 24 and 32 | + * | aes_ct | AES | 16 | 16, 24 and 32 | + * | aes_ct64 | AES | 16 | 16, 24 and 32 | + * | aes_x86ni | AES | 16 | 16, 24 and 32 | + * | aes_pwr8 | AES | 16 | 16, 24 and 32 | + * | des_ct | DES/3DES | 8 | 8, 16 and 24 | + * | des_tab | DES/3DES | 8 | 8, 16 and 24 | + * + * **Note:** DES/3DES nominally uses keys of 64, 128 and 192 bits (i.e. 8, + * 16 and 24 bytes), but some of the bits are ignored by the algorithm, so + * the _effective_ key lengths, from a security point of view, are 56, + * 112 and 168 bits, respectively. + * + * `aes_big` is a "classical" AES implementation, using tables. It + * is fast but not constant-time, since it makes data-dependent array + * accesses. + * + * `aes_small` is an AES implementation optimized for code size. It + * is substantially slower than `aes_big`; it is not constant-time + * either. + * + * `aes_ct` is a constant-time implementation of AES; its code is about + * as big as that of `aes_big`, while its performance is comparable to + * that of `aes_small`. However, it is constant-time. This + * implementation should thus be considered to be the "default" AES in + * BearSSL, to be used unless the operational context guarantees that a + * non-constant-time implementation is safe, or an architecture-specific + * constant-time implementation can be used (e.g. using dedicated + * hardware opcodes). + * + * `aes_ct64` is another constant-time implementation of AES. It is + * similar to `aes_ct` but uses 64-bit values. On 32-bit machines, + * `aes_ct64` is not faster than `aes_ct`, often a bit slower, and has + * a larger footprint; however, on 64-bit architectures, `aes_ct64` + * is typically twice faster than `aes_ct` for modes that allow parallel + * operations (i.e. CTR, and CBC decryption, but not CBC encryption). + * + * `aes_x86ni` exists only on x86 architectures (32-bit and 64-bit). It + * uses the AES-NI opcodes when available. + * + * `aes_pwr8` exists only on PowerPC / POWER architectures (32-bit and + * 64-bit, both little-endian and big-endian). It uses the AES opcodes + * present in POWER8 and later. + * + * `des_tab` is a classic, table-based implementation of DES/3DES. It + * is not constant-time. + * + * `des_ct` is an constant-time implementation of DES/3DES. It is + * substantially slower than `des_tab`. + * + * ## ChaCha20 and Poly1305 + * + * ChaCha20 is a stream cipher. Poly1305 is a MAC algorithm. They + * are described in [RFC 7539](https://tools.ietf.org/html/rfc7539). + * + * Two function pointer types are defined: + * + * - `br_chacha20_run` describes a function that implements ChaCha20 + * only. + * + * - `br_poly1305_run` describes an implementation of Poly1305, + * in the AEAD combination with ChaCha20 specified in RFC 7539 + * (the ChaCha20 implementation is provided as a function pointer). + * + * `chacha20_ct` is a straightforward implementation of ChaCha20 in + * plain C; it is constant-time, small, and reasonably fast. + * + * `chacha20_sse2` leverages SSE2 opcodes (on x86 architectures that + * support these opcodes). It is faster than `chacha20_ct`. + * + * `poly1305_ctmul` is an implementation of the ChaCha20+Poly1305 AEAD + * construction, where the Poly1305 part is performed with mixed 32-bit + * multiplications (operands are 32-bit, result is 64-bit). + * + * `poly1305_ctmul32` implements ChaCha20+Poly1305 using pure 32-bit + * multiplications (32-bit operands, 32-bit result). It is slower than + * `poly1305_ctmul`, except on some specific architectures such as + * the ARM Cortex M0+. + * + * `poly1305_ctmulq` implements ChaCha20+Poly1305 with mixed 64-bit + * multiplications (operands are 64-bit, result is 128-bit) on 64-bit + * platforms that support such operations. + * + * `poly1305_i15` implements ChaCha20+Poly1305 with the generic "i15" + * big integer implementation. It is meant mostly for testing purposes, + * although it can help with saving a few hundred bytes of code footprint + * on systems where code size is scarce. + */ + +/** + * \brief Class type for CBC encryption implementations. + * + * A `br_block_cbcenc_class` instance points to the functions implementing + * a specific block cipher, when used in CBC mode for encrypting data. + */ +typedef struct br_block_cbcenc_class_ br_block_cbcenc_class; +struct br_block_cbcenc_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_cbcenc_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CBC encryption. + * + * The `iv` parameter points to the IV for this run; it is + * updated with a copy of the last encrypted block. The data + * is encrypted "in place"; its length (`len`) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param iv IV for CBC encryption (updated). + * \param data data to encrypt. + * \param len data length (in bytes, multiple of block size). + */ + void (*run)(const br_block_cbcenc_class *const *ctx, + void *iv, void *data, size_t len); +}; + +/** + * \brief Class type for CBC decryption implementations. + * + * A `br_block_cbcdec_class` instance points to the functions implementing + * a specific block cipher, when used in CBC mode for decrypting data. + */ +typedef struct br_block_cbcdec_class_ br_block_cbcdec_class; +struct br_block_cbcdec_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_cbcdec_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CBC decryption. + * + * The `iv` parameter points to the IV for this run; it is + * updated with a copy of the last encrypted block. The data + * is decrypted "in place"; its length (`len`) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param iv IV for CBC decryption (updated). + * \param data data to decrypt. + * \param len data length (in bytes, multiple of block size). + */ + void (*run)(const br_block_cbcdec_class *const *ctx, + void *iv, void *data, size_t len); +}; + +/** + * \brief Class type for CTR encryption/decryption implementations. + * + * A `br_block_ctr_class` instance points to the functions implementing + * a specific block cipher, when used in CTR mode for encrypting or + * decrypting data. + */ +typedef struct br_block_ctr_class_ br_block_ctr_class; +struct br_block_ctr_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_ctr_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CTR encryption or decryption. + * + * The `iv` parameter points to the IV for this run; its + * length is exactly 4 bytes less than the block size (e.g. + * 12 bytes for AES/CTR). The IV is combined with a 32-bit + * block counter to produce the block value which is processed + * with the block cipher. + * + * The data to encrypt or decrypt is updated "in place". Its + * length (`len` bytes) is not required to be a multiple of + * the block size; if the final block is partial, then the + * corresponding key stream bits are dropped. + * + * The resulting counter value is returned. + * + * \param ctx context structure (already initialised). + * \param iv IV for CTR encryption/decryption. + * \param cc initial value for the block counter. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \return the new block counter value. + */ + uint32_t (*run)(const br_block_ctr_class *const *ctx, + const void *iv, uint32_t cc, void *data, size_t len); +}; + +/** + * \brief Class type for combined CTR and CBC-MAC implementations. + * + * A `br_block_ctrcbc_class` instance points to the functions implementing + * a specific block cipher, when used in CTR mode for encrypting or + * decrypting data, along with CBC-MAC. + */ +typedef struct br_block_ctrcbc_class_ br_block_ctrcbc_class; +struct br_block_ctrcbc_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate + * for containing subkeys. + */ + size_t context_size; + + /** + * \brief Size of individual blocks (in bytes). + */ + unsigned block_size; + + /** + * \brief Base-2 logarithm of the size of individual blocks, + * expressed in bytes. + */ + unsigned log_block_size; + + /** + * \brief Initialisation function. + * + * This function sets the `vtable` field in the context structure. + * The key length MUST be one of the key lengths supported by + * the implementation. + * + * \param ctx context structure to initialise. + * \param key secret key. + * \param key_len key length (in bytes). + */ + void (*init)(const br_block_ctrcbc_class **ctx, + const void *key, size_t key_len); + + /** + * \brief Run the CTR encryption + CBC-MAC. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as encryption proceeds. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (output of CTR + * encryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data to encrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to encrypt. + * \param len data length (in bytes). + */ + void (*encrypt)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + + /** + * \brief Run the CTR decryption + CBC-MAC. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as decryption proceeds. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (i.e. before CTR + * decryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data to decrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*decrypt)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + + /** + * \brief Run the CTR encryption/decryption only. + * + * The `ctr` parameter points to the counter; its length shall + * be equal to the block size. It is updated by this function + * as decryption proceeds. + * + * The data to decrypt is updated "in place". Its length (`len` + * bytes) MUST be a multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param ctr counter for CTR encryption (initial and final). + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*ctr)(const br_block_ctrcbc_class *const *ctx, + void *ctr, void *data, size_t len); + + /** + * \brief Run the CBC-MAC only. + * + * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC + * is computed over the encrypted data (i.e. before CTR + * decryption). Its length shall be equal to the block size. The + * computed CBC-MAC value is written over the `cbcmac` array. + * + * The data is unmodified. Its length (`len` bytes) MUST be a + * multiple of the block size. + * + * \param ctx context structure (already initialised). + * \param cbcmac IV and output buffer for CBC-MAC. + * \param data data to decrypt. + * \param len data length (in bytes). + */ + void (*mac)(const br_block_ctrcbc_class *const *ctx, + void *cbcmac, const void *data, size_t len); +}; + +/* + * Traditional, table-based AES implementation. It is fast, but uses + * internal tables (in particular a 1 kB table for encryption, another + * 1 kB table for decryption, and a 256-byte table for key schedule), + * and it is not constant-time. In contexts where cache-timing attacks + * apply, this implementation may leak the secret key. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_big_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_big_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_big` implementation). + */ +extern const br_block_cbcenc_class br_aes_big_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_big` implementation). + */ +extern const br_block_cbcdec_class br_aes_big_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_big` implementation). + */ +extern const br_block_ctr_class br_aes_big_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_big` implementation). + */ +extern const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_big` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to encrypt or decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_big` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * AES implementation optimized for size. It is slower than the + * traditional table-based AES implementation, but requires much less + * code. It still uses data-dependent table accesses (albeit within a + * much smaller 256-byte table), which makes it conceptually vulnerable + * to cache-timing attacks. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_small_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_small_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_small` implementation). + */ +extern const br_block_cbcenc_class br_aes_small_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_small` implementation). + */ +extern const br_block_cbcdec_class br_aes_small_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_small` implementation). + */ +extern const br_block_ctr_class br_aes_small_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_small` implementation). + */ +extern const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_small` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_small` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * Constant-time AES implementation. Its size is similar to that of + * 'aes_big', and its performance is similar to that of 'aes_small' (faster + * decryption, slower encryption). However, it is constant-time, i.e. + * immune to cache-timing and similar attacks. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_ct_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[60]; + unsigned num_rounds; +#endif +} br_aes_ct_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_ct` implementation). + */ +extern const br_block_cbcenc_class br_aes_ct_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_ct` implementation). + */ +extern const br_block_cbcdec_class br_aes_ct_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_ct` implementation). + */ +extern const br_block_ctr_class br_aes_ct_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_ct` implementation). + */ +extern const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_ct` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * 64-bit constant-time AES implementation. It is similar to 'aes_ct' + * but uses 64-bit registers, making it about twice faster than 'aes_ct' + * on 64-bit platforms, while remaining constant-time and with a similar + * code size. (The doubling in performance is only for CBC decryption + * and CTR mode; CBC encryption is non-parallel and cannot benefit from + * the larger registers.) + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_ct64_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t skey[30]; + unsigned num_rounds; +#endif +} br_aes_ct64_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_ct64` implementation). + */ +extern const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_ct64` implementation). + */ +extern const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_ct64` implementation). + */ +extern const br_block_ctr_class br_aes_ct64_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_ct64` implementation). + */ +extern const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_ct64` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_ct64` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/* + * AES implementation using AES-NI opcodes (x86 platform). + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_x86ni_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_cbcenc_get_vtable()`. + */ +extern const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_cbcdec_get_vtable()`. + */ +extern const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_ctr_get_vtable()`. + */ +extern const br_block_ctr_class br_aes_x86ni_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_ctrcbc_get_vtable()`. + */ +extern const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/** + * \brief Obtain the `aes_x86ni` AES-CBC (encryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_cbcenc_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CBC (encryption) implementation, or `NULL`. + */ +const br_block_cbcenc_class *br_aes_x86ni_cbcenc_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CBC (decryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_cbcdec_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CBC (decryption) implementation, or `NULL`. + */ +const br_block_cbcdec_class *br_aes_x86ni_cbcdec_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CTR implementation, if available. + * + * This function returns a pointer to `br_aes_x86ni_ctr_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CTR implementation, or `NULL`. + */ +const br_block_ctr_class *br_aes_x86ni_ctr_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CTR + CBC-MAC implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_ctrcbc_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x86ni` AES-CTR implementation, or `NULL`. + */ +const br_block_ctrcbc_class *br_aes_x86ni_ctrcbc_get_vtable(void); + +/* + * AES implementation using POWER8 opcodes. + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_pwr8_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_ctr_keys; + +/** + * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption + * and decryption + CBC-MAC). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctrcbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + } skey; + unsigned num_rounds; +#endif +} br_aes_pwr8_ctrcbc_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_cbcenc_get_vtable()`. + */ +extern const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_cbcdec_get_vtable()`. + */ +extern const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_ctr_get_vtable()`. + */ +extern const br_block_ctr_class br_aes_pwr8_ctr_vtable; + +/** + * \brief Class instance for AES CTR encryption/decryption + CBC-MAC + * (`aes_pwr8` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_pwr8_ctrcbc_get_vtable()`. + */ +extern const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC + * (`aes_pwr8` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief CTR encryption + CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR decryption + CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *cbcmac, void *data, size_t len); + +/** + * \brief CTR encryption/decryption with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param ctr counter for CTR (16 bytes, updated). + * \param data data to MAC (updated). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx, + void *ctr, void *data, size_t len); + +/** + * \brief CBC-MAC with AES (`aes_pwr8` implementation). + * + * \param ctx context (already initialised). + * \param cbcmac IV for CBC-MAC (updated). + * \param data data to MAC (unmodified). + * \param len data length (in bytes, MUST be a multiple of 16). + */ +void br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx, + void *cbcmac, const void *data, size_t len); + +/** + * \brief Obtain the `aes_pwr8` AES-CBC (encryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_cbcenc_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 + * crypto opcodes are available on the currently running CPU. If either + * of these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CBC (encryption) implementation, or `NULL`. + */ +const br_block_cbcenc_class *br_aes_pwr8_cbcenc_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CBC (decryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_cbcdec_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 + * crypto opcodes are available on the currently running CPU. If either + * of these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CBC (decryption) implementation, or `NULL`. + */ +const br_block_cbcdec_class *br_aes_pwr8_cbcdec_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CTR implementation, if available. + * + * This function returns a pointer to `br_aes_pwr8_ctr_vtable`, if that + * implementation was compiled in the library _and_ the POWER8 crypto + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CTR implementation, or `NULL`. + */ +const br_block_ctr_class *br_aes_pwr8_ctr_get_vtable(void); + +/** + * \brief Obtain the `aes_pwr8` AES-CTR + CBC-MAC implementation, if + * available. + * + * This function returns a pointer to `br_aes_pwr8_ctrcbc_vtable`, if + * that implementation was compiled in the library _and_ the POWER8 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_pwr8` AES-CTR implementation, or `NULL`. + */ +const br_block_ctrcbc_class *br_aes_pwr8_ctrcbc_get_vtable(void); + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC encryption) for all AES implementations. + */ +typedef union { + const br_block_cbcenc_class *vtable; + br_aes_big_cbcenc_keys c_big; + br_aes_small_cbcenc_keys c_small; + br_aes_ct_cbcenc_keys c_ct; + br_aes_ct64_cbcenc_keys c_ct64; + br_aes_x86ni_cbcenc_keys c_x86ni; + br_aes_pwr8_cbcenc_keys c_pwr8; +} br_aes_gen_cbcenc_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC decryption) for all AES implementations. + */ +typedef union { + const br_block_cbcdec_class *vtable; + br_aes_big_cbcdec_keys c_big; + br_aes_small_cbcdec_keys c_small; + br_aes_ct_cbcdec_keys c_ct; + br_aes_ct64_cbcdec_keys c_ct64; + br_aes_x86ni_cbcdec_keys c_x86ni; + br_aes_pwr8_cbcdec_keys c_pwr8; +} br_aes_gen_cbcdec_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CTR encryption and decryption) for all AES implementations. + */ +typedef union { + const br_block_ctr_class *vtable; + br_aes_big_ctr_keys c_big; + br_aes_small_ctr_keys c_small; + br_aes_ct_ctr_keys c_ct; + br_aes_ct64_ctr_keys c_ct64; + br_aes_x86ni_ctr_keys c_x86ni; + br_aes_pwr8_ctr_keys c_pwr8; +} br_aes_gen_ctr_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CTR encryption/decryption + CBC-MAC) for all AES implementations. + */ +typedef union { + const br_block_ctrcbc_class *vtable; + br_aes_big_ctrcbc_keys c_big; + br_aes_small_ctrcbc_keys c_small; + br_aes_ct_ctrcbc_keys c_ct; + br_aes_ct64_ctrcbc_keys c_ct64; + br_aes_x86ni_ctrcbc_keys c_x86ni; + br_aes_pwr8_ctrcbc_keys c_pwr8; +} br_aes_gen_ctrcbc_keys; + +/* + * Traditional, table-based implementation for DES/3DES. Since tables are + * used, cache-timing attacks are conceptually possible. + */ + +/** \brief DES/3DES block size (8 bytes). */ +#define br_des_tab_BLOCK_SIZE 8 + +/** + * \brief Context for DES subkeys (`des_tab` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_tab_cbcenc_keys; + +/** + * \brief Context for DES subkeys (`des_tab` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_tab_cbcdec_keys; + +/** + * \brief Class instance for DES CBC encryption (`des_tab` implementation). + */ +extern const br_block_cbcenc_class br_des_tab_cbcenc_vtable; + +/** + * \brief Class instance for DES CBC decryption (`des_tab` implementation). + */ +extern const br_block_cbcdec_class br_des_tab_cbcdec_vtable; + +/** + * \brief Context initialisation (key schedule) for DES CBC encryption + * (`des_tab` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for DES CBC decryption + * (`des_tab` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with DES (`des_tab` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with DES (`des_tab` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/* + * Constant-time implementation for DES/3DES. It is substantially slower + * (by a factor of about 4x), but also immune to cache-timing attacks. + */ + +/** \brief DES/3DES block size (8 bytes). */ +#define br_des_ct_BLOCK_SIZE 8 + +/** + * \brief Context for DES subkeys (`des_ct` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_ct_cbcenc_keys; + +/** + * \brief Context for DES subkeys (`des_ct` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint32_t skey[96]; + unsigned num_rounds; +#endif +} br_des_ct_cbcdec_keys; + +/** + * \brief Class instance for DES CBC encryption (`des_ct` implementation). + */ +extern const br_block_cbcenc_class br_des_ct_cbcenc_vtable; + +/** + * \brief Class instance for DES CBC decryption (`des_ct` implementation). + */ +extern const br_block_cbcdec_class br_des_ct_cbcdec_vtable; + +/** + * \brief Context initialisation (key schedule) for DES CBC encryption + * (`des_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for DES CBC decryption + * (`des_ct` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with DES (`des_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with DES (`des_ct` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 8). + */ +void br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/* + * These structures are large enough to accommodate subkeys for all + * DES/3DES implementations. + */ + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC encryption) for all DES implementations. + */ +typedef union { + const br_block_cbcenc_class *vtable; + br_des_tab_cbcenc_keys tab; + br_des_ct_cbcenc_keys ct; +} br_des_gen_cbcenc_keys; + +/** + * \brief Aggregate structure large enough to be used as context for + * subkeys (CBC decryption) for all DES implementations. + */ +typedef union { + const br_block_cbcdec_class *vtable; + br_des_tab_cbcdec_keys c_tab; + br_des_ct_cbcdec_keys c_ct; +} br_des_gen_cbcdec_keys; + +/** + * \brief Type for a ChaCha20 implementation. + * + * An implementation follows the description in RFC 7539: + * + * - Key is 256 bits (`key` points to exactly 32 bytes). + * + * - IV is 96 bits (`iv` points to exactly 12 bytes). + * + * - Block counter is over 32 bits and starts at value `cc`; the + * resulting value is returned. + * + * Data (pointed to by `data`, of length `len`) is encrypted/decrypted + * in place. If `len` is not a multiple of 64, then the excess bytes from + * the last block processing are dropped (therefore, "chunked" processing + * works only as long as each non-final chunk has a length multiple of 64). + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +typedef uint32_t (*br_chacha20_run)(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief ChaCha20 implementation (straightforward C code, constant-time). + * + * \see br_chacha20_run + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +uint32_t br_chacha20_ct_run(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief ChaCha20 implementation (SSE2 code, constant-time). + * + * This implementation is available only on x86 platforms, depending on + * compiler support. Moreover, in 32-bit mode, it might not actually run, + * if the underlying hardware does not implement the SSE2 opcode (in + * 64-bit mode, SSE2 is part of the ABI, so if the code could be compiled + * at all, then it can run). Use `br_chacha20_sse2_get()` to safely obtain + * a pointer to that function. + * + * \see br_chacha20_run + * + * \param key secret key (32 bytes). + * \param iv IV (12 bytes). + * \param cc initial counter value. + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + */ +uint32_t br_chacha20_sse2_run(const void *key, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief Obtain the `sse2` ChaCha20 implementation, if available. + * + * This function returns a pointer to `br_chacha20_sse2_run`, if + * that implementation was compiled in the library _and_ the SSE2 + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `0`. + * + * \return the `sse2` ChaCha20 implementation, or `0`. + */ +br_chacha20_run br_chacha20_sse2_get(void); + +/** + * \brief Type for a ChaCha20+Poly1305 AEAD implementation. + * + * The provided data is encrypted or decrypted with ChaCha20. The + * authentication tag is computed on the concatenation of the + * additional data and the ciphertext, with the padding and lengths + * as described in RFC 7539 (section 2.8). + * + * After decryption, the caller is responsible for checking that the + * computed tag matches the expected value. + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +typedef void (*br_poly1305_run)(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (mixed 32-bit multiplications). + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmul_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (pure 32-bit multiplications). + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmul32_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (i15). + * + * This implementation relies on the generic big integer code "i15" + * (which uses pure 32-bit multiplications). As such, it may save a + * little code footprint in a context where "i15" is already included + * (e.g. for elliptic curves or for RSA); however, it is also + * substantially slower than the ctmul and ctmul32 implementations. + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_i15_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief ChaCha20+Poly1305 AEAD implementation (ctmulq). + * + * This implementation uses 64-bit multiplications (result over 128 bits). + * It is available only on platforms that offer such a primitive (in + * practice, 64-bit architectures). Use `br_poly1305_ctmulq_get()` to + * dynamically obtain a pointer to that function, or 0 if not supported. + * + * \see br_poly1305_run + * + * \param key secret key (32 bytes). + * \param iv nonce (12 bytes). + * \param data data to encrypt or decrypt. + * \param len data length (in bytes). + * \param aad additional authenticated data. + * \param aad_len length of additional authenticated data (in bytes). + * \param tag output buffer for the authentication tag. + * \param ichacha implementation of ChaCha20. + * \param encrypt non-zero for encryption, zero for decryption. + */ +void br_poly1305_ctmulq_run(const void *key, const void *iv, + void *data, size_t len, const void *aad, size_t aad_len, + void *tag, br_chacha20_run ichacha, int encrypt); + +/** + * \brief Get the ChaCha20+Poly1305 "ctmulq" implementation, if available. + * + * This function returns a pointer to the `br_poly1305_ctmulq_run()` + * function if supported on the current platform; otherwise, it returns 0. + * + * \return the ctmulq ChaCha20+Poly1305 implementation, or 0. + */ +br_poly1305_run br_poly1305_ctmulq_get(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_ec.h b/include/bearssl/bearssl_ec.h new file mode 100644 index 000000000..f954309eb --- /dev/null +++ b/include/bearssl/bearssl_ec.h @@ -0,0 +1,967 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_EC_H__ +#define BR_BEARSSL_EC_H__ + +#include +#include + +#include "bearssl_rand.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_ec.h + * + * # Elliptic Curves + * + * This file documents the EC implementations provided with BearSSL, and + * ECDSA. + * + * ## Elliptic Curve API + * + * Only "named curves" are supported. Each EC implementation supports + * one or several named curves, identified by symbolic identifiers. + * These identifiers are small integers, that correspond to the values + * registered by the + * [IANA](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8). + * + * Since all currently defined elliptic curve identifiers are in the 0..31 + * range, it is convenient to encode support of some curves in a 32-bit + * word, such that bit x corresponds to curve of identifier x. + * + * An EC implementation is incarnated by a `br_ec_impl` instance, that + * offers the following fields: + * + * - `supported_curves` + * + * A 32-bit word that documents the identifiers of the curves supported + * by this implementation. + * + * - `generator()` + * + * Callback method that returns a pointer to the conventional generator + * point for that curve. + * + * - `order()` + * + * Callback method that returns a pointer to the subgroup order for + * that curve. That value uses unsigned big-endian encoding. + * + * - `xoff()` + * + * Callback method that returns the offset and length of the X + * coordinate in an encoded point. + * + * - `mul()` + * + * Multiply a curve point with an integer. + * + * - `mulgen()` + * + * Multiply the curve generator with an integer. This may be faster + * than the generic `mul()`. + * + * - `muladd()` + * + * Multiply two curve points by two integers, and return the sum of + * the two products. + * + * All curve points are represented in uncompressed format. The `mul()` + * and `muladd()` methods take care to validate that the provided points + * are really part of the relevant curve subgroup. + * + * For all point multiplication functions, the following holds: + * + * - Functions validate that the provided points are valid members + * of the relevant curve subgroup. An error is reported if that is + * not the case. + * + * - Processing is constant-time, even if the point operands are not + * valid. This holds for both the source and resulting points, and + * the multipliers (integers). Only the byte length of the provided + * multiplier arrays (not their actual value length in bits) may + * leak through timing-based side channels. + * + * - The multipliers (integers) MUST be lower than the subgroup order. + * If this property is not met, then the result is indeterminate, + * but an error value is not ncessearily returned. + * + * + * ## ECDSA + * + * ECDSA signatures have two standard formats, called "raw" and "asn1". + * Internally, such a signature is a pair of modular integers `(r,s)`. + * The "raw" format is the concatenation of the unsigned big-endian + * encodings of these two integers, possibly left-padded with zeros so + * that they have the same encoded length. The "asn1" format is the + * DER encoding of an ASN.1 structure that contains the two integer + * values: + * + * ECDSASignature ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * In general, in all of X.509 and SSL/TLS, the "asn1" format is used. + * BearSSL offers ECDSA implementations for both formats; conversion + * functions between the two formats are also provided. Conversion of a + * "raw" format signature into "asn1" may enlarge a signature by no more + * than 9 bytes for all supported curves; conversely, conversion of an + * "asn1" signature to "raw" may expand the signature but the "raw" + * length will never be more than twice the length of the "asn1" length + * (and usually it will be shorter). + * + * Note that for a given signature, the "raw" format is not fully + * deterministic, in that it does not enforce a minimal common length. + */ + +/* + * Standard curve ID. These ID are equal to the assigned numerical + * identifiers assigned to these curves for TLS: + * http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + */ + +/** \brief Identifier for named curve sect163k1. */ +#define BR_EC_sect163k1 1 + +/** \brief Identifier for named curve sect163r1. */ +#define BR_EC_sect163r1 2 + +/** \brief Identifier for named curve sect163r2. */ +#define BR_EC_sect163r2 3 + +/** \brief Identifier for named curve sect193r1. */ +#define BR_EC_sect193r1 4 + +/** \brief Identifier for named curve sect193r2. */ +#define BR_EC_sect193r2 5 + +/** \brief Identifier for named curve sect233k1. */ +#define BR_EC_sect233k1 6 + +/** \brief Identifier for named curve sect233r1. */ +#define BR_EC_sect233r1 7 + +/** \brief Identifier for named curve sect239k1. */ +#define BR_EC_sect239k1 8 + +/** \brief Identifier for named curve sect283k1. */ +#define BR_EC_sect283k1 9 + +/** \brief Identifier for named curve sect283r1. */ +#define BR_EC_sect283r1 10 + +/** \brief Identifier for named curve sect409k1. */ +#define BR_EC_sect409k1 11 + +/** \brief Identifier for named curve sect409r1. */ +#define BR_EC_sect409r1 12 + +/** \brief Identifier for named curve sect571k1. */ +#define BR_EC_sect571k1 13 + +/** \brief Identifier for named curve sect571r1. */ +#define BR_EC_sect571r1 14 + +/** \brief Identifier for named curve secp160k1. */ +#define BR_EC_secp160k1 15 + +/** \brief Identifier for named curve secp160r1. */ +#define BR_EC_secp160r1 16 + +/** \brief Identifier for named curve secp160r2. */ +#define BR_EC_secp160r2 17 + +/** \brief Identifier for named curve secp192k1. */ +#define BR_EC_secp192k1 18 + +/** \brief Identifier for named curve secp192r1. */ +#define BR_EC_secp192r1 19 + +/** \brief Identifier for named curve secp224k1. */ +#define BR_EC_secp224k1 20 + +/** \brief Identifier for named curve secp224r1. */ +#define BR_EC_secp224r1 21 + +/** \brief Identifier for named curve secp256k1. */ +#define BR_EC_secp256k1 22 + +/** \brief Identifier for named curve secp256r1. */ +#define BR_EC_secp256r1 23 + +/** \brief Identifier for named curve secp384r1. */ +#define BR_EC_secp384r1 24 + +/** \brief Identifier for named curve secp521r1. */ +#define BR_EC_secp521r1 25 + +/** \brief Identifier for named curve brainpoolP256r1. */ +#define BR_EC_brainpoolP256r1 26 + +/** \brief Identifier for named curve brainpoolP384r1. */ +#define BR_EC_brainpoolP384r1 27 + +/** \brief Identifier for named curve brainpoolP512r1. */ +#define BR_EC_brainpoolP512r1 28 + +/** \brief Identifier for named curve Curve25519. */ +#define BR_EC_curve25519 29 + +/** \brief Identifier for named curve Curve448. */ +#define BR_EC_curve448 30 + +/** + * \brief Structure for an EC public key. + */ +typedef struct { + /** \brief Identifier for the curve used by this key. */ + int curve; + /** \brief Public curve point (uncompressed format). */ + unsigned char *q; + /** \brief Length of public curve point (in bytes). */ + size_t qlen; +} br_ec_public_key; + +/** + * \brief Structure for an EC private key. + * + * The private key is an integer modulo the curve subgroup order. The + * encoding below tolerates extra leading zeros. In general, it is + * recommended that the private key has the same length as the curve + * subgroup order. + */ +typedef struct { + /** \brief Identifier for the curve used by this key. */ + int curve; + /** \brief Private key (integer, unsigned big-endian encoding). */ + unsigned char *x; + /** \brief Private key length (in bytes). */ + size_t xlen; +} br_ec_private_key; + +/** + * \brief Type for an EC implementation. + */ +typedef struct { + /** + * \brief Supported curves. + * + * This word is a bitfield: bit `x` is set if the curve of ID `x` + * is supported. E.g. an implementation supporting both NIST P-256 + * (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have + * value `0x01800000` in this field. + */ + uint32_t supported_curves; + + /** + * \brief Get the conventional generator. + * + * This function returns the conventional generator (encoded + * curve point) for the specified curve. This function MUST NOT + * be called if the curve is not supported. + * + * \param curve curve identifier. + * \param len receiver for the encoded generator length (in bytes). + * \return the encoded generator. + */ + const unsigned char *(*generator)(int curve, size_t *len); + + /** + * \brief Get the subgroup order. + * + * This function returns the order of the subgroup generated by + * the conventional generator, for the specified curve. Unsigned + * big-endian encoding is used. This function MUST NOT be called + * if the curve is not supported. + * + * \param curve curve identifier. + * \param len receiver for the encoded order length (in bytes). + * \return the encoded order. + */ + const unsigned char *(*order)(int curve, size_t *len); + + /** + * \brief Get the offset and length for the X coordinate. + * + * This function returns the offset and length (in bytes) of + * the X coordinate in an encoded non-zero point. + * + * \param curve curve identifier. + * \param len receiver for the X coordinate length (in bytes). + * \return the offset for the X coordinate (in bytes). + */ + size_t (*xoff)(int curve, size_t *len); + + /** + * \brief Multiply a curve point by an integer. + * + * The source point is provided in array `G` (of size `Glen` bytes); + * the multiplication result is written over it. The multiplier + * `x` (of size `xlen` bytes) uses unsigned big-endian encoding. + * + * Rules: + * + * - The specified curve MUST be supported. + * + * - The source point must be a valid point on the relevant curve + * subgroup (and not the "point at infinity" either). If this is + * not the case, then this function returns an error (0). + * + * - The multiplier integer MUST be non-zero and less than the + * curve subgroup order. If this property does not hold, then + * the result is indeterminate and an error code is not + * guaranteed. + * + * Returned value is 1 on success, 0 on error. On error, the + * contents of `G` are indeterminate. + * + * \param G point to multiply. + * \param Glen length of the encoded point (in bytes). + * \param x multiplier (unsigned big-endian). + * \param xlen multiplier length (in bytes). + * \param curve curve identifier. + * \return 1 on success, 0 on error. + */ + uint32_t (*mul)(unsigned char *G, size_t Glen, + const unsigned char *x, size_t xlen, int curve); + + /** + * \brief Multiply the generator by an integer. + * + * The multiplier MUST be non-zero and less than the curve + * subgroup order. Results are indeterminate if this property + * does not hold. + * + * \param R output buffer for the point. + * \param x multiplier (unsigned big-endian). + * \param xlen multiplier length (in bytes). + * \param curve curve identifier. + * \return encoded result point length (in bytes). + */ + size_t (*mulgen)(unsigned char *R, + const unsigned char *x, size_t xlen, int curve); + + /** + * \brief Multiply two points by two integers and add the + * results. + * + * The point `x*A + y*B` is computed and written back in the `A` + * array. + * + * Rules: + * + * - The specified curve MUST be supported. + * + * - The source points (`A` and `B`) must be valid points on + * the relevant curve subgroup (and not the "point at + * infinity" either). If this is not the case, then this + * function returns an error (0). + * + * - If the `B` pointer is `NULL`, then the conventional + * subgroup generator is used. With some implementations, + * this may be faster than providing a pointer to the + * generator. + * + * - The multiplier integers (`x` and `y`) MUST be non-zero + * and less than the curve subgroup order. If either integer + * is zero, then an error is reported, but if one of them is + * not lower than the subgroup order, then the result is + * indeterminate and an error code is not guaranteed. + * + * - If the final result is the point at infinity, then an + * error is returned. + * + * Returned value is 1 on success, 0 on error. On error, the + * contents of `A` are indeterminate. + * + * \param A first point to multiply. + * \param B second point to multiply (`NULL` for the generator). + * \param len common length of the encoded points (in bytes). + * \param x multiplier for `A` (unsigned big-endian). + * \param xlen length of multiplier for `A` (in bytes). + * \param y multiplier for `A` (unsigned big-endian). + * \param ylen length of multiplier for `A` (in bytes). + * \param curve curve identifier. + * \return 1 on success, 0 on error. + */ + uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len, + const unsigned char *x, size_t xlen, + const unsigned char *y, size_t ylen, int curve); +} br_ec_impl; + +/** + * \brief EC implementation "i31". + * + * This implementation internally uses generic code for modular integers, + * with a representation as sequences of 31-bit words. It supports secp256r1, + * secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521). + */ +extern const br_ec_impl br_ec_prime_i31; + +/** + * \brief EC implementation "i15". + * + * This implementation internally uses generic code for modular integers, + * with a representation as sequences of 15-bit words. It supports secp256r1, + * secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521). + */ +extern const br_ec_impl br_ec_prime_i15; + +/** + * \brief EC implementation "m15" for P-256. + * + * This implementation uses specialised code for curve secp256r1 (also + * known as NIST P-256), with optional Karatsuba decomposition, and fast + * modular reduction thanks to the field modulus special format. Only + * 32-bit multiplications are used (with 32-bit results, not 64-bit). + */ +extern const br_ec_impl br_ec_p256_m15; + +/** + * \brief EC implementation "m31" for P-256. + * + * This implementation uses specialised code for curve secp256r1 (also + * known as NIST P-256), relying on multiplications of 31-bit values + * (MUL31). + */ +extern const br_ec_impl br_ec_p256_m31; + +/** + * \brief EC implementation "m62" (specialised code) for P-256. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_p256_m62_get()` to dynamically obtain a pointer + * to that implementation. + */ +extern const br_ec_impl br_ec_p256_m62; + +/** + * \brief Get the "m62" implementation of P-256, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_p256_m62_get(void); + +/** + * \brief EC implementation "m64" (specialised code) for P-256. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_p256_m64_get()` to dynamically obtain a pointer + * to that implementation. + */ +extern const br_ec_impl br_ec_p256_m64; + +/** + * \brief Get the "m64" implementation of P-256, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_p256_m64_get(void); + +/** + * \brief EC implementation "i15" (generic code) for Curve25519. + * + * This implementation uses the generic code for modular integers (with + * 15-bit words) to support Curve25519. Due to the specificities of the + * curve definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_i15; + +/** + * \brief EC implementation "i31" (generic code) for Curve25519. + * + * This implementation uses the generic code for modular integers (with + * 31-bit words) to support Curve25519. Due to the specificities of the + * curve definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_i31; + +/** + * \brief EC implementation "m15" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 15 bits. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m15; + +/** + * \brief EC implementation "m31" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 31 bits. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m31; + +/** + * \brief EC implementation "m62" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 62 bits, with a 124-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_c25519_m62_get()` to dynamically obtain a pointer + * to that implementation. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m62; + +/** + * \brief Get the "m62" implementation of Curve25519, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_c25519_m62_get(void); + +/** + * \brief EC implementation "m64" (specialised code) for Curve25519. + * + * This implementation uses custom code relying on multiplication of + * integers up to 64 bits, with a 128-bit result. This implementation is + * defined only on platforms that offer the 64x64->128 multiplication + * support; use `br_ec_c25519_m64_get()` to dynamically obtain a pointer + * to that implementation. Due to the specificities of the curve + * definition, the following applies: + * + * - `muladd()` is not implemented (the function returns 0 systematically). + * - `order()` returns 2^255-1, since the point multiplication algorithm + * accepts any 32-bit integer as input (it clears the top bit and low + * three bits systematically). + */ +extern const br_ec_impl br_ec_c25519_m64; + +/** + * \brief Get the "m64" implementation of Curve25519, if available. + * + * \return the implementation, or 0. + */ +const br_ec_impl *br_ec_c25519_m64_get(void); + +/** + * \brief Aggregate EC implementation "m15". + * + * This implementation is a wrapper for: + * + * - `br_ec_c25519_m15` for Curve25519 + * - `br_ec_p256_m15` for NIST P-256 + * - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512) + */ +extern const br_ec_impl br_ec_all_m15; + +/** + * \brief Aggregate EC implementation "m31". + * + * This implementation is a wrapper for: + * + * - `br_ec_c25519_m31` for Curve25519 + * - `br_ec_p256_m31` for NIST P-256 + * - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512) + */ +extern const br_ec_impl br_ec_all_m31; + +/** + * \brief Get the "default" EC implementation for the current system. + * + * This returns a pointer to the preferred implementation on the + * current system. + * + * \return the default EC implementation. + */ +const br_ec_impl *br_ec_get_default(void); + +/** + * \brief Convert a signature from "raw" to "asn1". + * + * Conversion is done "in place" and the new length is returned. + * Conversion may enlarge the signature, but by no more than 9 bytes at + * most. On error, 0 is returned (error conditions include an odd raw + * signature length, or an oversized integer). + * + * \param sig signature to convert. + * \param sig_len signature length (in bytes). + * \return the new signature length, or 0 on error. + */ +size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len); + +/** + * \brief Convert a signature from "asn1" to "raw". + * + * Conversion is done "in place" and the new length is returned. + * Conversion may enlarge the signature, but the new signature length + * will be less than twice the source length at most. On error, 0 is + * returned (error conditions include an invalid ASN.1 structure or an + * oversized integer). + * + * \param sig signature to convert. + * \param sig_len signature length (in bytes). + * \return the new signature length, or 0 on error. + */ +size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len); + +/** + * \brief Type for an ECDSA signer function. + * + * A pointer to the EC implementation is provided. The hash value is + * assumed to have the length inferred from the designated hash function + * class. + * + * Signature is written in the buffer pointed to by `sig`, and the length + * (in bytes) is returned. On error, nothing is written in the buffer, + * and 0 is returned. This function returns 0 if the specified curve is + * not supported by the provided EC implementation. + * + * The signature format is either "raw" or "asn1", depending on the + * implementation; maximum length is predictable from the implemented + * curve: + * + * | curve | raw | asn1 | + * | :--------- | --: | ---: | + * | NIST P-256 | 64 | 72 | + * | NIST P-384 | 96 | 104 | + * | NIST P-521 | 132 | 139 | + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief Type for an ECDSA signature verification function. + * + * A pointer to the EC implementation is provided. The hashed value, + * computed over the purportedly signed data, is also provided with + * its length. + * + * The signature format is either "raw" or "asn1", depending on the + * implementation. + * + * Returned value is 1 on success (valid signature), 0 on error. This + * function returns 0 if the specified curve is not supported by the + * provided EC implementation. + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature generator, "i31" implementation, "asn1" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature generator, "i31" implementation, "raw" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature verifier, "i31" implementation, "asn1" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature verifier, "i31" implementation, "raw" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature generator, "i15" implementation, "asn1" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature generator, "i15" implementation, "raw" format. + * + * \see br_ecdsa_sign() + * + * \param impl EC implementation to use. + * \param hf hash function used to process the data. + * \param hash_value signed data (hashed). + * \param sk EC private key. + * \param sig destination buffer. + * \return the signature length (in bytes), or 0 on error. + */ +size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl, + const br_hash_class *hf, const void *hash_value, + const br_ec_private_key *sk, void *sig); + +/** + * \brief ECDSA signature verifier, "i15" implementation, "asn1" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief ECDSA signature verifier, "i15" implementation, "raw" format. + * + * \see br_ecdsa_vrfy() + * + * \param impl EC implementation to use. + * \param hash signed data (hashed). + * \param hash_len hash value length (in bytes). + * \param pk EC public key. + * \param sig signature. + * \param sig_len signature length (in bytes). + * \return 1 on success, 0 on error. + */ +uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl, + const void *hash, size_t hash_len, + const br_ec_public_key *pk, const void *sig, size_t sig_len); + +/** + * \brief Get "default" ECDSA implementation (signer, asn1 format). + * + * This returns the preferred implementation of ECDSA signature generation + * ("asn1" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (signer, raw format). + * + * This returns the preferred implementation of ECDSA signature generation + * ("raw" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_sign br_ecdsa_sign_raw_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (verifier, asn1 format). + * + * This returns the preferred implementation of ECDSA signature verification + * ("asn1" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (verifier, raw format). + * + * This returns the preferred implementation of ECDSA signature verification + * ("raw" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void); + +/** + * \brief Maximum size for EC private key element buffer. + * + * This is the largest number of bytes that `br_ec_keygen()` may need or + * ever return. + */ +#define BR_EC_KBUF_PRIV_MAX_SIZE 72 + +/** + * \brief Maximum size for EC public key element buffer. + * + * This is the largest number of bytes that `br_ec_compute_public()` may + * need or ever return. + */ +#define BR_EC_KBUF_PUB_MAX_SIZE 145 + +/** + * \brief Generate a new EC private key. + * + * If the specified `curve` is not supported by the elliptic curve + * implementation (`impl`), then this function returns zero. + * + * The `sk` structure fields are set to the new private key data. In + * particular, `sk.x` is made to point to the provided key buffer (`kbuf`), + * in which the actual private key data is written. That buffer is assumed + * to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum + * size for all supported curves. + * + * The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then + * the private key is not actually generated, and `sk` may also be `NULL`; + * the minimum length for `kbuf` is still computed and returned. + * + * If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is + * still generated and stored in `kbuf`. + * + * \param rng_ctx source PRNG context (already initialized). + * \param impl the elliptic curve implementation. + * \param sk the private key structure to fill, or `NULL`. + * \param kbuf the key element buffer, or `NULL`. + * \param curve the curve identifier. + * \return the key data length (in bytes), or zero. + */ +size_t br_ec_keygen(const br_prng_class **rng_ctx, + const br_ec_impl *impl, br_ec_private_key *sk, + void *kbuf, int curve); + +/** + * \brief Compute EC public key from EC private key. + * + * This function uses the provided elliptic curve implementation (`impl`) + * to compute the public key corresponding to the private key held in `sk`. + * The public key point is written into `kbuf`, which is then linked from + * the `*pk` structure. The size of the public key point, i.e. the number + * of bytes used in `kbuf`, is returned. + * + * If `kbuf` is `NULL`, then the public key point is NOT computed, and + * the public key structure `*pk` is unmodified (`pk` may be `NULL` in + * that case). The size of the public key point is still returned. + * + * If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key + * point is computed and stored in `kbuf`, and its size is returned. + * + * If the curve used by the private key is not supported by the curve + * implementation, then this function returns zero. + * + * The private key MUST be valid. An off-range private key value is not + * necessarily detected, and leads to unpredictable results. + * + * \param impl the elliptic curve implementation. + * \param pk the public key structure to fill (or `NULL`). + * \param kbuf the public key point buffer (or `NULL`). + * \param sk the source private key. + * \return the public key point length (in bytes), or zero. + */ +size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk, + void *kbuf, const br_ec_private_key *sk); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_hash.h b/include/bearssl/bearssl_hash.h new file mode 100644 index 000000000..ca4fa26cc --- /dev/null +++ b/include/bearssl/bearssl_hash.h @@ -0,0 +1,1346 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_HASH_H__ +#define BR_BEARSSL_HASH_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_hash.h + * + * # Hash Functions + * + * This file documents the API for hash functions. + * + * + * ## 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 accommodate 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. + * + * + * ## 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. + * + * + * ## 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 + * shared, thus making it more memory-efficient than separate MD5 and + * SHA-1. It can be useful in implementing SSL 3.0, TLS 1.0 and TLS + * 1.1.) + * + * + * ## 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. + * + * + * ## GHASH + * + * 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. + * + * A GHASH implementation is basically a function that uses the type defined + * in this file under the name `br_ghash`: + * + * 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. + */ + +/** + * \brief Class type for hash function implementations. + * + * A `br_hash_class` instance references the methods implementing a hash + * function. Constant instances of this structure are defined for each + * implemented hash function. Such instances are also called "vtables". + * + * Vtables are used to support object-oriented programming, as + * described on [the BearSSL Web site](https://www.bearssl.org/oop.html). + */ +typedef struct br_hash_class_ br_hash_class; +struct br_hash_class_ { + /** + * \brief Size (in bytes) of the context structure appropriate for + * computing this hash function. + */ + size_t context_size; + + /** + * \brief Descriptor word that contains information about the hash + * function. + * + * For each word `xxx` described below, use `BR_HASHDESC_xxx_OFF` + * and `BR_HASHDESC_xxx_MASK` to access the specific value, as + * follows: + * + * (hf->desc >> BR_HASHDESC_xxx_OFF) & BR_HASHDESC_xxx_MASK + * + * The defined elements are: + * + * - `ID`: the symbolic identifier for the function, as defined + * in [TLS](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1) + * (MD5 = 1, SHA-1 = 2,...). + * + * - `OUT`: hash output size, in bytes. + * + * - `STATE`: internal running state size, in bytes. + * + * - `LBLEN`: base-2 logarithm for the internal block size, as + * defined for HMAC processing (this is 6 for MD5, SHA-1, SHA-224 + * and SHA-256, since these functions use 64-byte blocks; for + * SHA-384 and SHA-512, this is 7, corresponding to their + * 128-byte blocks). + * + * The descriptor may contain a few other flags. + */ + uint32_t desc; + + /** + * \brief Initialisation method. + * + * This method takes as parameter a pointer to a context area, + * that it initialises. The first field of the context is set + * to this vtable; other elements are initialised for a new hash + * computation. + * + * \param ctx pointer to (the first field of) the context. + */ + void (*init)(const br_hash_class **ctx); + + /** + * \brief Data injection method. + * + * The `len` bytes starting at address `data` are injected into + * the running hash computation incarnated by the specified + * context. The context is updated accordingly. It is allowed + * to have `len == 0`, in which case `data` is ignored (and could + * be `NULL`), and nothing happens. + * on the input data. + * + * \param ctx pointer to (the first field of) the context. + * \param data pointer to the first data byte to inject. + * \param len number of bytes to inject. + */ + void (*update)(const br_hash_class **ctx, const void *data, size_t len); + + /** + * \brief Produce hash output. + * + * The hash output corresponding to all data bytes injected in the + * context since the last `init()` call is computed, and written + * in the buffer pointed to by `dst`. The hash output size depends + * on the implemented hash function (e.g. 16 bytes for MD5). + * The context is _not_ modified by this call, so further bytes + * may be afterwards injected to continue the current computation. + * + * \param ctx pointer to (the first field of) the context. + * \param dst destination buffer for the hash output. + */ + void (*out)(const br_hash_class *const *ctx, void *dst); + + /** + * \brief Get running state. + * + * This method saves the current running state into the `dst` + * buffer. What constitutes the "running state" depends on the + * hash function; for Merkle-Damgård hash functions (like + * MD5 or SHA-1), this is the output obtained after processing + * each block. The number of bytes injected so far is returned. + * The context is not modified by this call. + * + * \param ctx pointer to (the first field of) the context. + * \param dst destination buffer for the state. + * \return the injected total byte length. + */ + uint64_t (*state)(const br_hash_class *const *ctx, void *dst); + + /** + * \brief Set running state. + * + * This methods replaces the running state for the function. + * + * \param ctx pointer to (the first field of) the context. + * \param stb source buffer for the state. + * \param count injected total byte length. + */ + void (*set_state)(const br_hash_class **ctx, + const void *stb, uint64_t count); +}; + +#ifndef BR_DOXYGEN_IGNORE +#define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF) +#define BR_HASHDESC_ID_OFF 0 +#define BR_HASHDESC_ID_MASK 0xFF + +#define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF) +#define BR_HASHDESC_OUT_OFF 8 +#define BR_HASHDESC_OUT_MASK 0x7F + +#define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF) +#define BR_HASHDESC_STATE_OFF 15 +#define BR_HASHDESC_STATE_MASK 0xFF + +#define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF) +#define BR_HASHDESC_LBLEN_OFF 23 +#define BR_HASHDESC_LBLEN_MASK 0x0F + +#define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28) +#define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29) +#define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30) +#endif + +/* + * Specific hash functions. + * + * Rules for contexts: + * -- No interior pointer. + * -- No pointer to external dynamically allocated resources. + * -- First field is called 'vtable' and is a pointer to a + * const-qualified br_hash_class instance (pointer is set by init()). + * -- SHA-224 and SHA-256 contexts are identical. + * -- SHA-384 and SHA-512 contexts are identical. + * + * Thus, contexts can be moved and cloned to capture the hash function + * current state; and there is no need for any explicit "release" function. + */ + +/** + * \brief Symbolic identifier for MD5. + */ +#define br_md5_ID 1 + +/** + * \brief MD5 output size (in bytes). + */ +#define br_md5_SIZE 16 + +/** + * \brief Constant vtable for MD5. + */ +extern const br_hash_class br_md5_vtable; + +/** + * \brief MD5 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[4]; +#endif +} br_md5_context; + +/** + * \brief MD5 context initialisation. + * + * This function initialises or resets a context for a new MD5 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_md5_init(br_md5_context *ctx); + +/** + * \brief Inject some data bytes in a running MD5 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_md5_update(br_md5_context *ctx, const void *data, size_t len); + +/** + * \brief Compute MD5 output. + * + * The MD5 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_md5_out(const br_md5_context *ctx, void *out); + +/** + * \brief Save MD5 running state. + * + * The running state for MD5 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_md5_state(const br_md5_context *ctx, void *out); + +/** + * \brief Restore MD5 running state. + * + * The running state for MD5 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-1. + */ +#define br_sha1_ID 2 + +/** + * \brief SHA-1 output size (in bytes). + */ +#define br_sha1_SIZE 20 + +/** + * \brief Constant vtable for SHA-1. + */ +extern const br_hash_class br_sha1_vtable; + +/** + * \brief SHA-1 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[5]; +#endif +} br_sha1_context; + +/** + * \brief SHA-1 context initialisation. + * + * This function initialises or resets a context for a new SHA-1 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha1_init(br_sha1_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-1 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-1 output. + * + * The SHA-1 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha1_out(const br_sha1_context *ctx, void *out); + +/** + * \brief Save SHA-1 running state. + * + * The running state for SHA-1 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); + +/** + * \brief Restore SHA-1 running state. + * + * The running state for SHA-1 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-224. + */ +#define br_sha224_ID 3 + +/** + * \brief SHA-224 output size (in bytes). + */ +#define br_sha224_SIZE 28 + +/** + * \brief Constant vtable for SHA-224. + */ +extern const br_hash_class br_sha224_vtable; + +/** + * \brief SHA-224 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val[8]; +#endif +} br_sha224_context; + +/** + * \brief SHA-224 context initialisation. + * + * This function initialises or resets a context for a new SHA-224 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha224_init(br_sha224_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-224 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-224 output. + * + * The SHA-224 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha224_out(const br_sha224_context *ctx, void *out); + +/** + * \brief Save SHA-224 running state. + * + * The running state for SHA-224 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); + +/** + * \brief Restore SHA-224 running state. + * + * The running state for SHA-224 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha224_set_state(br_sha224_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-256. + */ +#define br_sha256_ID 4 + +/** + * \brief SHA-256 output size (in bytes). + */ +#define br_sha256_SIZE 32 + +/** + * \brief Constant vtable for SHA-256. + */ +extern const br_hash_class br_sha256_vtable; + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief SHA-256 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +} br_sha256_context; +#else +typedef br_sha224_context br_sha256_context; +#endif + +/** + * \brief SHA-256 context initialisation. + * + * This function initialises or resets a context for a new SHA-256 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha256_init(br_sha256_context *ctx); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Inject some data bytes in a running SHA-256 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha256_update(br_sha256_context *ctx, const void *data, size_t len); +#else +#define br_sha256_update br_sha224_update +#endif + +/** + * \brief Compute SHA-256 output. + * + * The SHA-256 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha256_out(const br_sha256_context *ctx, void *out); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Save SHA-256 running state. + * + * The running state for SHA-256 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha256_state(const br_sha256_context *ctx, void *out); +#else +#define br_sha256_state br_sha224_state +#endif + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Restore SHA-256 running state. + * + * The running state for SHA-256 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha256_set_state(br_sha256_context *ctx, + const void *stb, uint64_t count); +#else +#define br_sha256_set_state br_sha224_set_state +#endif + +/** + * \brief Symbolic identifier for SHA-384. + */ +#define br_sha384_ID 5 + +/** + * \brief SHA-384 output size (in bytes). + */ +#define br_sha384_SIZE 48 + +/** + * \brief Constant vtable for SHA-384. + */ +extern const br_hash_class br_sha384_vtable; + +/** + * \brief SHA-384 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[128]; + uint64_t count; + uint64_t val[8]; +#endif +} br_sha384_context; + +/** + * \brief SHA-384 context initialisation. + * + * This function initialises or resets a context for a new SHA-384 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha384_init(br_sha384_context *ctx); + +/** + * \brief Inject some data bytes in a running SHA-384 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len); + +/** + * \brief Compute SHA-384 output. + * + * The SHA-384 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha384_out(const br_sha384_context *ctx, void *out); + +/** + * \brief Save SHA-384 running state. + * + * The running state for SHA-384 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); + +/** + * \brief Restore SHA-384 running state. + * + * The running state for SHA-384 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha384_set_state(br_sha384_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Symbolic identifier for SHA-512. + */ +#define br_sha512_ID 6 + +/** + * \brief SHA-512 output size (in bytes). + */ +#define br_sha512_SIZE 64 + +/** + * \brief Constant vtable for SHA-512. + */ +extern const br_hash_class br_sha512_vtable; + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief SHA-512 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +} br_sha512_context; +#else +typedef br_sha384_context br_sha512_context; +#endif + +/** + * \brief SHA-512 context initialisation. + * + * This function initialises or resets a context for a new SHA-512 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_sha512_init(br_sha512_context *ctx); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Inject some data bytes in a running SHA-512 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_sha512_update(br_sha512_context *ctx, const void *data, size_t len); +#else +#define br_sha512_update br_sha384_update +#endif + +/** + * \brief Compute SHA-512 output. + * + * The SHA-512 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_sha512_out(const br_sha512_context *ctx, void *out); + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Save SHA-512 running state. + * + * The running state for SHA-512 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_sha512_state(const br_sha512_context *ctx, void *out); +#else +#define br_sha512_state br_sha384_state +#endif + +#ifdef BR_DOXYGEN_IGNORE +/** + * \brief Restore SHA-512 running state. + * + * The running state for SHA-512 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_sha512_set_state(br_sha512_context *ctx, + const void *stb, uint64_t count); +#else +#define br_sha512_set_state br_sha384_set_state +#endif + +/* + * "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 + * concatenation, in that order). State size is also 36 bytes. + */ + +/** + * \brief Symbolic identifier for MD5+SHA-1. + * + * MD5+SHA-1 is the concatenation of MD5 and SHA-1, computed over the + * same input. It is not one of the functions identified in TLS, so + * we give it a symbolic identifier of value 0. + */ +#define br_md5sha1_ID 0 + +/** + * \brief MD5+SHA-1 output size (in bytes). + */ +#define br_md5sha1_SIZE 36 + +/** + * \brief Constant vtable for MD5+SHA-1. + */ +extern const br_hash_class br_md5sha1_vtable; + +/** + * \brief MD5+SHA-1 context. + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** + * \brief Pointer to vtable for this context. + */ + const br_hash_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[64]; + uint64_t count; + uint32_t val_md5[4]; + uint32_t val_sha1[5]; +#endif +} br_md5sha1_context; + +/** + * \brief MD5+SHA-1 context initialisation. + * + * This function initialises or resets a context for a new SHA-512 + * computation. It also sets the vtable pointer. + * + * \param ctx pointer to the context structure. + */ +void br_md5sha1_init(br_md5sha1_context *ctx); + +/** + * \brief Inject some data bytes in a running MD5+SHA-1 computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len); + +/** + * \brief Compute MD5+SHA-1 output. + * + * The MD5+SHA-1 output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `out`. The context + * itself is not modified, so extra bytes may be injected afterwards + * to continue that computation. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the hash output. + */ +void br_md5sha1_out(const br_md5sha1_context *ctx, void *out); + +/** + * \brief Save MD5+SHA-1 running state. + * + * The running state for MD5+SHA-1 (output of the last internal block + * processing) is written in the buffer pointed to by `out`. The + * number of bytes injected since the last initialisation or reset + * call is returned. The context is not modified. + * + * \param ctx pointer to the context structure. + * \param out destination buffer for the running state. + * \return the injected total byte length. + */ +uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out); + +/** + * \brief Restore MD5+SHA-1 running state. + * + * The running state for MD5+SHA-1 is set to the provided values. + * + * \param ctx pointer to the context structure. + * \param stb source buffer for the running state. + * \param count the injected total byte length. + */ +void br_md5sha1_set_state(br_md5sha1_context *ctx, + const void *stb, uint64_t count); + +/** + * \brief Aggregate context for configurable hash function support. + * + * The `br_hash_compat_context` type is a type which is large enough to + * serve as context for all standard hash functions defined above. + */ +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_md5sha1_context md5sha1; +} br_hash_compat_context; + +/* + * The multi-hasher is a construct that handles hashing of the same input + * data with several hash functions, with a single shared input buffer. + * It can handle MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 + * simultaneously, though which functions are activated depends on + * the set implementation pointers. + */ + +/** + * \brief Multi-hasher context structure. + * + * The multi-hasher runs up to six hash functions in the standard TLS list + * (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) in parallel, over + * the same input. + * + * The multi-hasher does _not_ follow the OOP structure with a vtable. + * Instead, it is configured with the vtables of the hash functions it + * should run. Structure fields are not supposed to be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + unsigned char buf[128]; + uint64_t count; + uint32_t val_32[25]; + uint64_t val_64[16]; + const br_hash_class *impl[6]; +#endif +} br_multihash_context; + +/** + * \brief Clear a multi-hasher context. + * + * This should always be called once on a given context, _before_ setting + * the implementation pointers. + * + * \param ctx the multi-hasher context. + */ +void br_multihash_zero(br_multihash_context *ctx); + +/** + * \brief Set a hash function implementation. + * + * Implementations shall be set _after_ clearing the context (with + * `br_multihash_zero()`) but _before_ initialising the computation + * (with `br_multihash_init()`). The hash function implementation + * MUST be one of the standard hash functions (MD5, SHA-1, SHA-224, + * SHA-256, SHA-384 or SHA-512); it may also be `NULL` to remove + * an implementation from the multi-hasher. + * + * \param ctx the multi-hasher context. + * \param id the hash function symbolic identifier. + * \param impl the hash function vtable, or `NULL`. + */ +static inline void +br_multihash_setimpl(br_multihash_context *ctx, + int id, const br_hash_class *impl) +{ + /* + * This code relies on hash functions ID being values 1 to 6, + * in the MD5 to SHA-512 order. + */ + ctx->impl[id - 1] = impl; +} + +/** + * \brief Get a hash function implementation. + * + * This function returns the currently configured vtable for a given + * hash function (by symbolic ID). If no such function was configured in + * the provided multi-hasher context, then this function returns `NULL`. + * + * \param ctx the multi-hasher context. + * \param id the hash function symbolic identifier. + * \return the hash function vtable, or `NULL`. + */ +static inline const br_hash_class * +br_multihash_getimpl(const br_multihash_context *ctx, int id) +{ + return ctx->impl[id - 1]; +} + +/** + * \brief Reset a multi-hasher context. + * + * This function prepares the context for a new hashing computation, + * for all implementations configured at that point. + * + * \param ctx the multi-hasher context. + */ +void br_multihash_init(br_multihash_context *ctx); + +/** + * \brief Inject some data bytes in a running multi-hashing computation. + * + * The provided context is updated with some data bytes. If the number + * of bytes (`len`) is zero, then the data pointer (`data`) is ignored + * and may be `NULL`, and this function does nothing. + * + * \param ctx pointer to the context structure. + * \param data pointer to the injected data. + * \param len injected data length (in bytes). + */ +void br_multihash_update(br_multihash_context *ctx, + const void *data, size_t len); + +/** + * \brief Compute a hash output from a multi-hasher. + * + * The hash output for the concatenation of all bytes injected in the + * provided context since the last initialisation or reset call, is + * computed and written in the buffer pointed to by `dst`. The hash + * function to use is identified by `id` and must be one of the standard + * hash functions. If that hash function was indeed configured in the + * multi-hasher context, the corresponding hash value is written in + * `dst` and its length (in bytes) is returned. If the hash function + * was _not_ configured, then nothing is written in `dst` and 0 is + * returned. + * + * The context itself is not modified, so extra bytes may be injected + * afterwards to continue the hash computations. + * + * \param ctx pointer to the context structure. + * \param id the hash function symbolic identifier. + * \param dst destination buffer for the hash output. + * \return the hash output length (in bytes), or 0. + */ +size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst); + +/** + * \brief Type for a GHASH implementation. + * + * GHASH is a sort of keyed hash meant to be used to implement GCM in + * combination with a block cipher (with 16-byte blocks). + * + * The `y` array has length 16 bytes and is used for input and output; in + * a complete GHASH run, it starts with an all-zero value. `h` is a 16-byte + * value that serves as key (it is derived from the encryption key in GCM, + * using the block cipher). The data length (`len`) is expressed in bytes. + * The `y` array is updated. + * + * If the data length is not a multiple of 16, then the data is implicitly + * padded with zeros up to the next multiple of 16. Thus, when using GHASH + * in GCM, this method may be called twice, for the associated data and + * for the ciphertext, respectively; the zero-padding implements exactly + * the GCM rules. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (mixed 32-bit). + * + * This implementation uses multiplications of 32-bit values, with a + * 64-bit result. It is constant-time (if multiplications are + * constant-time). + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (strict 32-bit). + * + * This implementation uses multiplications of 32-bit values, with a + * 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`, + * but it is expected to be faster on architectures for which the + * 32-bit multiplication opcode does not yield the upper 32 bits of the + * product. It is constant-time (if multiplications are constant-time). + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using multiplications (64-bit). + * + * This implementation uses multiplications of 64-bit values, with a + * 64-bit result. It is constant-time (if multiplications are + * constant-time). It is substantially faster than `br_ghash_ctmul()` + * and `br_ghash_ctmul32()` on most 64-bit architectures. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); + +/** + * \brief GHASH implementation using the `pclmulqdq` opcode (part of the + * AES-NI instructions). + * + * This implementation is available only on x86 platforms where the + * compiler supports the relevant intrinsic functions. Even if the + * compiler supports these functions, the local CPU might not support + * the `pclmulqdq` opcode, meaning that a call will fail with an + * illegal instruction exception. To safely obtain a pointer to this + * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len); + +/** + * \brief Obtain the `pclmul` GHASH implementation, if available. + * + * If the `pclmul` implementation was compiled in the library (depending + * on the compiler abilities) _and_ the local CPU appears to support the + * opcode, then this function will return a pointer to the + * `br_ghash_pclmul()` function. Otherwise, it will return `0`. + * + * \return the `pclmul` GHASH implementation, or `0`. + */ +br_ghash br_ghash_pclmul_get(void); + +/** + * \brief GHASH implementation using the POWER8 opcodes. + * + * This implementation is available only on POWER8 platforms (and later). + * To safely obtain a pointer to this function when supported (or 0 + * otherwise), use `br_ghash_pwr8_get()`. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_pwr8(void *y, const void *h, const void *data, size_t len); + +/** + * \brief Obtain the `pwr8` GHASH implementation, if available. + * + * If the `pwr8` implementation was compiled in the library (depending + * on the compiler abilities) _and_ the local CPU appears to support the + * opcode, then this function will return a pointer to the + * `br_ghash_pwr8()` function. Otherwise, it will return `0`. + * + * \return the `pwr8` GHASH implementation, or `0`. + */ +br_ghash br_ghash_pwr8_get(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_hmac.h b/include/bearssl/bearssl_hmac.h new file mode 100644 index 000000000..4dc01ca31 --- /dev/null +++ b/include/bearssl/bearssl_hmac.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_HMAC_H__ +#define BR_BEARSSL_HMAC_H__ + +#include +#include + +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \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 + * key. + * + * With the key context, a HMAC context can be initialized to process + * the input bytes and obtain the MAC output. The key context is not + * modified during that process, and can be reused. + * + * 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. + */ + +/** + * \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; + +/** + * \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_vtable, const void *key, size_t key_len); + +/* + * \brief Get the underlying hash function. + * + * This function returns a pointer to the implementation vtable of the + * hash function used for this HMAC key context. + * + * \param kc HMAC key context. + * \return the hash function implementation. + */ +static inline const br_hash_class *br_hmac_key_get_digest( + const br_hmac_key_context *kc) +{ + return kc->dig_vtable; +} + +/** + * \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 { +#ifndef BR_DOXYGEN_IGNORE + br_hash_compat_context dig; + unsigned char kso[64]; + size_t out_len; +#endif +} br_hmac_context; + +/** + * \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. 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); + +/** + * \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. + */ +static inline size_t +br_hmac_size(br_hmac_context *ctx) +{ + return ctx->out_len; +} + +/* + * \brief Get the underlying hash function. + * + * This function returns a pointer to the implementation vtable of the + * hash function used for this HMAC context. + * + * \param hc HMAC context. + * \return the hash function implementation. + */ +static inline const br_hash_class *br_hmac_get_digest( + const br_hmac_context *hc) +{ + return hc->dig.vtable; +} + +/** + * \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); + +/** + * \brief Compute the HMAC output. + * + * The destination buffer MUST be large enough to accommodate 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); + +/** + * \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 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, + * SHA-384 or SHA-512). + * + * The provided context is NOT modified. + * + * \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, + void *out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_kdf.h b/include/bearssl/bearssl_kdf.h new file mode 100644 index 000000000..955b84367 --- /dev/null +++ b/include/bearssl/bearssl_kdf.h @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2018 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_KDF_H__ +#define BR_BEARSSL_KDF_H__ + +#include +#include + +#include "bearssl_hash.h" +#include "bearssl_hmac.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_kdf.h + * + * # Key Derivation Functions + * + * KDF are functions that takes a variable length input, and provide a + * variable length output, meant to be used to derive subkeys from a + * master key. + * + * ## HKDF + * + * HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869). + * It is based on HMAC, itself using an underlying hash function. Any + * hash function can be used, as long as it is compatible with the rules + * for the HMAC implementation (i.e. output size is 64 bytes or less, hash + * internal state size is 64 bytes or less, and the internal block length is + * a power of 2 between 16 and 256 bytes). HKDF has two phases: + * + * - HKDF-Extract: the input data in ingested, along with a "salt" value. + * + * - HKDF-Expand: the output is produced, from the result of processing + * the input and salt, and using an extra non-secret parameter called + * "info". + * + * The "salt" and "info" strings are non-secret and can be empty. Their role + * is normally to bind the input and output, respectively, to conventional + * identifiers that qualifu them within the used protocol or application. + * + * The implementation defined in this file uses the following functions: + * + * - `br_hkdf_init()`: initialize an HKDF context, with a hash function, + * and the salt. This starts the HKDF-Extract process. + * + * - `br_hkdf_inject()`: inject more input bytes. This function may be + * called repeatedly if the input data is provided by chunks. + * + * - `br_hkdf_flip()`: end the HKDF-Extract process, and start the + * HKDF-Expand process. + * + * - `br_hkdf_produce()`: get the next bytes of output. This function + * may be called several times to obtain the full output by chunks. + * For correct HKDF processing, the same "info" string must be + * provided for each call. + * + * Note that the HKDF total output size (the number of bytes that + * HKDF-Expand is willing to produce) is limited: if the hash output size + * is _n_ bytes, then the maximum output size is _255*n_. + * + * ## SHAKE + * + * SHAKE is defined in + * [FIPS 202](https://csrc.nist.gov/publications/detail/fips/202/final) + * under two versions: SHAKE128 and SHAKE256, offering an alleged + * "security level" of 128 and 256 bits, respectively (SHAKE128 is + * about 20 to 25% faster than SHAKE256). SHAKE internally relies on + * the Keccak family of sponge functions, not on any externally provided + * hash function. Contrary to HKDF, SHAKE does not have a concept of + * either a "salt" or an "info" string. The API consists in four + * functions: + * + * - `br_shake_init()`: initialize a SHAKE context for a given + * security level. + * + * - `br_shake_inject()`: inject more input bytes. This function may be + * called repeatedly if the input data is provided by chunks. + * + * - `br_shake_flip()`: end the data injection process, and start the + * data production process. + * + * - `br_shake_produce()`: get the next bytes of output. This function + * may be called several times to obtain the full output by chunks. + */ + +/** + * \brief HKDF context. + * + * The HKDF context is initialized with a hash function implementation + * and a salt value. 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 + union { + br_hmac_context hmac_ctx; + br_hmac_key_context prk_ctx; + } u; + unsigned char buf[64]; + size_t ptr; + size_t dig_len; + unsigned chunk_num; +#endif +} br_hkdf_context; + +/** + * \brief HKDF context initialization. + * + * The underlying hash function and salt value are provided. Arbitrary + * salt lengths can be used. + * + * HKDF makes a difference between a salt of length zero, and an + * absent salt (the latter being equivalent to a salt consisting of + * bytes of value zero, of the same length as the hash function output). + * If `salt_len` is zero, then this function assumes that the salt is + * present but of length zero. To specify an _absent_ salt, use + * `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored). + * + * \param hc HKDF context to initialise. + * \param digest_vtable pointer to the hash function implementation vtable. + * \param salt HKDF-Extract salt. + * \param salt_len HKDF-Extract salt length (in bytes). + */ +void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable, + const void *salt, size_t salt_len); + +/** + * \brief The special "absent salt" value for HKDF. + */ +#define BR_HKDF_NO_SALT (&br_hkdf_no_salt) + +#ifndef BR_DOXYGEN_IGNORE +extern const unsigned char br_hkdf_no_salt; +#endif + +/** + * \brief HKDF input injection (HKDF-Extract). + * + * This function injects some more input bytes ("key material") into + * HKDF. This function may be called several times, after `br_hkdf_init()` + * but before `br_hkdf_flip()`. + * + * \param hc HKDF context. + * \param ikm extra input bytes. + * \param ikm_len number of extra input bytes. + */ +void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len); + +/** + * \brief HKDF switch to the HKDF-Expand phase. + * + * This call terminates the HKDF-Extract process (input injection), and + * starts the HKDF-Expand process (output production). + * + * \param hc HKDF context. + */ +void br_hkdf_flip(br_hkdf_context *hc); + +/** + * \brief HKDF output production (HKDF-Expand). + * + * Produce more output bytes from the current state. This function may be + * called several times, but only after `br_hkdf_flip()`. + * + * Returned value is the number of actually produced bytes. The total + * output length is limited to 255 times the output length of the + * underlying hash function. + * + * \param hc HKDF context. + * \param info application specific information string. + * \param info_len application specific information string length (in bytes). + * \param out destination buffer for the HKDF output. + * \param out_len the length of the requested output (in bytes). + * \return the produced output length (in bytes). + */ +size_t br_hkdf_produce(br_hkdf_context *hc, + const void *info, size_t info_len, void *out, size_t out_len); + +/** + * \brief SHAKE context. + * + * The HKDF context is initialized with a "security level". The internal + * notion is called "capacity"; the capacity is twice the security level + * (for instance, SHAKE128 has capacity 256). + * + * 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 + unsigned char dbuf[200]; + size_t dptr; + size_t rate; + uint64_t A[25]; +#endif +} br_shake_context; + +/** + * \brief SHAKE context initialization. + * + * The context is initialized for the provided "security level". + * Internally, this sets the "capacity" to twice the security level; + * thus, for SHAKE128, the `security_level` parameter should be 128, + * which corresponds to a 256-bit capacity. + * + * Allowed security levels are all multiples of 32, from 32 to 768, + * inclusive. Larger security levels imply lower performance; levels + * beyond 256 bits don't make much sense. Standard levels are 128 + * and 256 bits (for SHAKE128 and SHAKE256, respectively). + * + * \param sc SHAKE context to initialise. + * \param security_level security level (in bits). + */ +void br_shake_init(br_shake_context *sc, int security_level); + +/** + * \brief SHAKE input injection. + * + * This function injects some more input bytes ("key material") into + * SHAKE. This function may be called several times, after `br_shake_init()` + * but before `br_shake_flip()`. + * + * \param sc SHAKE context. + * \param data extra input bytes. + * \param len number of extra input bytes. + */ +void br_shake_inject(br_shake_context *sc, const void *data, size_t len); + +/** + * \brief SHAKE switch to production phase. + * + * This call terminates the input injection process, and starts the + * output production process. + * + * \param sc SHAKE context. + */ +void br_shake_flip(br_shake_context *hc); + +/** + * \brief SHAKE output production. + * + * Produce more output bytes from the current state. This function may be + * called several times, but only after `br_shake_flip()`. + * + * There is no practical limit to the number of bytes that may be produced. + * + * \param sc SHAKE context. + * \param out destination buffer for the SHAKE output. + * \param len the length of the requested output (in bytes). + */ +void br_shake_produce(br_shake_context *sc, void *out, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_pem.h b/include/bearssl/bearssl_pem.h new file mode 100644 index 000000000..8dba58272 --- /dev/null +++ b/include/bearssl/bearssl_pem.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_PEM_H__ +#define BR_BEARSSL_PEM_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_pem.h + * + * # PEM Support + * + * PEM is a traditional encoding layer use to store binary objects (in + * particular X.509 certificates, and private keys) in text files. While + * the acronym comes from an old, defunct standard ("Privacy Enhanced + * Mail"), the format has been reused, with some variations, by many + * systems, and is a _de facto_ standard, even though it is not, actually, + * specified in all clarity anywhere. + * + * ## Format Details + * + * BearSSL contains a generic, streamed PEM decoder, which handles the + * following format: + * + * - The input source (a sequence of bytes) is assumed to be the + * encoding of a text file in an ASCII-compatible charset. This + * includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each + * line ends on a newline character (U+000A LINE FEED). The + * U+000D CARRIAGE RETURN characters are ignored, so the code + * accepts both Windows-style and Unix-style line endings. + * + * - Each object begins with a banner that occurs at the start of + * a line; the first banner characters are "`-----BEGIN `" (five + * dashes, the word "BEGIN", and a space). The banner matching is + * not case-sensitive. + * + * - The _object name_ consists in the characters that follow the + * banner start sequence, up to the end of the line, but without + * trailing dashes (in "normal" PEM, there are five trailing + * dashes, but this implementation is not picky about these dashes). + * The BearSSL decoder normalises the name characters to uppercase + * (for ASCII letters only) and accepts names up to 127 characters. + * + * - The object ends with a banner that again occurs at the start of + * a line, and starts with "`-----END `" (again case-insensitive). + * + * - Between that start and end banner, only Base64 data shall occur. + * Base64 converts each sequence of three bytes into four + * characters; the four characters are ASCII letters, digits, "`+`" + * or "`-`" signs, and one or two "`=`" signs may occur in the last + * quartet. Whitespace is ignored (whitespace is any ASCII character + * of code 32 or less, so control characters are whitespace) and + * lines may have arbitrary length; the only restriction is that the + * four characters of a quartet must appear on the same line (no + * line break inside a quartet). + * + * - A single file may contain more than one PEM object. Bytes that + * occur between objects are ignored. + * + * + * ## PEM Decoder API + * + * The PEM decoder offers a state-machine API. The caller allocates a + * decoder context, then injects source bytes. Source bytes are pushed + * with `br_pem_decoder_push()`. The decoder stops accepting bytes when + * it reaches an "event", which is either the start of an object, the + * end of an object, or a decoding error within an object. + * + * The `br_pem_decoder_event()` function is used to obtain the current + * event; it also clears it, thus allowing the decoder to accept more + * bytes. When a object start event is raised, the decoder context + * offers the found object name (normalised to ASCII uppercase). + * + * When an object is reached, the caller must set an appropriate callback + * function, which will receive (by chunks) the decoded object data. + * + * Since the decoder context makes no dynamic allocation, it requires + * no explicit deallocation. + */ + +/** + * \brief PEM decoder context. + * + * Contents are opaque (they should not be accessed directly). + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + const unsigned char *hbuf; + size_t hlen; + + void (*dest)(void *dest_ctx, const void *src, size_t len); + void *dest_ctx; + + unsigned char event; + char name[128]; + unsigned char buf[255]; + size_t ptr; +#endif +} br_pem_decoder_context; + +/** + * \brief Initialise a PEM decoder structure. + * + * \param ctx decoder context to initialise. + */ +void br_pem_decoder_init(br_pem_decoder_context *ctx); + +/** + * \brief Push some bytes into the decoder. + * + * Returned value is the number of bytes actually consumed; this may be + * less than the number of provided bytes if an event is raised. When an + * event is raised, it must be read (with `br_pem_decoder_event()`); + * until the event is read, this function will return 0. + * + * \param ctx decoder context. + * \param data new data bytes. + * \param len number of new data bytes. + * \return the number of bytes actually received (may be less than `len`). + */ +size_t br_pem_decoder_push(br_pem_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Set the receiver for decoded data. + * + * When an object is entered, the provided function (with opaque context + * pointer) will be called repeatedly with successive chunks of decoded + * data for that object. If `dest` is set to 0, then decoded data is + * simply ignored. The receiver can be set at any time, but, in practice, + * it should be called immediately after receiving a "start of object" + * event. + * + * \param ctx decoder context. + * \param dest callback for receiving decoded data. + * \param dest_ctx opaque context pointer for the `dest` callback. + */ +static inline void +br_pem_decoder_setdest(br_pem_decoder_context *ctx, + void (*dest)(void *dest_ctx, const void *src, size_t len), + void *dest_ctx) +{ + ctx->dest = dest; + ctx->dest_ctx = dest_ctx; +} + +/** + * \brief Get the last event. + * + * If an event was raised, then this function returns the event value, and + * also clears it, thereby allowing the decoder to proceed. If no event + * was raised since the last call to `br_pem_decoder_event()`, then this + * function returns 0. + * + * \param ctx decoder context. + * \return the raised event, or 0. + */ +int br_pem_decoder_event(br_pem_decoder_context *ctx); + +/** + * \brief Event: start of object. + * + * This event is raised when the start of a new object has been detected. + * The object name (normalised to uppercase) can be accessed with + * `br_pem_decoder_name()`. + */ +#define BR_PEM_BEGIN_OBJ 1 + +/** + * \brief Event: end of object. + * + * This event is raised when the end of the current object is reached + * (normally, i.e. with no decoding error). + */ +#define BR_PEM_END_OBJ 2 + +/** + * \brief Event: decoding error. + * + * This event is raised when decoding fails within an object. + * This formally closes the current object and brings the decoder back + * to the "out of any object" state. The offending line in the source + * is consumed. + */ +#define BR_PEM_ERROR 3 + +/** + * \brief Get the name of the encountered object. + * + * The encountered object name is defined only when the "start of object" + * event is raised. That name is normalised to uppercase (for ASCII letters + * only) and does not include trailing dashes. + * + * \param ctx decoder context. + * \return the current object name. + */ +static inline const char * +br_pem_decoder_name(br_pem_decoder_context *ctx) +{ + return ctx->name; +} + +/** + * \brief Encode an object in PEM. + * + * This function encodes the provided binary object (`data`, of length `len` + * bytes) into PEM. The `banner` text will be included in the header and + * footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header). + * + * The length (in characters) of the PEM output is returned; that length + * does NOT include the terminating zero, that this function nevertheless + * adds. If using the returned value for allocation purposes, the allocated + * buffer size MUST be at least one byte larger than the returned size. + * + * If `dest` is `NULL`, then the encoding does not happen; however, the + * length of the encoded object is still computed and returned. + * + * The `data` pointer may be `NULL` only if `len` is zero (when encoding + * an object of length zero, which is not very useful), or when `dest` + * is `NULL` (in that case, source data bytes are ignored). + * + * Some `flags` can be specified to alter the encoding behaviour: + * + * - If `BR_PEM_LINE64` is set, then line-breaking will occur after + * every 64 characters of output, instead of the default of 76. + * + * - If `BR_PEM_CRLF` is set, then end-of-line sequence will use + * CR+LF instead of a single LF. + * + * The `data` and `dest` buffers may overlap, in which case the source + * binary data is destroyed in the process. Note that the PEM-encoded output + * is always larger than the source binary. + * + * \param dest the destination buffer (or `NULL`). + * \param data the source buffer (can be `NULL` in some cases). + * \param len the source length (in bytes). + * \param banner the PEM banner expression. + * \param flags the behavioural flags. + * \return the PEM object length (in characters), EXCLUDING the final zero. + */ +size_t br_pem_encode(void *dest, const void *data, size_t len, + const char *banner, unsigned flags); + +/** + * \brief PEM encoding flag: split lines at 64 characters. + */ +#define BR_PEM_LINE64 0x0001 + +/** + * \brief PEM encoding flag: use CR+LF line endings. + */ +#define BR_PEM_CRLF 0x0002 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_prf.h b/include/bearssl/bearssl_prf.h new file mode 100644 index 000000000..fdf608c85 --- /dev/null +++ b/include/bearssl/bearssl_prf.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_PRF_H__ +#define BR_BEARSSL_PRF_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_prf.h + * + * # The TLS PRF + * + * The "PRF" is the pseudorandom function used internally during the + * SSL/TLS handshake, notably to expand negotiated 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. + * + * 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. 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. The "seed" is provided as an + * arbitrary number of binary chunks, that gets internally concatenated. + */ + +/** + * \brief Type for a seed chunk. + * + * Each chunk may have an arbitrary length, and may be empty (no byte at + * all). If the chunk length is zero, then the pointer to the chunk data + * may be `NULL`. + */ +typedef struct { + /** + * \brief Pointer to the chunk data. + */ + const void *data; + + /** + * \brief Chunk length (in bytes). + */ + size_t len; +} br_tls_prf_seed_chunk; + +/** + * \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_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls10_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * \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_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls12_sha256_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * \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_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +void br_tls12_sha384_prf(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +/** + * 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_num number of seed chunks. + * \param seed seed chnks for this computation (usually non-secret). + */ +typedef void (*br_tls_prf_impl)(void *dst, size_t len, + const void *secret, size_t secret_len, const char *label, + size_t seed_num, const br_tls_prf_seed_chunk *seed); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_rand.h b/include/bearssl/bearssl_rand.h new file mode 100644 index 000000000..0a9f544fc --- /dev/null +++ b/include/bearssl/bearssl_rand.h @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_RAND_H__ +#define BR_BEARSSL_RAND_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \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). + * + * + * ## 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. + * + * + * ## AESCTR_DRBG + * + * AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is + * meant to be used only in situations where you are desperate for + * speed, and have an hardware-optimized AES/CTR implementation. Whether + * this will yield perceptible improvements depends on what you use the + * pseudorandom bytes for, and how many you want; for instance, RSA key + * pair generation uses a substantial amount of randomness, and using + * AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key + * generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz). + * + * Internally, it uses CTR mode with successive counter values, starting + * at zero (counter value expressed over 128 bits, big-endian convention). + * The counter is not allowed to reach 32768; thus, every 32768*16 bytes + * at most, the `update()` function is run (on an empty seed, if none is + * provided). The `update()` function computes the new AES-128 key by + * applying a custom hash function to the concatenation of a state-dependent + * word (encryption of an all-one block with the current key) and the new + * seed. The custom hash function uses Hirose's construction over AES-256; + * see the comments in `aesctr_drbg.c` for details. + * + * This DRBG does not follow an existing standard, and thus should be + * considered as inadequate for production use until it has been properly + * analysed. + */ + +/** + * \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); +}; + +/** + * \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; + +/** + * \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 seed_len); + +/** + * \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); + +/** + * \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 seed_len); + +/** + * \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) +{ + return ctx->digest_class; +} + +/** + * \brief Type for a provider of entropy seeds. + * + * A "seeder" is a function that is able to obtain random values from + * some source and inject them as entropy seed in a PRNG. A seeder + * shall guarantee that the total entropy of the injected seed is large + * enough to seed a PRNG for purposes of cryptographic key generation + * (i.e. at least 128 bits). + * + * A seeder may report a failure to obtain adequate entropy. Seeders + * shall endeavour to fix themselves transient errors by trying again; + * thus, callers may consider reported errors as permanent. + * + * \param ctx PRNG context to seed. + * \return 1 on success, 0 on error. + */ +typedef int (*br_prng_seeder)(const br_prng_class **ctx); + +/** + * \brief Get a seeder backed by the operating system or hardware. + * + * Get a seeder that feeds on RNG facilities provided by the current + * operating system or hardware. If no such facility is known, then 0 + * is returned. + * + * If `name` is not `NULL`, then `*name` is set to a symbolic string + * that identifies the seeder implementation. If no seeder is returned + * and `name` is not `NULL`, then `*name` is set to a pointer to the + * constant string `"none"`. + * + * \param name receiver for seeder name, or `NULL`. + * \return the system seeder, if available, or 0. + */ +br_prng_seeder br_prng_seeder_system(const char **name); + +/** + * \brief Context for AESCTR_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 + br_aes_gen_ctr_keys sk; + uint32_t cc; +#endif +} br_aesctr_drbg_context; + +/** + * \brief Statically allocated, constant vtable for AESCTR_DRBG. + */ +extern const br_prng_class br_aesctr_drbg_vtable; + +/** + * \brief AESCTR_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 internal AES key is first set to the all-zero key; then, the + * `br_aesctr_drbg_update()` function is called with the provided `seed`. + * The call is performed even if the seed length (`seed_len`) is zero. + * + * The `aesctr` parameter defines the underlying AES/CTR implementation. + * + * \param ctx AESCTR_DRBG context to initialise. + * \param aesctr vtable for the AES/CTR implementation. + * \param seed initial seed (can be `NULL` if `seed_len` is zero). + * \param seed_len initial seed length (in bytes). + */ +void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx, + const br_block_ctr_class *aesctr, const void *seed, size_t seed_len); + +/** + * \brief Random bytes generation with AESCTR_DRBG. + * + * This method produces `len` pseudorandom bytes, in the `out` + * buffer. The context is updated accordingly. + * + * \param ctx AESCTR_DRBG context. + * \param out output buffer. + * \param len number of pseudorandom bytes to produce. + */ +void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, + void *out, size_t len); + +/** + * \brief Inject additional seed bytes in AESCTR_DRBG. + * + * The provided seed bytes are added into the AESCTR_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 AESCTR_DRBG context. + * \param seed additional seed. + * \param seed_len additional seed length (in bytes). + */ +void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, + const void *seed, size_t seed_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_rsa.h b/include/bearssl/bearssl_rsa.h new file mode 100644 index 000000000..0a069fd36 --- /dev/null +++ b/include/bearssl/bearssl_rsa.h @@ -0,0 +1,1655 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_RSA_H__ +#define BR_BEARSSL_RSA_H__ + +#include +#include + +#include "bearssl_hash.h" +#include "bearssl_rand.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_rsa.h + * + * # RSA + * + * This file documents the RSA implementations provided with BearSSL. + * Note that the SSL engine accesses these implementations through a + * configurable API, so it is possible to, for instance, run a SSL + * server which uses a RSA engine which is not based on this code. + * + * ## Key Elements + * + * RSA public and private keys consist in lists of big integers. All + * such integers are represented with big-endian unsigned notation: + * first byte is the most significant, and the value is positive (so + * there is no dedicated "sign bit"). Public and private key structures + * thus contain, for each such integer, a pointer to the first value byte + * (`unsigned char *`), and a length (`size_t`) which is the number of + * relevant bytes. As a general rule, minimal-length encoding is not + * enforced: values may have extra leading bytes of value 0. + * + * RSA public keys consist in two integers: + * + * - the modulus (`n`); + * - the public exponent (`e`). + * + * RSA private keys, as defined in + * [PKCS#1](https://tools.ietf.org/html/rfc3447), contain eight integers: + * + * - the modulus (`n`); + * - the public exponent (`e`); + * - the private exponent (`d`); + * - the first prime factor (`p`); + * - the second prime factor (`q`); + * - the first reduced exponent (`dp`, which is `d` modulo `p-1`); + * - the second reduced exponent (`dq`, which is `d` modulo `q-1`); + * - the CRT coefficient (`iq`, the inverse of `q` modulo `p`). + * + * However, the implementations defined in BearSSL use only five of + * these integers: `p`, `q`, `dp`, `dq` and `iq`. + * + * ## Security Features and Limitations + * + * The implementations contained in BearSSL have the following limitations + * and features: + * + * - They are constant-time. This means that the execution time and + * memory access pattern may depend on the _lengths_ of the private + * key components, but not on their value, nor on the value of + * the operand. Note that this property is not achieved through + * random masking, but "true" constant-time code. + * + * - They support only private keys with two prime factors. RSA private + * keys with three or more prime factors are nominally supported, but + * rarely used; they may offer faster operations, at the expense of + * more code and potentially a reduction in security if there are + * "too many" prime factors. + * + * - The public exponent may have arbitrary length. Of course, it is + * a good idea to keep public exponents small, so that public key + * operations are fast; but, contrary to some widely deployed + * implementations, BearSSL has no problem with public exponents + * longer than 32 bits. + * + * - The two prime factors of the modulus need not have the same length + * (but severely imbalanced factor lengths might reduce security). + * Similarly, there is no requirement that the first factor (`p`) + * be greater than the second factor (`q`). + * + * - Prime factors and modulus must be smaller than a compile-time limit. + * This is made necessary by the use of fixed-size stack buffers, and + * the limit has been adjusted to keep stack usage under 2 kB for the + * RSA operations. Currently, the maximum modulus size is 4096 bits, + * and the maximum prime factor size is 2080 bits. + * + * - The RSA functions themselves do not enforce lower size limits, + * except that which is absolutely necessary for the operation to + * mathematically make sense (e.g. a PKCS#1 v1.5 signature with + * SHA-1 requires a modulus of at least 361 bits). It is up to users + * of this code to enforce size limitations when appropriate (e.g. + * the X.509 validation engine, by default, rejects RSA keys of + * less than 1017 bits). + * + * - Within the size constraints expressed above, arbitrary bit lengths + * are supported. There is no requirement that prime factors or + * modulus have a size multiple of 8 or 16. + * + * - When verifying PKCS#1 v1.5 signatures, both variants of the hash + * function identifying header (with and without the ASN.1 NULL) are + * supported. When producing such signatures, the variant with the + * ASN.1 NULL is used. + * + * ## Implementations + * + * Three RSA implementations are included: + * + * - The **i32** implementation internally represents big integers + * as arrays of 32-bit integers. It is perfunctory and portable, + * but not very efficient. + * + * - The **i31** implementation uses 32-bit integers, each containing + * 31 bits worth of integer data. The i31 implementation is somewhat + * faster than the i32 implementation (the reduced integer size makes + * carry propagation easier) for a similar code footprint, but uses + * very slightly larger stack buffers (about 4% bigger). + * + * - The **i62** implementation is similar to the i31 implementation, + * except that it internally leverages the 64x64->128 multiplication + * opcode. This implementation is available only on architectures + * where such an opcode exists. It is much faster than i31. + * + * - The **i15** implementation uses 16-bit integers, each containing + * 15 bits worth of integer data. Multiplication results fit on + * 32 bits, so this won't use the "widening" multiplication routine + * on ARM Cortex M0/M0+, for much better performance and constant-time + * execution. + */ + +/** + * \brief RSA public key. + * + * The structure references the modulus and the public exponent. Both + * integers use unsigned big-endian representation; extra leading bytes + * of value 0 are allowed. + */ +typedef struct { + /** \brief Modulus. */ + unsigned char *n; + /** \brief Modulus length (in bytes). */ + size_t nlen; + /** \brief Public exponent. */ + unsigned char *e; + /** \brief Public exponent length (in bytes). */ + size_t elen; +} br_rsa_public_key; + +/** + * \brief RSA private key. + * + * The structure references the private factors, reduced private + * exponents, and CRT coefficient. It also contains the bit length of + * the modulus. The big integers use unsigned big-endian representation; + * extra leading bytes of value 0 are allowed. However, the modulus bit + * length (`n_bitlen`) MUST be exact. + */ +typedef struct { + /** \brief Modulus bit length (in bits, exact value). */ + uint32_t n_bitlen; + /** \brief First prime factor. */ + unsigned char *p; + /** \brief First prime factor length (in bytes). */ + size_t plen; + /** \brief Second prime factor. */ + unsigned char *q; + /** \brief Second prime factor length (in bytes). */ + size_t qlen; + /** \brief First reduced private exponent. */ + unsigned char *dp; + /** \brief First reduced private exponent length (in bytes). */ + size_t dplen; + /** \brief Second reduced private exponent. */ + unsigned char *dq; + /** \brief Second reduced private exponent length (in bytes). */ + size_t dqlen; + /** \brief CRT coefficient. */ + unsigned char *iq; + /** \brief CRT coefficient length (in bytes). */ + size_t iqlen; +} br_rsa_private_key; + +/** + * \brief Type for a RSA public key engine. + * + * The public key engine performs the modular exponentiation of the + * provided value with the public exponent. The value is modified in + * place. + * + * The value length (`xlen`) is verified to have _exactly_ the same + * length as the modulus (actual modulus length, without extra leading + * zeros in the modulus representation in memory). If the length does + * not match, then this function returns 0 and `x[]` is unmodified. + * + * It `xlen` is correct, then `x[]` is modified. Returned value is 1 + * on success, 0 on error. Error conditions include an oversized `x[]` + * (the array has the same length as the modulus, but the numerical value + * is not lower than the modulus) and an invalid modulus (e.g. an even + * integer). If an error is reported, then the new contents of `x[]` are + * unspecified. + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_public)(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief Type for a RSA signature verification engine (PKCS#1 v1.5). + * + * Parameters are: + * + * - The signature itself. The provided array is NOT modified. + * + * - The encoded OID for the hash function. The provided array must begin + * with a single byte that contains the length of the OID value (in + * bytes), followed by exactly that many bytes. This parameter may + * also be `NULL`, in which case the raw hash value should be used + * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up + * to TLS-1.1, with a 36-byte hash value). + * + * - The hash output length, in bytes. + * + * - The public key. + * + * - An output buffer for the hash value. The caller must still compare + * it with the hash of the data over which the signature is computed. + * + * **Constraints:** + * + * - Hash length MUST be no more than 64 bytes. + * + * - OID value length MUST be no more than 32 bytes (i.e. `hash_oid[0]` + * must have a value in the 0..32 range, inclusive). + * + * This function verifies that the signature length (`xlen`) matches the + * modulus length (this function returns 0 on mismatch). If the modulus + * size exceeds the maximum supported RSA size, then the function also + * returns 0. + * + * Returned value is 1 on success, 0 on error. + * + * Implementations of this type need not be constant-time. + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pkcs1_vrfy)(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief Type for a RSA signature verification engine (PSS). + * + * Parameters are: + * + * - The signature itself. The provided array is NOT modified. + * + * - The hash function which was used to hash the message. + * + * - The hash function to use with MGF1 within the PSS padding. This + * is not necessarily the same hash function as the one which was + * used to hash the signed message. + * + * - The hashed message (as an array of bytes). + * + * - The PSS salt length (in bytes). + * + * - The public key. + * + * **Constraints:** + * + * - Hash message length MUST be no more than 64 bytes. + * + * Note that, contrary to PKCS#1 v1.5 signature, the hash value of the + * signed data cannot be extracted from the signature; it must be + * provided to the verification function. + * + * This function verifies that the signature length (`xlen`) matches the + * modulus length (this function returns 0 on mismatch). If the modulus + * size exceeds the maximum supported RSA size, then the function also + * returns 0. + * + * Returned value is 1 on success, 0 on error. + * + * Implementations of this type need not be constant-time. + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pss_vrfy)(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief Type for a RSA encryption engine (OAEP). + * + * Parameters are: + * + * - A source of random bytes. The source must be already initialized. + * + * - A hash function, used internally with the mask generation function + * (MGF1). + * + * - A label. The `label` pointer may be `NULL` if `label_len` is zero + * (an empty label, which is the default in PKCS#1 v2.2). + * + * - The public key. + * + * - The destination buffer. Its maximum length (in bytes) is provided; + * if that length is lower than the public key length, then an error + * is reported. + * + * - The source message. + * + * The encrypted message output has exactly the same length as the modulus + * (mathematical length, in bytes, not counting extra leading zeros in the + * modulus representation in the public key). + * + * The source message (`src`, length `src_len`) may overlap with the + * destination buffer (`dst`, length `dst_max_len`). + * + * This function returns the actual encrypted message length, in bytes; + * on error, zero is returned. An error is reported if the output buffer + * is not large enough, or the public is invalid, or the public key + * modulus exceeds the maximum supported RSA size. + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +typedef size_t (*br_rsa_oaep_encrypt)( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief Type for a RSA private key engine. + * + * The `x[]` buffer is modified in place, and its length is inferred from + * the modulus length (`x[]` is assumed to have a length of + * `(sk->n_bitlen+7)/8` bytes). + * + * Returned value is 1 on success, 0 on error. + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_private)(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief Type for a RSA signature generation engine (PKCS#1 v1.5). + * + * Parameters are: + * + * - The encoded OID for the hash function. The provided array must begin + * with a single byte that contains the length of the OID value (in + * bytes), followed by exactly that many bytes. This parameter may + * also be `NULL`, in which case the raw hash value should be used + * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up + * to TLS-1.1, with a 36-byte hash value). + * + * - The hash value computes over the data to sign (its length is + * expressed in bytes). + * + * - The RSA private key. + * + * - The output buffer, that receives the signature. + * + * Returned value is 1 on success, 0 on error. Error conditions include + * a too small modulus for the provided hash OID and value, or some + * invalid key parameters. The signature length is exactly + * `(sk->n_bitlen+7)/8` bytes. + * + * This function is expected to be constant-time with regards to the + * private key bytes (lengths of the modulus and the individual factors + * may leak, though) and to the hashed data. + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pkcs1_sign)(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Type for a RSA signature generation engine (PSS). + * + * Parameters are: + * + * - An initialized PRNG for salt generation. If the salt length is + * zero (`salt_len` parameter), then the PRNG is optional (this is + * not the typical case, as the security proof of RSA/PSS is + * tighter when a non-empty salt is used). + * + * - The hash function which was used to hash the message. + * + * - The hash function to use with MGF1 within the PSS padding. This + * is not necessarily the same function as the one used to hash the + * message. + * + * - The hashed message. + * + * - The salt length, in bytes. + * + * - The RSA private key. + * + * - The output buffer, that receives the signature. + * + * Returned value is 1 on success, 0 on error. Error conditions include + * a too small modulus for the provided hash and salt lengths, or some + * invalid key parameters. The signature length is exactly + * `(sk->n_bitlen+7)/8` bytes. + * + * This function is expected to be constant-time with regards to the + * private key bytes (lengths of the modulus and the individual factors + * may leak, though) and to the hashed data. + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_pss_sign)(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Encoded OID for SHA-1 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA1 \ + ((const unsigned char *)"\x05\x2B\x0E\x03\x02\x1A") + +/** + * \brief Encoded OID for SHA-224 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA224 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04") + +/** + * \brief Encoded OID for SHA-256 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA256 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01") + +/** + * \brief Encoded OID for SHA-384 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA384 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02") + +/** + * \brief Encoded OID for SHA-512 (in RSA PKCS#1 signatures). + */ +#define BR_HASH_OID_SHA512 \ + ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03") + +/** + * \brief Type for a RSA decryption engine (OAEP). + * + * Parameters are: + * + * - A hash function, used internally with the mask generation function + * (MGF1). + * + * - A label. The `label` pointer may be `NULL` if `label_len` is zero + * (an empty label, which is the default in PKCS#1 v2.2). + * + * - The private key. + * + * - The source and destination buffer. The buffer initially contains + * the encrypted message; the buffer contents are altered, and the + * decrypted message is written at the start of that buffer + * (decrypted message is always shorter than the encrypted message). + * + * If decryption fails in any way, then `*len` is unmodified, and the + * function returns 0. Otherwise, `*len` is set to the decrypted message + * length, and 1 is returned. The implementation is responsible for + * checking that the input message length matches the key modulus length, + * and that the padding is correct. + * + * Implementations MUST use constant-time check of the validity of the + * OAEP padding, at least until the leading byte and hash value have + * been checked. Whether overall decryption worked, and the length of + * the decrypted message, may leak. + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +typedef uint32_t (*br_rsa_oaep_decrypt)( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/* + * RSA "i32" engine. Integers are internally represented as arrays of + * 32-bit integers, and the core multiplication primitive is the + * 32x32->64 multiplication. + */ + +/** + * \brief RSA public key engine "i32". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i32" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i32" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i32". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i32" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i32" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/* + * RSA "i31" engine. Similar to i32, but only 31 bits are used per 32-bit + * word. This uses slightly more stack space (about 4% more) and code + * space, but it quite faster. + */ + +/** + * \brief RSA public key engine "i31". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i31" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i31" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i31". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i31" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i31" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/* + * RSA "i62" engine. Similar to i31, but internal multiplication use + * 64x64->128 multiplications. This is available only on architecture + * that offer such an opcode. + */ + +/** + * \brief RSA public key engine "i62". + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_public_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i62" (PKCS#1 v1.5 signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pkcs1_vrfy_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i62" (PSS signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pss_vrfy_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i62". + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_private_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i62" (PKCS#1 v1.5 signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pkcs1_sign_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i62" (PSS signatures). + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_pss_sign_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Get the RSA "i62" implementation (public key operations), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_public br_rsa_i62_public_get(void); + +/** + * \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature verification), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pkcs1_vrfy br_rsa_i62_pkcs1_vrfy_get(void); + +/** + * \brief Get the RSA "i62" implementation (PSS signature verification), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pss_vrfy br_rsa_i62_pss_vrfy_get(void); + +/** + * \brief Get the RSA "i62" implementation (private key operations), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_private br_rsa_i62_private_get(void); + +/** + * \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pkcs1_sign br_rsa_i62_pkcs1_sign_get(void); + +/** + * \brief Get the RSA "i62" implementation (PSS signature generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_pss_sign br_rsa_i62_pss_sign_get(void); + +/** + * \brief Get the RSA "i62" implementation (OAEP encryption), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_oaep_encrypt br_rsa_i62_oaep_encrypt_get(void); + +/** + * \brief Get the RSA "i62" implementation (OAEP decryption), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_oaep_decrypt br_rsa_i62_oaep_decrypt_get(void); + +/* + * RSA "i15" engine. Integers are represented as 15-bit integers, so + * the code uses only 32-bit multiplication (no 64-bit result), which + * is vastly faster (and constant-time) on the ARM Cortex M0/M0+. + */ + +/** + * \brief RSA public key engine "i15". + * + * \see br_rsa_public + * + * \param x operand to exponentiate. + * \param xlen length of the operand (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_public(unsigned char *x, size_t xlen, + const br_rsa_public_key *pk); + +/** + * \brief RSA signature verification engine "i15" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash_len expected hash value length (in bytes). + * \param pk RSA public key. + * \param hash_out output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen, + const unsigned char *hash_oid, size_t hash_len, + const br_rsa_public_key *pk, unsigned char *hash_out); + +/** + * \brief RSA signature verification engine "i15" (PSS signatures). + * + * \see br_rsa_pss_vrfy + * + * \param x signature buffer. + * \param xlen signature length (in bytes). + * \param hf_data hash function applied on the message. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hash value of the signed message. + * \param salt_len PSS salt length (in bytes). + * \param pk RSA public key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const void *hash, size_t salt_len, const br_rsa_public_key *pk); + +/** + * \brief RSA private key engine "i15". + * + * \see br_rsa_private + * + * \param x operand to exponentiate. + * \param sk RSA private key. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_private(unsigned char *x, + const br_rsa_private_key *sk); + +/** + * \brief RSA signature generation engine "i15" (PKCS#1 v1.5 signatures). + * + * \see br_rsa_pkcs1_sign + * + * \param hash_oid encoded hash algorithm OID (or `NULL`). + * \param hash hash value. + * \param hash_len hash value length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the hash value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid, + const unsigned char *hash, size_t hash_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief RSA signature generation engine "i15" (PSS signatures). + * + * \see br_rsa_pss_sign + * + * \param rng PRNG for salt generation (`NULL` if `salt_len` is zero). + * \param hf_data hash function used to hash the signed data. + * \param hf_mgf1 hash function to use with MGF1. + * \param hash hashed message. + * \param salt_len salt length (in bytes). + * \param sk RSA private key. + * \param x output buffer for the signature value. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_pss_sign(const br_prng_class **rng, + const br_hash_class *hf_data, const br_hash_class *hf_mgf1, + const unsigned char *hash_value, size_t salt_len, + const br_rsa_private_key *sk, unsigned char *x); + +/** + * \brief Get "default" RSA implementation (public-key operations). + * + * This returns the preferred implementation of RSA (public-key operations) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_public br_rsa_public_get_default(void); + +/** + * \brief Get "default" RSA implementation (private-key operations). + * + * This returns the preferred implementation of RSA (private-key operations) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_private br_rsa_private_get_default(void); + +/** + * \brief Get "default" RSA implementation (PKCS#1 v1.5 signature verification). + * + * This returns the preferred implementation of RSA (signature verification) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pkcs1_vrfy br_rsa_pkcs1_vrfy_get_default(void); + +/** + * \brief Get "default" RSA implementation (PSS signature verification). + * + * This returns the preferred implementation of RSA (signature verification) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pss_vrfy br_rsa_pss_vrfy_get_default(void); + +/** + * \brief Get "default" RSA implementation (PKCS#1 v1.5 signature generation). + * + * This returns the preferred implementation of RSA (signature generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pkcs1_sign br_rsa_pkcs1_sign_get_default(void); + +/** + * \brief Get "default" RSA implementation (PSS signature generation). + * + * This returns the preferred implementation of RSA (signature generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pss_sign br_rsa_pss_sign_get_default(void); + +/** + * \brief Get "default" RSA implementation (OAEP encryption). + * + * This returns the preferred implementation of RSA (OAEP encryption) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_oaep_encrypt br_rsa_oaep_encrypt_get_default(void); + +/** + * \brief Get "default" RSA implementation (OAEP decryption). + * + * This returns the preferred implementation of RSA (OAEP decryption) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_oaep_decrypt br_rsa_oaep_decrypt_get_default(void); + +/** + * \brief RSA decryption helper, for SSL/TLS. + * + * This function performs the RSA decryption for a RSA-based key exchange + * in a SSL/TLS server. The provided RSA engine is used. The `data` + * parameter points to the value to decrypt, of length `len` bytes. On + * success, the 48-byte pre-master secret is copied into `data`, starting + * at the first byte of that buffer; on error, the contents of `data` + * become indeterminate. + * + * This function first checks that the provided value length (`len`) is + * not lower than 59 bytes, and matches the RSA modulus length; if neither + * of this property is met, then this function returns 0 and the buffer + * is unmodified. + * + * Otherwise, decryption and then padding verification are performed, both + * in constant-time. A decryption error, or a bad padding, or an + * incorrect decrypted value length are reported with a returned value of + * 0; on success, 1 is returned. The caller (SSL server engine) is supposed + * to proceed with a random pre-master secret in case of error. + * + * \param core RSA private key engine. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len length (in bytes) of the data to decrypt. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk, + unsigned char *data, size_t len); + +/** + * \brief RSA encryption (OAEP) with the "i15" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i15_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i15" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i15_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i31" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i31_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i31" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i31_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i32" engine. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i32_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i32" engine. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i32_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief RSA encryption (OAEP) with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_oaep_encrypt_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_oaep_encrypt + * + * \param rnd source of random bytes. + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param pk RSA public key. + * \param dst destination buffer. + * \param dst_max_len destination buffer length (maximum encrypted data size). + * \param src message to encrypt. + * \param src_len source message length (in bytes). + * \return encrypted message length (in bytes), or 0 on error. + */ +size_t br_rsa_i62_oaep_encrypt( + const br_prng_class **rnd, const br_hash_class *dig, + const void *label, size_t label_len, + const br_rsa_public_key *pk, + void *dst, size_t dst_max_len, + const void *src, size_t src_len); + +/** + * \brief RSA decryption (OAEP) with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_oaep_decrypt_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_oaep_decrypt + * + * \param dig hash function to use with MGF1. + * \param label label value (may be `NULL` if `label_len` is zero). + * \param label_len label length, in bytes. + * \param sk RSA private key. + * \param data input/output buffer. + * \param len encrypted/decrypted message length. + * \return 1 on success, 0 on error. + */ +uint32_t br_rsa_i62_oaep_decrypt( + const br_hash_class *dig, const void *label, size_t label_len, + const br_rsa_private_key *sk, void *data, size_t *len); + +/** + * \brief Get buffer size to hold RSA private key elements. + * + * This macro returns the length (in bytes) of the buffer needed to + * receive the elements of a RSA private key, as generated by one of + * the `br_rsa_*_keygen()` functions. If the provided size is a constant + * expression, then the whole macro evaluates to a constant expression. + * + * \param size target key size (modulus size, in bits) + * \return the length of the private key buffer, in bytes. + */ +#define BR_RSA_KBUF_PRIV_SIZE(size) (5 * (((size) + 15) >> 4)) + +/** + * \brief Get buffer size to hold RSA public key elements. + * + * This macro returns the length (in bytes) of the buffer needed to + * receive the elements of a RSA public key, as generated by one of + * the `br_rsa_*_keygen()` functions. If the provided size is a constant + * expression, then the whole macro evaluates to a constant expression. + * + * \param size target key size (modulus size, in bits) + * \return the length of the public key buffer, in bytes. + */ +#define BR_RSA_KBUF_PUB_SIZE(size) (4 + (((size) + 7) >> 3)) + +/** + * \brief Type for RSA key pair generator implementation. + * + * This function generates a new RSA key pair whose modulus has bit + * length `size` bits. The private key elements are written in the + * `kbuf_priv` buffer, and pointer values and length fields to these + * elements are populated in the provided private key structure `sk`. + * Similarly, the public key elements are written in `kbuf_pub`, with + * pointers and lengths set in `pk`. + * + * If `pk` is `NULL`, then `kbuf_pub` may be `NULL`, and only the + * private key is set. + * + * If `pubexp` is not zero, then its value will be used as public + * exponent. Valid RSA public exponent values are odd integers + * greater than 1. If `pubexp` is zero, then the public exponent will + * have value 3. + * + * The provided PRNG (`rng_ctx`) must have already been initialized + * and seeded. + * + * Returned value is 1 on success, 0 on error. An error is reported + * if the requested range is outside of the supported key sizes, or + * if an invalid non-zero public exponent value is provided. Supported + * range starts at 512 bits, and up to an implementation-defined + * maximum (by default 4096 bits). Note that key sizes up to 768 bits + * have been broken in practice, and sizes lower than 2048 bits are + * usually considered to be weak and should not be used. + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +typedef uint32_t (*br_rsa_keygen)( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i15" engine. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i15_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i31" engine. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i31_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief RSA key pair generation with the "i62" engine. + * + * This function is defined only on architecture that offer a 64x64->128 + * opcode. Use `br_rsa_i62_keygen_get()` to dynamically obtain a pointer + * to that function. + * + * \see br_rsa_keygen + * + * \param rng_ctx source PRNG context (already initialized) + * \param sk RSA private key structure (destination) + * \param kbuf_priv buffer for private key elements + * \param pk RSA public key structure (destination), or `NULL` + * \param kbuf_pub buffer for public key elements, or `NULL` + * \param size target RSA modulus size (in bits) + * \param pubexp public exponent to use, or zero + * \return 1 on success, 0 on error (invalid parameters) + */ +uint32_t br_rsa_i62_keygen( + const br_prng_class **rng_ctx, + br_rsa_private_key *sk, void *kbuf_priv, + br_rsa_public_key *pk, void *kbuf_pub, + unsigned size, uint32_t pubexp); + +/** + * \brief Get the RSA "i62" implementation (key pair generation), + * if available. + * + * \return the implementation, or 0. + */ +br_rsa_keygen br_rsa_i62_keygen_get(void); + +/** + * \brief Get "default" RSA implementation (key pair generation). + * + * This returns the preferred implementation of RSA (key pair generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_keygen br_rsa_keygen_get_default(void); + +/** + * \brief Type for a modulus computing function. + * + * Such a function computes the public modulus from the private key. The + * encoded modulus (unsigned big-endian) is written on `n`, and the size + * (in bytes) is returned. If `n` is `NULL`, then the size is returned but + * the modulus itself is not computed. + * + * If the key size exceeds an internal limit, 0 is returned. + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +typedef size_t (*br_rsa_compute_modulus)(void *n, const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA modulus ("i15" engine). + * + * \see br_rsa_compute_modulus + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +size_t br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA modulus ("i31" engine). + * + * \see br_rsa_compute_modulus + * + * \param n destination buffer (or `NULL`). + * \param sk RSA private key. + * \return the modulus length (in bytes), or 0. + */ +size_t br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk); + +/** + * \brief Get "default" RSA implementation (recompute modulus). + * + * This returns the preferred implementation of RSA (recompute modulus) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_modulus br_rsa_compute_modulus_get_default(void); + +/** + * \brief Type for a public exponent computing function. + * + * Such a function recomputes the public exponent from the private key. + * 0 is returned if any of the following occurs: + * + * - Either `p` or `q` is not equal to 3 modulo 4. + * + * - The public exponent does not fit on 32 bits. + * + * - An internal limit is exceeded. + * + * - The private key is invalid in some way. + * + * For all private keys produced by the key generator functions + * (`br_rsa_keygen` type), this function succeeds and returns the true + * public exponent. The public exponent is always an odd integer greater + * than 1. + * + * \return the public exponent, or 0. + */ +typedef uint32_t (*br_rsa_compute_pubexp)(const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA public exponent ("i15" engine). + * + * \see br_rsa_compute_pubexp + * + * \return the public exponent, or 0. + */ +uint32_t br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk); + +/** + * \brief Recompute RSA public exponent ("i31" engine). + * + * \see br_rsa_compute_pubexp + * + * \return the public exponent, or 0. + */ +uint32_t br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk); + +/** + * \brief Get "default" RSA implementation (recompute public exponent). + * + * This returns the preferred implementation of RSA (recompute public + * exponent) on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_pubexp br_rsa_compute_pubexp_get_default(void); + +/** + * \brief Type for a private exponent computing function. + * + * An RSA private key (`br_rsa_private_key`) contains two reduced + * private exponents, which are sufficient to perform private key + * operations. However, standard encoding formats for RSA private keys + * require also a copy of the complete private exponent (non-reduced), + * which this function recomputes. + * + * This function suceeds if all the following conditions hold: + * + * - Both private factors `p` and `q` are equal to 3 modulo 4. + * + * - The provided public exponent `pubexp` is correct, and, in particular, + * is odd, relatively prime to `p-1` and `q-1`, and greater than 1. + * + * - No internal storage limit is exceeded. + * + * For all private keys produced by the key generator functions + * (`br_rsa_keygen` type), this function succeeds. Note that the API + * restricts the public exponent to a maximum size of 32 bits. + * + * The encoded private exponent is written in `d` (unsigned big-endian + * convention), and the length (in bytes) is returned. If `d` is `NULL`, + * then the exponent is not written anywhere, but the length is still + * returned. On error, 0 is returned. + * + * Not all error conditions are detected when `d` is `NULL`; therefore, the + * returned value shall be checked also when actually producing the value. + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +typedef size_t (*br_rsa_compute_privexp)(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Recompute RSA private exponent ("i15" engine). + * + * \see br_rsa_compute_privexp + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +size_t br_rsa_i15_compute_privexp(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Recompute RSA private exponent ("i31" engine). + * + * \see br_rsa_compute_privexp + * + * \param d destination buffer (or `NULL`). + * \param sk RSA private key. + * \param pubexp the public exponent. + * \return the private exponent length (in bytes), or 0. + */ +size_t br_rsa_i31_compute_privexp(void *d, + const br_rsa_private_key *sk, uint32_t pubexp); + +/** + * \brief Get "default" RSA implementation (recompute private exponent). + * + * This returns the preferred implementation of RSA (recompute private + * exponent) on the current system. + * + * \return the default implementation. + */ +br_rsa_compute_privexp br_rsa_compute_privexp_get_default(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_ssl.h b/include/bearssl/bearssl_ssl.h new file mode 100644 index 000000000..0393e1f96 --- /dev/null +++ b/include/bearssl/bearssl_ssl.h @@ -0,0 +1,4308 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_SSL_H__ +#define BR_BEARSSL_SSL_H__ + +#include +#include + +#include "bearssl_block.h" +#include "bearssl_hash.h" +#include "bearssl_hmac.h" +#include "bearssl_prf.h" +#include "bearssl_rand.h" +#include "bearssl_x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_ssl.h + * + * # SSL + * + * For an overview of the SSL/TLS API, see [the BearSSL Web + * site](https://www.bearssl.org/api1.html). + * + * The `BR_TLS_*` constants correspond to the standard cipher suites and + * their values in the [IANA + * registry](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4). + * + * The `BR_ALERT_*` constants are for standard TLS alert messages. When + * a fatal alert message is sent of received, then the SSL engine context + * status is set to the sum of that alert value (an integer in the 0..255 + * range) and a fixed offset (`BR_ERR_SEND_FATAL_ALERT` for a sent alert, + * `BR_ERR_RECV_FATAL_ALERT` for a received alert). + */ + +/** \brief Optimal input buffer size. */ +#define BR_SSL_BUFSIZE_INPUT (16384 + 325) + +/** \brief Optimal output buffer size. */ +#define BR_SSL_BUFSIZE_OUTPUT (16384 + 85) + +/** \brief Optimal buffer size for monodirectional engine + (shared input/output buffer). */ +#define BR_SSL_BUFSIZE_MONO BR_SSL_BUFSIZE_INPUT + +/** \brief Optimal buffer size for bidirectional engine + (single buffer split into two separate input/output buffers). */ +#define BR_SSL_BUFSIZE_BIDI (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT) + +/* + * Constants for known SSL/TLS protocol versions (SSL 3.0, TLS 1.0, TLS 1.1 + * and TLS 1.2). Note that though there is a constant for SSL 3.0, that + * protocol version is not actually supported. + */ + +/** \brief Protocol version: SSL 3.0 (unsupported). */ +#define BR_SSL30 0x0300 +/** \brief Protocol version: TLS 1.0. */ +#define BR_TLS10 0x0301 +/** \brief Protocol version: TLS 1.1. */ +#define BR_TLS11 0x0302 +/** \brief Protocol version: TLS 1.2. */ +#define BR_TLS12 0x0303 + +/* + * Error constants. They are used to report the reason why a context has + * been marked as failed. + * + * Implementation note: SSL-level error codes should be in the 1..31 + * range. The 32..63 range is for certificate decoding and validation + * errors. Received fatal alerts imply an error code in the 256..511 range. + */ + +/** \brief SSL status: no error so far (0). */ +#define BR_ERR_OK 0 + +/** \brief SSL status: caller-provided parameter is incorrect. */ +#define BR_ERR_BAD_PARAM 1 + +/** \brief SSL status: operation requested by the caller cannot be applied + with the current context state (e.g. reading data while outgoing data + is waiting to be sent). */ +#define BR_ERR_BAD_STATE 2 + +/** \brief SSL status: incoming protocol or record version is unsupported. */ +#define BR_ERR_UNSUPPORTED_VERSION 3 + +/** \brief SSL status: incoming record version does not match the expected + version. */ +#define BR_ERR_BAD_VERSION 4 + +/** \brief SSL status: incoming record length is invalid. */ +#define BR_ERR_BAD_LENGTH 5 + +/** \brief SSL status: incoming record is too large to be processed, or + buffer is too small for the handshake message to send. */ +#define BR_ERR_TOO_LARGE 6 + +/** \brief SSL status: decryption found an invalid padding, or the record + MAC is not correct. */ +#define BR_ERR_BAD_MAC 7 + +/** \brief SSL status: no initial entropy was provided, and none can be + obtained from the OS. */ +#define BR_ERR_NO_RANDOM 8 + +/** \brief SSL status: incoming record type is unknown. */ +#define BR_ERR_UNKNOWN_TYPE 9 + +/** \brief SSL status: incoming record or message has wrong type with + regards to the current engine state. */ +#define BR_ERR_UNEXPECTED 10 + +/** \brief SSL status: ChangeCipherSpec message from the peer has invalid + contents. */ +#define BR_ERR_BAD_CCS 12 + +/** \brief SSL status: alert message from the peer has invalid contents + (odd length). */ +#define BR_ERR_BAD_ALERT 13 + +/** \brief SSL status: incoming handshake message decoding failed. */ +#define BR_ERR_BAD_HANDSHAKE 14 + +/** \brief SSL status: ServerHello contains a session ID which is larger + than 32 bytes. */ +#define BR_ERR_OVERSIZED_ID 15 + +/** \brief SSL status: server wants to use a cipher suite that we did + not claim to support. This is also reported if we tried to advertise + a cipher suite that we do not support. */ +#define BR_ERR_BAD_CIPHER_SUITE 16 + +/** \brief SSL status: server wants to use a compression that we did not + claim to support. */ +#define BR_ERR_BAD_COMPRESSION 17 + +/** \brief SSL status: server's max fragment length does not match + client's. */ +#define BR_ERR_BAD_FRAGLEN 18 + +/** \brief SSL status: secure renegotiation failed. */ +#define BR_ERR_BAD_SECRENEG 19 + +/** \brief SSL status: server sent an extension type that we did not + announce, or used the same extension type several times in a single + ServerHello. */ +#define BR_ERR_EXTRA_EXTENSION 20 + +/** \brief SSL status: invalid Server Name Indication contents (when + used by the server, this extension shall be empty). */ +#define BR_ERR_BAD_SNI 21 + +/** \brief SSL status: invalid ServerHelloDone from the server (length + is not 0). */ +#define BR_ERR_BAD_HELLO_DONE 22 + +/** \brief SSL status: internal limit exceeded (e.g. server's public key + is too large). */ +#define BR_ERR_LIMIT_EXCEEDED 23 + +/** \brief SSL status: Finished message from peer does not match the + expected value. */ +#define BR_ERR_BAD_FINISHED 24 + +/** \brief SSL status: session resumption attempt with distinct version + or cipher suite. */ +#define BR_ERR_RESUME_MISMATCH 25 + +/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve, + signature algorithm, hash function). */ +#define BR_ERR_INVALID_ALGORITHM 26 + +/** \brief SSL status: invalid signature (on ServerKeyExchange from + server, or in CertificateVerify from client). */ +#define BR_ERR_BAD_SIGNATURE 27 + +/** \brief SSL status: peer's public key does not have the proper type + or is not allowed for requested operation. */ +#define BR_ERR_WRONG_KEY_USAGE 28 + +/** \brief SSL status: client did not send a certificate upon request, + or the client certificate could not be validated. */ +#define BR_ERR_NO_CLIENT_AUTH 29 + +/** \brief SSL status: I/O error or premature close on underlying + transport stream. This error code is set only by the simplified + I/O API ("br_sslio_*"). */ +#define BR_ERR_IO 31 + +/** \brief SSL status: base value for a received fatal alert. + + When a fatal alert is received from the peer, the alert value + is added to this constant. */ +#define BR_ERR_RECV_FATAL_ALERT 256 + +/** \brief SSL status: base value for a sent fatal alert. + + When a fatal alert is sent to the peer, the alert value is added + to this constant. */ +#define BR_ERR_SEND_FATAL_ALERT 512 + +/* ===================================================================== */ + +/** + * \brief Decryption engine for SSL. + * + * When processing incoming records, the SSL engine will use a decryption + * engine that uses a specific context structure, and has a set of + * methods (a vtable) that follows this template. + * + * The decryption engine is responsible for applying decryption, verifying + * MAC, and keeping track of the record sequence number. + */ +typedef struct br_sslrec_in_class_ br_sslrec_in_class; +struct br_sslrec_in_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Test validity of the incoming record length. + * + * This function returns 1 if the announced length for an + * incoming record is valid, 0 otherwise, + * + * \param ctx decryption engine context. + * \param record_len incoming record length. + * \return 1 of a valid length, 0 otherwise. + */ + int (*check_length)(const br_sslrec_in_class *const *ctx, + size_t record_len); + + /** + * \brief Decrypt the incoming record. + * + * This function may assume that the record length is valid + * (it has been previously tested with `check_length()`). + * Decryption is done in place; `*len` is updated with the + * cleartext length, and the address of the first plaintext + * byte is returned. If the record is correct but empty, then + * `*len` is set to 0 and a non-`NULL` pointer is returned. + * + * On decryption/MAC error, `NULL` is returned. + * + * \param ctx decryption engine context. + * \param record_type record type (23 for application data, etc). + * \param version record version. + * \param payload address of encrypted payload. + * \param len pointer to payload length (updated). + * \return pointer to plaintext, or `NULL` on error. + */ + unsigned char *(*decrypt)(const br_sslrec_in_class **ctx, + int record_type, unsigned version, + void *payload, size_t *len); +}; + +/** + * \brief Encryption engine for SSL. + * + * When building outgoing records, the SSL engine will use an encryption + * engine that uses a specific context structure, and has a set of + * methods (a vtable) that follows this template. + * + * The encryption engine is responsible for applying encryption and MAC, + * and keeping track of the record sequence number. + */ +typedef struct br_sslrec_out_class_ br_sslrec_out_class; +struct br_sslrec_out_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Compute maximum plaintext sizes and offsets. + * + * When this function is called, the `*start` and `*end` + * values contain offsets designating the free area in the + * outgoing buffer for plaintext data; that free area is + * preceded by a 5-byte space which will receive the record + * header. + * + * The `max_plaintext()` function is responsible for adjusting + * both `*start` and `*end` to make room for any record-specific + * header, MAC, padding, and possible split. + * + * \param ctx encryption engine context. + * \param start pointer to start of plaintext offset (updated). + * \param end pointer to start of plaintext offset (updated). + */ + void (*max_plaintext)(const br_sslrec_out_class *const *ctx, + size_t *start, size_t *end); + + /** + * \brief Perform record encryption. + * + * This function encrypts the record. The plaintext address and + * length are provided. Returned value is the start of the + * encrypted record (or sequence of records, if a split was + * performed), _including_ the 5-byte header, and `*len` is + * adjusted to the total size of the record(s), there again + * including the header(s). + * + * \param ctx decryption engine context. + * \param record_type record type (23 for application data, etc). + * \param version record version. + * \param plaintext address of plaintext. + * \param len pointer to plaintext length (updated). + * \return pointer to start of built record. + */ + unsigned char *(*encrypt)(const br_sslrec_out_class **ctx, + int record_type, unsigned version, + void *plaintext, size_t *len); +}; + +/** + * \brief Context for a no-encryption engine. + * + * The no-encryption engine processes outgoing records during the initial + * handshake, before encryption is applied. + */ +typedef struct { + /** \brief No-encryption engine vtable. */ + const br_sslrec_out_class *vtable; +} br_sslrec_out_clear_context; + +/** \brief Static, constant vtable for the no-encryption engine. */ +extern const br_sslrec_out_class br_sslrec_out_clear_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for CBC mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for CBC processing: block cipher implementation, block cipher key, + * HMAC parameters (hash function, key, MAC length), and IV. If the + * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). + */ +typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class; +struct br_sslrec_in_cbc_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CBC decryption). + * \param bc_key block cipher key. + * \param bc_key_len block cipher key length (in bytes). + * \param dig_impl hash function for HMAC. + * \param mac_key HMAC key. + * \param mac_key_len HMAC key length (in bytes). + * \param mac_out_len HMAC output length (in bytes). + * \param iv initial IV (or `NULL`). + */ + void (*init)(const br_sslrec_in_cbc_class **ctx, + const br_block_cbcdec_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv); +}; + +/** + * \brief Record encryption engine class, for CBC mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for CBC processing: block cipher implementation, block cipher key, + * HMAC parameters (hash function, key, MAC length), and IV. If the + * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). + */ +typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class; +struct br_sslrec_out_cbc_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CBC encryption). + * \param bc_key block cipher key. + * \param bc_key_len block cipher key length (in bytes). + * \param dig_impl hash function for HMAC. + * \param mac_key HMAC key. + * \param mac_key_len HMAC key length (in bytes). + * \param mac_out_len HMAC output length (in bytes). + * \param iv initial IV (or `NULL`). + */ + void (*init)(const br_sslrec_out_cbc_class **ctx, + const br_block_cbcenc_class *bc_impl, + const void *bc_key, size_t bc_key_len, + const br_hash_class *dig_impl, + const void *mac_key, size_t mac_key_len, size_t mac_out_len, + const void *iv); +}; + +/** + * \brief Context structure for decrypting incoming records with + * CBC + HMAC. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_sslrec_in_cbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_cbcdec_class *vtable; + br_aes_gen_cbcdec_keys aes; + br_des_gen_cbcdec_keys des; + } bc; + br_hmac_key_context mac; + size_t mac_len; + unsigned char iv[16]; + int explicit_IV; +#endif +} br_sslrec_in_cbc_context; + +/** + * \brief Static, constant vtable for record decryption with CBC. + */ +extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable; + +/** + * \brief Context structure for encrypting outgoing records with + * CBC + HMAC. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_sslrec_out_cbc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_cbcenc_class *vtable; + br_aes_gen_cbcenc_keys aes; + br_des_gen_cbcenc_keys des; + } bc; + br_hmac_key_context mac; + size_t mac_len; + unsigned char iv[16]; + int explicit_IV; +#endif +} br_sslrec_out_cbc_context; + +/** + * \brief Static, constant vtable for record encryption with CBC. + */ +extern const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for GCM mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for GCM processing: block cipher implementation, block cipher key, + * GHASH implementation, and 4-byte IV. + */ +typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class; +struct br_sslrec_in_gcm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param gh_impl GHASH implementation. + * \param iv static IV (4 bytes). + */ + void (*init)(const br_sslrec_in_gcm_class **ctx, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv); +}; + +/** + * \brief Record encryption engine class, for GCM mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for GCM processing: block cipher implementation, block cipher key, + * GHASH implementation, and 4-byte IV. + */ +typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class; +struct br_sslrec_out_gcm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param gh_impl GHASH implementation. + * \param iv static IV (4 bytes). + */ + void (*init)(const br_sslrec_out_gcm_class **ctx, + const br_block_ctr_class *bc_impl, + const void *key, size_t key_len, + br_ghash gh_impl, + const void *iv); +}; + +/** + * \brief Context structure for processing records with GCM. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_gcm_class *in; + const br_sslrec_out_gcm_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_ctr_class *vtable; + br_aes_gen_ctr_keys aes; + } bc; + br_ghash gh; + unsigned char iv[4]; + unsigned char h[16]; +#endif +} br_sslrec_gcm_context; + +/** + * \brief Static, constant vtable for record decryption with GCM. + */ +extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable; + +/** + * \brief Static, constant vtable for record encryption with GCM. + */ +extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for ChaCha20+Poly1305. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for ChaCha20+Poly1305 processing: ChaCha20 implementation, + * Poly1305 implementation, key, and 12-byte IV. + */ +typedef struct br_sslrec_in_chapol_class_ br_sslrec_in_chapol_class; +struct br_sslrec_in_chapol_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param ichacha ChaCha20 implementation. + * \param ipoly Poly1305 implementation. + * \param key secret key (32 bytes). + * \param iv static IV (12 bytes). + */ + void (*init)(const br_sslrec_in_chapol_class **ctx, + br_chacha20_run ichacha, + br_poly1305_run ipoly, + const void *key, const void *iv); +}; + +/** + * \brief Record encryption engine class, for ChaCha20+Poly1305. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for ChaCha20+Poly1305 processing: ChaCha20 implementation, + * Poly1305 implementation, key, and 12-byte IV. + */ +typedef struct br_sslrec_out_chapol_class_ br_sslrec_out_chapol_class; +struct br_sslrec_out_chapol_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param ichacha ChaCha20 implementation. + * \param ipoly Poly1305 implementation. + * \param key secret key (32 bytes). + * \param iv static IV (12 bytes). + */ + void (*init)(const br_sslrec_out_chapol_class **ctx, + br_chacha20_run ichacha, + br_poly1305_run ipoly, + const void *key, const void *iv); +}; + +/** + * \brief Context structure for processing records with ChaCha20+Poly1305. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_chapol_class *in; + const br_sslrec_out_chapol_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + unsigned char key[32]; + unsigned char iv[12]; + br_chacha20_run ichacha; + br_poly1305_run ipoly; +#endif +} br_sslrec_chapol_context; + +/** + * \brief Static, constant vtable for record decryption with ChaCha20+Poly1305. + */ +extern const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable; + +/** + * \brief Static, constant vtable for record encryption with ChaCha20+Poly1305. + */ +extern const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable; + +/* ===================================================================== */ + +/** + * \brief Record decryption engine class, for CCM mode. + * + * This class type extends the decryption engine class with an + * initialisation method that receives the parameters needed + * for CCM processing: block cipher implementation, block cipher key, + * and 4-byte IV. + */ +typedef struct br_sslrec_in_ccm_class_ br_sslrec_in_ccm_class; +struct br_sslrec_in_ccm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_in_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR+CBC). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param iv static IV (4 bytes). + * \param tag_len tag length (in bytes) + */ + void (*init)(const br_sslrec_in_ccm_class **ctx, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len); +}; + +/** + * \brief Record encryption engine class, for CCM mode. + * + * This class type extends the encryption engine class with an + * initialisation method that receives the parameters needed + * for CCM processing: block cipher implementation, block cipher key, + * and 4-byte IV. + */ +typedef struct br_sslrec_out_ccm_class_ br_sslrec_out_ccm_class; +struct br_sslrec_out_ccm_class_ { + /** + * \brief Superclass, as first vtable field. + */ + br_sslrec_out_class inner; + + /** + * \brief Engine initialisation method. + * + * This method sets the vtable field in the context. + * + * \param ctx context to initialise. + * \param bc_impl block cipher implementation (CTR+CBC). + * \param key block cipher key. + * \param key_len block cipher key length (in bytes). + * \param iv static IV (4 bytes). + * \param tag_len tag length (in bytes) + */ + void (*init)(const br_sslrec_out_ccm_class **ctx, + const br_block_ctrcbc_class *bc_impl, + const void *key, size_t key_len, + const void *iv, size_t tag_len); +}; + +/** + * \brief Context structure for processing records with CCM. + * + * The same context structure is used for encrypting and decrypting. + * + * The first field points to the vtable. The other fields are opaque + * and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + union { + const void *gen; + const br_sslrec_in_ccm_class *in; + const br_sslrec_out_ccm_class *out; + } vtable; +#ifndef BR_DOXYGEN_IGNORE + uint64_t seq; + union { + const br_block_ctrcbc_class *vtable; + br_aes_gen_ctrcbc_keys aes; + } bc; + unsigned char iv[4]; + size_t tag_len; +#endif +} br_sslrec_ccm_context; + +/** + * \brief Static, constant vtable for record decryption with CCM. + */ +extern const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable; + +/** + * \brief Static, constant vtable for record encryption with CCM. + */ +extern const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable; + +/* ===================================================================== */ + +/** + * \brief Type for session parameters, to be saved for session resumption. + */ +typedef struct { + /** \brief Session ID buffer. */ + unsigned char session_id[32]; + /** \brief Session ID length (in bytes, at most 32). */ + unsigned char session_id_len; + /** \brief Protocol version. */ + uint16_t version; + /** \brief Cipher suite. */ + uint16_t cipher_suite; + /** \brief Master secret. */ + unsigned char master_secret[48]; +} br_ssl_session_parameters; + +#ifndef BR_DOXYGEN_IGNORE +/* + * Maximum number of cipher suites supported by a client or server. + */ +#define BR_MAX_CIPHER_SUITES 48 +#endif + +/** + * \brief Context structure for SSL engine. + * + * This strucuture is common to the client and server; both the client + * context (`br_ssl_client_context`) and the server context + * (`br_ssl_server_context`) include a `br_ssl_engine_context` as their + * first field. + * + * The engine context manages records, including alerts, closures, and + * transitions to new encryption/MAC algorithms. Processing of handshake + * records is delegated to externally provided code. This structure + * should not be used directly. + * + * Structure contents are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* + * The error code. When non-zero, then the state is "failed" and + * no I/O may occur until reset. + */ + int err; + + /* + * Configured I/O buffers. They are either disjoint, or identical. + */ + unsigned char *ibuf, *obuf; + size_t ibuf_len, obuf_len; + + /* + * Maximum fragment length applies to outgoing records; incoming + * records can be processed as long as they fit in the input + * buffer. It is guaranteed that incoming records at least as big + * as max_frag_len can be processed. + */ + uint16_t max_frag_len; + unsigned char log_max_frag_len; + unsigned char max_frag_len_negotiated; + unsigned char peer_log_max_frag_len; + + /* + * Buffering management registers. + */ + size_t ixa, ixb, ixc; + size_t oxa, oxb, oxc; + unsigned char iomode; + unsigned char incrypt; + + /* + * Shutdown flag: when set to non-zero, incoming record bytes + * will not be accepted anymore. This is used after a close_notify + * has been received: afterwards, the engine no longer claims that + * it could receive bytes from the transport medium. + */ + unsigned char shutdown_recv; + + /* + * 'record_type_in' is set to the incoming record type when the + * record header has been received. + * 'record_type_out' is used to make the next outgoing record + * header when it is ready to go. + */ + unsigned char record_type_in, record_type_out; + + /* + * When a record is received, its version is extracted: + * -- if 'version_in' is 0, then it is set to the received version; + * -- otherwise, if the received version is not identical to + * the 'version_in' contents, then a failure is reported. + * + * This implements the SSL requirement that all records shall + * use the negotiated protocol version, once decided (in the + * ServerHello). It is up to the handshake handler to adjust this + * field when necessary. + */ + uint16_t version_in; + + /* + * 'version_out' is used when the next outgoing record is ready + * to go. + */ + uint16_t version_out; + + /* + * Record handler contexts. + */ + union { + const br_sslrec_in_class *vtable; + br_sslrec_in_cbc_context cbc; + br_sslrec_gcm_context gcm; + br_sslrec_chapol_context chapol; + br_sslrec_ccm_context ccm; + } in; + union { + const br_sslrec_out_class *vtable; + br_sslrec_out_clear_context clear; + br_sslrec_out_cbc_context cbc; + br_sslrec_gcm_context gcm; + br_sslrec_chapol_context chapol; + br_sslrec_ccm_context ccm; + } out; + + /* + * The "application data" flag. Value: + * 0 handshake is in process, no application data acceptable + * 1 application data can be sent and received + * 2 closing, no application data can be sent, but some + * can still be received (and discarded) + */ + unsigned char application_data; + + /* + * Context RNG. + * + * rng_init_done is initially 0. It is set to 1 when the + * basic structure of the RNG is set, and 2 when some + * entropy has been pushed in. The value 2 marks the RNG + * as "properly seeded". + * + * rng_os_rand_done is initially 0. It is set to 1 when + * some seeding from the OS or hardware has been attempted. + */ + br_hmac_drbg_context rng; + int rng_init_done; + int rng_os_rand_done; + + /* + * Supported minimum and maximum versions, and cipher suites. + */ + uint16_t version_min; + uint16_t version_max; + uint16_t suites_buf[BR_MAX_CIPHER_SUITES]; + unsigned char suites_num; + + /* + * For clients, the server name to send as a SNI extension. For + * servers, the name received in the SNI extension (if any). + */ + char server_name[256]; + + /* + * "Security parameters". These are filled by the handshake + * handler, and used when switching encryption state. + */ + unsigned char client_random[32]; + unsigned char server_random[32]; + br_ssl_session_parameters session; + + /* + * ECDHE elements: curve and point from the peer. The server also + * uses that buffer for the point to send to the client. + */ + unsigned char ecdhe_curve; + unsigned char ecdhe_point[133]; + unsigned char ecdhe_point_len; + + /* + * Secure renegotiation (RFC 5746): 'reneg' can be: + * 0 first handshake (server support is not known) + * 1 peer does not support secure renegotiation + * 2 peer supports secure renegotiation + * + * The saved_finished buffer contains the client and the + * server "Finished" values from the last handshake, in + * that order (12 bytes each). + */ + unsigned char reneg; + unsigned char saved_finished[24]; + + /* + * Behavioural flags. + */ + uint32_t flags; + + /* + * Context variables for the handshake processor. The 'pad' must + * be large enough to accommodate an RSA-encrypted pre-master + * secret, or an RSA signature; since we want to support up to + * RSA-4096, this means at least 512 bytes. (Other pad usages + * require its length to be at least 256.) + */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + unsigned char pad[512]; + unsigned char *hbuf_in, *hbuf_out, *saved_hbuf_out; + size_t hlen_in, hlen_out; + void (*hsrun)(void *ctx); + + /* + * The 'action' value communicates OOB information between the + * engine and the handshake processor. + * + * From the engine: + * 0 invocation triggered by I/O + * 1 invocation triggered by explicit close + * 2 invocation triggered by explicit renegotiation + */ + unsigned char action; + + /* + * State for alert messages. Value is either 0, or the value of + * the alert level byte (level is either 1 for warning, or 2 for + * fatal; we convert all other values to 'fatal'). + */ + unsigned char alert; + + /* + * Closure flags. This flag is set when a close_notify has been + * received from the peer. + */ + unsigned char close_received; + + /* + * Multi-hasher for the handshake messages. The handshake handler + * is responsible for resetting it when appropriate. + */ + br_multihash_context mhash; + + /* + * Pointer to the X.509 engine. The engine is supposed to be + * already initialized. It is used to validate the peer's + * certificate. + */ + const br_x509_class **x509ctx; + + /* + * Certificate chain to send. This is used by both client and + * server, when they send their respective Certificate messages. + * If chain_len is 0, then chain may be NULL. + */ + const br_x509_certificate *chain; + size_t chain_len; + const unsigned char *cert_cur; + size_t cert_len; + + /* + * List of supported protocol names (ALPN extension). If unset, + * (number of names is 0), then: + * - the client sends no ALPN extension; + * - the server ignores any incoming ALPN extension. + * + * Otherwise: + * - the client sends an ALPN extension with all the names; + * - the server selects the first protocol in its list that + * the client also supports, or fails (fatal alert 120) + * if the client sends an ALPN extension and there is no + * match. + * + * The 'selected_protocol' field contains 1+n if the matching + * name has index n in the list (the value is 0 if no match was + * performed, e.g. the peer did not send an ALPN extension). + */ + const char **protocol_names; + uint16_t protocol_names_num; + uint16_t selected_protocol; + + /* + * Pointers to implementations; left to NULL for unsupported + * functions. For the raw hash functions, implementations are + * referenced from the multihasher (mhash field). + */ + br_tls_prf_impl prf10; + br_tls_prf_impl prf_sha256; + br_tls_prf_impl prf_sha384; + const br_block_cbcenc_class *iaes_cbcenc; + const br_block_cbcdec_class *iaes_cbcdec; + const br_block_ctr_class *iaes_ctr; + const br_block_ctrcbc_class *iaes_ctrcbc; + const br_block_cbcenc_class *ides_cbcenc; + const br_block_cbcdec_class *ides_cbcdec; + br_ghash ighash; + br_chacha20_run ichacha; + br_poly1305_run ipoly; + const br_sslrec_in_cbc_class *icbc_in; + const br_sslrec_out_cbc_class *icbc_out; + const br_sslrec_in_gcm_class *igcm_in; + const br_sslrec_out_gcm_class *igcm_out; + const br_sslrec_in_chapol_class *ichapol_in; + const br_sslrec_out_chapol_class *ichapol_out; + const br_sslrec_in_ccm_class *iccm_in; + const br_sslrec_out_ccm_class *iccm_out; + const br_ec_impl *iec; + br_rsa_pkcs1_vrfy irsavrfy; + br_ecdsa_vrfy iecdsa; +#endif +} br_ssl_engine_context; + +/** + * \brief Get currently defined engine behavioural flags. + * + * \param cc SSL engine context. + * \return the flags. + */ +static inline uint32_t +br_ssl_engine_get_flags(br_ssl_engine_context *cc) +{ + return cc->flags; +} + +/** + * \brief Set all engine behavioural flags. + * + * \param cc SSL engine context. + * \param flags new value for all flags. + */ +static inline void +br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags = flags; +} + +/** + * \brief Set some engine behavioural flags. + * + * The flags set in the `flags` parameter are set in the context; other + * flags are untouched. + * + * \param cc SSL engine context. + * \param flags additional set flags. + */ +static inline void +br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags |= flags; +} + +/** + * \brief Clear some engine behavioural flags. + * + * The flags set in the `flags` parameter are cleared from the context; other + * flags are untouched. + * + * \param cc SSL engine context. + * \param flags flags to remove. + */ +static inline void +br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags) +{ + cc->flags &= ~flags; +} + +/** + * \brief Behavioural flag: enforce server preferences. + * + * If this flag is set, then the server will enforce its own cipher suite + * preference order; otherwise, it follows the client preferences. + */ +#define BR_OPT_ENFORCE_SERVER_PREFERENCES ((uint32_t)1 << 0) + +/** + * \brief Behavioural flag: disable renegotiation. + * + * If this flag is set, then renegotiations are rejected unconditionally: + * they won't be honoured if asked for programmatically, and requests from + * the peer are rejected. + */ +#define BR_OPT_NO_RENEGOTIATION ((uint32_t)1 << 1) + +/** + * \brief Behavioural flag: tolerate lack of client authentication. + * + * If this flag is set in a server and the server requests a client + * certificate, but the authentication fails (the client does not send + * a certificate, or the client's certificate chain cannot be validated), + * then the connection keeps on. Without this flag, a failed client + * authentication terminates the connection. + * + * Notes: + * + * - If the client's certificate can be validated and its public key is + * supported, then a wrong signature value terminates the connection + * regardless of that flag. + * + * - If using full-static ECDH, then a failure to validate the client's + * certificate prevents the handshake from succeeding. + */ +#define BR_OPT_TOLERATE_NO_CLIENT_AUTH ((uint32_t)1 << 2) + +/** + * \brief Behavioural flag: fail on application protocol mismatch. + * + * The ALPN extension ([RFC 7301](https://tools.ietf.org/html/rfc7301)) + * allows the client to send a list of application protocol names, and + * the server to select one. A mismatch is one of the following occurrences: + * + * - On the client: the client sends a list of names, the server + * responds with a protocol name which is _not_ part of the list of + * names sent by the client. + * + * - On the server: the client sends a list of names, and the server + * is also configured with a list of names, but there is no common + * protocol name between the two lists. + * + * Normal behaviour in case of mismatch is to report no matching name + * (`br_ssl_engine_get_selected_protocol()` returns `NULL`) and carry on. + * If the flag is set, then a mismatch implies a protocol failure (if + * the mismatch is detected by the server, it will send a fatal alert). + * + * Note: even with this flag, `br_ssl_engine_get_selected_protocol()` + * may still return `NULL` if the client or the server does not send an + * ALPN extension at all. + */ +#define BR_OPT_FAIL_ON_ALPN_MISMATCH ((uint32_t)1 << 3) + +/** + * \brief Set the minimum and maximum supported protocol versions. + * + * The two provided versions MUST be supported by the implementation + * (i.e. TLS 1.0, 1.1 and 1.2), and `version_max` MUST NOT be lower + * than `version_min`. + * + * \param cc SSL engine context. + * \param version_min minimum supported TLS version. + * \param version_max maximum supported TLS version. + */ +static inline void +br_ssl_engine_set_versions(br_ssl_engine_context *cc, + unsigned version_min, unsigned version_max) +{ + cc->version_min = version_min; + cc->version_max = version_max; +} + +/** + * \brief Set the list of cipher suites advertised by this context. + * + * The provided array is copied into the context. It is the caller + * responsibility to ensure that all provided suites will be supported + * by the context. The engine context has enough room to receive _all_ + * suites supported by the implementation. The provided array MUST NOT + * contain duplicates. + * + * If the engine is for a client, the "signaling" pseudo-cipher suite + * `TLS_FALLBACK_SCSV` can be added at the end of the list, if the + * calling application is performing a voluntary downgrade (voluntary + * downgrades are not recommended, but if such a downgrade is done, then + * adding the fallback pseudo-suite is a good idea). + * + * \param cc SSL engine context. + * \param suites cipher suites. + * \param suites_num number of cipher suites. + */ +void br_ssl_engine_set_suites(br_ssl_engine_context *cc, + const uint16_t *suites, size_t suites_num); + +/** + * \brief Set the X.509 engine. + * + * The caller shall ensure that the X.509 engine is properly initialised. + * + * \param cc SSL engine context. + * \param x509ctx X.509 certificate validation context. + */ +static inline void +br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx) +{ + cc->x509ctx = x509ctx; +} + +/** + * \brief Set the supported protocol names. + * + * Protocol names are part of the ALPN extension ([RFC + * 7301](https://tools.ietf.org/html/rfc7301)). Each protocol name is a + * character string, containing no more than 255 characters (256 with the + * terminating zero). When names are set, then: + * + * - The client will send an ALPN extension, containing the names. If + * the server responds with an ALPN extension, the client will verify + * that the response contains one of its name, and report that name + * through `br_ssl_engine_get_selected_protocol()`. + * + * - The server will parse incoming ALPN extension (from clients), and + * try to find a common protocol; if none is found, the connection + * is aborted with a fatal alert. On match, a response ALPN extension + * is sent, and name is reported through + * `br_ssl_engine_get_selected_protocol()`. + * + * The provided array is linked in, and must remain valid while the + * connection is live. + * + * Names MUST NOT be empty. Names MUST NOT be longer than 255 characters + * (excluding the terminating 0). + * + * \param ctx SSL engine context. + * \param names list of protocol names (zero-terminated). + * \param num number of protocol names (MUST be 1 or more). + */ +static inline void +br_ssl_engine_set_protocol_names(br_ssl_engine_context *ctx, + const char **names, size_t num) +{ + ctx->protocol_names = names; + ctx->protocol_names_num = num; +} + +/** + * \brief Get the selected protocol. + * + * If this context was initialised with a non-empty list of protocol + * names, and both client and server sent ALPN extensions during the + * handshake, and a common name was found, then that name is returned. + * Otherwise, `NULL` is returned. + * + * The returned pointer is one of the pointers provided to the context + * with `br_ssl_engine_set_protocol_names()`. + * + * \return the selected protocol, or `NULL`. + */ +static inline const char * +br_ssl_engine_get_selected_protocol(br_ssl_engine_context *ctx) +{ + unsigned k; + + k = ctx->selected_protocol; + return (k == 0 || k == 0xFFFF) ? NULL : ctx->protocol_names[k - 1]; +} + +/** + * \brief Set a hash function implementation (by ID). + * + * Hash functions set with this call will be used for SSL/TLS specific + * usages, not X.509 certificate validation. Only "standard" hash functions + * may be set (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512). If `impl` + * is `NULL`, then the hash function support is removed, not added. + * + * \param ctx SSL engine context. + * \param id hash function identifier. + * \param impl hash function implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_hash(br_ssl_engine_context *ctx, + int id, const br_hash_class *impl) +{ + br_multihash_setimpl(&ctx->mhash, id, impl); +} + +/** + * \brief Get a hash function implementation (by ID). + * + * This function retrieves a hash function implementation which was + * set with `br_ssl_engine_set_hash()`. + * + * \param ctx SSL engine context. + * \param id hash function identifier. + * \return the hash function implementation (or `NULL`). + */ +static inline const br_hash_class * +br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id) +{ + return br_multihash_getimpl(&ctx->mhash, id); +} + +/** + * \brief Set the PRF implementation (for TLS 1.0 and 1.1). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the PRF used in TLS 1.0 and 1.1. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf10 = impl; +} + +/** + * \brief Set the PRF implementation with SHA-256 (for TLS 1.2). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the SHA-256 variant of the PRF used in TLS 1.2. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf_sha256 = impl; +} + +/** + * \brief Set the PRF implementation with SHA-384 (for TLS 1.2). + * + * This function sets (or removes, if `impl` is `NULL`) the implementation + * for the SHA-384 variant of the PRF used in TLS 1.2. + * + * \param cc SSL engine context. + * \param impl PRF implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl) +{ + cc->prf_sha384 = impl; +} + +/** + * \brief Set the AES/CBC implementations. + * + * \param cc SSL engine context. + * \param impl_enc AES/CBC encryption implementation (or `NULL`). + * \param impl_dec AES/CBC decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc, + const br_block_cbcenc_class *impl_enc, + const br_block_cbcdec_class *impl_dec) +{ + cc->iaes_cbcenc = impl_enc; + cc->iaes_cbcdec = impl_dec; +} + +/** + * \brief Set the "default" AES/CBC implementations. + * + * This function configures in the engine the AES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc); + +/** + * \brief Set the AES/CTR implementation. + * + * \param cc SSL engine context. + * \param impl AES/CTR encryption/decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc, + const br_block_ctr_class *impl) +{ + cc->iaes_ctr = impl; +} + +/** + * \brief Set the "default" implementations for AES/GCM (AES/CTR + GHASH). + * + * This function configures in the engine the AES/CTR and GHASH + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for GCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc); + +/** + * \brief Set the DES/CBC implementations. + * + * \param cc SSL engine context. + * \param impl_enc DES/CBC encryption implementation (or `NULL`). + * \param impl_dec DES/CBC decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc, + const br_block_cbcenc_class *impl_enc, + const br_block_cbcdec_class *impl_dec) +{ + cc->ides_cbcenc = impl_enc; + cc->ides_cbcdec = impl_dec; +} + +/** + * \brief Set the "default" DES/CBC implementations. + * + * This function configures in the engine the DES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc); + +/** + * \brief Set the GHASH implementation (used in GCM mode). + * + * \param cc SSL engine context. + * \param impl GHASH implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl) +{ + cc->ighash = impl; +} + +/** + * \brief Set the ChaCha20 implementation. + * + * \param cc SSL engine context. + * \param ichacha ChaCha20 implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_chacha20(br_ssl_engine_context *cc, + br_chacha20_run ichacha) +{ + cc->ichacha = ichacha; +} + +/** + * \brief Set the Poly1305 implementation. + * + * \param cc SSL engine context. + * \param ipoly Poly1305 implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_poly1305(br_ssl_engine_context *cc, + br_poly1305_run ipoly) +{ + cc->ipoly = ipoly; +} + +/** + * \brief Set the "default" ChaCha20 and Poly1305 implementations. + * + * This function configures in the engine the ChaCha20 and Poly1305 + * implementations that should provide best runtime performance on the + * local system, while still being safe (in particular, constant-time). + * It also sets the handlers for ChaCha20+Poly1305 records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc); + +/** + * \brief Set the AES/CTR+CBC implementation. + * + * \param cc SSL engine context. + * \param impl AES/CTR+CBC encryption/decryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_aes_ctrcbc(br_ssl_engine_context *cc, + const br_block_ctrcbc_class *impl) +{ + cc->iaes_ctrcbc = impl; +} + +/** + * \brief Set the "default" implementations for AES/CCM. + * + * This function configures in the engine the AES/CTR+CBC + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for CCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc); + +/** + * \brief Set the record encryption and decryption engines for CBC + HMAC. + * + * \param cc SSL engine context. + * \param impl_in record CBC decryption implementation (or `NULL`). + * \param impl_out record CBC encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_cbc(br_ssl_engine_context *cc, + const br_sslrec_in_cbc_class *impl_in, + const br_sslrec_out_cbc_class *impl_out) +{ + cc->icbc_in = impl_in; + cc->icbc_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for GCM. + * + * \param cc SSL engine context. + * \param impl_in record GCM decryption implementation (or `NULL`). + * \param impl_out record GCM encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_gcm(br_ssl_engine_context *cc, + const br_sslrec_in_gcm_class *impl_in, + const br_sslrec_out_gcm_class *impl_out) +{ + cc->igcm_in = impl_in; + cc->igcm_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for CCM. + * + * \param cc SSL engine context. + * \param impl_in record CCM decryption implementation (or `NULL`). + * \param impl_out record CCM encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_ccm(br_ssl_engine_context *cc, + const br_sslrec_in_ccm_class *impl_in, + const br_sslrec_out_ccm_class *impl_out) +{ + cc->iccm_in = impl_in; + cc->iccm_out = impl_out; +} + +/** + * \brief Set the record encryption and decryption engines for + * ChaCha20+Poly1305. + * + * \param cc SSL engine context. + * \param impl_in record ChaCha20 decryption implementation (or `NULL`). + * \param impl_out record ChaCha20 encryption implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_chapol(br_ssl_engine_context *cc, + const br_sslrec_in_chapol_class *impl_in, + const br_sslrec_out_chapol_class *impl_out) +{ + cc->ichapol_in = impl_in; + cc->ichapol_out = impl_out; +} + +/** + * \brief Set the EC implementation. + * + * The elliptic curve implementation will be used for ECDH and ECDHE + * cipher suites, and for ECDSA support. + * + * \param cc SSL engine context. + * \param iec EC implementation (or `NULL`). + */ +static inline void +br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec) +{ + cc->iec = iec; +} + +/** + * \brief Set the "default" EC implementation. + * + * This function sets the elliptic curve implementation for ECDH and + * ECDHE cipher suites, and for ECDSA support. It selects the fastest + * implementation on the current system. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ec(br_ssl_engine_context *cc); + +/** + * \brief Get the EC implementation configured in the provided engine. + * + * \param cc SSL engine context. + * \return the EC implementation. + */ +static inline const br_ec_impl * +br_ssl_engine_get_ec(br_ssl_engine_context *cc) +{ + return cc->iec; +} + +/** + * \brief Set the RSA signature verification implementation. + * + * On the client, this is used to verify the server's signature on its + * ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server, + * this is used to verify the client's CertificateVerify message (if a + * client certificate is requested, and that certificate contains a RSA key). + * + * \param cc SSL engine context. + * \param irsavrfy RSA signature verification implementation. + */ +static inline void +br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy) +{ + cc->irsavrfy = irsavrfy; +} + +/** + * \brief Set the "default" RSA implementation (signature verification). + * + * This function sets the RSA implementation (signature verification) + * to the fastest implementation available on the current platform. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc); + +/** + * \brief Get the RSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the RSA signature verification implementation. + */ +static inline br_rsa_pkcs1_vrfy +br_ssl_engine_get_rsavrfy(br_ssl_engine_context *cc) +{ + return cc->irsavrfy; +} + +/* + * \brief Set the ECDSA implementation (signature verification). + * + * On the client, this is used to verify the server's signature on its + * ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server, + * this is used to verify the client's CertificateVerify message (if a + * client certificate is requested, that certificate contains an EC key, + * and full-static ECDH is not used). + * + * The ECDSA implementation will use the EC core implementation configured + * in the engine context. + * + * \param cc client context. + * \param iecdsa ECDSA verification implementation. + */ +static inline void +br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa) +{ + cc->iecdsa = iecdsa; +} + +/** + * \brief Set the "default" ECDSA implementation (signature verification). + * + * This function sets the ECDSA implementation (signature verification) + * to the fastest implementation available on the current platform. This + * call also sets the elliptic curve implementation itself, there again + * to the fastest EC implementation available. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc); + +/** + * \brief Get the ECDSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the ECDSA signature verification implementation. + */ +static inline br_ecdsa_vrfy +br_ssl_engine_get_ecdsa(br_ssl_engine_context *cc) +{ + return cc->iecdsa; +} + +/** + * \brief Set the I/O buffer for the SSL engine. + * + * Once this call has been made, `br_ssl_client_reset()` or + * `br_ssl_server_reset()` MUST be called before using the context. + * + * The provided buffer will be used as long as the engine context is + * used. The caller is responsible for keeping it available. + * + * If `bidi` is 0, then the engine will operate in half-duplex mode + * (it won't be able to send data while there is unprocessed incoming + * data in the buffer, and it won't be able to receive data while there + * is unsent data in the buffer). The optimal buffer size in half-duplex + * mode is `BR_SSL_BUFSIZE_MONO`; if the buffer is larger, then extra + * bytes are ignored. If the buffer is smaller, then this limits the + * capacity of the engine to support all allowed record sizes. + * + * If `bidi` is 1, then the engine will split the buffer into two + * parts, for separate handling of outgoing and incoming data. This + * enables full-duplex processing, but requires more RAM. The optimal + * buffer size in full-duplex mode is `BR_SSL_BUFSIZE_BIDI`; if the + * buffer is larger, then extra bytes are ignored. If the buffer is + * smaller, then the split will favour the incoming part, so that + * interoperability is maximised. + * + * \param cc SSL engine context + * \param iobuf I/O buffer. + * \param iobuf_len I/O buffer length (in bytes). + * \param bidi non-zero for full-duplex mode. + */ +void br_ssl_engine_set_buffer(br_ssl_engine_context *cc, + void *iobuf, size_t iobuf_len, int bidi); + +/** + * \brief Set the I/O buffers for the SSL engine. + * + * Once this call has been made, `br_ssl_client_reset()` or + * `br_ssl_server_reset()` MUST be called before using the context. + * + * This function is similar to `br_ssl_engine_set_buffer()`, except + * that it enforces full-duplex mode, and the two I/O buffers are + * provided as separate chunks. + * + * The macros `BR_SSL_BUFSIZE_INPUT` and `BR_SSL_BUFSIZE_OUTPUT` + * evaluate to the optimal (maximum) sizes for the input and output + * buffer, respectively. + * + * \param cc SSL engine context + * \param ibuf input buffer. + * \param ibuf_len input buffer length (in bytes). + * \param obuf output buffer. + * \param obuf_len output buffer length (in bytes). + */ +void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc, + void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len); + +/** + * \brief Determine if MFLN negotiation was successful + * + * \param cc SSL engine context. + */ +static inline uint8_t +br_ssl_engine_get_mfln_negotiated(br_ssl_engine_context *cc) +{ + return cc->max_frag_len_negotiated; +} + +/** + * \brief Inject some "initial entropy" in the context. + * + * This entropy will be added to what can be obtained from the + * underlying operating system, if that OS is supported. + * + * This function may be called several times; all injected entropy chunks + * are cumulatively mixed. + * + * If entropy gathering from the OS is supported and compiled in, then this + * step is optional. Otherwise, it is mandatory to inject randomness, and + * the caller MUST take care to push (as one or several successive calls) + * enough entropy to achieve cryptographic resistance (at least 80 bits, + * preferably 128 or more). The engine will report an error if no entropy + * was provided and none can be obtained from the OS. + * + * Take care that this function cannot assess the cryptographic quality of + * the provided bytes. + * + * In all generality, "entropy" must here be considered to mean "that + * which the attacker cannot predict". If your OS/architecture does not + * have a suitable source of randomness, then you can make do with the + * combination of a large enough secret value (possibly a copy of an + * asymmetric private key that you also store on the system) AND a + * non-repeating value (e.g. current time, provided that the local clock + * cannot be reset or altered by the attacker). + * + * \param cc SSL engine context. + * \param data extra entropy to inject. + * \param len length of the extra data (in bytes). + */ +void br_ssl_engine_inject_entropy(br_ssl_engine_context *cc, + const void *data, size_t len); + +/** + * \brief Get the "server name" in this engine. + * + * For clients, this is the name provided with `br_ssl_client_reset()`; + * for servers, this is the name received from the client as part of the + * ClientHello message. If there is no such name (e.g. the client did + * not send an SNI extension) then the returned string is empty + * (returned pointer points to a byte of value 0). + * + * The returned pointer refers to a buffer inside the context, which may + * be overwritten as part of normal SSL activity (even within the same + * connection, if a renegotiation occurs). + * + * \param cc SSL engine context. + * \return the server name (possibly empty). + */ +static inline const char * +br_ssl_engine_get_server_name(const br_ssl_engine_context *cc) +{ + return cc->server_name; +} + +/** + * \brief Get the protocol version. + * + * This function returns the protocol version that is used by the + * engine. That value is set after sending (for a server) or receiving + * (for a client) the ServerHello message. + * + * \param cc SSL engine context. + * \return the protocol version. + */ +static inline unsigned +br_ssl_engine_get_version(const br_ssl_engine_context *cc) +{ + return cc->session.version; +} + +/** + * \brief Get a copy of the session parameters. + * + * The session parameters are filled during the handshake, so this + * function shall not be called before completion of the handshake. + * The initial handshake is completed when the context first allows + * application data to be injected. + * + * This function copies the current session parameters into the provided + * structure. Beware that the session parameters include the master + * secret, which is sensitive data, to handle with great care. + * + * \param cc SSL engine context. + * \param pp destination structure for the session parameters. + */ +static inline void +br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc, + br_ssl_session_parameters *pp) +{ + memcpy(pp, &cc->session, sizeof *pp); +} + +/** + * \brief Set the session parameters to the provided values. + * + * This function is meant to be used in the client, before doing a new + * handshake; a session resumption will be attempted with these + * parameters. In the server, this function has no effect. + * + * \param cc SSL engine context. + * \param pp source structure for the session parameters. + */ +static inline void +br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc, + const br_ssl_session_parameters *pp) +{ + memcpy(&cc->session, pp, sizeof *pp); +} + +/** + * \brief Get identifier for the curve used for key exchange. + * + * If the cipher suite uses ECDHE, then this function returns the + * identifier for the curve used for transient parameters. This is + * defined during the course of the handshake, when the ServerKeyExchange + * is sent (on the server) or received (on the client). If the + * cipher suite does not use ECDHE (e.g. static ECDH, or RSA key + * exchange), then this value is indeterminate. + * + * @param cc SSL engine context. + * @return the ECDHE curve identifier. + */ +static inline int +br_ssl_engine_get_ecdhe_curve(br_ssl_engine_context *cc) +{ + return cc->ecdhe_curve; +} + +/** + * \brief Get the current engine state. + * + * An SSL engine (client or server) has, at any time, a state which is + * the combination of zero, one or more of these flags: + * + * - `BR_SSL_CLOSED` + * + * Engine is finished, no more I/O (until next reset). + * + * - `BR_SSL_SENDREC` + * + * Engine has some bytes to send to the peer. + * + * - `BR_SSL_RECVREC` + * + * Engine expects some bytes from the peer. + * + * - `BR_SSL_SENDAPP` + * + * Engine may receive application data to send (or flush). + * + * - `BR_SSL_RECVAPP` + * + * Engine has obtained some application data from the peer, + * that should be read by the caller. + * + * If no flag at all is set (state value is 0), then the engine is not + * fully initialised yet. + * + * The `BR_SSL_CLOSED` flag is exclusive; when it is set, no other flag + * is set. To distinguish between a normal closure and an error, use + * `br_ssl_engine_last_error()`. + * + * Generally speaking, `BR_SSL_SENDREC` and `BR_SSL_SENDAPP` are mutually + * exclusive: the input buffer, at any point, either accumulates + * plaintext data, or contains an assembled record that is being sent. + * Similarly, `BR_SSL_RECVREC` and `BR_SSL_RECVAPP` are mutually exclusive. + * This may change in a future library version. + * + * \param cc SSL engine context. + * \return the current engine state. + */ +unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc); + +/** \brief SSL engine state: closed or failed. */ +#define BR_SSL_CLOSED 0x0001 +/** \brief SSL engine state: record data is ready to be sent to the peer. */ +#define BR_SSL_SENDREC 0x0002 +/** \brief SSL engine state: engine may receive records from the peer. */ +#define BR_SSL_RECVREC 0x0004 +/** \brief SSL engine state: engine may accept application data to send. */ +#define BR_SSL_SENDAPP 0x0008 +/** \brief SSL engine state: engine has received application data. */ +#define BR_SSL_RECVAPP 0x0010 + +/** + * \brief Get the engine error indicator. + * + * The error indicator is `BR_ERR_OK` (0) if no error was encountered + * since the last call to `br_ssl_client_reset()` or + * `br_ssl_server_reset()`. Other status values are "sticky": they + * remain set, and prevent all I/O activity, until cleared. Only the + * reset calls clear the error indicator. + * + * \param cc SSL engine context. + * \return 0, or a non-zero error code. + */ +static inline int +br_ssl_engine_last_error(const br_ssl_engine_context *cc) +{ + return cc->err; +} + +/* + * There are four I/O operations, each identified by a symbolic name: + * + * sendapp inject application data in the engine + * recvapp retrieving application data from the engine + * sendrec sending records on the transport medium + * recvrec receiving records from the transport medium + * + * Terminology works thus: in a layered model where the SSL engine sits + * between the application and the network, "send" designates operations + * where bytes flow from application to network, and "recv" for the + * reverse operation. Application data (the plaintext that is to be + * conveyed through SSL) is "app", while encrypted records are "rec". + * Note that from the SSL engine point of view, "sendapp" and "recvrec" + * designate bytes that enter the engine ("inject" operation), while + * "recvapp" and "sendrec" designate bytes that exit the engine + * ("extract" operation). + * + * For the operation 'xxx', two functions are defined: + * + * br_ssl_engine_xxx_buf + * Returns a pointer and length to the buffer to use for that + * operation. '*len' is set to the number of bytes that may be read + * from the buffer (extract operation) or written to the buffer + * (inject operation). If no byte may be exchanged for that operation + * at that point, then '*len' is set to zero, and NULL is returned. + * The engine state is unmodified by this call. + * + * br_ssl_engine_xxx_ack + * Informs the engine that 'len' bytes have been read from the buffer + * (extract operation) or written to the buffer (inject operation). + * The 'len' value MUST NOT be zero. The 'len' value MUST NOT exceed + * that which was obtained from a preceding br_ssl_engine_xxx_buf() + * call. + */ + +/** + * \brief Get buffer for application data to send. + * + * If the engine is ready to accept application data to send to the + * peer, then this call returns a pointer to the buffer where such + * data shall be written, and its length is written in `*len`. + * Otherwise, `*len` is set to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the application data output buffer length, or 0. + * \return the application data output buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_sendapp_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Inform the engine of some new application data. + * + * After writing `len` bytes in the buffer returned by + * `br_ssl_engine_sendapp_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_sendapp_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes pushed (not zero). + */ +void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for received application data. + * + * If the engine has received application data from the peer, hen this + * call returns a pointer to the buffer from where such data shall be + * read, and its length is written in `*len`. Otherwise, `*len` is set + * to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the application data input buffer length, or 0. + * \return the application data input buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_recvapp_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Acknowledge some received application data. + * + * After reading `len` bytes from the buffer returned by + * `br_ssl_engine_recvapp_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_recvapp_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes read (not zero). + */ +void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for record data to send. + * + * If the engine has prepared some records to send to the peer, then this + * call returns a pointer to the buffer from where such data shall be + * read, and its length is written in `*len`. Otherwise, `*len` is set + * to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the record data output buffer length, or 0. + * \return the record data output buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_sendrec_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Acknowledge some sent record data. + * + * After reading `len` bytes from the buffer returned by + * `br_ssl_engine_sendrec_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_sendrec_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes read (not zero). + */ +void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Get buffer for incoming records. + * + * If the engine is ready to accept records from the peer, then this + * call returns a pointer to the buffer where such data shall be + * written, and its length is written in `*len`. Otherwise, `*len` is + * set to 0 and `NULL` is returned. + * + * \param cc SSL engine context. + * \param len receives the record data input buffer length, or 0. + * \return the record data input buffer, or `NULL`. + */ +unsigned char *br_ssl_engine_recvrec_buf( + const br_ssl_engine_context *cc, size_t *len); + +/** + * \brief Inform the engine of some new record data. + * + * After writing `len` bytes in the buffer returned by + * `br_ssl_engine_recvrec_buf()`, the application shall call this + * function to trigger any relevant processing. The `len` parameter + * MUST NOT be 0, and MUST NOT exceed the value obtained in the + * `br_ssl_engine_recvrec_buf()` call. + * + * \param cc SSL engine context. + * \param len number of bytes pushed (not zero). + */ +void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len); + +/** + * \brief Flush buffered application data. + * + * If some application data has been buffered in the engine, then wrap + * it into a record and mark it for sending. If no application data has + * been buffered but the engine would be ready to accept some, AND the + * `force` parameter is non-zero, then an empty record is assembled and + * marked for sending. In all other cases, this function does nothing. + * + * Empty records are technically legal, but not all existing SSL/TLS + * implementations support them. Empty records can be useful as a + * transparent "keep-alive" mechanism to maintain some low-level + * network activity. + * + * \param cc SSL engine context. + * \param force non-zero to force sending an empty record. + */ +void br_ssl_engine_flush(br_ssl_engine_context *cc, int force); + +/** + * \brief Initiate a closure. + * + * If, at that point, the context is open and in ready state, then a + * `close_notify` alert is assembled and marked for sending; this + * triggers the closure protocol. Otherwise, no such alert is assembled. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_close(br_ssl_engine_context *cc); + +/** + * \brief Initiate a renegotiation. + * + * If the engine is failed or closed, or if the peer is known not to + * support secure renegotiation (RFC 5746), or if renegotiations have + * been disabled with the `BR_OPT_NO_RENEGOTIATION` flag, or if there + * is buffered incoming application data, then this function returns 0 + * and nothing else happens. + * + * Otherwise, this function returns 1, and a renegotiation attempt is + * triggered (if a handshake is already ongoing at that point, then + * no new handshake is triggered). + * + * \param cc SSL engine context. + * \return 1 on success, 0 on error. + */ +int br_ssl_engine_renegotiate(br_ssl_engine_context *cc); + +/** + * \brief Export key material from a connected SSL engine (RFC 5705). + * + * This calls compute a secret key of arbitrary length from the master + * secret of a connected SSL engine. If the provided context is not + * currently in "application data" state (initial handshake is not + * finished, another handshake is ongoing, or the connection failed or + * was closed), then this function returns 0. Otherwise, a secret key of + * length `len` bytes is computed and written in the buffer pointed to + * by `dst`, and 1 is returned. + * + * The computed key follows the specification described in RFC 5705. + * That RFC includes two key computations, with and without a "context + * value". If `context` is `NULL`, then the variant without context is + * used; otherwise, the `context_len` bytes located at the address + * pointed to by `context` are used in the computation. Note that it + * is possible to have a "with context" key with a context length of + * zero bytes, by setting `context` to a non-`NULL` value but + * `context_len` to 0. + * + * When context bytes are used, the context length MUST NOT exceed + * 65535 bytes. + * + * \param cc SSL engine context. + * \param dst destination buffer for exported key. + * \param len exported key length (in bytes). + * \param label disambiguation label. + * \param context context value (or `NULL`). + * \param context_len context length (in bytes). + * \return 1 on success, 0 on error. + */ +int br_ssl_key_export(br_ssl_engine_context *cc, + void *dst, size_t len, const char *label, + const void *context, size_t context_len); + +/* + * Pre-declaration for the SSL client context. + */ +typedef struct br_ssl_client_context_ br_ssl_client_context; + +/** + * \brief Type for the client certificate, if requested by the server. + */ +typedef struct { + /** + * \brief Authentication type. + * + * This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA` + * (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange). + */ + int auth_type; + + /** + * \brief Hash function for computing the CertificateVerify. + * + * This is the symbolic identifier for the hash function that + * will be used to produce the hash of handshake messages, to + * be signed into the CertificateVerify. For full static ECDH + * (client and server certificates are both EC in the same + * curve, and static ECDH is used), this value is set to -1. + * + * Take care that with TLS 1.0 and 1.1, that value MUST match + * the protocol requirements: value must be 0 (MD5+SHA-1) for + * a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only + * TLS 1.2 allows for other hash functions. + */ + int hash_id; + + /** + * \brief Certificate chain to send to the server. + * + * This is an array of `br_x509_certificate` objects, each + * normally containing a DER-encoded certificate. The client + * code does not try to decode these elements. If there is no + * chain to send to the server, then this pointer shall be + * set to `NULL`. + */ + const br_x509_certificate *chain; + + /** + * \brief Certificate chain length (number of certificates). + * + * If there is no chain to send to the server, then this value + * shall be set to 0. + */ + size_t chain_len; + +} br_ssl_client_certificate; + +/* + * Note: the constants below for signatures match the TLS constants. + */ + +/** \brief Client authentication type: static ECDH. */ +#define BR_AUTH_ECDH 0 +/** \brief Client authentication type: RSA signature. */ +#define BR_AUTH_RSA 1 +/** \brief Client authentication type: ECDSA signature. */ +#define BR_AUTH_ECDSA 3 + +/** + * \brief Class type for a certificate handler (client side). + * + * A certificate handler selects a client certificate chain to send to + * the server, upon explicit request from that server. It receives + * the list of trust anchor DN from the server, and supported types + * of certificates and signatures, and returns the chain to use. It + * is also invoked to perform the corresponding private key operation + * (a signature, or an ECDH computation). + * + * The SSL client engine will first push the trust anchor DN with + * `start_name_list()`, `start_name()`, `append_name()`, `end_name()` + * and `end_name_list()`. Then it will call `choose()`, to select the + * actual chain (and signature/hash algorithms). Finally, it will call + * either `do_sign()` or `do_keyx()`, depending on the algorithm choices. + */ +typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class; +struct br_ssl_client_certificate_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Begin reception of a list of trust anchor names. This + * is called while parsing the incoming CertificateRequest. + * + * \param pctx certificate handler context. + */ + void (*start_name_list)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief Begin reception of a new trust anchor name. + * + * The total encoded name length is provided; it is less than + * 65535 bytes. + * + * \param pctx certificate handler context. + * \param len encoded name length (in bytes). + */ + void (*start_name)(const br_ssl_client_certificate_class **pctx, + size_t len); + + /** + * \brief Receive some more bytes for the current trust anchor name. + * + * The provided reference (`data`) points to a transient buffer + * they may be reused as soon as this function returns. The chunk + * length (`len`) is never zero. + * + * \param pctx certificate handler context. + * \param data anchor name chunk. + * \param len anchor name chunk length (in bytes). + */ + void (*append_name)(const br_ssl_client_certificate_class **pctx, + const unsigned char *data, size_t len); + + /** + * \brief End current trust anchor name. + * + * This function is called when all the encoded anchor name data + * has been provided. + * + * \param pctx certificate handler context. + */ + void (*end_name)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief End list of trust anchor names. + * + * This function is called when all the anchor names in the + * CertificateRequest message have been obtained. + * + * \param pctx certificate handler context. + */ + void (*end_name_list)(const br_ssl_client_certificate_class **pctx); + + /** + * \brief Select client certificate and algorithms. + * + * This callback function shall fill the provided `choices` + * structure with the selected algorithms and certificate chain. + * The `hash_id`, `chain` and `chain_len` fields must be set. If + * the client cannot or does not wish to send a certificate, + * then it shall set `chain` to `NULL` and `chain_len` to 0. + * + * The `auth_types` parameter describes the authentication types, + * signature algorithms and hash functions that are supported by + * both the client context and the server, and compatible with + * the current protocol version. This is a bit field with the + * following contents: + * + * - If RSA signatures with hash function x are supported, then + * bit x is set. + * + * - If ECDSA signatures with hash function x are supported, + * then bit 8+x is set. + * + * - If static ECDH is supported, with a RSA-signed certificate, + * then bit 16 is set. + * + * - If static ECDH is supported, with an ECDSA-signed certificate, + * then bit 17 is set. + * + * Notes: + * + * - When using TLS 1.0 or 1.1, the hash function for RSA + * signatures is always the special MD5+SHA-1 (id 0), and the + * hash function for ECDSA signatures is always SHA-1 (id 2). + * + * - When using TLS 1.2, the list of hash functions is trimmed + * down to include only hash functions that the client context + * can support. The actual server list can be obtained with + * `br_ssl_client_get_server_hashes()`; that list may be used + * to select the certificate chain to send to the server. + * + * \param pctx certificate handler context. + * \param cc SSL client context. + * \param auth_types supported authentication types and algorithms. + * \param choices destination structure for the policy choices. + */ + void (*choose)(const br_ssl_client_certificate_class **pctx, + const br_ssl_client_context *cc, uint32_t auth_types, + br_ssl_client_certificate *choices); + + /** + * \brief Perform key exchange (client part). + * + * This callback is invoked in case of a full static ECDH key + * exchange: + * + * - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`; + * + * - the server requests a client certificate; + * + * - the client has, and sends, a client certificate that + * uses an EC key in the same curve as the server's key, + * and chooses static ECDH (the `hash_id` field in the choice + * structure was set to -1). + * + * In that situation, this callback is invoked to compute the + * client-side ECDH: the provided `data` (of length `*len` bytes) + * is the server's public key point (as decoded from its + * certificate), and the client shall multiply that point with + * its own private key, and write back the X coordinate of the + * resulting point in the same buffer, starting at offset 0. + * The `*len` value shall be modified to designate the actual + * length of the X coordinate. + * + * The callback must uphold the following: + * + * - If the input array does not have the proper length for + * an encoded curve point, then an error (0) shall be reported. + * + * - If the input array has the proper length, then processing + * MUST be constant-time, even if the data is not a valid + * encoded point. + * + * - This callback MUST check that the input point is valid. + * + * Returned value is 1 on success, 0 on error. + * + * \param pctx certificate handler context. + * \param data server public key point. + * \param len public key point length / X coordinate length. + * \return 1 on success, 0 on error. + */ + uint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx, + unsigned char *data, size_t *len); + + /** + * \brief Perform a signature (client authentication). + * + * This callback is invoked when a client certificate was sent, + * and static ECDH is not used. It shall compute a signature, + * using the client's private key, over the provided hash value + * (which is the hash of all previous handshake messages). + * + * On input, the hash value to sign is in `data`, of size + * `hv_len`; the involved hash function is identified by + * `hash_id`. The signature shall be computed and written + * back into `data`; the total size of that buffer is `len` + * bytes. + * + * This callback shall verify that the signature length does not + * exceed `len` bytes, and abstain from writing the signature if + * it does not fit. + * + * For RSA signatures, the `hash_id` may be 0, in which case + * this is the special header-less signature specified in TLS 1.0 + * and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1 + * v1.5 signatures shall be computed. + * + * For ECDSA signatures, the signature value shall use the ASN.1 + * based encoding. + * + * Returned value is the signature length (in bytes), or 0 on error. + * + * \param pctx certificate handler context. + * \param hash_id hash function identifier. + * \param hv_len hash value length (in bytes). + * \param data input/output buffer (hash value, then signature). + * \param len total buffer length (in bytes). + * \return signature length (in bytes) on success, or 0 on error. + */ + size_t (*do_sign)(const br_ssl_client_certificate_class **pctx, + int hash_id, size_t hv_len, unsigned char *data, size_t len); +}; + +/** + * \brief A single-chain RSA client certificate handler. + * + * This handler uses a single certificate chain, with a RSA + * signature. The list of trust anchor DN is ignored. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_client_certificate_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_rsa_private_key *sk; + br_rsa_pkcs1_sign irsasign; +#endif +} br_ssl_client_certificate_rsa_context; + +/** + * \brief A single-chain EC client certificate handler. + * + * This handler uses a single certificate chain, with a RSA + * signature. The list of trust anchor DN is ignored. + * + * This handler may support both static ECDH, and ECDSA signatures + * (either usage may be selectively disabled). + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_client_certificate_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_ec_private_key *sk; + unsigned allowed_usages; + unsigned issuer_key_type; + const br_multihash_context *mhash; + const br_ec_impl *iec; + br_ecdsa_sign iecdsa; +#endif +} br_ssl_client_certificate_ec_context; + +/** + * \brief Context structure for a SSL client. + * + * The first field (called `eng`) is the SSL engine; all functions that + * work on a `br_ssl_engine_context` structure shall take as parameter + * a pointer to that field. The other structure fields are opaque and + * must not be accessed directly. + */ +struct br_ssl_client_context_ { + /** + * \brief The encapsulated engine context. + */ + br_ssl_engine_context eng; + +#ifndef BR_DOXYGEN_IGNORE + /* + * Minimum ClientHello length; padding with an extension (RFC + * 7685) is added if necessary to match at least that length. + * Such padding is nominally unnecessary, but it has been used + * to work around some server implementation bugs. + */ + uint16_t min_clienthello_len; + + /* + * Bit field for algoithms (hash + signature) supported by the + * server when requesting a client certificate. + */ + uint32_t hashes; + + /* + * Server's public key curve. + */ + int server_curve; + + /* + * Context for certificate handler. + */ + const br_ssl_client_certificate_class **client_auth_vtable; + + /* + * Client authentication type. + */ + unsigned char auth_type; + + /* + * Hash function to use for the client signature. This is 0xFF + * if static ECDH is used. + */ + unsigned char hash_id; + + /* + * For the core certificate handlers, thus avoiding (in most + * cases) the need for an externally provided policy context. + */ + union { + const br_ssl_client_certificate_class *vtable; + br_ssl_client_certificate_rsa_context single_rsa; + br_ssl_client_certificate_ec_context single_ec; + } client_auth; + + /* + * Implementations. + */ + br_rsa_public irsapub; +#endif +}; + +/** + * \brief Get the hash functions and signature algorithms supported by + * the server. + * + * This value is a bit field: + * + * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, + * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, + * or 2 to 6 for the SHA family). + * + * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` + * is set. + * + * - Newer algorithms are symbolic 16-bit identifiers that do not + * represent signature algorithm and hash function separately. If + * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 + * range, then bit `16+x` is set. + * + * "New algorithms" are currently defined only in draft documents, so + * this support is subject to possible change. Right now (early 2017), + * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA + * on Curve448) to bit 24. If the identifiers on the wire change in + * future document, then the decoding mechanism in BearSSL will be + * amended to keep mapping ed25519 and ed448 on bits 23 and 24, + * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not + * guaranteed yet. + * + * \param cc client context. + * \return the server-supported hash functions and signature algorithms. + */ +static inline uint32_t +br_ssl_client_get_server_hashes(const br_ssl_client_context *cc) +{ + return cc->hashes; +} + +/** + * \brief Get the server key curve. + * + * This function returns the ID for the curve used by the server's public + * key. This is set when the server's certificate chain is processed; + * this value is 0 if the server's key is not an EC key. + * + * \return the server's public key curve ID, or 0. + */ +static inline int +br_ssl_client_get_server_curve(const br_ssl_client_context *cc) +{ + return cc->server_curve; +} + +/* + * Each br_ssl_client_init_xxx() function sets the list of supported + * cipher suites and used implementations, as specified by the profile + * name 'xxx'. Defined profile names are: + * + * full all supported versions and suites; constant-time implementations + * TODO: add other profiles + */ + +/** + * \brief SSL client profile: full. + * + * This function initialises the provided SSL client context with + * all supported algorithms and cipher suites. It also initialises + * a companion X.509 validation engine with all supported algorithms, + * and the provided trust anchors; the X.509 engine will be used by + * the client context to validate the server's certificate. + * + * \param cc client context to initialise. + * \param xc X.509 validation context to initialise. + * \param trust_anchors trust anchors to use. + * \param trust_anchors_num number of trust anchors. + */ +void br_ssl_client_init_full(br_ssl_client_context *cc, + br_x509_minimal_context *xc, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Clear the complete contents of a SSL client context. + * + * Everything is cleared, including the reference to the configured buffer, + * implementations, cipher suites and state. This is a preparatory step + * to assembling a custom profile. + * + * \param cc client context to clear. + */ +void br_ssl_client_zero(br_ssl_client_context *cc); + +/** + * \brief Set an externally provided client certificate handler context. + * + * The handler's methods are invoked when the server requests a client + * certificate. + * + * \param cc client context. + * \param pctx certificate handler context (pointer to its vtable field). + */ +static inline void +br_ssl_client_set_client_certificate(br_ssl_client_context *cc, + const br_ssl_client_certificate_class **pctx) +{ + cc->client_auth_vtable = pctx; +} + +/** + * \brief Set the RSA public-key operations implementation. + * + * This will be used to encrypt the pre-master secret with the server's + * RSA public key (RSA-encryption cipher suites only). + * + * \param cc client context. + * \param irsapub RSA public-key encryption implementation. + */ +static inline void +br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub) +{ + cc->irsapub = irsapub; +} + +/** + * \brief Set the "default" RSA implementation for public-key operations. + * + * This sets the RSA implementation in the client context (for encrypting + * the pre-master secret, in `TLS_RSA_*` cipher suites) to the fastest + * available on the current platform. + * + * \param cc client context. + */ +void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc); + +/** + * \brief Set the minimum ClientHello length (RFC 7685 padding). + * + * If this value is set and the ClientHello would be shorter, then + * the Pad ClientHello extension will be added with enough padding bytes + * to reach the target size. Because of the extension header, the resulting + * size will sometimes be slightly more than `len` bytes if the target + * size cannot be exactly met. + * + * The target length relates to the _contents_ of the ClientHello, not + * counting its 4-byte header. For instance, if `len` is set to 512, + * then the padding will bring the ClientHello size to 516 bytes with its + * header, and 521 bytes when counting the 5-byte record header. + * + * \param cc client context. + * \param len minimum ClientHello length (in bytes). + */ +static inline void +br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len) +{ + cc->min_clienthello_len = len; +} + +/** + * \brief Prepare or reset a client context for a new connection. + * + * The `server_name` parameter is used to fill the SNI extension; the + * X.509 "minimal" engine will also match that name against the server + * names included in the server's certificate. If the parameter is + * `NULL` then no SNI extension will be sent, and the X.509 "minimal" + * engine (if used for server certificate validation) will not check + * presence of any specific name in the received certificate. + * + * Therefore, setting the `server_name` to `NULL` shall be reserved + * to cases where alternate or additional methods are used to ascertain + * that the right server public key is used (e.g. a "known key" model). + * + * If `resume_session` is non-zero and the context was previously used + * then the session parameters may be reused (depending on whether the + * server previously sent a non-empty session ID, and accepts the session + * resumption). The session parameters for session resumption can also + * be set explicitly with `br_ssl_engine_set_session_parameters()`. + * + * On failure, the context is marked as failed, and this function + * returns 0. A possible failure condition is when no initial entropy + * was injected, and none could be obtained from the OS (either OS + * randomness gathering is not supported, or it failed). + * + * \param cc client context. + * \param server_name target server name, or `NULL`. + * \param resume_session non-zero to try session resumption. + * \return 0 on failure, 1 on success. + */ +int br_ssl_client_reset(br_ssl_client_context *cc, + const char *server_name, int resume_session); + +/** + * \brief Forget any session in the context. + * + * This means that the next handshake that uses this context will + * necessarily be a full handshake (this applies both to new connections + * and to renegotiations). + * + * \param cc client context. + */ +static inline void +br_ssl_client_forget_session(br_ssl_client_context *cc) +{ + cc->eng.session.session_id_len = 0; +} + +/** + * \brief Set client certificate chain and key (single RSA case). + * + * This function sets a client certificate chain, that the client will + * send to the server whenever a client certificate is requested. This + * certificate uses an RSA public key; the corresponding private key is + * invoked for authentication. Trust anchor names sent by the server are + * ignored. + * + * The provided chain and private key are linked in the client context; + * they must remain valid as long as they may be used, i.e. normally + * for the duration of the connection, since they might be invoked + * again upon renegotiations. + * + * \param cc SSL client context. + * \param chain client certificate chain (SSL order: EE comes first). + * \param chain_len client chain length (number of certificates). + * \param sk client private key. + * \param irsasign RSA signature implementation (PKCS#1 v1.5). + */ +void br_ssl_client_set_single_rsa(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign); + +/* + * \brief Set the client certificate chain and key (single EC case). + * + * This function sets a client certificate chain, that the client will + * send to the server whenever a client certificate is requested. This + * certificate uses an EC public key; the corresponding private key is + * invoked for authentication. Trust anchor names sent by the server are + * ignored. + * + * The provided chain and private key are linked in the client context; + * they must remain valid as long as they may be used, i.e. normally + * for the duration of the connection, since they might be invoked + * again upon renegotiations. + * + * The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX` + * value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value + * allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA + * signature implementation must be provided; otherwise, the `iecdsa` + * parameter may be 0. + * + * The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or + * `BR_KEYTYPE_EC`; it is the type of the public key used the the CA + * that issued (signed) the client certificate. That value is used with + * full static ECDH: support of the certificate by the server depends + * on how the certificate was signed. (Note: when using TLS 1.2, this + * parameter is ignored; but its value matters for TLS 1.0 and 1.1.) + * + * \param cc server context. + * \param chain server certificate chain to send. + * \param chain_len chain length (number of certificates). + * \param sk server private key (EC). + * \param allowed_usages allowed private key usages. + * \param cert_issuer_key_type issuing CA's key type. + * \param iec EC core implementation. + * \param iecdsa ECDSA signature implementation ("asn1" format). + */ +void br_ssl_client_set_single_ec(br_ssl_client_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa); + +/** + * \brief Type for a "translated cipher suite", as an array of two + * 16-bit integers. + * + * The first element is the cipher suite identifier (as used on the wire). + * The second element is the concatenation of four 4-bit elements which + * characterise the cipher suite contents. In most to least significant + * order, these 4-bit elements are: + * + * - Bits 12 to 15: key exchange + server key type + * + * | val | symbolic constant | suite type | details | + * | :-- | :----------------------- | :---------- | :----------------------------------------------- | + * | 0 | `BR_SSLKEYX_RSA` | RSA | RSA key exchange, key is RSA (encryption) | + * | 1 | `BR_SSLKEYX_ECDHE_RSA` | ECDHE_RSA | ECDHE key exchange, key is RSA (signature) | + * | 2 | `BR_SSLKEYX_ECDHE_ECDSA` | ECDHE_ECDSA | ECDHE key exchange, key is EC (signature) | + * | 3 | `BR_SSLKEYX_ECDH_RSA` | ECDH_RSA | Key is EC (key exchange), cert signed with RSA | + * | 4 | `BR_SSLKEYX_ECDH_ECDSA` | ECDH_ECDSA | Key is EC (key exchange), cert signed with ECDSA | + * + * - Bits 8 to 11: symmetric encryption algorithm + * + * | val | symbolic constant | symmetric encryption | key strength (bits) | + * | :-- | :--------------------- | :------------------- | :------------------ | + * | 0 | `BR_SSLENC_3DES_CBC` | 3DES/CBC | 168 | + * | 1 | `BR_SSLENC_AES128_CBC` | AES-128/CBC | 128 | + * | 2 | `BR_SSLENC_AES256_CBC` | AES-256/CBC | 256 | + * | 3 | `BR_SSLENC_AES128_GCM` | AES-128/GCM | 128 | + * | 4 | `BR_SSLENC_AES256_GCM` | AES-256/GCM | 256 | + * | 5 | `BR_SSLENC_CHACHA20` | ChaCha20/Poly1305 | 256 | + * + * - Bits 4 to 7: MAC algorithm + * + * | val | symbolic constant | MAC type | details | + * | :-- | :----------------- | :----------- | :------------------------------------ | + * | 0 | `BR_SSLMAC_AEAD` | AEAD | No dedicated MAC (encryption is AEAD) | + * | 2 | `BR_SSLMAC_SHA1` | HMAC/SHA-1 | Value matches `br_sha1_ID` | + * | 4 | `BR_SSLMAC_SHA256` | HMAC/SHA-256 | Value matches `br_sha256_ID` | + * | 5 | `BR_SSLMAC_SHA384` | HMAC/SHA-384 | Value matches `br_sha384_ID` | + * + * - Bits 0 to 3: hash function for PRF when used with TLS-1.2 + * + * | val | symbolic constant | hash function | details | + * | :-- | :----------------- | :------------ | :----------------------------------- | + * | 4 | `BR_SSLPRF_SHA256` | SHA-256 | Value matches `br_sha256_ID` | + * | 5 | `BR_SSLPRF_SHA384` | SHA-384 | Value matches `br_sha384_ID` | + * + * For instance, cipher suite `TLS_RSA_WITH_AES_128_GCM_SHA256` has + * standard identifier 0x009C, and is translated to 0x0304, for, in + * that order: RSA key exchange (0), AES-128/GCM (3), AEAD integrity (0), + * SHA-256 in the TLS PRF (4). + */ +typedef uint16_t br_suite_translated[2]; + +#ifndef BR_DOXYGEN_IGNORE +/* + * Constants are already documented in the br_suite_translated type. + */ + +#define BR_SSLKEYX_RSA 0 +#define BR_SSLKEYX_ECDHE_RSA 1 +#define BR_SSLKEYX_ECDHE_ECDSA 2 +#define BR_SSLKEYX_ECDH_RSA 3 +#define BR_SSLKEYX_ECDH_ECDSA 4 + +#define BR_SSLENC_3DES_CBC 0 +#define BR_SSLENC_AES128_CBC 1 +#define BR_SSLENC_AES256_CBC 2 +#define BR_SSLENC_AES128_GCM 3 +#define BR_SSLENC_AES256_GCM 4 +#define BR_SSLENC_CHACHA20 5 + +#define BR_SSLMAC_AEAD 0 +#define BR_SSLMAC_SHA1 br_sha1_ID +#define BR_SSLMAC_SHA256 br_sha256_ID +#define BR_SSLMAC_SHA384 br_sha384_ID + +#define BR_SSLPRF_SHA256 br_sha256_ID +#define BR_SSLPRF_SHA384 br_sha384_ID + +#endif + +/* + * Pre-declaration for the SSL server context. + */ +typedef struct br_ssl_server_context_ br_ssl_server_context; + +/** + * \brief Type for the server policy choices, taken after analysis of + * the client message (ClientHello). + */ +typedef struct { + /** + * \brief Cipher suite to use with that client. + */ + uint16_t cipher_suite; + + /** + * \brief Hash function or algorithm for signing the ServerKeyExchange. + * + * This parameter is ignored for `TLS_RSA_*` and `TLS_ECDH_*` + * cipher suites; it is used only for `TLS_ECDHE_*` suites, in + * which the server _signs_ the ephemeral EC Diffie-Hellman + * parameters sent to the client. + * + * This identifier must be one of the following values: + * + * - `0xFF00 + id`, where `id` is a hash function identifier + * (0 for MD5+SHA-1, or 2 to 6 for one of the SHA functions); + * + * - a full 16-bit identifier, lower than `0xFF00`. + * + * If the first option is used, then the SSL engine will + * compute the hash of the data that is to be signed, with the + * designated hash function. The `do_sign()` method will be + * invoked with that hash value provided in the the `data` + * buffer. + * + * If the second option is used, then the SSL engine will NOT + * compute a hash on the data; instead, it will provide the + * to-be-signed data itself in `data`, i.e. the concatenation of + * the client random, server random, and encoded ECDH + * parameters. Furthermore, with TLS-1.2 and later, the 16-bit + * identifier will be used "as is" in the protocol, in the + * SignatureAndHashAlgorithm; for instance, `0x0401` stands for + * RSA PKCS#1 v1.5 signature (the `01`) with SHA-256 as hash + * function (the `04`). + * + * Take care that with TLS 1.0 and 1.1, the hash function is + * constrainted by the protocol: RSA signature must use + * MD5+SHA-1 (so use `0xFF00`), while ECDSA must use SHA-1 + * (`0xFF02`). Since TLS 1.0 and 1.1 don't include a + * SignatureAndHashAlgorithm field in their ServerKeyExchange + * messages, any value below `0xFF00` will be usable to send the + * raw ServerKeyExchange data to the `do_sign()` callback, but + * that callback must still follow the protocol requirements + * when generating the signature. + */ + unsigned algo_id; + + /** + * \brief Certificate chain to send to the client. + * + * This is an array of `br_x509_certificate` objects, each + * normally containing a DER-encoded certificate. The server + * code does not try to decode these elements. + */ + const br_x509_certificate *chain; + + /** + * \brief Certificate chain length (number of certificates). + */ + size_t chain_len; + +} br_ssl_server_choices; + +/** + * \brief Class type for a policy handler (server side). + * + * A policy handler selects the policy parameters for a connection + * (cipher suite and other algorithms, and certificate chain to send to + * the client); it also performs the server-side computations involving + * its permanent private key. + * + * The SSL server engine will invoke first `choose()`, once the + * ClientHello message has been received, then either `do_keyx()` + * `do_sign()`, depending on the cipher suite. + */ +typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class; +struct br_ssl_server_policy_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Select algorithms and certificates for this connection. + * + * This callback function shall fill the provided `choices` + * structure with the policy choices for this connection. This + * entails selecting the cipher suite, hash function for signing + * the ServerKeyExchange (applicable only to ECDHE cipher suites), + * and certificate chain to send. + * + * The callback receives a pointer to the server context that + * contains the relevant data. In particular, the functions + * `br_ssl_server_get_client_suites()`, + * `br_ssl_server_get_client_hashes()` and + * `br_ssl_server_get_client_curves()` can be used to obtain + * the cipher suites, hash functions and elliptic curves + * supported by both the client and server, respectively. The + * `br_ssl_engine_get_version()` and `br_ssl_engine_get_server_name()` + * functions yield the protocol version and requested server name + * (SNI), respectively. + * + * This function may modify its context structure (`pctx`) in + * arbitrary ways to keep track of its own choices. + * + * This function shall return 1 if appropriate policy choices + * could be made, or 0 if this connection cannot be pursued. + * + * \param pctx policy context. + * \param cc SSL server context. + * \param choices destination structure for the policy choices. + * \return 1 on success, 0 on error. + */ + int (*choose)(const br_ssl_server_policy_class **pctx, + const br_ssl_server_context *cc, + br_ssl_server_choices *choices); + + /** + * \brief Perform key exchange (server part). + * + * This callback is invoked to perform the server-side cryptographic + * operation for a key exchange that is not ECDHE. This callback + * uses the private key. + * + * **For RSA key exchange**, the provided `data` (of length `*len` + * bytes) shall be decrypted with the server's private key, and + * the 48-byte premaster secret copied back to the first 48 bytes + * of `data`. + * + * - The caller makes sure that `*len` is at least 59 bytes. + * + * - This callback MUST check that the provided length matches + * that of the key modulus; it shall report an error otherwise. + * + * - If the length matches that of the RSA key modulus, then + * processing MUST be constant-time, even if decryption fails, + * or the padding is incorrect, or the plaintext message length + * is not exactly 48 bytes. + * + * - This callback needs not check the two first bytes of the + * obtained pre-master secret (the caller will do that). + * + * - If an error is reported (0), then what the callback put + * in the first 48 bytes of `data` is unimportant (the caller + * will use random bytes instead). + * + * **For ECDH key exchange**, the provided `data` (of length `*len` + * bytes) is the elliptic curve point from the client. The + * callback shall multiply it with its private key, and store + * the resulting X coordinate in `data`, starting at offset 0, + * and set `*len` to the length of the X coordinate. + * + * - If the input array does not have the proper length for + * an encoded curve point, then an error (0) shall be reported. + * + * - If the input array has the proper length, then processing + * MUST be constant-time, even if the data is not a valid + * encoded point. + * + * - This callback MUST check that the input point is valid. + * + * Returned value is 1 on success, 0 on error. + * + * \param pctx policy context. + * \param data key exchange data from the client. + * \param len key exchange data length (in bytes). + * \return 1 on success, 0 on error. + */ + uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx, + unsigned char *data, size_t *len); + + /** + * \brief Perform a signature (for a ServerKeyExchange message). + * + * This callback function is invoked for ECDHE cipher suites. On + * input, the hash value or message to sign is in `data`, of + * size `hv_len`; the involved hash function or algorithm is + * identified by `algo_id`. The signature shall be computed and + * written back into `data`; the total size of that buffer is + * `len` bytes. + * + * This callback shall verify that the signature length does not + * exceed `len` bytes, and abstain from writing the signature if + * it does not fit. + * + * The `algo_id` value matches that which was written in the + * `choices` structures by the `choose()` callback. This will be + * one of the following: + * + * - `0xFF00 + id` for a hash function identifier `id`. In + * that case, the `data` buffer contains a hash value + * already computed over the data that is to be signed, + * of length `hv_len`. The `id` may be 0 to designate the + * special MD5+SHA-1 concatenation (old-style RSA signing). + * + * - Another value, lower than `0xFF00`. The `data` buffer + * then contains the raw, non-hashed data to be signed + * (concatenation of the client and server randoms and + * ECDH parameters). The callback is responsible to apply + * any relevant hashing as part of the signing process. + * + * Returned value is the signature length (in bytes), or 0 on error. + * + * \param pctx policy context. + * \param algo_id hash function / algorithm identifier. + * \param data input/output buffer (message/hash, then signature). + * \param hv_len hash value or message length (in bytes). + * \param len total buffer length (in bytes). + * \return signature length (in bytes) on success, or 0 on error. + */ + size_t (*do_sign)(const br_ssl_server_policy_class **pctx, + unsigned algo_id, + unsigned char *data, size_t hv_len, size_t len); +}; + +/** + * \brief A single-chain RSA policy handler. + * + * This policy context uses a single certificate chain, and a RSA + * private key. The context can be restricted to only signatures or + * only key exchange. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_server_policy_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_rsa_private_key *sk; + unsigned allowed_usages; + br_rsa_private irsacore; + br_rsa_pkcs1_sign irsasign; +#endif +} br_ssl_server_policy_rsa_context; + +/** + * \brief A single-chain EC policy handler. + * + * This policy context uses a single certificate chain, and an EC + * private key. The context can be restricted to only signatures or + * only key exchange. + * + * Due to how TLS is defined, this context must be made aware whether + * the server certificate was itself signed with RSA or ECDSA. The code + * does not try to decode the certificate to obtain that information. + * + * Apart from the first field (vtable pointer), its contents are + * opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_server_policy_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + const br_x509_certificate *chain; + size_t chain_len; + const br_ec_private_key *sk; + unsigned allowed_usages; + unsigned cert_issuer_key_type; + const br_multihash_context *mhash; + const br_ec_impl *iec; + br_ecdsa_sign iecdsa; +#endif +} br_ssl_server_policy_ec_context; + +/** + * \brief Class type for a session parameter cache. + * + * Session parameters are saved in the cache with `save()`, and + * retrieved with `load()`. The cache implementation can apply any + * storage and eviction strategy that it sees fit. The SSL server + * context that performs the request is provided, so that its + * functionalities may be used by the implementation (e.g. hash + * functions or random number generation). + */ +typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class; +struct br_ssl_session_cache_class_ { + /** + * \brief Context size (in bytes). + */ + size_t context_size; + + /** + * \brief Record a session. + * + * This callback should record the provided session parameters. + * The `params` structure is transient, so its contents shall + * be copied into the cache. The session ID has been randomly + * generated and always has length exactly 32 bytes. + * + * \param ctx session cache context. + * \param server_ctx SSL server context. + * \param params session parameters to save. + */ + void (*save)(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + const br_ssl_session_parameters *params); + + /** + * \brief Lookup a session in the cache. + * + * The session ID to lookup is in `params` and always has length + * exactly 32 bytes. If the session parameters are found in the + * cache, then the parameters shall be copied into the `params` + * structure. Returned value is 1 on successful lookup, 0 + * otherwise. + * + * \param ctx session cache context. + * \param server_ctx SSL server context. + * \param params destination for session parameters. + * \return 1 if found, 0 otherwise. + */ + int (*load)(const br_ssl_session_cache_class **ctx, + br_ssl_server_context *server_ctx, + br_ssl_session_parameters *params); +}; + +/** + * \brief Context for a basic cache system. + * + * The system stores session parameters in a buffer provided at + * initialisation time. Each entry uses exactly 100 bytes, and + * buffer sizes up to 4294967295 bytes are supported. + * + * Entries are evicted with a LRU (Least Recently Used) policy. A + * search tree is maintained to keep lookups fast even with large + * caches. + * + * Apart from the first field (vtable pointer), the structure + * contents are opaque and shall not be accessed directly. + */ +typedef struct { + /** \brief Pointer to vtable. */ + const br_ssl_session_cache_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + unsigned char *store; + size_t store_len, store_ptr; + unsigned char index_key[32]; + const br_hash_class *hash; + int init_done; + uint32_t head, tail, root; +#endif +} br_ssl_session_cache_lru; + +/** + * \brief Initialise a LRU session cache with the provided storage space. + * + * The provided storage space must remain valid as long as the cache + * is used. Arbitrary lengths are supported, up to 4294967295 bytes; + * each entry uses up exactly 100 bytes. + * + * \param cc session cache context. + * \param store storage space for cached entries. + * \param store_len storage space length (in bytes). + */ +void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc, + unsigned char *store, size_t store_len); + +/** + * \brief Forget an entry in an LRU session cache. + * + * The session cache context must have been initialised. The entry + * with the provided session ID (of exactly 32 bytes) is looked for + * in the cache; if located, it is disabled. + * + * \param cc session cache context. + * \param id session ID to forget. + */ +void br_ssl_session_cache_lru_forget( + br_ssl_session_cache_lru *cc, const unsigned char *id); + +/** + * \brief Context structure for a SSL server. + * + * The first field (called `eng`) is the SSL engine; all functions that + * work on a `br_ssl_engine_context` structure shall take as parameter + * a pointer to that field. The other structure fields are opaque and + * must not be accessed directly. + */ +struct br_ssl_server_context_ { + /** + * \brief The encapsulated engine context. + */ + br_ssl_engine_context eng; + +#ifndef BR_DOXYGEN_IGNORE + /* + * Maximum version from the client. + */ + uint16_t client_max_version; + + /* + * Session cache. + */ + const br_ssl_session_cache_class **cache_vtable; + + /* + * Translated cipher suites supported by the client. The list + * is trimmed to include only the cipher suites that the + * server also supports; they are in the same order as in the + * client message. + */ + br_suite_translated client_suites[BR_MAX_CIPHER_SUITES]; + unsigned char client_suites_num; + + /* + * Hash functions supported by the client, with ECDSA and RSA + * (bit mask). For hash function with id 'x', set bit index is + * x for RSA, x+8 for ECDSA. For newer algorithms, with ID + * 0x08**, bit 16+k is set for algorithm 0x0800+k. + */ + uint32_t hashes; + + /* + * Curves supported by the client (bit mask, for named curves). + */ + uint32_t curves; + + /* + * Context for chain handler. + */ + const br_ssl_server_policy_class **policy_vtable; + uint16_t sign_hash_id; + + /* + * For the core handlers, thus avoiding (in most cases) the + * need for an externally provided policy context. + */ + union { + const br_ssl_server_policy_class *vtable; + br_ssl_server_policy_rsa_context single_rsa; + br_ssl_server_policy_ec_context single_ec; + } chain_handler; + + /* + * Buffer for the ECDHE private key. + */ + unsigned char ecdhe_key[70]; + size_t ecdhe_key_len; + + /* + * Trust anchor names for client authentication. "ta_names" and + * "tas" cannot be both non-NULL. + */ + const br_x500_name *ta_names; + const br_x509_trust_anchor *tas; + size_t num_tas; + size_t cur_dn_index; + const unsigned char *cur_dn; + size_t cur_dn_len; + + /* + * Buffer for the hash value computed over all handshake messages + * prior to CertificateVerify, and identifier for the hash function. + */ + unsigned char hash_CV[64]; + size_t hash_CV_len; + int hash_CV_id; + + /* + * Server-specific implementations. + * (none for now) + */ +#endif +}; + +/* + * Each br_ssl_server_init_xxx() function sets the list of supported + * cipher suites and used implementations, as specified by the profile + * name 'xxx'. Defined profile names are: + * + * full_rsa all supported algorithm, server key type is RSA + * full_ec all supported algorithm, server key type is EC + * TODO: add other profiles + * + * Naming scheme for "minimal" profiles: min123 + * + * -- character 1: key exchange + * r = RSA + * e = ECDHE_RSA + * f = ECDHE_ECDSA + * u = ECDH_RSA + * v = ECDH_ECDSA + * -- character 2: version / PRF + * 0 = TLS 1.0 / 1.1 with MD5+SHA-1 + * 2 = TLS 1.2 with SHA-256 + * 3 = TLS 1.2 with SHA-384 + * -- character 3: encryption + * a = AES/CBC + * d = 3DES/CBC + * g = AES/GCM + * c = ChaCha20+Poly1305 + */ + +/** + * \brief SSL server profile: full_rsa. + * + * This function initialises the provided SSL server context with + * all supported algorithms and cipher suites that rely on a RSA + * key pair. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_full_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: full_ec. + * + * This function initialises the provided SSL server context with + * all supported algorithms and cipher suites that rely on an EC + * key pair. + * + * The key type of the CA that issued the server's certificate must + * be provided, since it matters for ECDH cipher suites (ECDH_RSA + * suites require a RSA-powered CA). The key type is either + * `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len chain length (number of certificates). + * \param cert_issuer_key_type certificate issuer's key type. + * \param sk EC private key. + */ +void br_ssl_server_init_full_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + unsigned cert_issuer_key_type, const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minr2g. + * + * This profile uses only TLS_RSA_WITH_AES_128_GCM_SHA256. Server key is + * RSA, and RSA key exchange is used (not forward secure, but uses little + * CPU in the client). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_minr2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: mine2g. + * + * This profile uses only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Server key + * is RSA, and ECDHE key exchange is used. This suite provides forward + * security, with a higher CPU expense on the client, and a somewhat + * larger code footprint (compared to "minr2g"). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_mine2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: minf2g. + * + * This profile uses only TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDHE key exchange is used. This suite provides + * forward security, with a higher CPU expense on the client and server + * (by a factor of about 3 to 4), and a somewhat larger code footprint + * (compared to "minu2g" and "minv2g"). + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minf2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minu2g. + * + * This profile uses only TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDH key exchange is used; the issuing CA used + * a RSA key. + * + * The "minu2g" and "minv2g" profiles do not provide forward secrecy, + * but are the lightest on the server (for CPU usage), and are rather + * inexpensive on the client as well. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minu2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: minv2g. + * + * This profile uses only TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256. + * Server key is EC, and ECDH key exchange is used; the issuing CA used + * an EC key. + * + * The "minu2g" and "minv2g" profiles do not provide forward secrecy, + * but are the lightest on the server (for CPU usage), and are rather + * inexpensive on the client as well. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minv2g(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief SSL server profile: mine2c. + * + * This profile uses only TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256. + * Server key is RSA, and ECDHE key exchange is used. This suite + * provides forward security. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk RSA private key. + */ +void br_ssl_server_init_mine2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk); + +/** + * \brief SSL server profile: minf2c. + * + * This profile uses only TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256. + * Server key is EC, and ECDHE key exchange is used. This suite provides + * forward security. + * + * \param cc server context to initialise. + * \param chain server certificate chain. + * \param chain_len certificate chain length (number of certificate). + * \param sk EC private key. + */ +void br_ssl_server_init_minf2c(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk); + +/** + * \brief Get the supported client suites. + * + * This function shall be called only after the ClientHello has been + * processed, typically from the policy engine. The returned array + * contains the cipher suites that are supported by both the client + * and the server; these suites are in client preference order, unless + * the `BR_OPT_ENFORCE_SERVER_PREFERENCES` flag was set, in which case + * they are in server preference order. + * + * The suites are _translated_, which means that each suite is given + * as two 16-bit integers: the standard suite identifier, and its + * translated version, broken down into its individual components, + * as explained with the `br_suite_translated` type. + * + * The returned array is allocated in the context and will be rewritten + * by each handshake. + * + * \param cc server context. + * \param num receives the array size (number of suites). + * \return the translated common cipher suites, in preference order. + */ +static inline const br_suite_translated * +br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num) +{ + *num = cc->client_suites_num; + return cc->client_suites; +} + +/** + * \brief Get the hash functions and signature algorithms supported by + * the client. + * + * This value is a bit field: + * + * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, + * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, + * or 2 to 6 for the SHA family). + * + * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` + * is set. + * + * - Newer algorithms are symbolic 16-bit identifiers that do not + * represent signature algorithm and hash function separately. If + * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 + * range, then bit `16+x` is set. + * + * "New algorithms" are currently defined only in draft documents, so + * this support is subject to possible change. Right now (early 2017), + * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA + * on Curve448) to bit 24. If the identifiers on the wire change in + * future document, then the decoding mechanism in BearSSL will be + * amended to keep mapping ed25519 and ed448 on bits 23 and 24, + * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not + * guaranteed yet. + * + * \param cc server context. + * \return the client-supported hash functions and signature algorithms. + */ +static inline uint32_t +br_ssl_server_get_client_hashes(const br_ssl_server_context *cc) +{ + return cc->hashes; +} + +/** + * \brief Get the elliptic curves supported by the client. + * + * This is a bit field (bit x is set if curve of ID x is supported). + * + * \param cc server context. + * \return the client-supported elliptic curves. + */ +static inline uint32_t +br_ssl_server_get_client_curves(const br_ssl_server_context *cc) +{ + return cc->curves; +} + +/** + * \brief Clear the complete contents of a SSL server context. + * + * Everything is cleared, including the reference to the configured buffer, + * implementations, cipher suites and state. This is a preparatory step + * to assembling a custom profile. + * + * \param cc server context to clear. + */ +void br_ssl_server_zero(br_ssl_server_context *cc); + +/** + * \brief Set an externally provided policy context. + * + * The policy context's methods are invoked to decide the cipher suite + * and certificate chain, and to perform operations involving the server's + * private key. + * + * \param cc server context. + * \param pctx policy context (pointer to its vtable field). + */ +static inline void +br_ssl_server_set_policy(br_ssl_server_context *cc, + const br_ssl_server_policy_class **pctx) +{ + cc->policy_vtable = pctx; +} + +/** + * \brief Set the server certificate chain and key (single RSA case). + * + * This function uses a policy context included in the server context. + * It configures use of a single server certificate chain with a RSA + * private key. The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables + * the corresponding cipher suites (i.e. `TLS_RSA_*` use the RSA key for + * key exchange, while `TLS_ECDHE_RSA_*` use the RSA key for signatures). + * + * \param cc server context. + * \param chain server certificate chain to send to the client. + * \param chain_len chain length (number of certificates). + * \param sk server private key (RSA). + * \param allowed_usages allowed private key usages. + * \param irsacore RSA core implementation. + * \param irsasign RSA signature implementation (PKCS#1 v1.5). + */ +void br_ssl_server_set_single_rsa(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_rsa_private_key *sk, unsigned allowed_usages, + br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign); + +/** + * \brief Set the server certificate chain and key (single EC case). + * + * This function uses a policy context included in the server context. + * It configures use of a single server certificate chain with an EC + * private key. The `allowed_usages` is a combination of usages, namely + * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables + * the corresponding cipher suites (i.e. `TLS_ECDH_*` use the EC key for + * key exchange, while `TLS_ECDHE_ECDSA_*` use the EC key for signatures). + * + * In order to support `TLS_ECDH_*` cipher suites (non-ephemeral ECDH), + * the algorithm type of the key used by the issuing CA to sign the + * server's certificate must be provided, as `cert_issuer_key_type` + * parameter (this value is either `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`). + * + * \param cc server context. + * \param chain server certificate chain to send. + * \param chain_len chain length (number of certificates). + * \param sk server private key (EC). + * \param allowed_usages allowed private key usages. + * \param cert_issuer_key_type issuing CA's key type. + * \param iec EC core implementation. + * \param iecdsa ECDSA signature implementation ("asn1" format). + */ +void br_ssl_server_set_single_ec(br_ssl_server_context *cc, + const br_x509_certificate *chain, size_t chain_len, + const br_ec_private_key *sk, unsigned allowed_usages, + unsigned cert_issuer_key_type, + const br_ec_impl *iec, br_ecdsa_sign iecdsa); + +/** + * \brief Activate client certificate authentication. + * + * The trust anchor encoded X.500 names (DN) to send to the client are + * provided. A client certificate will be requested and validated through + * the X.509 validator configured in the SSL engine. If `num` is 0, then + * client certificate authentication is disabled. + * + * If the client does not send a certificate, or on validation failure, + * the handshake aborts. Unauthenticated clients can be tolerated by + * setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag. + * + * The provided array is linked in, not copied, so that pointer must + * remain valid as long as anchor names may be used. + * + * \param cc server context. + * \param ta_names encoded trust anchor names. + * \param num number of encoded trust anchor names. + */ +static inline void +br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc, + const br_x500_name *ta_names, size_t num) +{ + cc->ta_names = ta_names; + cc->tas = NULL; + cc->num_tas = num; +} + +/** + * \brief Activate client certificate authentication. + * + * This is a variant for `br_ssl_server_set_trust_anchor_names()`: the + * trust anchor names are provided not as an array of stand-alone names + * (`br_x500_name` structures), but as an array of trust anchors + * (`br_x509_trust_anchor` structures). The server engine itself will + * only use the `dn` field of each trust anchor. This is meant to allow + * defining a single array of trust anchors, to be used here and in the + * X.509 validation engine itself. + * + * The provided array is linked in, not copied, so that pointer must + * remain valid as long as anchor names may be used. + * + * \param cc server context. + * \param tas trust anchors (only names are used). + * \param num number of trust anchors. + */ +static inline void +br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc, + const br_x509_trust_anchor *tas, size_t num) +{ + cc->ta_names = NULL; + cc->tas = tas; + cc->num_tas = num; +} + +/** + * \brief Configure the cache for session parameters. + * + * The cache context is provided as a pointer to its first field (vtable + * pointer). + * + * \param cc server context. + * \param vtable session cache context. + */ +static inline void +br_ssl_server_set_cache(br_ssl_server_context *cc, + const br_ssl_session_cache_class **vtable) +{ + cc->cache_vtable = vtable; +} + +/** + * \brief Prepare or reset a server context for handling an incoming client. + * + * \param cc server context. + * \return 1 on success, 0 on error. + */ +int br_ssl_server_reset(br_ssl_server_context *cc); + +/* ===================================================================== */ + +/* + * Context for the simplified I/O context. The transport medium is accessed + * through the low_read() and low_write() callback functions, each with + * its own opaque context pointer. + * + * low_read() read some bytes, at most 'len' bytes, into data[]. The + * returned value is the number of read bytes, or -1 on error. + * The 'len' parameter is guaranteed never to exceed 20000, + * so the length always fits in an 'int' on all platforms. + * + * low_write() write up to 'len' bytes, to be read from data[]. The + * returned value is the number of written bytes, or -1 on + * error. The 'len' parameter is guaranteed never to exceed + * 20000, so the length always fits in an 'int' on all + * parameters. + * + * A socket closure (if the transport medium is a socket) should be reported + * as an error (-1). The callbacks shall endeavour to block until at least + * one byte can be read or written; a callback returning 0 at times is + * acceptable, but this normally leads to the callback being immediately + * called again, so the callback should at least always try to block for + * some time if no I/O can take place. + * + * The SSL engine naturally applies some buffering, so the callbacks need + * not apply buffers of their own. + */ +/** + * \brief Context structure for the simplified SSL I/O wrapper. + * + * This structure is initialised with `br_sslio_init()`. Its contents + * are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + br_ssl_engine_context *engine; + int (*low_read)(void *read_context, + unsigned char *data, size_t len); + void *read_context; + int (*low_write)(void *write_context, + const unsigned char *data, size_t len); + void *write_context; +#endif +} br_sslio_context; + +/** + * \brief Initialise a simplified I/O wrapper context. + * + * The simplified I/O wrapper offers a simpler read/write API for a SSL + * engine (client or server), using the provided callback functions for + * reading data from, or writing data to, the transport medium. + * + * The callback functions have the following semantics: + * + * - Each callback receives an opaque context value (of type `void *`) + * that the callback may use arbitrarily (or possibly ignore). + * + * - `low_read()` reads at least one byte, at most `len` bytes, from + * the transport medium. Read bytes shall be written in `data`. + * + * - `low_write()` writes at least one byte, at most `len` bytes, unto + * the transport medium. The bytes to write are read from `data`. + * + * - The `len` parameter is never zero, and is always lower than 20000. + * + * - The number of processed bytes (read or written) is returned. Since + * that number is less than 20000, it always fits on an `int`. + * + * - On error, the callbacks return -1. Reaching end-of-stream is an + * error. Errors are permanent: the SSL connection is terminated. + * + * - Callbacks SHOULD NOT return 0. This is tolerated, as long as + * callbacks endeavour to block for some non-negligible amount of + * time until at least one byte can be sent or received (if a + * callback returns 0, then the wrapper invokes it again + * immediately). + * + * - Callbacks MAY return as soon as at least one byte is processed; + * they MAY also insist on reading or writing _all_ requested bytes. + * Since SSL is a self-terminated protocol (each record has a length + * header), this does not change semantics. + * + * - Callbacks need not apply any buffering (for performance) since SSL + * itself uses buffers. + * + * \param ctx wrapper context to initialise. + * \param engine SSL engine to wrap. + * \param low_read callback for reading data from the transport. + * \param read_context context pointer for `low_read()`. + * \param low_write callback for writing data on the transport. + * \param write_context context pointer for `low_write()`. + */ +void br_sslio_init(br_sslio_context *ctx, + br_ssl_engine_context *engine, + int (*low_read)(void *read_context, + unsigned char *data, size_t len), + void *read_context, + int (*low_write)(void *write_context, + const unsigned char *data, size_t len), + void *write_context); + +/** + * \brief Read some application data from a SSL connection. + * + * If `len` is zero, then this function returns 0 immediately. In + * all other cases, it never returns 0. + * + * This call returns only when at least one byte has been obtained. + * Returned value is the number of bytes read, or -1 on error. The + * number of bytes always fits on an 'int' (data from a single SSL/TLS + * record is returned). + * + * On error or SSL closure, this function returns -1. The caller should + * inspect the error status on the SSL engine to distinguish between + * normal closure and error. + * + * \param cc SSL wrapper context. + * \param dst destination buffer for application data. + * \param len maximum number of bytes to obtain. + * \return number of bytes obtained, or -1 on error. + */ +int br_sslio_read(br_sslio_context *cc, void *dst, size_t len); + +/** + * \brief Read application data from a SSL connection. + * + * This calls returns only when _all_ requested `len` bytes are read, + * or an error is reached. Returned value is 0 on success, -1 on error. + * A normal (verified) SSL closure before that many bytes are obtained + * is reported as an error by this function. + * + * \param cc SSL wrapper context. + * \param dst destination buffer for application data. + * \param len number of bytes to obtain. + * \return 0 on success, or -1 on error. + */ +int br_sslio_read_all(br_sslio_context *cc, void *dst, size_t len); + +/** + * \brief Write some application data unto a SSL connection. + * + * If `len` is zero, then this function returns 0 immediately. In + * all other cases, it never returns 0. + * + * This call returns only when at least one byte has been written. + * Returned value is the number of bytes written, or -1 on error. The + * number of bytes always fits on an 'int' (less than 20000). + * + * On error or SSL closure, this function returns -1. The caller should + * inspect the error status on the SSL engine to distinguish between + * normal closure and error. + * + * **Important:** SSL is buffered; a "written" byte is a byte that was + * injected into the wrapped SSL engine, but this does not necessarily mean + * that it has been scheduled for sending. Use `br_sslio_flush()` to + * ensure that all pending data has been sent to the transport medium. + * + * \param cc SSL wrapper context. + * \param src source buffer for application data. + * \param len maximum number of bytes to write. + * \return number of bytes written, or -1 on error. + */ +int br_sslio_write(br_sslio_context *cc, const void *src, size_t len); + +/** + * \brief Write application data unto a SSL connection. + * + * This calls returns only when _all_ requested `len` bytes have been + * written, or an error is reached. Returned value is 0 on success, -1 + * on error. A normal (verified) SSL closure before that many bytes are + * written is reported as an error by this function. + * + * **Important:** SSL is buffered; a "written" byte is a byte that was + * injected into the wrapped SSL engine, but this does not necessarily mean + * that it has been scheduled for sending. Use `br_sslio_flush()` to + * ensure that all pending data has been sent to the transport medium. + * + * \param cc SSL wrapper context. + * \param src source buffer for application data. + * \param len number of bytes to write. + * \return 0 on success, or -1 on error. + */ +int br_sslio_write_all(br_sslio_context *cc, const void *src, size_t len); + +/** + * \brief Flush pending data. + * + * This call makes sure that any buffered application data in the + * provided context (including the wrapped SSL engine) has been sent + * to the transport medium (i.e. accepted by the `low_write()` callback + * method). If there is no such pending data, then this function does + * nothing (and returns a success, i.e. 0). + * + * If the underlying transport medium has its own buffers, then it is + * up to the caller to ensure the corresponding flushing. + * + * Returned value is 0 on success, -1 on error. + * + * \param cc SSL wrapper context. + * \return 0 on success, or -1 on error. + */ +int br_sslio_flush(br_sslio_context *cc); + +/** + * \brief Close the SSL connection. + * + * This call runs the SSL closure protocol (sending a `close_notify`, + * receiving the response `close_notify`). When it returns, the SSL + * connection is finished. It is still up to the caller to manage the + * possible transport-level termination, if applicable (alternatively, + * the underlying transport stream may be reused for non-SSL messages). + * + * Returned value is 0 on success, -1 on error. A failure by the peer + * to process the complete closure protocol (i.e. sending back the + * `close_notify`) is an error. + * + * \param cc SSL wrapper context. + * \return 0 on success, or -1 on error. + */ +int br_sslio_close(br_sslio_context *cc); + +/* ===================================================================== */ + +/* + * Symbolic constants for cipher suites. + */ + +/* From RFC 5246 */ +#define BR_TLS_NULL_WITH_NULL_NULL 0x0000 +#define BR_TLS_RSA_WITH_NULL_MD5 0x0001 +#define BR_TLS_RSA_WITH_NULL_SHA 0x0002 +#define BR_TLS_RSA_WITH_NULL_SHA256 0x003B +#define BR_TLS_RSA_WITH_RC4_128_MD5 0x0004 +#define BR_TLS_RSA_WITH_RC4_128_SHA 0x0005 +#define BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A +#define BR_TLS_RSA_WITH_AES_128_CBC_SHA 0x002F +#define BR_TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 +#define BR_TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C +#define BR_TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D +#define BR_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D +#define BR_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010 +#define BR_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013 +#define BR_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 +#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030 +#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031 +#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032 +#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 +#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036 +#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037 +#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 +#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 +#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E +#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F +#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040 +#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 +#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068 +#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069 +#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A +#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B +#define BR_TLS_DH_anon_WITH_RC4_128_MD5 0x0018 +#define BR_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B +#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 +#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A +#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C +#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D + +/* From RFC 4492 */ +#define BR_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 +#define BR_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 +#define BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 +#define BR_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 +#define BR_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 +#define BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A +#define BR_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B +#define BR_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C +#define BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D +#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E +#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F +#define BR_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 +#define BR_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 +#define BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 +#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 +#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 +#define BR_TLS_ECDH_anon_WITH_NULL_SHA 0xC015 +#define BR_TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016 +#define BR_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017 +#define BR_TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018 +#define BR_TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019 + +/* From RFC 5288 */ +#define BR_TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C +#define BR_TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D +#define BR_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E +#define BR_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F +#define BR_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0 +#define BR_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1 +#define BR_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2 +#define BR_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3 +#define BR_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4 +#define BR_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5 +#define BR_TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6 +#define BR_TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7 + +/* From RFC 5289 */ +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 +#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 +#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 +#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 +#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C +#define BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D +#define BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E +#define BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F +#define BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 +#define BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 +#define BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 + +/* From RFC 6655 and 7251 */ +#define BR_TLS_RSA_WITH_AES_128_CCM 0xC09C +#define BR_TLS_RSA_WITH_AES_256_CCM 0xC09D +#define BR_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 +#define BR_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD +#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE +#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF + +/* From RFC 7905 */ +#define BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 +#define BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 +#define BR_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA +#define BR_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB +#define BR_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC +#define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD +#define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE + +/* From RFC 7507 */ +#define BR_TLS_FALLBACK_SCSV 0x5600 + +/* + * Symbolic constants for alerts. + */ +#define BR_ALERT_CLOSE_NOTIFY 0 +#define BR_ALERT_UNEXPECTED_MESSAGE 10 +#define BR_ALERT_BAD_RECORD_MAC 20 +#define BR_ALERT_RECORD_OVERFLOW 22 +#define BR_ALERT_DECOMPRESSION_FAILURE 30 +#define BR_ALERT_HANDSHAKE_FAILURE 40 +#define BR_ALERT_BAD_CERTIFICATE 42 +#define BR_ALERT_UNSUPPORTED_CERTIFICATE 43 +#define BR_ALERT_CERTIFICATE_REVOKED 44 +#define BR_ALERT_CERTIFICATE_EXPIRED 45 +#define BR_ALERT_CERTIFICATE_UNKNOWN 46 +#define BR_ALERT_ILLEGAL_PARAMETER 47 +#define BR_ALERT_UNKNOWN_CA 48 +#define BR_ALERT_ACCESS_DENIED 49 +#define BR_ALERT_DECODE_ERROR 50 +#define BR_ALERT_DECRYPT_ERROR 51 +#define BR_ALERT_PROTOCOL_VERSION 70 +#define BR_ALERT_INSUFFICIENT_SECURITY 71 +#define BR_ALERT_INTERNAL_ERROR 80 +#define BR_ALERT_USER_CANCELED 90 +#define BR_ALERT_NO_RENEGOTIATION 100 +#define BR_ALERT_UNSUPPORTED_EXTENSION 110 +#define BR_ALERT_NO_APPLICATION_PROTOCOL 120 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/bearssl/bearssl_x509.h b/include/bearssl/bearssl_x509.h new file mode 100644 index 000000000..f2f6e6f87 --- /dev/null +++ b/include/bearssl/bearssl_x509.h @@ -0,0 +1,1592 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef BR_BEARSSL_X509_H__ +#define BR_BEARSSL_X509_H__ + +#include +#include + +#include "bearssl_ec.h" +#include "bearssl_hash.h" +#include "bearssl_rsa.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file bearssl_x509.h + * + * # X.509 Certificate Chain Processing + * + * An X.509 processing engine receives an X.509 chain, chunk by chunk, + * as received from a SSL/TLS client or server (the client receives the + * server's certificate chain, and the server receives the client's + * certificate chain if it requested a client certificate). The chain + * is thus injected in the engine in SSL order (end-entity first). + * + * The engine's job is to return the public key to use for SSL/TLS. + * How exactly that key is obtained and verified is entirely up to the + * engine. + * + * **The "known key" engine** returns a public key which is already known + * from out-of-band information (e.g. the client _remembers_ the key from + * a previous connection, as in the usual SSH model). This is the simplest + * engine since it simply ignores the chain, thereby avoiding the need + * for any decoding logic. + * + * **The "minimal" engine** implements minimal X.509 decoding and chain + * validation: + * + * - The provided chain should validate "as is". There is no attempt + * at reordering, skipping or downloading extra certificates. + * + * - X.509 v1, v2 and v3 certificates are supported. + * + * - Trust anchors are a DN and a public key. Each anchor is either a + * "CA" anchor, or a non-CA. + * + * - If the end-entity certificate matches a non-CA anchor (subject DN + * is equal to the non-CA name, and public key is also identical to + * the anchor key), then this is a _direct trust_ case and the + * remaining certificates are ignored. + * + * - Unless direct trust is applied, the chain must be verifiable up to + * a certificate whose issuer DN matches the DN from a "CA" trust anchor, + * and whose signature is verifiable against that anchor's public key. + * Subsequent certificates in the chain are ignored. + * + * - The engine verifies subject/issuer DN matching, and enforces + * processing of Basic Constraints and Key Usage extensions. The + * Authority Key Identifier, Subject Key Identifier, Issuer Alt Name, + * Subject Directory Attribute, CRL Distribution Points, Freshest CRL, + * Authority Info Access and Subject Info Access extensions are + * ignored. The Subject Alt Name is decoded for the end-entity + * certificate under some conditions (see below). Other extensions + * are ignored if non-critical, or imply chain rejection if critical. + * + * - The Subject Alt Name extension is parsed for names of type `dNSName` + * when decoding the end-entity certificate, and only if there is a + * server name to match. If there is no SAN extension, then the + * Common Name from the subjectDN is used. That name matching is + * case-insensitive and honours a single starting wildcard (i.e. if + * the name in the certificate starts with "`*.`" then this matches + * any word as first element). Note: this name matching is performed + * also in the "direct trust" model. + * + * - DN matching is byte-to-byte equality (a future version might + * include some limited processing for case-insensitive matching and + * whitespace normalisation). + * + * - Successful validation produces a public key type but also a set + * of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * The caller is responsible for checking that the key type and + * usages are compatible with the expected values (e.g. with the + * selected cipher suite, when the client validates the server's + * certificate). + * + * **Important caveats:** + * + * - The "minimal" engine does not check revocation status. The relevant + * extensions are ignored, and CRL or OCSP responses are not gathered + * or checked. + * + * - The "minimal" engine does not currently support Name Constraints + * (some basic functionality to handle sub-domains may be added in a + * later version). + * + * - The decoder is not "validating" in the sense that it won't reject + * some certificates with invalid field values when these fields are + * not actually processed. + */ + +/* + * X.509 error codes are in the 32..63 range. + */ + +/** \brief X.509 status: validation was successful; this is not actually + an error. */ +#define BR_ERR_X509_OK 32 + +/** \brief X.509 status: invalid value in an ASN.1 structure. */ +#define BR_ERR_X509_INVALID_VALUE 33 + +/** \brief X.509 status: truncated certificate. */ +#define BR_ERR_X509_TRUNCATED 34 + +/** \brief X.509 status: empty certificate chain (no certificate at all). */ +#define BR_ERR_X509_EMPTY_CHAIN 35 + +/** \brief X.509 status: decoding error: inner element extends beyond + outer element size. */ +#define BR_ERR_X509_INNER_TRUNC 36 + +/** \brief X.509 status: decoding error: unsupported tag class (application + or private). */ +#define BR_ERR_X509_BAD_TAG_CLASS 37 + +/** \brief X.509 status: decoding error: unsupported tag value. */ +#define BR_ERR_X509_BAD_TAG_VALUE 38 + +/** \brief X.509 status: decoding error: indefinite length. */ +#define BR_ERR_X509_INDEFINITE_LENGTH 39 + +/** \brief X.509 status: decoding error: extraneous element. */ +#define BR_ERR_X509_EXTRA_ELEMENT 40 + +/** \brief X.509 status: decoding error: unexpected element. */ +#define BR_ERR_X509_UNEXPECTED 41 + +/** \brief X.509 status: decoding error: expected constructed element, but + is primitive. */ +#define BR_ERR_X509_NOT_CONSTRUCTED 42 + +/** \brief X.509 status: decoding error: expected primitive element, but + is constructed. */ +#define BR_ERR_X509_NOT_PRIMITIVE 43 + +/** \brief X.509 status: decoding error: BIT STRING length is not multiple + of 8. */ +#define BR_ERR_X509_PARTIAL_BYTE 44 + +/** \brief X.509 status: decoding error: BOOLEAN value has invalid length. */ +#define BR_ERR_X509_BAD_BOOLEAN 45 + +/** \brief X.509 status: decoding error: value is off-limits. */ +#define BR_ERR_X509_OVERFLOW 46 + +/** \brief X.509 status: invalid distinguished name. */ +#define BR_ERR_X509_BAD_DN 47 + +/** \brief X.509 status: invalid date/time representation. */ +#define BR_ERR_X509_BAD_TIME 48 + +/** \brief X.509 status: certificate contains unsupported features that + cannot be ignored. */ +#define BR_ERR_X509_UNSUPPORTED 49 + +/** \brief X.509 status: key or signature size exceeds internal limits. */ +#define BR_ERR_X509_LIMIT_EXCEEDED 50 + +/** \brief X.509 status: key type does not match that which was expected. */ +#define BR_ERR_X509_WRONG_KEY_TYPE 51 + +/** \brief X.509 status: signature is invalid. */ +#define BR_ERR_X509_BAD_SIGNATURE 52 + +/** \brief X.509 status: validation time is unknown. */ +#define BR_ERR_X509_TIME_UNKNOWN 53 + +/** \brief X.509 status: certificate is expired or not yet valid. */ +#define BR_ERR_X509_EXPIRED 54 + +/** \brief X.509 status: issuer/subject DN mismatch in the chain. */ +#define BR_ERR_X509_DN_MISMATCH 55 + +/** \brief X.509 status: expected server name was not found in the chain. */ +#define BR_ERR_X509_BAD_SERVER_NAME 56 + +/** \brief X.509 status: unknown critical extension in certificate. */ +#define BR_ERR_X509_CRITICAL_EXTENSION 57 + +/** \brief X.509 status: not a CA, or path length constraint violation */ +#define BR_ERR_X509_NOT_CA 58 + +/** \brief X.509 status: Key Usage extension prohibits intended usage. */ +#define BR_ERR_X509_FORBIDDEN_KEY_USAGE 59 + +/** \brief X.509 status: public key found in certificate is too small. */ +#define BR_ERR_X509_WEAK_PUBLIC_KEY 60 + +/** \brief X.509 status: chain could not be linked to a trust anchor. */ +#define BR_ERR_X509_NOT_TRUSTED 62 + +/** + * \brief Aggregate structure for public keys. + */ +typedef struct { + /** \brief Key type: `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC` */ + unsigned char key_type; + /** \brief Actual public key. */ + union { + /** \brief RSA public key. */ + br_rsa_public_key rsa; + /** \brief EC public key. */ + br_ec_public_key ec; + } key; +} br_x509_pkey; + +/** + * \brief Distinguished Name (X.500) structure. + * + * The DN is DER-encoded. + */ +typedef struct { + /** \brief Encoded DN data. */ + unsigned char *data; + /** \brief Encoded DN length (in bytes). */ + size_t len; +} br_x500_name; + +/** + * \brief Trust anchor structure. + */ +typedef struct { + /** \brief Encoded DN (X.500 name). */ + br_x500_name dn; + /** \brief Anchor flags (e.g. `BR_X509_TA_CA`). */ + unsigned flags; + /** \brief Anchor public key. */ + br_x509_pkey pkey; +} br_x509_trust_anchor; + +/** + * \brief Trust anchor flag: CA. + * + * A "CA" anchor is deemed fit to verify signatures on certificates. + * A "non-CA" anchor is accepted only for direct trust (server's + * certificate name and key match the anchor). + */ +#define BR_X509_TA_CA 0x0001 + +/* + * Key type: combination of a basic key type (low 4 bits) and some + * optional flags. + * + * For a public key, the basic key type only is set. + * + * For an expected key type, the flags indicate the intended purpose(s) + * for the key; the basic key type may be set to 0 to indicate that any + * key type compatible with the indicated purpose is acceptable. + */ +/** \brief Key type: algorithm is RSA. */ +#define BR_KEYTYPE_RSA 1 +/** \brief Key type: algorithm is EC. */ +#define BR_KEYTYPE_EC 2 + +/** + * \brief Key type: usage is "key exchange". + * + * This value is combined (with bitwise OR) with the algorithm + * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509 + * validation engine that it should find a public key of that type, + * fit for key exchanges (e.g. `TLS_RSA_*` and `TLS_ECDH_*` cipher + * suites). + */ +#define BR_KEYTYPE_KEYX 0x10 + +/** + * \brief Key type: usage is "signature". + * + * This value is combined (with bitwise OR) with the algorithm + * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509 + * validation engine that it should find a public key of that type, + * fit for signatures (e.g. `TLS_ECDHE_*` cipher suites). + */ +#define BR_KEYTYPE_SIGN 0x20 + +/* + * start_chain Called when a new chain is started. If 'server_name' + * is not NULL and non-empty, then it is a name that + * should be looked for in the EE certificate (in the + * SAN extension as dNSName, or in the subjectDN's CN + * if there is no SAN extension). + * The caller ensures that the provided 'server_name' + * pointer remains valid throughout validation. + * + * start_cert Begins a new certificate in the chain. The provided + * length is in bytes; this is the total certificate length. + * + * append Get some additional bytes for the current certificate. + * + * end_cert Ends the current certificate. + * + * end_chain Called at the end of the chain. Returned value is + * 0 on success, or a non-zero error code. + * + * get_pkey Returns the EE certificate public key. + * + * For a complete chain, start_chain() and end_chain() are always + * called. For each certificate, start_cert(), some append() calls, then + * end_cert() are called, in that order. There may be no append() call + * at all if the certificate is empty (which is not valid but may happen + * if the peer sends exactly that). + * + * get_pkey() shall return a pointer to a structure that is valid as + * long as a new chain is not started. This may be a sub-structure + * within the context for the engine. This function MAY return a valid + * pointer to a public key even in some cases of validation failure, + * depending on the validation engine. + */ + +/** + * \brief Class type for an X.509 engine. + * + * A certificate chain validation uses a caller-allocated context, which + * contains the running state for that validation. Methods are called + * in due order: + * + * - `start_chain()` is called at the start of the validation. + * - Certificates are processed one by one, in SSL order (end-entity + * comes first). For each certificate, the following methods are + * called: + * + * - `start_cert()` at the beginning of the certificate. + * - `append()` is called zero, one or more times, to provide + * the certificate (possibly in chunks). + * - `end_cert()` at the end of the certificate. + * + * - `end_chain()` is called when the last certificate in the chain + * was processed. + * - `get_pkey()` is called after chain processing, if the chain + * validation was successful. + * + * A context structure may be reused; the `start_chain()` method shall + * ensure (re)initialisation. + */ +typedef struct br_x509_class_ br_x509_class; +struct br_x509_class_ { + /** + * \brief X.509 context size, in bytes. + */ + size_t context_size; + + /** + * \brief Start a new chain. + * + * This method shall set the vtable (first field) of the context + * structure. + * + * The `server_name`, if not `NULL`, will be considered as a + * fully qualified domain name, to be matched against the `dNSName` + * elements of the end-entity certificate's SAN extension (if there + * is no SAN, then the Common Name from the subjectDN will be used). + * If `server_name` is `NULL` then no such matching is performed. + * + * \param ctx validation context. + * \param server_name server name to match (or `NULL`). + */ + void (*start_chain)(const br_x509_class **ctx, + const char *server_name); + + /** + * \brief Start a new certificate. + * + * \param ctx validation context. + * \param length new certificate length (in bytes). + */ + void (*start_cert)(const br_x509_class **ctx, uint32_t length); + + /** + * \brief Receive some bytes for the current certificate. + * + * This function may be called several times in succession for + * a given certificate. The caller guarantees that for each + * call, `len` is not zero, and the sum of all chunk lengths + * for a certificate matches the total certificate length which + * was provided in the previous `start_cert()` call. + * + * If the new certificate is empty (no byte at all) then this + * function won't be called at all. + * + * \param ctx validation context. + * \param buf certificate data chunk. + * \param len certificate data chunk length (in bytes). + */ + void (*append)(const br_x509_class **ctx, + const unsigned char *buf, size_t len); + + /** + * \brief Finish the current certificate. + * + * This function is called when the end of the current certificate + * is reached. + * + * \param ctx validation context. + */ + void (*end_cert)(const br_x509_class **ctx); + + /** + * \brief Finish the chain. + * + * This function is called at the end of the chain. It shall + * return either 0 if the validation was successful, or a + * non-zero error code. The `BR_ERR_X509_*` constants are + * error codes, though other values may be possible. + * + * \param ctx validation context. + * \return 0 on success, or a non-zero error code. + */ + unsigned (*end_chain)(const br_x509_class **ctx); + + /** + * \brief Get the resulting end-entity public key. + * + * The decoded public key is returned. The returned pointer + * may be valid only as long as the context structure is + * unmodified, i.e. it may cease to be valid if the context + * is released or reused. + * + * This function _may_ return `NULL` if the validation failed. + * However, returning a public key does not mean that the + * validation was wholly successful; some engines may return + * a decoded public key even if the chain did not end on a + * trusted anchor. + * + * If validation succeeded and `usage` is not `NULL`, then + * `*usage` is filled with a combination of `BR_KEYTYPE_SIGN` + * and/or `BR_KEYTYPE_KEYX` that specifies the validated key + * usage types. It is the caller's responsibility to check + * that value against the intended use of the public key. + * + * \param ctx validation context. + * \return the end-entity public key, or `NULL`. + */ + const br_x509_pkey *(*get_pkey)( + const br_x509_class *const *ctx, unsigned *usages); +}; + +/** + * \brief The "known key" X.509 engine structure. + * + * The structure contents are opaque (they shall not be accessed directly), + * except for the first field (the vtable). + * + * The "known key" engine returns an externally configured public key, + * and totally ignores the certificate contents. + */ +typedef struct { + /** \brief Reference to the context vtable. */ + const br_x509_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + br_x509_pkey pkey; + unsigned usages; +#endif +} br_x509_knownkey_context; + +/** + * \brief Class instance for the "known key" X.509 engine. + */ +extern const br_x509_class br_x509_knownkey_vtable; + +/** + * \brief Initialize a "known key" X.509 engine with a known RSA public key. + * + * The `usages` parameter indicates the allowed key usages for that key + * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * + * The provided pointers are linked in, not copied, so they must remain + * valid while the public key may be in usage. + * + * \param ctx context to initialise. + * \param pk known public key. + * \param usages allowed key usages. + */ +void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx, + const br_rsa_public_key *pk, unsigned usages); + +/** + * \brief Initialize a "known key" X.509 engine with a known EC public key. + * + * The `usages` parameter indicates the allowed key usages for that key + * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). + * + * The provided pointers are linked in, not copied, so they must remain + * valid while the public key may be in usage. + * + * \param ctx context to initialise. + * \param pk known public key. + * \param usages allowed key usages. + */ +void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx, + const br_ec_public_key *pk, unsigned usages); + +#ifndef BR_DOXYGEN_IGNORE +/* + * The minimal X.509 engine has some state buffers which must be large + * enough to simultaneously accommodate: + * -- the public key extracted from the current certificate; + * -- the signature on the current certificate or on the previous + * certificate; + * -- the public key extracted from the EE certificate. + * + * We store public key elements in their raw unsigned big-endian + * encoding. We want to support up to RSA-4096 with a short (up to 64 + * bits) public exponent, thus a buffer for a public key must have + * length at least 520 bytes. Similarly, a RSA-4096 signature has length + * 512 bytes. + * + * Though RSA public exponents can formally be as large as the modulus + * (mathematically, even larger exponents would work, but PKCS#1 forbids + * them), exponents that do not fit on 32 bits are extremely rare, + * notably because some widespread implementations (e.g. Microsoft's + * CryptoAPI) don't support them. Moreover, large public exponent do not + * seem to imply any tangible security benefit, and they increase the + * cost of public key operations. The X.509 "minimal" engine will tolerate + * public exponents of arbitrary size as long as the modulus and the + * exponent can fit together in the dedicated buffer. + * + * EC public keys are shorter than RSA public keys; even with curve + * NIST P-521 (the largest curve we care to support), a public key is + * encoded over 133 bytes only. + */ +#define BR_X509_BUFSIZE_KEY 520 +#define BR_X509_BUFSIZE_SIG 512 +#endif + +/** + * \brief Type for receiving a name element. + * + * An array of such structures can be provided to the X.509 decoding + * engines. If the specified elements are found in the certificate + * subject DN or the SAN extension, then the name contents are copied + * as zero-terminated strings into the buffer. + * + * The decoder converts TeletexString and BMPString to UTF8String, and + * ensures that the resulting string is zero-terminated. If the string + * does not fit in the provided buffer, then the copy is aborted and an + * error is reported. + */ +typedef struct { + /** + * \brief Element OID. + * + * For X.500 name elements (to be extracted from the subject DN), + * this is the encoded OID for the requested name element; the + * first byte shall contain the length of the DER-encoded OID + * value, followed by the OID value (for instance, OID 2.5.4.3, + * for id-at-commonName, will be `03 55 04 03`). This is + * equivalent to full DER encoding with the length but without + * the tag. + * + * For SAN name elements, the first byte (`oid[0]`) has value 0, + * followed by another byte that matches the expected GeneralName + * tag. Allowed second byte values are then: + * + * - 1: `rfc822Name` + * + * - 2: `dNSName` + * + * - 6: `uniformResourceIdentifier` + * + * - 0: `otherName` + * + * If first and second byte are 0, then this is a SAN element of + * type `otherName`; the `oid[]` array should then contain, right + * after the two bytes of value 0, an encoded OID (with the same + * conventions as for X.500 name elements). If a match is found + * for that OID, then the corresponding name element will be + * extracted, as long as it is a supported string type. + */ + const unsigned char *oid; + + /** + * \brief Destination buffer. + */ + char *buf; + + /** + * \brief Length (in bytes) of the destination buffer. + * + * The buffer MUST NOT be smaller than 1 byte. + */ + size_t len; + + /** + * \brief Decoding status. + * + * Status is 0 if the name element was not found, 1 if it was + * found and decoded, or -1 on error. Error conditions include + * an unrecognised encoding, an invalid encoding, or a string + * too large for the destination buffer. + */ + int status; + +} br_name_element; + +/** + * \brief The "minimal" X.509 engine structure. + * + * The structure contents are opaque (they shall not be accessed directly), + * except for the first field (the vtable). + * + * The "minimal" engine performs a rudimentary but serviceable X.509 path + * validation. + */ +typedef struct { + const br_x509_class *vtable; + +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the EE public key. */ + br_x509_pkey pkey; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + /* Server name to match with the SAN / CN of the EE certificate. */ + const char *server_name; + + /* Validated key usages. */ + unsigned char key_usages; + + /* Explicitly set date and time. */ + uint32_t days, seconds; + + /* Current certificate length (in bytes). Set to 0 when the + certificate has been fully processed. */ + uint32_t cert_length; + + /* Number of certificates processed so far in the current chain. + It is incremented at the end of the processing of a certificate, + so it is 0 for the EE. */ + uint32_t num_certs; + + /* Certificate data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Buffer for EE public key data. */ + unsigned char ee_pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Buffer for currently decoded public key. */ + unsigned char pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Signature type: signer key type, offset to the hash + function OID (in the T0 data block) and hash function + output length (TBS hash length). */ + unsigned char cert_signer_key_type; + uint16_t cert_sig_hash_oid; + unsigned char cert_sig_hash_len; + + /* Current/last certificate signature. */ + unsigned char cert_sig[BR_X509_BUFSIZE_SIG]; + uint16_t cert_sig_len; + + /* Minimum RSA key length (difference in bytes from 128). */ + int16_t min_rsa_size; + + /* Configured trust anchors. */ + const br_x509_trust_anchor *trust_anchors; + size_t trust_anchors_num; + + /* private context for dynamic callbacks */ + void *trust_anchor_dynamic_ctx; + /* Dynamic trust anchor, for on-the-fly loading of TAs */ + const br_x509_trust_anchor* (*trust_anchor_dynamic)(void *ctx, void *hashed_dn, size_t hashed_dn_len); + /* And a chance to free any dynamically allocated TA returned from above */ + void (*trust_anchor_dynamic_free)(void *ctx, const br_x509_trust_anchor *ta); + + /* + * Multi-hasher for the TBS. + */ + unsigned char do_mhash; + br_multihash_context mhash; + unsigned char tbs_hash[64]; + + /* + * Simple hasher for the subject/issuer DN. + */ + unsigned char do_dn_hash; + const br_hash_class *dn_hash_impl; + br_hash_compat_context dn_hash; + unsigned char current_dn_hash[64]; + unsigned char next_dn_hash[64]; + unsigned char saved_dn_hash[64]; + + /* + * Name elements to gather. + */ + br_name_element *name_elts; + size_t num_name_elts; + + /* + * Public key cryptography implementations (signature verification). + */ + br_rsa_pkcs1_vrfy irsa; + br_ecdsa_vrfy iecdsa; + const br_ec_impl *iec; +#endif + +} br_x509_minimal_context; + +/** + * \brief Class instance for the "minimal" X.509 engine. + */ +extern const br_x509_class br_x509_minimal_vtable; + +/** + * \brief Initialise a "minimal" X.509 engine. + * + * The `dn_hash_impl` parameter shall be a hash function internally used + * to match X.500 names (subject/issuer DN, and anchor names). Any standard + * hash function may be used, but a collision-resistant hash function is + * advised. + * + * After initialization, some implementations for signature verification + * (hash functions and signature algorithms) MUST be added. + * + * \param ctx context to initialise. + * \param dn_hash_impl hash function for DN comparisons. + * \param trust_anchors trust anchors. + * \param trust_anchors_num number of trust anchors. + */ +void br_x509_minimal_init(br_x509_minimal_context *ctx, + const br_hash_class *dn_hash_impl, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Set the optional dynamic trust anchor lookup callbacks + * + * The dynamic trust anchor lookup callbacks allow an application to implement + * a non-memory resident trust anchor store. This can be useful on embedded + * systems where RAM is at a premium, but there is an external stable store, + * such as embedded flash or SD card, to keep many CA certificates. Set or + * leave these functions as NULL to not use such a feature. + * + * The dynamic routine will be passed in the hashed DN in question using the + * dn_hash_impl, and should compare this DN to its set of hashed known DNs. + * Of course, the same dn_hash_impl needs to be used in the dynamic routine. + * After the trust_anchor* is used, the dynamic_free callback is given a + * chance to deallocate its memory, if needed. + * + * \param ctx context to initialise. + * \param dynamic_ctx private context for the dynamic callback + * \param trust_anchor_dynamic provides a trust_anchor* for a hashed_dn + * \param trust_anchor_dynamic_free allows deallocation of returned TA + */ +static inline void +br_x509_minimal_set_dynamic(br_x509_minimal_context *ctx, void *dynamic_ctx, + const br_x509_trust_anchor* (*dynamic)(void *ctx, void *hashed_dn, size_t hashed_dn_len), + void (*dynamic_free)(void *ctx, const br_x509_trust_anchor *ta)) +{ + ctx->trust_anchor_dynamic_ctx = dynamic_ctx; + ctx->trust_anchor_dynamic = dynamic; + ctx->trust_anchor_dynamic_free = dynamic_free; +} + +/** + * \brief Set a supported hash function in an X.509 "minimal" engine. + * + * Hash functions are used with signature verification algorithms. + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the hash functions it shall support for that + * purpose. The hash function identifier MUST be one of the standard + * hash function identifiers (1 to 6, for MD5, SHA-1, SHA-224, SHA-256, + * SHA-384 and SHA-512). + * + * If `impl` is `NULL`, this _removes_ support for the designated + * hash function. + * + * \param ctx validation context. + * \param id hash function identifier (from 1 to 6). + * \param impl hash function implementation (or `NULL`). + */ +static inline void +br_x509_minimal_set_hash(br_x509_minimal_context *ctx, + int id, const br_hash_class *impl) +{ + br_multihash_setimpl(&ctx->mhash, id, impl); +} + +/** + * \brief Set a RSA signature verification implementation in the X.509 + * "minimal" engine. + * + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the signature verification implementations that + * it is supposed to support. If `irsa` is `0`, then the RSA support + * is disabled. + * + * \param ctx validation context. + * \param irsa RSA signature verification implementation (or `0`). + */ +static inline void +br_x509_minimal_set_rsa(br_x509_minimal_context *ctx, + br_rsa_pkcs1_vrfy irsa) +{ + ctx->irsa = irsa; +} + +/** + * \brief Set a ECDSA signature verification implementation in the X.509 + * "minimal" engine. + * + * Once initialised (with `br_x509_minimal_init()`), the context must + * be configured with the signature verification implementations that + * it is supposed to support. + * + * If `iecdsa` is `0`, then this call disables ECDSA support; in that + * case, `iec` may be `NULL`. Otherwise, `iecdsa` MUST point to a function + * that verifies ECDSA signatures with format "asn1", and it will use + * `iec` as underlying elliptic curve support. + * + * \param ctx validation context. + * \param iec elliptic curve implementation (or `NULL`). + * \param iecdsa ECDSA implementation (or `0`). + */ +static inline void +br_x509_minimal_set_ecdsa(br_x509_minimal_context *ctx, + const br_ec_impl *iec, br_ecdsa_vrfy iecdsa) +{ + ctx->iecdsa = iecdsa; + ctx->iec = iec; +} + +/** + * \brief Initialise a "minimal" X.509 engine with default algorithms. + * + * This function performs the same job as `br_x509_minimal_init()`, but + * also sets implementations for RSA, ECDSA, and the standard hash + * functions. + * + * \param ctx context to initialise. + * \param trust_anchors trust anchors. + * \param trust_anchors_num number of trust anchors. + */ +void br_x509_minimal_init_full(br_x509_minimal_context *ctx, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + +/** + * \brief Set the validation time for the X.509 "minimal" engine. + * + * The validation time is set as two 32-bit integers, for days and + * seconds since a fixed epoch: + * + * - Days are counted in a proleptic Gregorian calendar since + * January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD"; + * it is also traditionally known as "1 BC". + * + * - Seconds are counted since midnight, from 0 to 86400 (a count of + * 86400 is possible only if a leap second happened). + * + * The validation date and time is understood in the UTC time zone. + * + * If the validation date and time are not explicitly set, but BearSSL + * was compiled with support for the system clock on the underlying + * platform, then the current time will automatically be used. Otherwise, + * not setting the validation date and time implies a validation + * failure (except in case of direct trust of the EE key). + * + * \param ctx validation context. + * \param days days since January 1st, 0 AD (Gregorian calendar). + * \param seconds seconds since midnight (0 to 86400). + */ +static inline void +br_x509_minimal_set_time(br_x509_minimal_context *ctx, + uint32_t days, uint32_t seconds) +{ + ctx->days = days; + ctx->seconds = seconds; +} + +/** + * \brief Set the minimal acceptable length for RSA keys (X.509 "minimal" + * engine). + * + * The RSA key length is expressed in bytes. The default minimum key + * length is 128 bytes, corresponding to 1017 bits. RSA keys shorter + * than the configured length will be rejected, implying validation + * failure. This setting applies to keys extracted from certificates + * (both end-entity, and intermediate CA) but not to "CA" trust anchors. + * + * \param ctx validation context. + * \param byte_length minimum RSA key length, **in bytes** (not bits). + */ +static inline void +br_x509_minimal_set_minrsa(br_x509_minimal_context *ctx, int byte_length) +{ + ctx->min_rsa_size = (int16_t)(byte_length - 128); +} + +/** + * \brief Set the name elements to gather. + * + * The provided array is linked in the context. The elements are + * gathered from the EE certificate. If the same element type is + * requested several times, then the relevant structures will be filled + * in the order the matching values are encountered in the certificate. + * + * \param ctx validation context. + * \param elts array of name element structures to fill. + * \param num_elts number of name element structures to fill. + */ +static inline void +br_x509_minimal_set_name_elements(br_x509_minimal_context *ctx, + br_name_element *elts, size_t num_elts) +{ + ctx->name_elts = elts; + ctx->num_name_elts = num_elts; +} + +/** + * \brief X.509 decoder context. + * + * This structure is _not_ for X.509 validation, but for extracting + * names and public keys from encoded certificates. Intended usage is + * to use (self-signed) certificates as trust anchors. + * + * Contents are opaque and shall not be accessed directly. + */ +typedef struct { + +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the public key. */ + br_x509_pkey pkey; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Flag set when decoding succeeds. */ + unsigned char decoded; + + /* Validity dates. */ + uint32_t notbefore_days, notbefore_seconds; + uint32_t notafter_days, notafter_seconds; + + /* The "CA" flag. This is set to true if the certificate contains + a Basic Constraints extension that asserts CA status. */ + unsigned char isCA; + + /* DN processing: the subject DN is extracted and pushed to the + provided callback. */ + unsigned char copy_dn; + void *append_dn_ctx; + void (*append_dn)(void *ctx, const void *buf, size_t len); + + /* DN processing: the issuer DN is extracted and pushed to the + provided callback. */ + unsigned char copy_in; + void *append_in_ctx; + void (*append_in)(void *ctx, const void *buf, size_t len); + + /* Certificate data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* Buffer for decoded public key. */ + unsigned char pkey_data[BR_X509_BUFSIZE_KEY]; + + /* Type of key and hash function used in the certificate signature. */ + unsigned char signer_key_type; + unsigned char signer_hash_id; +#endif + +} br_x509_decoder_context; + +/** + * \brief Initialise an X.509 decoder context for processing a new + * certificate. + * + * The `append_dn()` callback (with opaque context `append_dn_ctx`) + * will be invoked to receive, chunk by chunk, the certificate's + * subject DN. If `append_dn` is `0` then the subject DN will be + * ignored. + * + * \param ctx X.509 decoder context to initialise. + * \param append_dn DN receiver callback (or `0`). + * \param append_dn_ctx context for the DN receiver callback. + * \param append_in issuer DN receiver callback (or `0`). + * \param append_in_ctx context for the issuer DN receiver callback. + */ +void br_x509_decoder_init(br_x509_decoder_context *ctx, + void (*append_dn)(void *ctx, const void *buf, size_t len), + void *append_dn_ctx, + void (*append_in)(void *ctx, const void *buf, size_t len), + void *append_in_ctx); + +/** + * \brief Push some certificate bytes into a decoder context. + * + * If `len` is non-zero, then that many bytes are pushed, from address + * `data`, into the provided decoder context. + * + * \param ctx X.509 decoder context. + * \param data certificate data chunk. + * \param len certificate data chunk length (in bytes). + */ +void br_x509_decoder_push(br_x509_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Obtain the decoded public key. + * + * Returned value is a pointer to a structure internal to the decoder + * context; releasing or reusing the decoder context invalidates that + * structure. + * + * If decoding was not finished, or failed, then `NULL` is returned. + * + * \param ctx X.509 decoder context. + * \return the public key, or `NULL` on unfinished/error. + */ +static inline br_x509_pkey * +br_x509_decoder_get_pkey(br_x509_decoder_context *ctx) +{ + if (ctx->decoded && ctx->err == 0) { + return &ctx->pkey; + } else { + return NULL; + } +} + +/** + * \brief Get decoder error status. + * + * If no error was reported yet but the certificate decoding is not + * finished, then the error code is `BR_ERR_X509_TRUNCATED`. If decoding + * was successful, then 0 is returned. + * + * \param ctx X.509 decoder context. + * \return 0 on successful decoding, or a non-zero error code. + */ +static inline int +br_x509_decoder_last_error(br_x509_decoder_context *ctx) +{ + if (ctx->err != 0) { + return ctx->err; + } + if (!ctx->decoded) { + return BR_ERR_X509_TRUNCATED; + } + return 0; +} + +/** + * \brief Get the "isCA" flag from an X.509 decoder context. + * + * This flag is set if the decoded certificate claims to be a CA through + * a Basic Constraints extension. This flag should not be read before + * decoding completed successfully. + * + * \param ctx X.509 decoder context. + * \return the "isCA" flag. + */ +static inline int +br_x509_decoder_isCA(br_x509_decoder_context *ctx) +{ + return ctx->isCA; +} + +/** + * \brief Get the issuing CA key type (type of algorithm used to sign the + * decoded certificate). + * + * This is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. The value 0 is returned + * if the signature type was not recognised. + * + * \param ctx X.509 decoder context. + * \return the issuing CA key type. + */ +static inline int +br_x509_decoder_get_signer_key_type(br_x509_decoder_context *ctx) +{ + return ctx->signer_key_type; +} + +/** + * \brief Get the identifier for the hash function used to sign the decoded + * certificate. + * + * This is 0 if the hash function was not recognised. + * + * \param ctx X.509 decoder context. + * \return the signature hash function identifier. + */ +static inline int +br_x509_decoder_get_signer_hash_id(br_x509_decoder_context *ctx) +{ + return ctx->signer_hash_id; +} + +/** + * \brief Type for an X.509 certificate (DER-encoded). + */ +typedef struct { + /** \brief The DER-encoded certificate data. */ + unsigned char *data; + /** \brief The DER-encoded certificate length (in bytes). */ + size_t data_len; +} br_x509_certificate; + +/** + * \brief Private key decoder context. + * + * The private key decoder recognises RSA and EC private keys, either in + * their raw, DER-encoded format, or wrapped in an unencrypted PKCS#8 + * archive (again DER-encoded). + * + * Structure contents are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the private key. */ + union { + br_rsa_private_key rsa; + br_ec_private_key ec; + } key; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + /* Private key data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Decoded key type; 0 until decoding is complete. */ + unsigned char key_type; + + /* Buffer for the private key elements. It shall be large enough + to accommodate all elements for a RSA-4096 private key (roughly + five 2048-bit integers, possibly a bit more). */ + unsigned char key_data[3 * BR_X509_BUFSIZE_SIG]; +#endif +} br_skey_decoder_context; + +/** + * \brief Initialise a private key decoder context. + * + * \param ctx key decoder context to initialise. + */ +void br_skey_decoder_init(br_skey_decoder_context *ctx); + +/** + * \brief Push some data bytes into a private key decoder context. + * + * If `len` is non-zero, then that many data bytes, starting at address + * `data`, are pushed into the decoder. + * + * \param ctx key decoder context. + * \param data private key data chunk. + * \param len private key data chunk length (in bytes). + */ +void br_skey_decoder_push(br_skey_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Get the decoding status for a private key. + * + * Decoding status is 0 on success, or a non-zero error code. If the + * decoding is unfinished when this function is called, then the + * status code `BR_ERR_X509_TRUNCATED` is returned. + * + * \param ctx key decoder context. + * \return 0 on successful decoding, or a non-zero error code. + */ +static inline int +br_skey_decoder_last_error(const br_skey_decoder_context *ctx) +{ + if (ctx->err != 0) { + return ctx->err; + } + if (ctx->key_type == 0) { + return BR_ERR_X509_TRUNCATED; + } + return 0; +} + +/** + * \brief Get the decoded private key type. + * + * Private key type is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. If decoding is + * not finished or failed, then 0 is returned. + * + * \param ctx key decoder context. + * \return decoded private key type, or 0. + */ +static inline int +br_skey_decoder_key_type(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0) { + return ctx->key_type; + } else { + return 0; + } +} + +/** + * \brief Get the decoded RSA private key. + * + * This function returns `NULL` if the decoding failed, or is not + * finished, or the key is not RSA. The returned pointer references + * structures within the context that can become invalid if the context + * is reused or released. + * + * \param ctx key decoder context. + * \return decoded RSA private key, or `NULL`. + */ +static inline const br_rsa_private_key * +br_skey_decoder_get_rsa(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_RSA) { + return &ctx->key.rsa; + } else { + return NULL; + } +} + +/** + * \brief Get the decoded EC private key. + * + * This function returns `NULL` if the decoding failed, or is not + * finished, or the key is not EC. The returned pointer references + * structures within the context that can become invalid if the context + * is reused or released. + * + * \param ctx key decoder context. + * \return decoded EC private key, or `NULL`. + */ +static inline const br_ec_private_key * +br_skey_decoder_get_ec(const br_skey_decoder_context *ctx) +{ + if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_EC) { + return &ctx->key.ec; + } else { + return NULL; + } +} + +/** + * \brief Public key decoder context. + * + * The public key decoder recognises RSA and EC private keys, either in + * their raw, DER-encoded format, or wrapped in an unencrypted PKCS#8 + * archive (again DER-encoded). + * + * Structure contents are opaque and shall not be accessed directly. + */ +typedef struct { +#ifndef BR_DOXYGEN_IGNORE + /* Structure for returning the private key. */ + union { + br_rsa_public_key rsa; + br_ec_public_key ec; + } key; + + /* CPU for the T0 virtual machine. */ + struct { + uint32_t *dp; + uint32_t *rp; + const unsigned char *ip; + } cpu; + uint32_t dp_stack[32]; + uint32_t rp_stack[32]; + int err; + + /* Private key data chunk. */ + const unsigned char *hbuf; + size_t hlen; + + /* The pad serves as destination for various operations. */ + unsigned char pad[256]; + + /* Decoded key type; 0 until decoding is complete. */ + unsigned char key_type; + + /* Buffer for the private key elements. It shall be large enough + to accommodate all elements for a RSA-4096 private key (roughly + five 2048-bit integers, possibly a bit more). */ + unsigned char key_data[3 * BR_X509_BUFSIZE_SIG]; +#endif +} br_pkey_decoder_context; + + +/** + * \brief Initialise a public key decoder context. + * + * \param ctx key decoder context to initialise. + */ +void br_pkey_decoder_init(br_pkey_decoder_context *ctx); + +/** + * \brief Push some data bytes into a public key decoder context. + * + * If `len` is non-zero, then that many data bytes, starting at address + * `data`, are pushed into the decoder. + * + * \param ctx key decoder context. + * \param data private key data chunk. + * \param len private key data chunk length (in bytes). + */ +void br_pkey_decoder_push(br_pkey_decoder_context *ctx, + const void *data, size_t len); + +/** + * \brief Get the decoding status for a public key. + * + * Decoding status is 0 on success, or a non-zero error code. If the + * decoding is unfinished when this function is called, then the + * status code `BR_ERR_X509_TRUNCATED` is returned. + * + * \param ctx key decoder context. + * \return 0 on successful decoding, or a non-zero error code. + */ +static inline int +br_pkey_decoder_last_error(const br_pkey_decoder_context *ctx) +{ + if (ctx->err != 0) { + return ctx->err; + } + if (ctx->key_type == 0) { + return BR_ERR_X509_TRUNCATED; + } + return 0; +} + +/** + * \brief Get the decoded public key type. + * + * Public key type is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. If decoding is + * not finished or failed, then 0 is returned. + * + * \param ctx key decoder context. + * \return decoded private key type, or 0. + */ +static inline int +br_pkey_decoder_key_type(const br_pkey_decoder_context *ctx) +{ + if (ctx->err == 0) { + return ctx->key_type; + } else { + return 0; + } +} + +/** + * \brief Get the decoded RSA public key. + * + * This function returns `NULL` if the decoding failed, or is not + * finished, or the key is not RSA. The returned pointer references + * structures within the context that can become invalid if the context + * is reused or released. + * + * \param ctx key decoder context. + * \return decoded RSA public key, or `NULL`. + */ +static inline const br_rsa_public_key * +br_pkey_decoder_get_rsa(const br_pkey_decoder_context *ctx) +{ + if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_RSA) { + return &ctx->key.rsa; + } else { + return NULL; + } +} + +/** + * \brief Get the decoded EC private key. + * + * This function returns `NULL` if the decoding failed, or is not + * finished, or the key is not EC. The returned pointer references + * structures within the context that can become invalid if the context + * is reused or released. + * + * \param ctx key decoder context. + * \return decoded EC private key, or `NULL`. + */ +static inline const br_ec_public_key * +br_pkey_decoder_get_ec(const br_pkey_decoder_context *ctx) +{ + if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_EC) { + return &ctx->key.ec; + } else { + return NULL; + } +} + +/** + * \brief Encode an RSA private key (raw DER format). + * + * This function encodes the provided key into the "raw" format specified + * in PKCS#1 (RFC 8017, Appendix C, type `RSAPrivateKey`), with DER + * encoding rules. + * + * The key elements are: + * + * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) + * + * - `pk`: the public key (`n` and `e`) + * + * - `d` (size: `dlen` bytes): the private exponent + * + * The public key elements, and the private exponent `d`, can be + * recomputed from the private key (see `br_rsa_compute_modulus()`, + * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the RSA private key. + * \param pk the RSA public key. + * \param d the RSA private exponent. + * \param dlen the RSA private exponent length (in bytes). + * \return the encoded key length (in bytes). + */ +size_t br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen); + +/** + * \brief Encode an RSA private key (PKCS#8 DER format). + * + * This function encodes the provided key into the PKCS#8 format + * (RFC 5958, type `OneAsymmetricKey`). It wraps around the "raw DER" + * format for the RSA key, as implemented by `br_encode_rsa_raw_der()`. + * + * The key elements are: + * + * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) + * + * - `pk`: the public key (`n` and `e`) + * + * - `d` (size: `dlen` bytes): the private exponent + * + * The public key elements, and the private exponent `d`, can be + * recomputed from the private key (see `br_rsa_compute_modulus()`, + * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the RSA private key. + * \param pk the RSA public key. + * \param d the RSA private exponent. + * \param dlen the RSA private exponent length (in bytes). + * \return the encoded key length (in bytes). + */ +size_t br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen); + +/** + * \brief Encode an EC private key (raw DER format). + * + * This function encodes the provided key into the "raw" format specified + * in RFC 5915 (type `ECPrivateKey`), with DER encoding rules. + * + * The private key is provided in `sk`, the public key being `pk`. If + * `pk` is `NULL`, then the encoded key will not include the public key + * in its `publicKey` field (which is nominally optional). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * If the key cannot be encoded (e.g. because there is no known OBJECT + * IDENTIFIER for the used curve), then 0 is returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the EC private key. + * \param pk the EC public key (or `NULL`). + * \return the encoded key length (in bytes), or 0. + */ +size_t br_encode_ec_raw_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk); + +/** + * \brief Encode an EC private key (PKCS#8 DER format). + * + * This function encodes the provided key into the PKCS#8 format + * (RFC 5958, type `OneAsymmetricKey`). The curve is identified + * by an OID provided as parameters to the `privateKeyAlgorithm` + * field. The private key value (contents of the `privateKey` field) + * contains the DER encoding of the `ECPrivateKey` type defined in + * RFC 5915, without the `parameters` field (since they would be + * redundant with the information in `privateKeyAlgorithm`). + * + * The private key is provided in `sk`, the public key being `pk`. If + * `pk` is not `NULL`, then the encoded public key is included in the + * `publicKey` field of the private key value (but not in the `publicKey` + * field of the PKCS#8 `OneAsymmetricKey` wrapper). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * If the key cannot be encoded (e.g. because there is no known OBJECT + * IDENTIFIER for the used curve), then 0 is returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the EC private key. + * \param pk the EC public key (or `NULL`). + * \return the encoded key length (in bytes), or 0. + */ +size_t br_encode_ec_pkcs8_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk); + +/** + * \brief PEM banner for RSA private key (raw). + */ +#define BR_ENCODE_PEM_RSA_RAW "RSA PRIVATE KEY" + +/** + * \brief PEM banner for EC private key (raw). + */ +#define BR_ENCODE_PEM_EC_RAW "EC PRIVATE KEY" + +/** + * \brief PEM banner for an RSA or EC private key in PKCS#8 format. + */ +#define BR_ENCODE_PEM_PKCS8 "PRIVATE KEY" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib_bearssl/README.md b/lib_bearssl/README.md index 008e62624..33dce81d4 100644 --- a/lib_bearssl/README.md +++ b/lib_bearssl/README.md @@ -16,6 +16,9 @@ There are only two changes in `src/inner.h`: Then compile with -```make CONF=esp8266``` +``` +make CONF=esp8266 +xtensa-lx106-elf-ar d esp8266/libbearssl.a `xtensa-lx106-elf-ar t esp8266/libbearssl.a | egrep 'i31|i32|x86|sse|pwr8|i62|m31|m32|m62|m64|ct64|ctmul64'` +``` Finally copy `libbearssl.a` to this directory. diff --git a/lib_bearssl/libbearssl.a b/lib_bearssl/libbearssl.a index dc8a6a34c192dc5c2ae54b5d533d40d24d6222da..e15f48f8142cdb36f0a17c26ef251aea4afb98a8 100644 GIT binary patch delta 53440 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̷w9YCTU5g0?v3UavH5eXP;iALu?1=Pg7^*d73wrg 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 -#ifdef ARDUINO_ESP8266_RELEASE_2_5_2 - #define LWIP_INTERNAL #include @@ -45,12 +42,13 @@ extern "C" { #include "lwip/netif.h" #include #include "c_types.h" -#include "coredecls.h" -#define SKEY_ON_STACK // copy private key+cert on stack rather than on heap, this works for now because it takes ~800 bytes +#include "my_user_config.h" + //#define DEBUG_TLS #ifdef DEBUG_TLS +#include "coredecls.h" #define LOG_HEAP_SIZE(a) _Log_heap_size(a) void _Log_heap_size(const char *msg) { register uint32_t *sp asm("a1"); @@ -247,14 +245,24 @@ void WiFiClientSecure_light::setBufferSizes(int recv, int xmit) { } bool WiFiClientSecure_light::stop(unsigned int maxWaitMs) { +#ifdef ARDUINO_ESP8266_RELEASE_2_4_2 + WiFiClient::stop(); // calls our virtual flush() + _freeSSL(); + return true; +#else bool ret = WiFiClient::stop(maxWaitMs); // calls our virtual flush() _freeSSL(); return ret; +#endif } bool WiFiClientSecure_light::flush(unsigned int maxWaitMs) { (void) _run_until(BR_SSL_SENDAPP); +#ifdef ARDUINO_ESP8266_RELEASE_2_4_2 + WiFiClient::flush(); +#else return WiFiClient::flush(maxWaitMs); +#endif } int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port) { @@ -283,10 +291,6 @@ int WiFiClientSecure_light::connect(const char* name, uint16_t port) { return _connectSSL(name); } -int WiFiClientSecure_light::connect(const String& host, uint16_t port) { - return connect(host.c_str(), port); -} - void WiFiClientSecure_light::_freeSSL() { _ctx_present = false; _recvapp_buf = nullptr; @@ -776,11 +780,13 @@ extern "C" { // Called by connect() to do the actual SSL setup and handshake. // Returns if the SSL handshake succeeded. bool WiFiClientSecure_light::_connectSSL(const char* hostName) { +#ifdef USE_MQTT_AWS_IOT br_ec_private_key sk_ec; br_x509_certificate chain; -#ifdef SKEY_ON_STACK +#ifdef USE_MQTT_AWS_IOT_SKEY_ON_STACK unsigned char chain_data[_chain_P->data_len]; unsigned char sk_data[_sk_ec_P->xlen]; +#endif #endif br_x509_pubkeyfingerprint_context *x509_insecure; @@ -808,11 +814,10 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size); LOG_HEAP_SIZE("_connectSSL after PrivKey allocation"); +#ifdef USE_MQTT_AWS_IOT // allocate Private key and client certificate - //chain = new X509List(_chain_PEM); - //sk = new PrivateKey(_sk_PEM); chain.data_len = _chain_P->data_len; -#ifdef SKEY_ON_STACK // allocate on stack +#ifdef USE_MQTT_AWS_IOT_SKEY_ON_STACK // allocate on stack chain.data = &chain_data[0]; #else // allocate with malloc chain.data = (unsigned char *) malloc(chain.data_len); @@ -821,38 +826,47 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { sk_ec.curve = _sk_ec_P->curve; sk_ec.xlen = _sk_ec_P->xlen; -#ifdef SKEY_ON_STACK +#ifdef USE_MQTT_AWS_IOT_SKEY_ON_STACK sk_ec.x = &sk_data[0]; -#else +#else // USE_MQTT_AWS_IOT_SKEY_ON_STACK sk_ec.x = (unsigned char *) malloc(sk_ec.xlen); -#endif +#endif // USE_MQTT_AWS_IOT_SKEY_ON_STACK if (sk_ec.x) memcpy_P(sk_ec.x, _sk_ec_P->x, sk_ec.xlen); LOG_HEAP_SIZE("_connectSSL after PrivKey allocation"); +#endif // USE_MQTT_AWS_IOT // check if memory was correctly allocated +#ifdef USE_MQTT_AWS_IOT if ((!stack_thunk_light_get_stack_bot()) || (!x509_insecure) || (!chain.data) || (!sk_ec.x)) { - // memory allocation problem - setLastError(ERR_OOM); -#ifndef SKEY_ON_STACK +#ifndef USE_MQTT_AWS_IOT_SKEY_ON_STACK free(chain.data); free(sk_ec.x); -#endif +#endif // USE_MQTT_AWS_IOT_SKEY_ON_STACK +#else + if ((!stack_thunk_light_get_stack_bot()) || (!x509_insecure)) { +#endif // USE_MQTT_AWS_IOT + // memory allocation problem + setLastError(ERR_OOM); free(x509_insecure); stack_thunk_light_del_ref(); DEBUG_BSSL("_connectSSL: Out of memory\n"); return false; } +#ifdef USE_MQTT_AWS_IOT // limited to P256 curve br_ssl_client_set_single_ec(_sc.get(), &chain, 1, &sk_ec, _allowed_usages, _cert_issuer_key_type, &br_ec_p256_m15, br_ecdsa_sign_asn1_get_default()); +#endif if (!br_ssl_client_reset(_sc.get(), hostName, 0)) { -#ifndef SKEY_ON_STACK +#ifdef USE_MQTT_AWS_IOT +#ifndef USE_MQTT_AWS_IOT_SKEY_ON_STACK free(chain.data); free(sk_ec.x); +#endif #endif free(x509_insecure); stack_thunk_light_del_ref(); @@ -873,9 +887,11 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { stack_thunk_light_del_ref(); //stack_thunk_light_repaint(); LOG_HEAP_SIZE("_connectSSL.end, freeing StackThunk"); -#ifndef SKEY_ON_STACK +#ifdef USE_MQTT_AWS_IOT +#ifndef USE_MQTT_AWS_IOT_SKEY_ON_STACK free(chain.data); free(sk_ec.x); +#endif #endif free(x509_insecure); LOG_HEAP_SIZE("_connectSSL after release of Priv Key"); @@ -883,5 +899,3 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { } }; - -#endif // ARDUINO_ESP8266_RELEASE_2_5_2 \ No newline at end of file diff --git a/sonoff/WiFiClientSecureLightBearSSL.h b/sonoff/WiFiClientSecureLightBearSSL.h index c63392c04..fc938cfe6 100644 --- a/sonoff/WiFiClientSecureLightBearSSL.h +++ b/sonoff/WiFiClientSecureLightBearSSL.h @@ -21,15 +21,12 @@ */ #include -#ifdef ARDUINO_ESP8266_RELEASE_2_5_2 #ifndef wificlientlightbearssl_h #define wificlientlightbearssl_h #include #include "WiFiClient.h" #include -#include "BearSSLHelpers.h" -#include "CertStoreBearSSL.h" namespace BearSSL { @@ -41,7 +38,6 @@ class WiFiClientSecure_light : public WiFiClient { void allocateBuffers(void); int connect(IPAddress ip, uint16_t port) override; - int connect(const String& host, uint16_t port) override; int connect(const char* name, uint16_t port) override; uint8_t connected() override; @@ -148,5 +144,3 @@ class WiFiClientSecure_light : public WiFiClient { }; #endif - -#endif // ARDUINO_ESP8266_RELEASE_2_5_2 \ No newline at end of file diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e77bae119..4c7c64139 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -7,6 +7,7 @@ * Fix include of my_user_config.h in sonoff_aws_iot.cpp (#5930) * Fix exception 9 when syslog is enabled and NTP is just synced (#5917) * Fix Toggle functionality to button double press when one button and two devices are detected (#5935) + * Refactored TLS based on BearSSL, warning breaking change for fongerprints validation (see doc) * * 6.5.0.14 20190602 * Change webserver HTML input, button, textarea, and select name based on id diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 42cb07c54..75aaaf064 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -262,16 +262,15 @@ #define USE_HOME_ASSISTANT // Enable Home Assistant Discovery Support (+7k code) #define HOME_ASSISTANT_DISCOVERY_PREFIX "homeassistant" // Home Assistant discovery prefix -// -- MQTT - TLS ---------------------------------- - // !!! TLS uses a LOT OF MEMORY so be careful to enable other options at the same time !!! -//#define USE_MQTT_TLS // Use TLS for MQTT connection (+53k code, +15k mem) -// #define USE_MQTT_TLS_CA_CERT // Use LetsEncrypt Certificate from sonoff_letsencrypt.h - Not supported with core 2.3.0 - -// -- MQTT - Special version for AWS IoT on core 2.5.2 only -//#define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+56.7k code, +6.0k mem and +6.6k additional during connection handshake) +// -- MQTT - TLS - AWS IoT ---------------------------------- +//#define USE_MQTT_TLS // Use TLS for MQTT connection (+56.7k code, +6.0k mem and +6.6k additional during connection handshake) + //#define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+56.7k code, +6.0k mem and +6.6k additional during connection handshake) + // note: enabling USE_MQTT_AWS_IOT autoamtically enables USE_MQTT_TLS // you need to generate a private key + certificate per device // and update 'sonoff/sonoff_aws_iot.cpp' // Full documentation here: https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT + #define USE_MQTT_AWS_IOT_SKEY_ON_STACK // copy private key+cert on stack rather than on heap, don't disable unless you see crashes during connections + // -- KNX IP Protocol ----------------------------- //#define USE_KNX // Enable KNX IP Protocol Support (+9.4k code, +3k7 mem) @@ -285,7 +284,7 @@ #define USE_EMULATION_WEMO // Enable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) // -- mDNS ---------------------------------------- -#define USE_DISCOVERY // Enable mDNS for the following services (+8k code or +23.5k code with core 2_5_x, +0.3k mem) +//#define USE_DISCOVERY // Enable mDNS for the following services (+8k code or +23.5k code with core 2_5_x, +0.3k mem) #define WEBSERVER_ADVERTISE // Provide access to webserver by name .local/ #define MQTT_HOST_DISCOVERY // Find MQTT host server (overrides MQTT_HOST if found) @@ -475,15 +474,7 @@ * No user configurable items below \*********************************************************************************************/ -#if defined(USE_MQTT_TLS) && defined(USE_WEBSERVER) - #error "Select either USE_MQTT_TLS or USE_WEBSERVER as there is just not enough memory to play with" -#endif - -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - #error "Select either USE_MQTT_TLS or USE_MQTT_AWS_IOT, they are not compatible" -#endif - -#if defined(USE_DISCOVERY) && defined(USE_MQTT_AWS_IOT) +#if defined(USE_DISCOVERY) && defined(USE_MQTT_TLS) #error "Select either USE_DISCOVERY or USE_MQTT_AWS_IOT, mDNS takes too much code space and is not needed for AWS IoT" #endif diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 575776072..e1d84a65f 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1855,8 +1855,13 @@ void PublishStatus(uint8_t payload) } if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { +#ifdef USE_MQTT_AWS_IOT + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), + Settings.mqtt_user, Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); +#else Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, Settings.mqtt_user, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); +#endif MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); } diff --git a/sonoff/sonoff_ca.ino b/sonoff/sonoff_ca.ino new file mode 100644 index 000000000..de579a57a --- /dev/null +++ b/sonoff/sonoff_ca.ino @@ -0,0 +1,236 @@ +/* + sonoff_ca.ino - Certificate authorities for Sonoff-Tasmota, LetsEncrypt and AWS + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// The below is currenlty not used, CA validation takes too much memory and compute time. +// Please use fingerprint validation instead +// However, the CA are available below for future use if it appears to be useful + +#ifdef USE_MQTT_TLS_CA_CERT +/*********************************************************************************************\ + * LetsEncrypt IdenTrust DST Root CA X3 certificate, RSA 2048 bits SHA 256, valid until 20210417 + * + * https://letsencrypt.org/certificates/ + * Downloaded from https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt + * + * to convert do: ‘bearssl chain lets-encrypt-x3-cross-signed.pem.txt’ + * then copy and paste below, chain the generic names to the same as below + * remove ‘static’ and add ‘PROGMEM’ +\*********************************************************************************************/ + +const unsigned char PROGMEM LetsencryptRootCA3[] = { + 0x30, 0x82, 0x04, 0x92, 0x30, 0x82, 0x03, 0x7A, 0xA0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x10, 0x0A, 0x01, 0x41, 0x42, 0x00, 0x00, 0x01, 0x53, 0x85, + 0x73, 0x6A, 0x0B, 0x85, 0xEC, 0xA7, 0x08, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x3F, + 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x44, + 0x69, 0x67, 0x69, 0x74, 0x61, 0x6C, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, + 0x6F, 0x2E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x0E, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, + 0x20, 0x58, 0x33, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x30, 0x33, 0x31, + 0x37, 0x31, 0x36, 0x34, 0x30, 0x34, 0x36, 0x5A, 0x17, 0x0D, 0x32, 0x31, + 0x30, 0x33, 0x31, 0x37, 0x31, 0x36, 0x34, 0x30, 0x34, 0x36, 0x5A, 0x30, + 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + 0x0D, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x1A, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, + 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, + 0x9C, 0xD3, 0x0C, 0xF0, 0x5A, 0xE5, 0x2E, 0x47, 0xB7, 0x72, 0x5D, 0x37, + 0x83, 0xB3, 0x68, 0x63, 0x30, 0xEA, 0xD7, 0x35, 0x26, 0x19, 0x25, 0xE1, + 0xBD, 0xBE, 0x35, 0xF1, 0x70, 0x92, 0x2F, 0xB7, 0xB8, 0x4B, 0x41, 0x05, + 0xAB, 0xA9, 0x9E, 0x35, 0x08, 0x58, 0xEC, 0xB1, 0x2A, 0xC4, 0x68, 0x87, + 0x0B, 0xA3, 0xE3, 0x75, 0xE4, 0xE6, 0xF3, 0xA7, 0x62, 0x71, 0xBA, 0x79, + 0x81, 0x60, 0x1F, 0xD7, 0x91, 0x9A, 0x9F, 0xF3, 0xD0, 0x78, 0x67, 0x71, + 0xC8, 0x69, 0x0E, 0x95, 0x91, 0xCF, 0xFE, 0xE6, 0x99, 0xE9, 0x60, 0x3C, + 0x48, 0xCC, 0x7E, 0xCA, 0x4D, 0x77, 0x12, 0x24, 0x9D, 0x47, 0x1B, 0x5A, + 0xEB, 0xB9, 0xEC, 0x1E, 0x37, 0x00, 0x1C, 0x9C, 0xAC, 0x7B, 0xA7, 0x05, + 0xEA, 0xCE, 0x4A, 0xEB, 0xBD, 0x41, 0xE5, 0x36, 0x98, 0xB9, 0xCB, 0xFD, + 0x6D, 0x3C, 0x96, 0x68, 0xDF, 0x23, 0x2A, 0x42, 0x90, 0x0C, 0x86, 0x74, + 0x67, 0xC8, 0x7F, 0xA5, 0x9A, 0xB8, 0x52, 0x61, 0x14, 0x13, 0x3F, 0x65, + 0xE9, 0x82, 0x87, 0xCB, 0xDB, 0xFA, 0x0E, 0x56, 0xF6, 0x86, 0x89, 0xF3, + 0x85, 0x3F, 0x97, 0x86, 0xAF, 0xB0, 0xDC, 0x1A, 0xEF, 0x6B, 0x0D, 0x95, + 0x16, 0x7D, 0xC4, 0x2B, 0xA0, 0x65, 0xB2, 0x99, 0x04, 0x36, 0x75, 0x80, + 0x6B, 0xAC, 0x4A, 0xF3, 0x1B, 0x90, 0x49, 0x78, 0x2F, 0xA2, 0x96, 0x4F, + 0x2A, 0x20, 0x25, 0x29, 0x04, 0xC6, 0x74, 0xC0, 0xD0, 0x31, 0xCD, 0x8F, + 0x31, 0x38, 0x95, 0x16, 0xBA, 0xA8, 0x33, 0xB8, 0x43, 0xF1, 0xB1, 0x1F, + 0xC3, 0x30, 0x7F, 0xA2, 0x79, 0x31, 0x13, 0x3D, 0x2D, 0x36, 0xF8, 0xE3, + 0xFC, 0xF2, 0x33, 0x6A, 0xB9, 0x39, 0x31, 0xC5, 0xAF, 0xC4, 0x8D, 0x0D, + 0x1D, 0x64, 0x16, 0x33, 0xAA, 0xFA, 0x84, 0x29, 0xB6, 0xD4, 0x0B, 0xC0, + 0xD8, 0x7D, 0xC3, 0x93, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, + 0x7D, 0x30, 0x82, 0x01, 0x79, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, + 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, + 0x00, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, + 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x7F, 0x06, 0x08, 0x2B, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x73, 0x30, 0x71, 0x30, 0x32, 0x06, + 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x26, 0x68, + 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x69, 0x73, 0x72, 0x67, 0x2E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x69, 0x64, 0x2E, 0x6F, 0x63, 0x73, 0x70, 0x2E, + 0x69, 0x64, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x63, 0x6F, + 0x6D, 0x30, 0x3B, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, + 0x02, 0x86, 0x2F, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x61, 0x70, + 0x70, 0x73, 0x2E, 0x69, 0x64, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x72, 0x6F, 0x6F, 0x74, 0x73, 0x2F, 0x64, + 0x73, 0x74, 0x72, 0x6F, 0x6F, 0x74, 0x63, 0x61, 0x78, 0x33, 0x2E, 0x70, + 0x37, 0x63, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, + 0x16, 0x80, 0x14, 0xC4, 0xA7, 0xB1, 0xA4, 0x7B, 0x2C, 0x71, 0xFA, 0xDB, + 0xE1, 0x4B, 0x90, 0x75, 0xFF, 0xC4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30, + 0x54, 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04, 0x4D, 0x30, 0x4B, 0x30, 0x08, + 0x06, 0x06, 0x67, 0x81, 0x0C, 0x01, 0x02, 0x01, 0x30, 0x3F, 0x06, 0x0B, + 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xDF, 0x13, 0x01, 0x01, 0x01, 0x30, + 0x30, 0x30, 0x2E, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, + 0x01, 0x16, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x70, + 0x73, 0x2E, 0x72, 0x6F, 0x6F, 0x74, 0x2D, 0x78, 0x31, 0x2E, 0x6C, 0x65, + 0x74, 0x73, 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2E, 0x6F, 0x72, + 0x67, 0x30, 0x3C, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x35, 0x30, 0x33, + 0x30, 0x31, 0xA0, 0x2F, 0xA0, 0x2D, 0x86, 0x2B, 0x68, 0x74, 0x74, 0x70, + 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, 0x69, 0x64, 0x65, 0x6E, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x44, 0x53, 0x54, + 0x52, 0x4F, 0x4F, 0x54, 0x43, 0x41, 0x58, 0x33, 0x43, 0x52, 0x4C, 0x2E, + 0x63, 0x72, 0x6C, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + 0x04, 0x14, 0xA8, 0x4A, 0x6A, 0x63, 0x04, 0x7D, 0xDD, 0xBA, 0xE6, 0xD1, + 0x39, 0xB7, 0xA6, 0x45, 0x65, 0xEF, 0xF3, 0xA8, 0xEC, 0xA1, 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xDD, 0x33, 0xD7, 0x11, 0xF3, 0x63, + 0x58, 0x38, 0xDD, 0x18, 0x15, 0xFB, 0x09, 0x55, 0xBE, 0x76, 0x56, 0xB9, + 0x70, 0x48, 0xA5, 0x69, 0x47, 0x27, 0x7B, 0xC2, 0x24, 0x08, 0x92, 0xF1, + 0x5A, 0x1F, 0x4A, 0x12, 0x29, 0x37, 0x24, 0x74, 0x51, 0x1C, 0x62, 0x68, + 0xB8, 0xCD, 0x95, 0x70, 0x67, 0xE5, 0xF7, 0xA4, 0xBC, 0x4E, 0x28, 0x51, + 0xCD, 0x9B, 0xE8, 0xAE, 0x87, 0x9D, 0xEA, 0xD8, 0xBA, 0x5A, 0xA1, 0x01, + 0x9A, 0xDC, 0xF0, 0xDD, 0x6A, 0x1D, 0x6A, 0xD8, 0x3E, 0x57, 0x23, 0x9E, + 0xA6, 0x1E, 0x04, 0x62, 0x9A, 0xFF, 0xD7, 0x05, 0xCA, 0xB7, 0x1F, 0x3F, + 0xC0, 0x0A, 0x48, 0xBC, 0x94, 0xB0, 0xB6, 0x65, 0x62, 0xE0, 0xC1, 0x54, + 0xE5, 0xA3, 0x2A, 0xAD, 0x20, 0xC4, 0xE9, 0xE6, 0xBB, 0xDC, 0xC8, 0xF6, + 0xB5, 0xC3, 0x32, 0xA3, 0x98, 0xCC, 0x77, 0xA8, 0xE6, 0x79, 0x65, 0x07, + 0x2B, 0xCB, 0x28, 0xFE, 0x3A, 0x16, 0x52, 0x81, 0xCE, 0x52, 0x0C, 0x2E, + 0x5F, 0x83, 0xE8, 0xD5, 0x06, 0x33, 0xFB, 0x77, 0x6C, 0xCE, 0x40, 0xEA, + 0x32, 0x9E, 0x1F, 0x92, 0x5C, 0x41, 0xC1, 0x74, 0x6C, 0x5B, 0x5D, 0x0A, + 0x5F, 0x33, 0xCC, 0x4D, 0x9F, 0xAC, 0x38, 0xF0, 0x2F, 0x7B, 0x2C, 0x62, + 0x9D, 0xD9, 0xA3, 0x91, 0x6F, 0x25, 0x1B, 0x2F, 0x90, 0xB1, 0x19, 0x46, + 0x3D, 0xF6, 0x7E, 0x1B, 0xA6, 0x7A, 0x87, 0xB9, 0xA3, 0x7A, 0x6D, 0x18, + 0xFA, 0x25, 0xA5, 0x91, 0x87, 0x15, 0xE0, 0xF2, 0x16, 0x2F, 0x58, 0xB0, + 0x06, 0x2F, 0x2C, 0x68, 0x26, 0xC6, 0x4B, 0x98, 0xCD, 0xDA, 0x9F, 0x0C, + 0xF9, 0x7F, 0x90, 0xED, 0x43, 0x4A, 0x12, 0x44, 0x4E, 0x6F, 0x73, 0x7A, + 0x28, 0xEA, 0xA4, 0xAA, 0x6E, 0x7B, 0x4C, 0x7D, 0x87, 0xDD, 0xE0, 0xC9, + 0x02, 0x44, 0xA7, 0x87, 0xAF, 0xC3, 0x34, 0x5B, 0xB4, 0x42 +}; + +const br_x509_certificate PROGMEM LetsencryptRootCA3_chain[] = { + { (unsigned char *)LetsencryptRootCA3, sizeof LetsencryptRootCA3 } +}; + +#define LETSENCRYPTROOTCA3LEN 1 + +#endif // USE_MQTT_TLS_CA_CERT + +#ifdef USE_MQTT_AWS_IOT +/*********************************************************************************************\ + * Amazon Root CA, RSA 2048 bits SHA 256, valid until 20380117 + * + * https://letsencrypt.org/certificates/ + * Downloaded from https://www.amazontrust.com/repository/AmazonRootCA1.pem + * + * to convert do: ‘bearssl chain AmazonRootCA1.pem’ + * then copy and paste below, chain the generic names to the same as below + * remove ‘static’ and add ‘PROGMEM’ +\*********************************************************************************************/ + +const unsigned char PROGMEM AmazonRootCA1[] = { + 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xA0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x13, 0x06, 0x6C, 0x9F, 0xCF, 0x99, 0xBF, 0x8C, 0x0A, 0x39, + 0xE2, 0xF0, 0x78, 0x8A, 0x43, 0xE6, 0x96, 0x36, 0x5B, 0xCA, 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x0A, 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, + 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x35, 0x32, 0x36, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x31, 0x31, + 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x39, 0x31, 0x0B, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x06, 0x41, 0x6D, + 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, + 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, + 0x82, 0x01, 0x01, 0x00, 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, + 0x71, 0xAF, 0x47, 0x80, 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, + 0xF4, 0x99, 0x68, 0xF7, 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, + 0xAC, 0x02, 0x2D, 0x86, 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, + 0x36, 0xBA, 0x01, 0xBE, 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, + 0xF4, 0xEE, 0x88, 0x23, 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, + 0x49, 0x68, 0xB0, 0xDE, 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, + 0xFE, 0x82, 0x36, 0xA5, 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, + 0xB4, 0x16, 0xFA, 0x74, 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, + 0x20, 0x50, 0x06, 0x6C, 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, + 0x47, 0x19, 0x8F, 0x50, 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, + 0xBA, 0xD5, 0xA9, 0xF9, 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, + 0x6F, 0x89, 0xA3, 0x51, 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, + 0x54, 0xEB, 0xA3, 0xC3, 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, + 0x2D, 0x7D, 0x2D, 0x74, 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, + 0x59, 0x6E, 0xBB, 0x73, 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, + 0xFA, 0xB7, 0x1D, 0xAA, 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, + 0xF7, 0x71, 0x5C, 0x5E, 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, + 0xAE, 0x50, 0x38, 0x6F, 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, + 0x54, 0xE1, 0x77, 0xE0, 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, + 0x40, 0x20, 0x7F, 0x20, 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, + 0x8E, 0x04, 0xAE, 0x6C, 0x9A, 0xC8, 0xAA, 0x0D, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xA3, 0x42, 0x30, 0x40, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, + 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, + 0x01, 0x86, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0x84, 0x18, 0xCC, 0x85, 0x34, 0xEC, 0xBC, 0x0C, 0x94, 0x94, 0x2E, + 0x08, 0x59, 0x9C, 0xC7, 0xB2, 0x10, 0x4E, 0x0A, 0x08, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x01, 0x00, 0x98, 0xF2, 0x37, 0x5A, 0x41, 0x90, 0xA1, + 0x1A, 0xC5, 0x76, 0x51, 0x28, 0x20, 0x36, 0x23, 0x0E, 0xAE, 0xE6, 0x28, + 0xBB, 0xAA, 0xF8, 0x94, 0xAE, 0x48, 0xA4, 0x30, 0x7F, 0x1B, 0xFC, 0x24, + 0x8D, 0x4B, 0xB4, 0xC8, 0xA1, 0x97, 0xF6, 0xB6, 0xF1, 0x7A, 0x70, 0xC8, + 0x53, 0x93, 0xCC, 0x08, 0x28, 0xE3, 0x98, 0x25, 0xCF, 0x23, 0xA4, 0xF9, + 0xDE, 0x21, 0xD3, 0x7C, 0x85, 0x09, 0xAD, 0x4E, 0x9A, 0x75, 0x3A, 0xC2, + 0x0B, 0x6A, 0x89, 0x78, 0x76, 0x44, 0x47, 0x18, 0x65, 0x6C, 0x8D, 0x41, + 0x8E, 0x3B, 0x7F, 0x9A, 0xCB, 0xF4, 0xB5, 0xA7, 0x50, 0xD7, 0x05, 0x2C, + 0x37, 0xE8, 0x03, 0x4B, 0xAD, 0xE9, 0x61, 0xA0, 0x02, 0x6E, 0xF5, 0xF2, + 0xF0, 0xC5, 0xB2, 0xED, 0x5B, 0xB7, 0xDC, 0xFA, 0x94, 0x5C, 0x77, 0x9E, + 0x13, 0xA5, 0x7F, 0x52, 0xAD, 0x95, 0xF2, 0xF8, 0x93, 0x3B, 0xDE, 0x8B, + 0x5C, 0x5B, 0xCA, 0x5A, 0x52, 0x5B, 0x60, 0xAF, 0x14, 0xF7, 0x4B, 0xEF, + 0xA3, 0xFB, 0x9F, 0x40, 0x95, 0x6D, 0x31, 0x54, 0xFC, 0x42, 0xD3, 0xC7, + 0x46, 0x1F, 0x23, 0xAD, 0xD9, 0x0F, 0x48, 0x70, 0x9A, 0xD9, 0x75, 0x78, + 0x71, 0xD1, 0x72, 0x43, 0x34, 0x75, 0x6E, 0x57, 0x59, 0xC2, 0x02, 0x5C, + 0x26, 0x60, 0x29, 0xCF, 0x23, 0x19, 0x16, 0x8E, 0x88, 0x43, 0xA5, 0xD4, + 0xE4, 0xCB, 0x08, 0xFB, 0x23, 0x11, 0x43, 0xE8, 0x43, 0x29, 0x72, 0x62, + 0xA1, 0xA9, 0x5D, 0x5E, 0x08, 0xD4, 0x90, 0xAE, 0xB8, 0xD8, 0xCE, 0x14, + 0xC2, 0xD0, 0x55, 0xF2, 0x86, 0xF6, 0xC4, 0x93, 0x43, 0x77, 0x66, 0x61, + 0xC0, 0xB9, 0xE8, 0x41, 0xD7, 0x97, 0x78, 0x60, 0x03, 0x6E, 0x4A, 0x72, + 0xAE, 0xA5, 0xD1, 0x7D, 0xBA, 0x10, 0x9E, 0x86, 0x6C, 0x1B, 0x8A, 0xB9, + 0x59, 0x33, 0xF8, 0xEB, 0xC4, 0x90, 0xBE, 0xF1, 0xB9 +}; + +const br_x509_certificate PROGMEM AmazonRootCA1_chain[] = { + { (unsigned char *)AmazonRootCA1, sizeof AmazonRootCA1 } +}; + +#define AMAZONROOTCA1_LEN 1 + +#endif diff --git a/sonoff/sonoff_letsencrypt.h b/sonoff/sonoff_letsencrypt.h deleted file mode 100644 index 24735b2bd..000000000 --- a/sonoff/sonoff_letsencrypt.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - sonoff_letsencrypt.h - TLS Lets Encrypt certificate for Sonoff-Tasmota - - Copyright (C) 2019 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_MQTT_TLS_CA_CERT -/*********************************************************************************************\ - * LetsEncrypt IdenTrust DST Root CA X3 certificate valid until 20210930 - * - * https://letsencrypt.org/certificates/ - * Downloaded from https://www.identrust.com/support/downloads -\*********************************************************************************************/ - -#define MQTT_TLS_CA_CERT_LENGTH 846 // Letsencrypt -#define MQTT_TLS_CA_CERT { \ - 0x30, 0x82, 0x03, 0x4a, 0x30, 0x82, 0x02, 0x32, 0xa0, 0x03, 0x02, 0x01, \ - 0x02, 0x02, 0x10, 0x44, 0xaf, 0xb0, 0x80, 0xd6, 0xa3, 0x27, 0xba, 0x89, \ - 0x30, 0x39, 0x86, 0x2e, 0xf8, 0x40, 0x6b, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3f, \ - 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x44, \ - 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, \ - 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, \ - 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ - 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, \ - 0x20, 0x58, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x39, 0x33, \ - 0x30, 0x32, 0x31, 0x31, 0x32, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x31, \ - 0x30, 0x39, 0x33, 0x30, 0x31, 0x34, 0x30, 0x31, 0x31, 0x35, 0x5a, 0x30, \ - 0x3f, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, \ - 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, \ - 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, \ - 0x43, 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, \ - 0x13, 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, \ - 0x41, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, \ - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, \ - 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, \ - 0x00, 0xdf, 0xaf, 0xe9, 0x97, 0x50, 0x08, 0x83, 0x57, 0xb4, 0xcc, 0x62, \ - 0x65, 0xf6, 0x90, 0x82, 0xec, 0xc7, 0xd3, 0x2c, 0x6b, 0x30, 0xca, 0x5b, \ - 0xec, 0xd9, 0xc3, 0x7d, 0xc7, 0x40, 0xc1, 0x18, 0x14, 0x8b, 0xe0, 0xe8, \ - 0x33, 0x76, 0x49, 0x2a, 0xe3, 0x3f, 0x21, 0x49, 0x93, 0xac, 0x4e, 0x0e, \ - 0xaf, 0x3e, 0x48, 0xcb, 0x65, 0xee, 0xfc, 0xd3, 0x21, 0x0f, 0x65, 0xd2, \ - 0x2a, 0xd9, 0x32, 0x8f, 0x8c, 0xe5, 0xf7, 0x77, 0xb0, 0x12, 0x7b, 0xb5, \ - 0x95, 0xc0, 0x89, 0xa3, 0xa9, 0xba, 0xed, 0x73, 0x2e, 0x7a, 0x0c, 0x06, \ - 0x32, 0x83, 0xa2, 0x7e, 0x8a, 0x14, 0x30, 0xcd, 0x11, 0xa0, 0xe1, 0x2a, \ - 0x38, 0xb9, 0x79, 0x0a, 0x31, 0xfd, 0x50, 0xbd, 0x80, 0x65, 0xdf, 0xb7, \ - 0x51, 0x63, 0x83, 0xc8, 0xe2, 0x88, 0x61, 0xea, 0x4b, 0x61, 0x81, 0xec, \ - 0x52, 0x6b, 0xb9, 0xa2, 0xe2, 0x4b, 0x1a, 0x28, 0x9f, 0x48, 0xa3, 0x9e, \ - 0x0c, 0xda, 0x09, 0x8e, 0x3e, 0x17, 0x2e, 0x1e, 0xdd, 0x20, 0xdf, 0x5b, \ - 0xc6, 0x2a, 0x8a, 0xab, 0x2e, 0xbd, 0x70, 0xad, 0xc5, 0x0b, 0x1a, 0x25, \ - 0x90, 0x74, 0x72, 0xc5, 0x7b, 0x6a, 0xab, 0x34, 0xd6, 0x30, 0x89, 0xff, \ - 0xe5, 0x68, 0x13, 0x7b, 0x54, 0x0b, 0xc8, 0xd6, 0xae, 0xec, 0x5a, 0x9c, \ - 0x92, 0x1e, 0x3d, 0x64, 0xb3, 0x8c, 0xc6, 0xdf, 0xbf, 0xc9, 0x41, 0x70, \ - 0xec, 0x16, 0x72, 0xd5, 0x26, 0xec, 0x38, 0x55, 0x39, 0x43, 0xd0, 0xfc, \ - 0xfd, 0x18, 0x5c, 0x40, 0xf1, 0x97, 0xeb, 0xd5, 0x9a, 0x9b, 0x8d, 0x1d, \ - 0xba, 0xda, 0x25, 0xb9, 0xc6, 0xd8, 0xdf, 0xc1, 0x15, 0x02, 0x3a, 0xab, \ - 0xda, 0x6e, 0xf1, 0x3e, 0x2e, 0xf5, 0x5c, 0x08, 0x9c, 0x3c, 0xd6, 0x83, \ - 0x69, 0xe4, 0x10, 0x9b, 0x19, 0x2a, 0xb6, 0x29, 0x57, 0xe3, 0xe5, 0x3d, \ - 0x9b, 0x9f, 0xf0, 0x02, 0x5d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, \ - 0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, \ - 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, \ - 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, \ - 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc4, 0xa7, \ - 0xb1, 0xa4, 0x7b, 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, 0x75, 0xff, \ - 0xc4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, \ - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, \ - 0x01, 0x00, 0xa3, 0x1a, 0x2c, 0x9b, 0x17, 0x00, 0x5c, 0xa9, 0x1e, 0xee, \ - 0x28, 0x66, 0x37, 0x3a, 0xbf, 0x83, 0xc7, 0x3f, 0x4b, 0xc3, 0x09, 0xa0, \ - 0x95, 0x20, 0x5d, 0xe3, 0xd9, 0x59, 0x44, 0xd2, 0x3e, 0x0d, 0x3e, 0xbd, \ - 0x8a, 0x4b, 0xa0, 0x74, 0x1f, 0xce, 0x10, 0x82, 0x9c, 0x74, 0x1a, 0x1d, \ - 0x7e, 0x98, 0x1a, 0xdd, 0xcb, 0x13, 0x4b, 0xb3, 0x20, 0x44, 0xe4, 0x91, \ - 0xe9, 0xcc, 0xfc, 0x7d, 0xa5, 0xdb, 0x6a, 0xe5, 0xfe, 0xe6, 0xfd, 0xe0, \ - 0x4e, 0xdd, 0xb7, 0x00, 0x3a, 0xb5, 0x70, 0x49, 0xaf, 0xf2, 0xe5, 0xeb, \ - 0x02, 0xf1, 0xd1, 0x02, 0x8b, 0x19, 0xcb, 0x94, 0x3a, 0x5e, 0x48, 0xc4, \ - 0x18, 0x1e, 0x58, 0x19, 0x5f, 0x1e, 0x02, 0x5a, 0xf0, 0x0c, 0xf1, 0xb1, \ - 0xad, 0xa9, 0xdc, 0x59, 0x86, 0x8b, 0x6e, 0xe9, 0x91, 0xf5, 0x86, 0xca, \ - 0xfa, 0xb9, 0x66, 0x33, 0xaa, 0x59, 0x5b, 0xce, 0xe2, 0xa7, 0x16, 0x73, \ - 0x47, 0xcb, 0x2b, 0xcc, 0x99, 0xb0, 0x37, 0x48, 0xcf, 0xe3, 0x56, 0x4b, \ - 0xf5, 0xcf, 0x0f, 0x0c, 0x72, 0x32, 0x87, 0xc6, 0xf0, 0x44, 0xbb, 0x53, \ - 0x72, 0x6d, 0x43, 0xf5, 0x26, 0x48, 0x9a, 0x52, 0x67, 0xb7, 0x58, 0xab, \ - 0xfe, 0x67, 0x76, 0x71, 0x78, 0xdb, 0x0d, 0xa2, 0x56, 0x14, 0x13, 0x39, \ - 0x24, 0x31, 0x85, 0xa2, 0xa8, 0x02, 0x5a, 0x30, 0x47, 0xe1, 0xdd, 0x50, \ - 0x07, 0xbc, 0x02, 0x09, 0x90, 0x00, 0xeb, 0x64, 0x63, 0x60, 0x9b, 0x16, \ - 0xbc, 0x88, 0xc9, 0x12, 0xe6, 0xd2, 0x7d, 0x91, 0x8b, 0xf9, 0x3d, 0x32, \ - 0x8d, 0x65, 0xb4, 0xe9, 0x7c, 0xb1, 0x57, 0x76, 0xea, 0xc5, 0xb6, 0x28, \ - 0x39, 0xbf, 0x15, 0x65, 0x1c, 0xc8, 0xf6, 0x77, 0x96, 0x6a, 0x0a, 0x8d, \ - 0x77, 0x0b, 0xd8, 0x91, 0x0b, 0x04, 0x8e, 0x07, 0xdb, 0x29, 0xb6, 0x0a, \ - 0xee, 0x9d, 0x82, 0x35, 0x35, 0x10 } - -#endif // USE_MQTT_TLS_CA_CERT diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 416f1a3d0..fdfcbbeae 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -46,11 +46,21 @@ void KNX_CB_Action(message_t const &msg, void *arg); * Default global defines \*********************************************************************************************/ -#ifdef USE_MQTT_AWS_IOT -#include -#ifndef ARDUINO_ESP8266_RELEASE_2_5_2 - #error "USE_MQTT_AWS_IOT is only supported on core version 2.5.2" +// #ifdef USE_MQTT_AWS_IOT +// #include +// #ifndef ARDUINO_ESP8266_RELEASE_2_5_2 +// #error "USE_MQTT_AWS_IOT is only supported on core version 2.5.2" +// #endif +// #endif + +#ifdef USE_EMULATION_HUE +#define USE_EMULATION #endif +#ifdef USE_EMULATION_WEMO +#define USE_EMULATION +#endif +#ifdef USE_MQTT_AWS_IOT +#define USE_MQTT_TLS #endif #if defined(USE_MQTT_TLS) || defined(USE_MQTT_AWS_IOT) @@ -59,11 +69,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); const uint16_t WEB_LOG_SIZE = 4000; // Max number of characters in weblog #endif -#ifdef USE_EMULATION_HUE -#define USE_EMULATION -#endif -#ifdef USE_EMULATION_WEMO -#define USE_EMULATION +#if defined(USE_MQTT_TLS) && defined(ARDUINO_ESP8266_RELEASE_2_3_0) + #error "TLS is no more supported on Core 2.3.0, use 2.4.2 or higher." #endif #ifndef MODULE diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 939ab5b7c..a1a2c2d89 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1759,9 +1759,14 @@ void HandleInformation(void) } WSContentSend_P(PSTR("}1}2 ")); // Empty line if (Settings.flag.mqtt_enabled) { +#ifdef USE_MQTT_AWS_IOT + WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s%s"), Settings.mqtt_user, Settings.mqtt_host); + WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); +#else WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), Settings.mqtt_host); WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), Settings.mqtt_user); +#endif WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), Settings.mqtt_topic); WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), Settings.mqtt_grptopic); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index d1a0b8d26..4b7b53f74 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -20,13 +20,8 @@ #define XDRV_02 2 #ifdef USE_MQTT_TLS -#ifdef USE_MQTT_TLS_CA_CERT - #include "sonoff_letsencrypt.h" // LetsEncrypt certificate -#endif - WiFiClientSecure EspClient; // Wifi Secure Client -#elif defined(USE_MQTT_AWS_IOT) #include "WiFiClientSecureLightBearSSL.h" - BearSSL::WiFiClientSecure_light *awsClient; + BearSSL::WiFiClientSecure_light *tlsClient; #else WiFiClient EspClient; // Wifi Client #endif @@ -49,13 +44,35 @@ uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state bool mqtt_connected = false; // MQTT virtual connection status bool mqtt_allowed = false; // MQTT enabled and parameters valid -#ifdef USE_MQTT_AWS_IOT +#ifdef USE_MQTT_TLS + +// see https://stackoverflow.com/questions/6357031/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-in-c +void to_hex(unsigned char * in, size_t insz, char * out, size_t outsz) { + unsigned char * pin = in; + static const char * hex = "0123456789ABCDEF"; + char * pout = out; + for(; pin < in+insz; pout +=3, pin++){ + pout[0] = hex[(*pin>>4) & 0xF]; + pout[1] = hex[ *pin & 0xF]; + pout[2] = ' '; + if (pout + 3 - out > outsz){ + /* Better to truncate output string than overflow buffer */ + /* it would be still better to either return a status */ + /* or ensure the target buffer is large enough and it never happen */ + break; + } + } + pout[-1] = 0; +} + +#ifdef USE_MQTT_AWS_IOT namespace aws_iot_privkey { // this is where the Private Key and Certificate are stored extern const br_ec_private_key *AWS_IoT_Private_Key; extern const br_x509_certificate *AWS_IoT_Client_Certificate; } +#endif // A typical AWS IoT endpoint is 50 characters long, it does not fit // in MqttHost field (32 chars). We need to concatenate both MqttUser and MqttHost @@ -73,7 +90,7 @@ bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value) { return true; } -#endif // USE_MQTT_AWS_IOT +#endif // USE_MQTT_TLS /*********************************************************************************************\ * MQTT driver specific code need to provide the following functions: @@ -91,7 +108,7 @@ bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value) { #error "MQTT_MAX_PACKET_SIZE is too small in libraries/PubSubClient/src/PubSubClient.h, increase it to at least 1000" #endif -#ifdef USE_MQTT_AWS_IOT +#ifdef USE_MQTT_TLS PubSubClient MqttClient; #else PubSubClient MqttClient(EspClient); @@ -99,24 +116,18 @@ PubSubClient MqttClient(EspClient); void MqttInit(void) { -#ifdef USE_MQTT_AWS_IOT - AWS_endpoint[0] = 0; - uint8_t len_user = strlen(Settings.mqtt_user); - uint8_t len_host = strlen(Settings.mqtt_host); - if (len_user > 0) { - strcpy(AWS_endpoint, Settings.mqtt_user); - if (('.' != AWS_endpoint[len_user-1]) && ('.' != Settings.mqtt_host[0])) { - AWS_endpoint[len_user++] = '.'; - } - strcpy(&AWS_endpoint[len_user], Settings.mqtt_host); - } +#ifdef USE_MQTT_TLS + tlsClient = new BearSSL::WiFiClientSecure_light(1024,1024); - awsClient = new BearSSL::WiFiClientSecure_light(1024,1024); - awsClient->setClientECCert(aws_iot_privkey::AWS_IoT_Client_Certificate, +#ifdef USE_MQTT_AWS_IOT + snprintf(AWS_endpoint, sizeof(AWS_endpoint), PSTR("%s%s"), Settings.mqtt_user, Settings.mqtt_host); + + tlsClient->setClientECCert(aws_iot_privkey::AWS_IoT_Client_Certificate, aws_iot_privkey::AWS_IoT_Private_Key, 0xFFFF /* all usages, don't care */, 0); +#endif - MqttClient.setClient(*awsClient); + MqttClient.setClient(*tlsClient); #endif } @@ -411,67 +422,6 @@ void MqttConnected(void) } } -#ifdef USE_MQTT_TLS -bool MqttCheckTls(void) -{ - char fingerprint1[60]; - char fingerprint2[60]; - bool result = false; - - fingerprint1[0] = '\0'; - fingerprint2[0] = '\0'; - for (uint8_t i = 0; i < sizeof(Settings.mqtt_fingerprint[0]); i++) { - snprintf_P(fingerprint1, sizeof(fingerprint1), PSTR("%s%s%02X"), fingerprint1, (i) ? " " : "", Settings.mqtt_fingerprint[0][i]); - snprintf_P(fingerprint2, sizeof(fingerprint2), PSTR("%s%s%02X"), fingerprint2, (i) ? " " : "", Settings.mqtt_fingerprint[1][i]); - } - - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_FINGERPRINT)); - -//#ifdef ARDUINO_ESP8266_RELEASE_2_4_1 - EspClient = WiFiClientSecure(); // Wifi Secure Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) -//#endif - - if (!EspClient.connect(Settings.mqtt_host, Settings.mqtt_port)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT D_TLS_CONNECT_FAILED_TO " %s:%d. " D_RETRY_IN " %d " D_UNIT_SECOND), Settings.mqtt_host, Settings.mqtt_port, mqtt_retry_counter); - } else { -#ifdef USE_MQTT_TLS_CA_CERT - unsigned char tls_ca_cert[] = MQTT_TLS_CA_CERT; - if (EspClient.setCACert(tls_ca_cert, MQTT_TLS_CA_CERT_LENGTH)) { - if (EspClient.verifyCertChain(Settings.mqtt_host)) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "CA")); - result = true; - } - } -#else - if (EspClient.verify(fingerprint1, Settings.mqtt_host)) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "1")); - result = true; - } - else if (EspClient.verify(fingerprint2, Settings.mqtt_host)) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "2")); - result = true; - } -#ifdef MDNS_HOSTNAME - // If the hostname is set, check that as well. - // This lets certs with the hostname for the CN be used. - else if (EspClient.verify(fingerprint1, MDNS_HOSTNAME)) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "1")); - result = true; - } - else if (EspClient.verify(fingerprint2, MDNS_HOSTNAME)) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "2")); - result = true; - } -#endif // MDNS_HOSTNAME -#endif // USE_MQTT_TLS_CA_CERT - } - if (!result) AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_FAILED)); - EspClient.stop(); - yield(); - return result; -} -#endif // USE_MQTT_TLS - void MqttReconnect(void) { char stopic[TOPSZ]; @@ -512,19 +462,13 @@ void MqttReconnect(void) if (MqttClient.connected()) { MqttClient.disconnect(); } #ifdef USE_MQTT_TLS - EspClient = WiFiClientSecure(); // Wifi Secure Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) - MqttClient.setClient(EspClient); -#elif defined(USE_MQTT_AWS_IOT) - awsClient->stop(); + tlsClient->stop(); #else EspClient = WiFiClient(); // Wifi Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) MqttClient.setClient(EspClient); #endif if (2 == mqtt_initial_connection_state) { // Executed once just after power on and wifi is connected -#ifdef USE_MQTT_TLS - if (!MqttCheckTls()) return; -#endif // USE_MQTT_TLS mqtt_initial_connection_state = 1; } @@ -535,17 +479,9 @@ void MqttReconnect(void) #else MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); #endif -/* - // Skip MQTT host DNS lookup if not needed - uint32_t current_hash = GetHash(Settings.mqtt_host, strlen(Settings.mqtt_host)); - if (mqtt_host_hash != current_hash) { - mqtt_host_hash = current_hash; - WiFi.hostByName(Settings.mqtt_host, mqtt_host_addr); // Skips DNS lookup if mqtt_host is IP address string as from mDns - } - MqttClient.setServer(mqtt_host_addr, Settings.mqtt_port); -*/ - uint32_t time = millis(); -#ifdef USE_MQTT_AWS_IOT + +#ifdef USE_MQTT_TLS + uint32_t mqtt_connect_time = millis(); bool allow_all_fingerprints = false; bool learn_fingerprint1 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0x00); bool learn_fingerprint2 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0x00); @@ -553,18 +489,29 @@ void MqttReconnect(void) allow_all_fingerprints |= is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0xff); allow_all_fingerprints |= learn_fingerprint1; allow_all_fingerprints |= learn_fingerprint2; - awsClient->setPubKeyFingerprint(Settings.mqtt_fingerprint[0], Settings.mqtt_fingerprint[1], allow_all_fingerprints); + tlsClient->setPubKeyFingerprint(Settings.mqtt_fingerprint[0], Settings.mqtt_fingerprint[1], allow_all_fingerprints); +#endif +#ifdef USE_MQTT_AWS_IOT AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "AWS IoT endpoint: %s"), AWS_endpoint); - if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, nullptr, 0, false, nullptr)) { + //if (MqttClient.connect(mqtt_client, nullptr, nullptr, nullptr, 0, false, nullptr)) { + if (MqttClient.connect(mqtt_client, nullptr, nullptr, stopic, 1, false, mqtt_data, MQTT_CLEAN_SESSION)) { #else if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data, MQTT_CLEAN_SESSION)) { #endif -#ifdef USE_MQTT_AWS_IOT - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "AWS IoT connected in %d ms"), millis() - time); +#ifdef USE_MQTT_TLS + // create a printable version of the fingerprint received + char buf_fingerprint[64]; + to_hex((unsigned char *)tlsClient->getRecvPubKeyFingerprint(), 20, buf_fingerprint, 64); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms"), millis() - mqtt_connect_time); + if (!tlsClient->getMFLNStatus()) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR("MFLN not supported by TLS server")); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Server fingerprint: %s"), buf_fingerprint); if (learn_fingerprint1 || learn_fingerprint2) { // we potentially need to learn the fingerprint just seen bool fingerprint_matched = false; - const uint8_t *recv_fingerprint = awsClient->getRecvPubKeyFingerprint(); + const uint8_t *recv_fingerprint = tlsClient->getRecvPubKeyFingerprint(); if (0 == memcmp(recv_fingerprint, Settings.mqtt_fingerprint[0], 20)) { fingerprint_matched = true; } @@ -579,14 +526,16 @@ void MqttReconnect(void) if (learn_fingerprint2) { memcpy(Settings.mqtt_fingerprint[1], recv_fingerprint, 20); } - restart_flag = 2; // save and restart + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Fingerprint learned: %s"), buf_fingerprint); + + SettingsSaveAll(); // save settings } } -#endif +#endif // USE_MQTT_TLS MqttConnected(); } else { -#ifdef USE_MQTT_AWS_IOT - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "AWS IoT connection error: %d"), awsClient->getLastError()); +#ifdef USE_MQTT_TLS + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connection error: %d"), tlsClient->getLastError()); #endif MqttDisconnected(MqttClient.state()); // status codes are documented here http://pubsubclient.knolleary.net/api.html#state } @@ -618,6 +567,20 @@ void MqttCheck(void) /*********************************************************************************************/ +#ifdef USE_MQTT_AWS_IOT +void setLongMqttHost(const char *mqtt_host) { + if (strlen(mqtt_host) <= sizeof(Settings.mqtt_host)) { + strlcpy(Settings.mqtt_host, mqtt_host, sizeof(Settings.mqtt_host)); + Settings.mqtt_user[0] = 0; + } else { + // need to split in mqtt_user first then mqtt_host + strlcpy(Settings.mqtt_user, mqtt_host, sizeof(Settings.mqtt_user)); + strlcpy(Settings.mqtt_host, &mqtt_host[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host)); + } + strlcpy(AWS_endpoint, mqtt_host, sizeof(AWS_endpoint)); +} +#endif // USE_MQTT_AWS_IOT + bool MqttCommand(void) { char command [CMDSZ]; @@ -639,11 +602,19 @@ bool MqttCommand(void) serviced = false; // Unknown command } else if (CMND_MQTTHOST == command_code) { +#ifdef USE_MQTT_AWS_IOT + if ((data_len > 0) && (data_len <= sizeof(Settings.mqtt_host) + sizeof(Settings.mqtt_user) - 2)) { + setLongMqttHost((SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_HOST : dataBuf); + restart_flag = 2; + } + Response_P(S_JSON_COMMAND_SVALUE, command, AWS_endpoint); +#else if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_host))) { strlcpy(Settings.mqtt_host, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_HOST : dataBuf, sizeof(Settings.mqtt_host)); restart_flag = 2; } Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_host); +#endif } else if (CMND_MQTTPORT == command_code) { if (payload16 > 0) { @@ -668,7 +639,7 @@ bool MqttCommand(void) } Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1)); } -#if defined(USE_MQTT_TLS) || defined(USE_MQTT_AWS_IOT) +#ifdef USE_MQTT_TLS else if ((CMND_MQTTFINGERPRINT == command_code) && (index > 0) && (index <= 2)) { char fingerprint[60]; if ((data_len > 0) && (data_len < sizeof(fingerprint))) { @@ -693,6 +664,7 @@ bool MqttCommand(void) } Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_client); } +#ifndef USE_MQTT_AWS_IOT // user and password are diabled with AWS IoT else if (CMND_MQTTUSER == command_code) { if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_user))) { strlcpy(Settings.mqtt_user, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_USER : dataBuf, sizeof(Settings.mqtt_user)); @@ -709,6 +681,7 @@ bool MqttCommand(void) Response_P(S_JSON_COMMAND_ASTERIX, command); } } +#endif // USE_MQTT_AWS_IOT else if (CMND_FULLTOPIC == command_code) { if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_fulltopic))) { MakeValidMqtt(1, dataBuf); @@ -869,8 +842,10 @@ const char HTTP_FORM_MQTT1[] PROGMEM = "

" D_PORT " (" STR(MQTT_PORT) ")

" "

" D_CLIENT " (%s)

"; const char HTTP_FORM_MQTT2[] PROGMEM = +#ifndef USE_MQTT_AWS_IOT // user and password disabled with AWS IoT "

" D_USER " (" MQTT_USER ")

" "

" D_PASSWORD "

" +#endif // USE_MQTT_AWS_IOT "

" D_TOPIC " = %%topic%% (%s)

" "

" D_FULL_TOPIC " (%s)

"; @@ -891,7 +866,11 @@ void HandleMqttConfiguration(void) WSContentStart_P(S_CONFIGURE_MQTT); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_MQTT1, +#ifdef USE_MQTT_AWS_IOT + AWS_endpoint, +#else Settings.mqtt_host, +#endif Settings.mqtt_port, Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, Settings.mqtt_client); WSContentSend_P(HTTP_FORM_MQTT2, @@ -922,17 +901,26 @@ void MqttSaveSettings(void) strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic)); strlcpy(Settings.mqtt_fulltopic, stemp2, sizeof(Settings.mqtt_fulltopic)); WebGetArg("mh", tmp, sizeof(tmp)); +#ifdef USE_MQTT_AWS_IOT + setLongMqttHost((!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); +#else strlcpy(Settings.mqtt_host, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_host)); +#endif WebGetArg("ml", tmp, sizeof(tmp)); Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); WebGetArg("mc", tmp, sizeof(tmp)); strlcpy(Settings.mqtt_client, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp, sizeof(Settings.mqtt_client)); +#ifndef USE_MQTT_AWS_IOT WebGetArg("mu", tmp, sizeof(tmp)); strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); WebGetArg("mp", tmp, sizeof(tmp)); strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd)); AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_topic, Settings.mqtt_fulltopic); +#else // USE_MQTT_AWS_IOT +AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + AWS_endpoint, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_topic, Settings.mqtt_fulltopic); +#endif } #endif // USE_WEBSERVER @@ -946,7 +934,7 @@ bool Xdrv02(uint8_t function) if (Settings.flag.mqtt_enabled) { switch (function) { -#ifdef USE_MQTT_AWS_IOT +#ifdef USE_MQTT_TLS case FUNC_PRE_INIT: MqttInit(); break;