Fixed selection of ECDHE_RSA suites for pre-1.2 TLS versions.
[BearSSL] / inc / bearssl_block.h
index 38108b7..415bc28 100644 (file)
 #include <stddef.h>
 #include <stdint.h>
 
 #include <stddef.h>
 #include <stdint.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /** \file bearssl_block.h
  *
 /** \file bearssl_block.h
  *
- * # Block Ciphers
+ * # Block Ciphers and Symmetric Ciphers
  *
  *
- * This file documents the API for block ciphers.
+ * This file documents the API for block ciphers and other symmetric
+ * ciphers.
  *
  *
  * ## Procedural API
  *
  *
  * ## Procedural API
  * | 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_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        |
  *
  * | des_ct    | DES/3DES |         8          | 8, 16 and 24        |
  * | des_tab   | DES/3DES |         8          | 8, 16 and 24        |
  *
  * is typically twice faster than `aes_ct` for modes that allow parallel
  * operations (i.e. CTR, and CBC decryption, but not CBC encryption).
  *
  * 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`.
  * `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.
+ *
+ * `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).
  */
 
 /**
  */
 
 /**
@@ -972,16 +1007,404 @@ void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv,
 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);
 
 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);
 
+/*
+ * 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 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 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 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 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_x868ni` 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_x868ni` 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_x868ni` AES-CTR implementation, or `NULL`.
+ */
+const br_block_ctr_class *br_aes_x86ni_ctr_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 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 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 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 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 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;
 /**
  * \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 big;
-       br_aes_small_cbcenc_keys small;
-       br_aes_ct_cbcenc_keys ct;
-       br_aes_ct64_cbcenc_keys ct64;
+       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;
 
 /**
 } br_aes_gen_cbcenc_keys;
 
 /**
@@ -990,10 +1413,12 @@ typedef union {
  */
 typedef union {
        const br_block_cbcdec_class *vtable;
  */
 typedef union {
        const br_block_cbcdec_class *vtable;
-       br_aes_big_cbcdec_keys big;
-       br_aes_small_cbcdec_keys small;
-       br_aes_ct_cbcdec_keys ct;
-       br_aes_ct64_cbcdec_keys ct64;
+       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;
 
 /**
 } br_aes_gen_cbcdec_keys;
 
 /**
@@ -1002,10 +1427,12 @@ typedef union {
  */
 typedef union {
        const br_block_ctr_class *vtable;
  */
 typedef union {
        const br_block_ctr_class *vtable;
-       br_aes_big_ctr_keys big;
-       br_aes_small_ctr_keys small;
-       br_aes_ct_ctr_keys ct;
-       br_aes_ct64_ctr_keys ct64;
+       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;
 
 /*
 } br_aes_gen_ctr_keys;
 
 /*
@@ -1213,8 +1640,174 @@ typedef union {
  */
 typedef union {
        const br_block_cbcdec_class *vtable;
  */
 typedef union {
        const br_block_cbcdec_class *vtable;
-       br_des_tab_cbcdec_keys tab;
-       br_des_ct_cbcdec_keys ct;
+       br_des_tab_cbcdec_keys c_tab;
+       br_des_ct_cbcdec_keys c_ct;
 } br_des_gen_cbcdec_keys;
 
 } 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 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
 #endif