Added support for CCM and CCM_8 cipher suites.
[BearSSL] / inc / bearssl_ssl.h
index 3faf1be..8c8c86b 100644 (file)
 #include "bearssl_rand.h"
 #include "bearssl_x509.h"
 
-/*
- * SSL
- * ---
+#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).
  */
 
-/* Optimal input buffer size. */
+/** \brief Optimal input buffer size. */
 #define BR_SSL_BUFSIZE_INPUT    (16384 + 325)
 
-/* Optimal output buffer size. */
+/** \brief Optimal output buffer size. */
 #define BR_SSL_BUFSIZE_OUTPUT   (16384 + 85)
 
-/* Optimal buffer size for monodirectional engine
-   (shared input/output buffer). */
+/** \brief Optimal buffer size for monodirectional engine
+    (shared input/output buffer). */
 #define BR_SSL_BUFSIZE_MONO     BR_SSL_BUFSIZE_INPUT
 
-/* Optimal buffer size for bidirectional engine
-   (single buffer split into two separate input/output buffers). */
+/** \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)
 
 /*
  * 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
 
 /*
  * errors. Received fatal alerts imply an error code in the 256..511 range.
  */
 
-/* No error so far (0). */
+/** \brief SSL status: no error so far (0). */
 #define BR_ERR_OK                      0
 
-/* Caller-provided parameter is incorrect. */
+/** \brief SSL status: caller-provided parameter is incorrect. */
 #define BR_ERR_BAD_PARAM               1
 
-/* 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). */
+/** \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
 
-/* Incoming protocol or record version is unsupported. */
+/** \brief SSL status: incoming protocol or record version is unsupported. */
 #define BR_ERR_UNSUPPORTED_VERSION     3
 
-/* Incoming record version does not match the expected version. */
+/** \brief SSL status: incoming record version does not match the expected
+    version. */
 #define BR_ERR_BAD_VERSION             4
 
-/* Incoming record length is invalid. */
+/** \brief SSL status: incoming record length is invalid. */
 #define BR_ERR_BAD_LENGTH              5
 
-/* Incoming record is too large to be processed, or buffer is too small
-   for the handshake message to send. */
+/** \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
 
-/* Decryption found an invalid padding, or the record MAC is not correct. */
+/** \brief SSL status: decryption found an invalid padding, or the record
+    MAC is not correct. */
 #define BR_ERR_BAD_MAC                 7
 
-/* No initial entropy was provided, and none can be obtained from the OS. */
+/** \brief SSL status: no initial entropy was provided, and none can be
+    obtained from the OS. */
 #define BR_ERR_NO_RANDOM               8
 
-/* Incoming record type is unknown. */
+/** \brief SSL status: incoming record type is unknown. */
 #define BR_ERR_UNKNOWN_TYPE            9
 
-/* Incoming record or message has wrong type with regards to the
-   current engine state. */
+/** \brief SSL status: incoming record or message has wrong type with
+    regards to the current engine state. */
 #define BR_ERR_UNEXPECTED             10
 
-/* ChangeCipherSpec message from the peer has invalid contents. */
+/** \brief SSL status: ChangeCipherSpec message from the peer has invalid
+    contents. */
 #define BR_ERR_BAD_CCS                12
 
-/* Alert message from the peer has invalid contents (odd length). */
+/** \brief SSL status: alert message from the peer has invalid contents
+    (odd length). */
 #define BR_ERR_BAD_ALERT              13
 
-/* Incoming handshake message decoding failed. */
+/** \brief SSL status: incoming handshake message decoding failed. */
 #define BR_ERR_BAD_HANDSHAKE          14
 
-/* ServerHello contains a session ID which is larger than 32 bytes. */
+/** \brief SSL status: ServerHello contains a session ID which is larger
+    than 32 bytes. */
 #define BR_ERR_OVERSIZED_ID           15
 
-/* 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. */
+/** \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
 
-/* Server wants to use a compression that we did not claim to support. */
+/** \brief SSL status: server wants to use a compression that we did not
+    claim to support. */
 #define BR_ERR_BAD_COMPRESSION        17
 
-/* Server's max fragment length does not match client's. */
+/** \brief SSL status: server's max fragment length does not match
+    client's. */
 #define BR_ERR_BAD_FRAGLEN            18
 
-/* Secure renegotiation failed. */
+/** \brief SSL status: secure renegotiation failed. */
 #define BR_ERR_BAD_SECRENEG           19
 
-/* Server sent an extension type that we did not announce, or used the
-   same extension type several times in a single ServerHello. */
+/** \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
 
-/* Invalid Server Name Indication contents (when used by the server,
-   this extension shall be empty). */
+/** \brief SSL status: invalid Server Name Indication contents (when
+    used by the server, this extension shall be empty). */
 #define BR_ERR_BAD_SNI                21
 
-/* Invalid ServerHelloDone from the server (length is not 0). */
+/** \brief SSL status: invalid ServerHelloDone from the server (length
+    is not 0). */
 #define BR_ERR_BAD_HELLO_DONE         22
 
-/* Internal limit exceeded (e.g. server's public key is too large). */
+/** \brief SSL status: internal limit exceeded (e.g. server's public key
+    is too large). */
 #define BR_ERR_LIMIT_EXCEEDED         23
 
-/* Finished message from peer does not match the expected value. */
+/** \brief SSL status: Finished message from peer does not match the
+    expected value. */
 #define BR_ERR_BAD_FINISHED           24
 
-/* Session resumption attempt with distinct version or cipher suite. */
+/** \brief SSL status: session resumption attempt with distinct version
+    or cipher suite. */
 #define BR_ERR_RESUME_MISMATCH        25
 
-/* Unsupported or invalid algorithm (ECDHE curve, signature algorithm,
-   hash function). */
+/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve,
+    signature algorithm, hash function). */
 #define BR_ERR_INVALID_ALGORITHM      26
 
-/* Invalid signature on ServerKeyExchange message. */
+/** \brief SSL status: invalid signature (on ServerKeyExchange from
+    server, or in CertificateVerify from client). */
 #define BR_ERR_BAD_SIGNATURE          27
 
-/* I/O error or premature close on underlying transport stream. This
-   error code is set only by the simplified I/O API ("br_sslio_*"). */
+/** \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
 
-/* When a fatal alert is received from the peer, the alert value is added
-   to this constant. */
+/** \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
 
-/* When a fatal alert is sent to the peer, the alert value is added
-   to this constant. */
+/** \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
 
 /* ===================================================================== */
 
-/*
- * The decryption engine for incoming records is an object that implements
- * the following functions:
+/**
+ * \brief Decryption engine for SSL.
  *
- *   check_length   test whether the provided record length is valid
- *   decrypt        decrypt and verify the provided record
+ * 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 decrypt() function receives as parameters a pointer to its context
- * structure, the record type, the record version, a pointer to the
- * start of the record payload, and a pointer to a word containing the
- * payload length. The decrypt() function may assume that the length is
- * proper (check_length() was called and returned 1). On success, a
- * pointer to the first plaintext byte is returned, and *len is adjusted
- * to contain the plaintext length; on error, NULL is returned.
- *
- * The decryption engine is responsible for keeping track of the record
- * sequence number.
+ * 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);
 };
 
-/*
- * The encryption engine for outgoing records is an object that implements
- * the following functions:
- *
- *   max_plaintext   get start and end offsets for payload
- *   encrypt         encrypt and apply MAC on current record
- *
- * The max_plaintext() function receives as inputs the start and end
- * of the buffer where the payload will be stored; this function assumes
- * that there will be room for a record header (5 bytes) BEFORE the
- * offset specified by *start. The max_plaintext() function then adjusts
- * the two offsets to designate the area for the plaintext.
- *
- * The encrypt() function assumes that the provided plaintext data is
- * in a buffer with enough room before and after the data chunk to
- * receive the needed headers (i.e. the plaintext is at offsets which
- * were computed by an earlier call to max_plaintext()). It returns
- * a pointer to the start of the encrypted record, and writes the
- * encrypted record length in '*len' (that length includes the record
- * header).
- *
- * The encryption engine MUST fill the record header. If the engine
- * performs a "split" into several records, then the successive records
- * MUST be consecutive in RAM; the returned length is thus the sum of
- * the individual record lengths.
- *
- * The encryption engine is responsible for keeping track of the record
- * sequence number.
+/**
+ * \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);
 };
 
-/*
- * An outgoing no-encryption engine is defined, to process outgoing
- * records before completion of the initial handshake.
+/**
+ * \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;
 
 /* ===================================================================== */
 
-/*
- * An engine for processing incoming records with a block cipher in
- * CBC mode has an extra initialization function, that takes as inputs:
- * -- a block cipher (CBC decryption) and its key;
- * -- a hash function for HMAC, with the MAC key and output length;
- * -- an optional initial IV.
- * If the IV is not provided (the 'iv' parameter is NULL), then the
- * engine will use an explicit per-record IV (as is mandated in TLS 1.1+).
+/**
+ * \brief Record decryption engine class, for CBC mode.
  *
- * The initialization function is responsible for setting the 'vtable'
- * field of the context.
+ * 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,
@@ -279,21 +394,37 @@ struct br_sslrec_in_cbc_class_ {
                const void *iv);
 };
 
-/*
- * An engine for processing outgoing records with a block cipher in
- * CBC mode has an extra initialization function, that takes as inputs:
- * -- a block cipher (CBC encryption) and its key;
- * -- a hash function for HMAC, with the MAC key and output length;
- * -- an optional initial IV.
- * If the IV is not provided (the 'iv' parameter is NULL), then the
- * engine will use an explicit per-record IV (as is mandated in TLS 1.1+).
+/**
+ * \brief Record encryption engine class, for CBC mode.
  *
- * The initialization function is responsible for setting the 'vtable'
- * field of the context.
+ * 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,
@@ -302,11 +433,17 @@ struct br_sslrec_out_cbc_class_ {
                const void *iv);
 };
 
-/*
- * Context structure for decrypting incoming records with CBC + HMAC.
+/**
+ * \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;
@@ -317,14 +454,25 @@ typedef struct {
        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;
 
-/*
- * Context structure for encrypting outgoing records with CBC + HMAC.
+/**
+ * \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;
@@ -335,24 +483,43 @@ typedef struct {
        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;
 
 /* ===================================================================== */
 
-/*
- * An engine for processing incoming records with a block cipher in
- * GCM mode has an extra initialization function, that takes as inputs:
- * -- a block cipher (CTR) and its key;
- * -- a GHASH implementation;
- * -- an initial IV (4 bytes).
+/**
+ * \brief Record decryption engine class, for GCM mode.
  *
- * The initialization function is responsible for setting the 'vtable'
- * field of the context.
+ * 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,
@@ -360,19 +527,33 @@ struct br_sslrec_in_gcm_class_ {
                const void *iv);
 };
 
-/*
- * An engine for processing outgoing records with a block cipher in
- * GCM mode has an extra initialization function, that takes as inputs:
- * -- a block cipher (CTR) and its key;
- * -- a GHASH implementation;
- * -- an initial IV (4 bytes).
+/**
+ * \brief Record encryption engine class, for GCM mode.
  *
- * The initialization function is responsible for setting the 'vtable'
- * field of the context.
+ * 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,
@@ -380,16 +561,22 @@ struct br_sslrec_out_gcm_class_ {
                const void *iv);
 };
 
-/*
- * We use the same context structure for incoming and outgoing records
- * with GCM, because it allows internal code sharing.
+/**
+ * \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;
@@ -398,39 +585,265 @@ typedef struct {
        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;
 
 /* ===================================================================== */
 
-/*
- * Type for session parameters, to be saved for session resumption.
+/**
+ * \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 numnber of cipher suites supported by a client or server.
+ * Maximum number of cipher suites supported by a client or server.
  */
-#define BR_MAX_CIPHER_SUITES   40
+#define BR_MAX_CIPHER_SUITES   48
+#endif
 
-/*
- * Context structure for SSL engine. This is common to the client and
- * server; the engine manages records, including alerts, closures, and
+/**
+ * \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, but is meant to be included as first
- * field of the context structures for SSL clients and servers.
+ * 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.
@@ -503,22 +916,37 @@ typedef struct {
                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. It is set when application data
-        * can be exchanged, cleared otherwise.
+        * 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;
@@ -544,13 +972,6 @@ typedef struct {
         */
        unsigned char client_random[32];
        unsigned char server_random[32];
-       /* obsolete
-       unsigned char session_id[32];
-       unsigned char session_id_len;
-       uint16_t version;
-       uint16_t cipher_suite;
-       unsigned char master_secret[48];
-       */
        br_ssl_session_parameters session;
 
        /*
@@ -564,8 +985,8 @@ typedef struct {
        /*
         * Secure renegotiation (RFC 5746): 'reneg' can be:
         *   0   first handshake (server support is not known)
-        *   1   server does not support secure renegotiation
-        *   2   server supports secure renegotiation
+        *   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
@@ -580,12 +1001,11 @@ typedef struct {
        uint32_t flags;
 
        /*
-        * Context variables for the handshake processor.
-        * The 'pad' must be large enough to accommodate an
-        * RSA-encrypted pre-master secret, or a RSA signature on
-        * key exchange parameters; 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.)
+        * 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;
@@ -636,6 +1056,37 @@ typedef struct {
         */
        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
@@ -647,19 +1098,31 @@ typedef struct {
        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;
 
-/*
- * Get currently defined engine behavioural flags.
+/**
+ * \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)
@@ -667,9 +1130,11 @@ br_ssl_engine_get_flags(br_ssl_engine_context *cc)
        return cc->flags;
 }
 
-/*
- * Set all engine flags. Flags which are not in the 'flags' argument
- * are cleared.
+/**
+ * \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)
@@ -677,9 +1142,14 @@ br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags)
        cc->flags = flags;
 }
 
-/*
- * Add some engine flags. The provided flags are set in the engine context,
- * but other flags are untouched.
+/**
+ * \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)
@@ -687,9 +1157,14 @@ br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags)
        cc->flags |= flags;
 }
 
-/*
- * Remove some engine flags. The provided flags are cleared from the
- * engine context, but other flags are untouched.
+/**
+ * \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)
@@ -697,8 +1172,79 @@ br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)
        cc->flags &= ~flags;
 }
 
-/*
- * Set the minimum and maximum supported protocol versions.
+/**
+ * \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,
@@ -708,17 +1254,35 @@ br_ssl_engine_set_versions(br_ssl_engine_context *cc,
        cc->version_max = version_max;
 }
 
-/*
- * 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.
+/**
+ * \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);
 
-/*
- * Set the X.509 engine. The context should be already initialized and
- * ready to process a new chain.
+/**
+ * \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)
@@ -726,36 +1290,123 @@ br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx)
        cc->x509ctx = x509ctx;
 }
 
-/*
- * Set a hash function implementation (by ID).
+/**
+ * \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_hash(br_ssl_engine_context *ctx,
-       int id, const br_hash_class *impl)
+br_ssl_engine_set_protocol_names(br_ssl_engine_context *ctx,
+       const char **names, size_t num)
 {
-       br_multihash_setimpl(&ctx->mhash, id, impl);
+       ctx->protocol_names = names;
+       ctx->protocol_names_num = num;
 }
 
-/*
- * Get a hash function implementation (by ID).
+/**
+ * \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 br_hash_class *
-br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id)
+static inline const char *
+br_ssl_engine_get_selected_protocol(br_ssl_engine_context *ctx)
 {
-       return br_multihash_getimpl(&ctx->mhash, id);
+       unsigned k;
+
+       k = ctx->selected_protocol;
+       return (k == 0 || k == 0xFFFF) ? NULL : ctx->protocol_names[k - 1];
 }
 
-/*
- * Set the PRF implementation (for TLS 1.0 and 1.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_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl)
+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;
 }
 
-/*
- * Set the PRF implementation (for TLS 1.2, with SHA-256).
+/**
+ * \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)
@@ -763,8 +1414,14 @@ br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl)
        cc->prf_sha256 = impl;
 }
 
-/*
- * Set the PRF implementation (for TLS 1.2, with SHA-384).
+/**
+ * \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)
@@ -772,8 +1429,12 @@ br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl)
        cc->prf_sha384 = impl;
 }
 
-/*
- * Set the AES/CBC implementations.
+/**
+ * \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,
@@ -784,8 +1445,23 @@ br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc,
        cc->iaes_cbcdec = impl_dec;
 }
 
-/*
- * Set the AES/CTR implementation.
+/**
+ * \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,
@@ -794,8 +1470,24 @@ br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc,
        cc->iaes_ctr = impl;
 }
 
-/*
- * Set the 3DES/CBC implementations.
+/**
+ * \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,
@@ -806,8 +1498,23 @@ br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc,
        cc->ides_cbcdec = impl_dec;
 }
 
-/*
- * Set the GHASH implementation (for GCM).
+/**
+ * \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)
@@ -815,8 +1522,75 @@ br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl)
        cc->ighash = impl;
 }
 
-/*
- * Set the CBC+HMAC record processor implementations.
+/**
+ * \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,
@@ -827,8 +1601,12 @@ br_ssl_engine_set_cbc(br_ssl_engine_context *cc,
        cc->icbc_out = impl_out;
 }
 
-/*
- * Set the GCM record processor implementations.
+/**
+ * \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,
@@ -839,9 +1617,47 @@ br_ssl_engine_set_gcm(br_ssl_engine_context *cc,
        cc->igcm_out = impl_out;
 }
 
-/*
- * Set the ECC core operations implementation. The 'iec' parameter
- * points to the core EC code used for both ECDHE and ECDSA.
+/**
+ * \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)
@@ -849,44 +1665,176 @@ 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;
+}
+
 /*
- * Set the I/O buffer for a SSL engine. Once this call has been made,
- * br_ssl_client_reset() or br_ssl_server_reset() must be called before
- * using the context.
- *
- * If 'bidi' is 1, then the buffer will be internally split to support
- * concurrent input and output; otherwise, the caller will be responsible
- * for reading all buffered incoming data before writing. The latter
- * case makes support of HTTPS pipelining difficult, thus bidirectional
- * buffering is recommended if the RAM can be spared.
- *
- * The BR_SSL_BUFSIZE_MONO and BR_SSL_BUFSIZE_BIDI macros yield optimal
- * buffer sizes for the monodirectional and bidirectional cases,
- * respectively. If using optimal sizes (or larger), then records with
- * the maximum length supported by the TLS standard will be accepted
- * and emitted.
+ * \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);
 
-/*
- * Set the I/O buffers for a SSL engine. This call sets two buffers, for
- * concurrent input and output. The two buffers MUST be disjoint. Once
- * this call has been made, br_ssl_client_reset() or
- * br_ssl_server_reset() must be called before using the context.
+/**
+ * \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.
  *
- * The BR_SSL_BUFSIZE_INPUT and BR_SSL_BUFSIZE_OUTPUT macros evaluate to
- * optimal sizes for the input and output buffers, respectively. If
- * using optimal sizes (or larger), then records with the maximum length
- * supported by the TLS standard will be accepted and emitted.
+ * 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);
 
-/*
- * 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.
+/**
+ * \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.
@@ -908,64 +1856,177 @@ void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc,
  * 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);
 
-/*
- * 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).
+/**
+ * \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(br_ssl_engine_context *cc)
+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
+ *   - `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 initialized yet.
+ * 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().
+ * 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
+ * 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.
+ * 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
 
-/*
- * Get the current engine state.
- */
-unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc);
-
-/*
- * Get the engine error indicator. This is BR_ERR_OK (0) if no error was
- * encountered since the last call to br_ssl_client_reset() or
- * br_ssl_server_reset(). Only these calls clear the error indicator.
+/**
+ * \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)
@@ -1005,65 +2066,545 @@ br_ssl_engine_last_error(const br_ssl_engine_context *cc)
  *      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 preceeding br_ssl_engine_xxx_buf()
+ *      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
+ * `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);
 
-/*
- * Close the context. If, at that point, the context is open and in
- * ready state, then a close_notify alert is assembled and marked for
- * sending. Otherwise, no such alert is assembled.
+/**
+ * \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);
 
-/*
- * Initiate a renegotiation. If the engine is failed or closed, or if
- * the peer is known not to support secure renegotiation (RFC 5746),
- * then this function returns 0. Otherwise, this function returns 1 and
- * a renegotiation attempt is triggered, unless a handshake is already
- * taking place, in which case the call is ignored.
+/**
+ * \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);
+
 /*
- * Context structure for a SSL client.
+ * 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 {
-       /*
-        * The encapsulated engine context.
+       /**
+        * \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.
@@ -1072,14 +2613,100 @@ typedef struct {
         */
        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;
-       br_rsa_pkcs1_vrfy irsavrfy;
-       br_ecdsa_vrfy iecdsa;
+#endif
+};
 
-} br_ssl_client_context;
+/**
+ * \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
@@ -1087,54 +2714,96 @@ typedef struct {
  * name 'xxx'. Defined profile names are:
  *
  *    full    all supported versions and suites; constant-time implementations
- *    FIXME: add other profiles
+ *    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);
 
-/*
- * Clear the complete contents of a SSL client context, including the
- * reference to the configured buffer, implementations, cipher suites
- * and state.
+/**
+ * \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);
 
-/*
- * 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).
+/**
+ * \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_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)
+br_ssl_client_set_client_certificate(br_ssl_client_context *cc,
+       const br_ssl_client_certificate_class **pctx)
 {
-       cc->irsapub = irsapub;
+       cc->client_auth_vtable = pctx;
 }
 
-/*
- * Set the RSA signature verification implementation. This will be used
- * to verify the server's signature on its ServerKeyExchange message
- * (ECDHE_RSA cipher suites only).
+/**
+ * \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_rsavrfy(br_ssl_client_context *cc, br_rsa_pkcs1_vrfy irsavrfy)
+br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)
 {
-       cc->irsavrfy = irsavrfy;
+       cc->irsapub = irsapub;
 }
 
-/*
- * Set the ECDSA implementation (signature verification). The ECC core
- * implementation must also have been set.
+/**
+ * \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.
  */
-static inline void
-br_ssl_client_set_ecdsa(br_ssl_client_context *cc, br_ecdsa_vrfy iecdsa)
-{
-       cc->iecdsa = iecdsa;
-}
+void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc);
 
-/*
- * Set the minimum ClientHello length (RFC 7685 padding).
+/**
+ * \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)
@@ -1142,29 +2811,47 @@ br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len)
        cc->min_clienthello_len = len;
 }
 
-/*
- * Prepare or reset a client context for connecting with a server of
- * name 'server_name'. The 'server_name' parameter is used to fill the
- * SNI extension; if the parameter is NULL then no SNI extension will
- * be sent.
+/**
+ * \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.
  *
- * If 'resume_session' is non-zero and the context was previously used
+ * 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).
+ * 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);
 
-/*
- * 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).
+/**
+ * \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)
@@ -1172,40 +2859,131 @@ 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);
+
 /*
- * Type for a "translated cipher suite", as an array of 16-bit integers:
- * first element is the cipher suite identifier (as used on the wire),
- * and the second element is the concatenation of four 4-bit elements which
+ * \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
- *      0   RSA            RSA key exchange, key is RSA (encryption)
- *      1   ECDHE-RSA      ECDHE key exchange, key is RSA (signature)
- *      2   ECDHE-ECDSA    ECDHE key exchange, key is EC (signature)
- *      3   ECDH-RSA       Key is EC (key exchange), cert is signed with RSA
- *      4   ECDH-ECDSA     Key is EC (key exchange), cert is signed with ECDSA
- *
- *   Bits 8 to 11: symmetric encryption algorithm
- *      0   3DES/CBC
- *      1   AES-128/CBC
- *      2   AES-256/CBC
- *      3   AES-128/GCM
- *      4   AES-256/GCM
- *      5   ChaCha20/Poly1305
- *
- *   Bits 4 to 7: MAC algorithm
- *      0   AEAD           No dedicated MAC because encryption is AEAD
- *      2   HMAC/SHA-1     Value matches br_sha1_ID
- *      4   HMAC/SHA-256   Value matches br_sha256_ID
- *      5   HMAC/SHA-384   Value matches br_sha384_ID
- *
- *   Bits 0 to 3: hash function for PRF when used with TLS-1.2
- *      4   SHA-256        Value matches br_sha256_ID
- *      5   SHA-384        Value matches br_sha384_ID
+ *   - 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
@@ -1227,122 +3005,275 @@ typedef uint16_t br_suite_translated[2];
 #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;
 
-/*
- * Type for the server policy choices, taken after analysis of the client
- * message:
- *
- *     cipher_suite   Cipher suite to use.
- *
- *     hash_id        Signature hash function identifier (hash function
- *                    to use for signing the ServerKeyExchange, when the
- *                    suite uses ECDHE).
- *
- *     chain          The certificate chain to send (number of certificates
- *     chain_len      is in chain_length). The certificates are send "as is"
- *                    and shall be in standard SSL/TLS order (i.e. end-entity
- *                    first, each subsequent certificate signs the previous).
+/**
+ * \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;
-       int hash_id;
+
+       /**
+        * \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;
 
-/*
- * Type for the certificate and private key handler on the server: an
- * object with the following methods:
- *
- *   choose    Select the parameters for this connection (cipher suite,
- *             certificate chain...). The selection is written into the
- *             '*choices' structure. Returned value is 1 on success, or
- *             0 on error (an error here means that the handshake will
- *             fail, and a handshake_failure alert will be sent to the
- *             client).
- *
- *   do_keyx   Perform the server-side key exchange operation. Returned
- *             value is 1 on success, 0 on error (see below). This is
- *             called only when the selected cipher suite calls for a
- *             RSA or ECDH key exchange involving the server key.
- *
- *   do_sign   Perform the server-side signature operation. Returned
- *             value is the signature length, or 0 on error (see below).
- *             This is called only when the selected cipher suite calls
- *             for an ECDHE key exchange, signed by the server with its key.
- *
- *
- * The do_keyx() method shall apply the following semantics:
- *
- * -- For RSA key exchange, it shall decrypt the incoming data along
- * the rules of PKCS#1 v1.5. The method must verify the proper padding
- * and also that the decrypted message length is exactly 48 bytes.
- * IMPORTANT: these operations MUST be constant-time (or adequatly blinded).
- * The decrypted message is written in the first 48 bytes of data[]. The
- * caller makes sure that the data[] buffer is large enough, and that 'len'
- * is at least 59 bytes.
- *
- * -- For ECDH key exchange, the provided data is an EC point (uncompressed
- * format); the method shall multiply that point with the server private
- * key, and write the X coordinate of the resulting point in the data[]
- * buffer, starting at offset 1 (so if the method produces a compressed or
- * uncompressed point, form offset 0, then everything is fine).
+/**
+ * \brief Class type for a policy handler (server side).
  *
- * In both cases, returned value is 1 on success, 0 on error.
+ * 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 do_sign() method shall compute the signature on the hash value
- * provided in the data[] buffer. The 'hv_len' value contains the hash
- * value length, while the 'len' parameter is the total size of the
- * buffer. The method must verify that the signature length is no more
- * than 'len' bytes, and report an error otherwise.
- *
- * The hash identifier is either 0 for the MD5+SHA-1 method in TLS-1.0 and
- * 1.1, or a non-zero hash function identifier in TLS-1.2 and later. In
- * the MD5+SHA-1 method, the hash value has length 36 bytes and there is
- * no hash function identifying header to add in the padding.
- *
- * Returned value is the signature length (in bytes). On error, this method
- * shall return 0.
+ * 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);
+               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,
-               int hash_id, size_t hv_len, unsigned char *data, size_t len);
+               unsigned algo_id,
+               unsigned char *data, size_t hv_len, size_t len);
 };
 
-/*
- * A single-chain RSA policy handler, that always uses a single chain and
- * a RSA key. It may be restricted to do only signatures or only key
- * exchange.
+/**
+ * \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;
 
-/*
- * A single-chain EC policy handler, that always uses a single chain and
- * an EC key. It may be restricted to do only signatures or only key
- * exchange.
+/**
+ * \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;
@@ -1351,69 +3282,130 @@ typedef struct {
        const br_multihash_context *mhash;
        const br_ec_impl *iec;
        br_ecdsa_sign iecdsa;
+#endif
 } br_ssl_server_policy_ec_context;
 
-/*
- * Class type for a session parameter cache.
- *
- *  save   Record session parameters. The session ID has been randomly
- *         generated, and the session ID length is always 32 bytes.
- *         The method shall copy the provided information (the structure
- *         is transient).
+/**
+ * \brief Class type for a session parameter cache.
  *
- *  load   Find session parameters by ID. The session ID is in the relevant
- *         field in the '*params' structure, and has always length exactly
- *         32 bytes. The method shall fill in the other field with the
- *         session data, if found. Returned value is 1 when the session was
- *         found, 0 otherwise.
- *
- * Note that the requesting server context is provided. Implementations
- * may used some of the resources of that context, e.g. random number
- * generator or implementations of some cryptographic algorithms.
+ * 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);
 };
 
-/*
- * Context for a very basic cache system that uses a linked list, managed
- * with an LRU algorithm (when the cache is full and a new set of parameters
- * must be saved, the least recently used entry is evicted). The storage
- * buffer is externally provided. Internally, an index tree is used to
- * speed up operations.
+/**
+ * \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;
 
-/*
- * Initialise a LRU session cache with the provided storage space.
+/**
+ * \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);
 
-/*
- * Context structure for a SSL server.
+/**
+ * \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_ {
-       /*
-        * The encapsulated engine context.
+       /**
+        * \brief The encapsulated engine context.
         */
        br_ssl_engine_context eng;
 
+#ifndef BR_DOXYGEN_IGNORE
        /*
         * Maximum version from the client.
         */
@@ -1436,9 +3428,10 @@ struct br_ssl_server_context_ {
        /*
         * 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.
+        * x for RSA, x+8 for ECDSA. For newer algorithms, with ID
+        * 0x08**, bit 16+k is set for algorithm 0x0800+k.
         */
-       uint16_t hashes;
+       uint32_t hashes;
 
        /*
         * Curves supported by the client (bit mask, for named curves).
@@ -1449,11 +3442,7 @@ struct br_ssl_server_context_ {
         * Context for chain handler.
         */
        const br_ssl_server_policy_class **policy_vtable;
-       const br_x509_certificate *chain;
-       size_t chain_len;
-       const unsigned char *cert_cur;
-       size_t cert_len;
-       unsigned char sign_hash_id;
+       uint16_t sign_hash_id;
 
        /*
         * For the core handlers, thus avoiding (in most cases) the
@@ -1472,22 +3461,30 @@ struct br_ssl_server_context_ {
        size_t ecdhe_key_len;
 
        /*
-        * Server-specific implementations.
+        * 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;
 
-/*
- * 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)
+       /*
+        * 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;
 
-/*
- * 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)
+       /*
+        * Server-specific implementations.
+        * (none for now)
+        */
+#endif
+};
 
 /*
  * Each br_ssl_server_init_xxx() function sets the list of supported
@@ -1496,7 +3493,7 @@ struct br_ssl_server_context_ {
  *
  *    full_rsa    all supported algorithm, server key type is RSA
  *    full_ec     all supported algorithm, server key type is EC
- *    FIXME: add other profiles
+ *    TODO: add other profiles
  *
  * Naming scheme for "minimal" profiles: min123
  *
@@ -1512,37 +3509,193 @@ struct br_ssl_server_context_ {
  *      3 = TLS 1.2 with SHA-384
  * -- character 3: encryption
  *      a = AES/CBC
- *      g = AES/GCM
  *      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);
 
-/*
- * Get the supported client suites. The returned array is ordered by
- * client or server preferences, depending on the relevant flag.
+/**
+ * \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)
@@ -1551,20 +3704,49 @@ br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num)
        return cc->client_suites;
 }
 
-/*
- * Get the hash functions supported by the client. This is a field of
- * bits: for hash function of ID x, bit x is set if the hash function
- * is supported in RSA signatures, 8+x if it is supported with ECDSA.
+/**
+ * \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 uint16_t
+static inline uint32_t
 br_ssl_server_get_client_hashes(const br_ssl_server_context *cc)
 {
        return cc->hashes;
 }
 
-/*
- * Get the elliptic curves supported by the client. This is a bit field
- * (bit x is set if curve of ID x is supported).
+/**
+ * \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)
@@ -1572,15 +3754,26 @@ br_ssl_server_get_client_curves(const br_ssl_server_context *cc)
        return cc->curves;
 }
 
-/*
- * Clear the complete contents of a SSL server context, including the
- * reference to the configured buffer, implementations, cipher suites
- * and state.
+/**
+ * \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);
 
-/*
- * Set an externally provided policy context.
+/**
+ * \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,
@@ -1589,30 +3782,122 @@ br_ssl_server_set_policy(br_ssl_server_context *cc,
        cc->policy_vtable = pctx;
 }
 
-/*
- * Set the server certificate chain and key (single RSA case).
- * The 'allowed_usages' is a combination of usages, namely
- * BR_KEYTYPE_KEYX and/or BR_KEYTYPE_SIGN.
+/**
+ * \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_length,
+       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);
 
-/*
- * Set the server certificate chain and key (single EC case).
- * The 'allowed_usages' is a combination of usages, namely
- * BR_KEYTYPE_KEYX and/or BR_KEYTYPE_SIGN.
+/**
+ * \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_length,
+       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);
 
-/*
- * Configure the server context to use the provided cache for session
- * parameters.
+/**
+ * \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,
@@ -1621,8 +3906,11 @@ br_ssl_server_set_cache(br_ssl_server_context *cc,
        cc->cache_vtable = vtable;
 }
 
-/*
- * Prepare or reset a server context for handling an incoming client.
+/**
+ * \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);
 
@@ -1654,7 +3942,14 @@ int br_ssl_server_reset(br_ssl_server_context *cc);
  * 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);
@@ -1662,11 +3957,55 @@ typedef struct {
        int (*low_write)(void *write_context,
                const unsigned char *data, size_t len);
        void *write_context;
+#endif
 } br_sslio_context;
 
-/*
- * Initialise a simplified I/O context over the provided engine and
- * I/O callbacks.
+/**
+ * \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,
@@ -1677,64 +4016,123 @@ void br_sslio_init(br_sslio_context *ctx,
                const unsigned char *data, size_t len),
        void *write_context);
 
-/*
- * Read some application data from a SSL connection. 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).
+/**
+ * \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);
 
-/*
- * Read some application data from a SSL connection. This call returns
- * only when ALL requested bytes have been read. Returned value is 0
- * on success, -1 on error. A normal SSL closure before that many bytes
- * are obtained is reported as an error by this function.
+/**
+ * \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);
 
-/*
- * Write some application data onto a SSL connection. This call returns
- * only when at least one byte had been written onto the connection (but
- * not necessarily flushed). Returned value is the number of written
- * bytes, or -1 on error (error conditions include a closed connection).
- * It is guaranteed that the number of bytes written by such a call will
- * fit in an 'int' on all architectures.
+/**
+ * \brief Write some application data unto a SSL connection.
  *
- * Note that some written bytes may be buffered; use br_sslio_flush()
- * to make sure that the data is sent to the transport stream.
+ * 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);
 
-/*
- * Write some application data onto a SSL connection. This call returns
- * only when ALL the bytes have been written onto the connection (but
- * not necessarily flushed). Returned value is 0 on success, -1 on error.
- * 
- * Note that some written bytes may be buffered; use br_sslio_flush()
- * to make sure that the data is sent to the transport stream.
+/**
+ * \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);
 
-/*
- * Make sure that any buffered application data in the provided context
- * get packed up and sent unto the low_write() callback method. If that
- * callback method represents a buffered system, it is up to the caller
- * to then "flush" that system too.
+/**
+ * \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);
 
-/*
- * Perform a SSL close. This implies sending a close_notify, and reading
- * the response from the server. Returned value is 0 on success, -1 on
- * error.
+/**
+ * \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);
 
@@ -1842,6 +4240,16 @@ int br_sslio_close(br_sslio_context *cc);
 #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
@@ -1851,6 +4259,9 @@ int br_sslio_close(br_sslio_context *cc);
 #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.
  */
@@ -1876,5 +4287,10 @@ int br_sslio_close(br_sslio_context *cc);
 #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