Added certificate name extraction API (from subject DN and SAN extension).
[BearSSL] / inc / bearssl_ssl.h
index 24d773c..b038500 100644 (file)
 #include "bearssl_rand.h"
 #include "bearssl_x509.h"
 
 #include "bearssl_rand.h"
 #include "bearssl_x509.h"
 
-/*
- * SSL
- * ---
+/** \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)
 
 #define BR_SSL_BUFSIZE_INPUT    (16384 + 325)
 
-/* Optimal output buffer size. */
+/** \brief Optimal output buffer size. */
 #define BR_SSL_BUFSIZE_OUTPUT   (16384 + 85)
 
 #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
 
 #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)
 
 /*
 #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.
  */
  * 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
 #define BR_SSL30   0x0300
+/** \brief Protocol version: TLS 1.0. */
 #define BR_TLS10   0x0301
 #define BR_TLS10   0x0301
+/** \brief Protocol version: TLS 1.1. */
 #define BR_TLS11   0x0302
 #define BR_TLS11   0x0302
+/** \brief Protocol version: TLS 1.2. */
 #define BR_TLS12   0x0303
 
 /*
 #define BR_TLS12   0x0303
 
 /*
  * errors. Received fatal alerts imply an error code in the 256..511 range.
  */
 
  * 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
 
 #define BR_ERR_OK                      0
 
-/* Caller-provided parameter is incorrect. */
+/** \brief SSL status: caller-provided parameter is incorrect. */
 #define BR_ERR_BAD_PARAM               1
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #define BR_ERR_BAD_FRAGLEN            18
 
-/* Secure renegotiation failed. */
+/** \brief SSL status: secure renegotiation failed. */
 #define BR_ERR_BAD_SECRENEG           19
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 #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
 
 /* ===================================================================== */
 
 #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_ {
  */
 typedef struct br_sslrec_in_class_ br_sslrec_in_class;
 struct br_sslrec_in_class_ {
+       /**
+        * \brief Context size (in bytes).
+        */
        size_t context_size;
        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);
        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);
 };
 
        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_ {
  */
 typedef struct br_sslrec_out_class_ br_sslrec_out_class;
 struct br_sslrec_out_class_ {
+       /**
+        * \brief Context size (in bytes).
+        */
        size_t context_size;
        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);
        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);
 };
 
        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 {
  */
 typedef struct {
+       /** \brief No-encryption engine vtable. */
        const br_sslrec_out_class *vtable;
 } br_sslrec_out_clear_context;
        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;
 
 /* ===================================================================== */
 
 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_ {
  */
 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;
        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,
        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 +390,37 @@ struct br_sslrec_in_cbc_class_ {
                const void *iv);
 };
 
                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_ {
  */
 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;
        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,
        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 +429,17 @@ struct br_sslrec_out_cbc_class_ {
                const void *iv);
 };
 
                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 {
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        const br_sslrec_in_cbc_class *vtable;
        const br_sslrec_in_cbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
        uint64_t seq;
        union {
                const br_block_cbcdec_class *vtable;
        uint64_t seq;
        union {
                const br_block_cbcdec_class *vtable;
@@ -317,14 +450,25 @@ typedef struct {
        size_t mac_len;
        unsigned char iv[16];
        int explicit_IV;
        size_t mac_len;
        unsigned char iv[16];
        int explicit_IV;
+#endif
 } br_sslrec_in_cbc_context;
 } 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;
 
 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 {
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        const br_sslrec_out_cbc_class *vtable;
        const br_sslrec_out_cbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
        uint64_t seq;
        union {
                const br_block_cbcenc_class *vtable;
        uint64_t seq;
        union {
                const br_block_cbcenc_class *vtable;
@@ -335,24 +479,43 @@ typedef struct {
        size_t mac_len;
        unsigned char iv[16];
        int explicit_IV;
        size_t mac_len;
        unsigned char iv[16];
        int explicit_IV;
+#endif
 } br_sslrec_out_cbc_context;
 } 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;
 
 /* ===================================================================== */
 
 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 implementtion, and 4-byte IV.
  */
 typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class;
 struct br_sslrec_in_gcm_class_ {
  */
 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;
        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,
        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 +523,33 @@ struct br_sslrec_in_gcm_class_ {
                const void *iv);
 };
 
                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 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 implementtion, and 4-byte IV.
  */
 typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class;
 struct br_sslrec_out_gcm_class_ {
  */
 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;
        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,
        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 +557,22 @@ struct br_sslrec_out_gcm_class_ {
                const void *iv);
 };
 
                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 {
  */
 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;
        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;
        uint64_t seq;
        union {
                const br_block_ctr_class *vtable;
@@ -398,39 +581,61 @@ typedef struct {
        br_ghash gh;
        unsigned char iv[4];
        unsigned char h[16];
        br_ghash gh;
        unsigned char iv[4];
        unsigned char h[16];
+#endif
 } br_sslrec_gcm_context;
 
 } 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;
 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;
 
 /* ===================================================================== */
 
 extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable;
 
 /* ===================================================================== */
 
-/*
- * Type for session parameters, to be saved for session resumption.
+/**
+ * \brief Type for session parameters, to be saved for session resumption.
  */
 typedef struct {
  */
 typedef struct {
+       /** \brief Session ID buffer. */
        unsigned char session_id[32];
        unsigned char session_id[32];
+       /** \brief Session ID length (in bytes, at most 32). */
        unsigned char session_id_len;
        unsigned char session_id_len;
+       /** \brief Protocol version. */
        uint16_t version;
        uint16_t version;
+       /** \brief Cipher suite. */
        uint16_t cipher_suite;
        uint16_t cipher_suite;
+       /** \brief Master secret. */
        unsigned char master_secret[48];
 } br_ssl_session_parameters;
 
        unsigned char master_secret[48];
 } br_ssl_session_parameters;
 
+#ifndef BR_DOXYGEN_IGNORE
 /*
  * Maximum numnber of cipher suites supported by a client or server.
  */
 #define BR_MAX_CIPHER_SUITES   40
 /*
  * Maximum numnber of cipher suites supported by a client or server.
  */
 #define BR_MAX_CIPHER_SUITES   40
+#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
  * 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 {
  */
 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.
        /*
         * The error code. When non-zero, then the state is "failed" and
         * no I/O may occur until reset.
@@ -544,13 +749,6 @@ typedef struct {
         */
        unsigned char client_random[32];
        unsigned char server_random[32];
         */
        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;
 
        /*
        br_ssl_session_parameters session;
 
        /*
@@ -575,12 +773,16 @@ typedef struct {
        unsigned char saved_finished[24];
 
        /*
        unsigned char saved_finished[24];
 
        /*
-        * 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.)
+        * Behavioural flags.
+        */
+       uint32_t flags;
+
+       /*
+        * Context variables for the handshake processor. The 'pad' must
+        * be large enough to accommodate an RSA-encrypted pre-master
+        * secret, or an RSA signature; since we want to support up to
+        * RSA-4096, this means at least 512 bytes. (Other pad usages
+        * require its length to be at least 256.)
         */
        struct {
                uint32_t *dp;
         */
        struct {
                uint32_t *dp;
@@ -631,6 +833,16 @@ typedef struct {
         */
        const br_x509_class **x509ctx;
 
         */
        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;
+
        /*
         * Pointers to implementations; left to NULL for unsupported
         * functions. For the raw hash functions, implementations are
        /*
         * Pointers to implementations; left to NULL for unsupported
         * functions. For the raw hash functions, implementations are
@@ -650,11 +862,112 @@ typedef struct {
        const br_sslrec_in_gcm_class *igcm_in;
        const br_sslrec_out_gcm_class *igcm_out;
        const br_ec_impl *iec;
        const br_sslrec_in_gcm_class *igcm_in;
        const br_sslrec_out_gcm_class *igcm_out;
        const br_ec_impl *iec;
-
+       br_rsa_pkcs1_vrfy irsavrfy;
+       br_ecdsa_vrfy iecdsa;
+#endif
 } br_ssl_engine_context;
 
 } br_ssl_engine_context;
 
-/*
- * Set the minimum and maximum supported protocol versions.
+/**
+ * \brief Get currently defined engine behavioural flags.
+ *
+ * \param cc   SSL engine context.
+ * \return  the flags.
+ */
+static inline uint32_t
+br_ssl_engine_get_flags(br_ssl_engine_context *cc)
+{
+       return cc->flags;
+}
+
+/**
+ * \brief Set all engine behavioural flags.
+ *
+ * \param cc      SSL engine context.
+ * \param flags   new value for all flags.
+ */
+static inline void
+br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags)
+{
+       cc->flags = flags;
+}
+
+/**
+ * \brief Set some engine behavioural flags.
+ *
+ * The flags set in the `flags` parameter are set in the context; other
+ * flags are untouched.
+ *
+ * \param cc      SSL engine context.
+ * \param flags   additional set flags.
+ */
+static inline void
+br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags)
+{
+       cc->flags |= flags;
+}
+
+/**
+ * \brief Clear some engine behavioural flags.
+ *
+ * The flags set in the `flags` parameter are cleared from the context; other
+ * flags are untouched.
+ *
+ * \param cc      SSL engine context.
+ * \param flags   flags to remove.
+ */
+static inline void
+br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)
+{
+       cc->flags &= ~flags;
+}
+
+/**
+ * \brief Behavioural flag: enforce server preferences.
+ *
+ * If this flag is set, then the server will enforce its own cipher suite
+ * preference order; otherwise, it follows the client preferences.
+ */
+#define BR_OPT_ENFORCE_SERVER_PREFERENCES      ((uint32_t)1 << 0)
+
+/**
+ * \brief Behavioural flag: disable renegotiation.
+ *
+ * If this flag is set, then renegotiations are rejected unconditionally:
+ * they won't be honoured if asked for programmatically, and requests from
+ * the peer are rejected.
+ */
+#define BR_OPT_NO_RENEGOTIATION                ((uint32_t)1 << 1)
+
+/**
+ * \brief Behavioural flag: tolerate lack of client authentication.
+ *
+ * If this flag is set in a server and the server requests a client
+ * certificate, but the authentication fails (the client does not send
+ * a certificate, or the client's certificate chain cannot be validated),
+ * then the connection keeps on. Without this flag, a failed client
+ * authentication terminates the connection.
+ *
+ * Notes:
+ *
+ *   - If the client's certificate can be validated and its public key is
+ *     supported, then a wrong signature value terminates the connection
+ *     regardless of that flag.
+ *
+ *   - If using full-static ECDH, then a failure to validate the client's
+ *     certificate prevents the handshake from succeeding.
+ */
+#define BR_OPT_TOLERATE_NO_CLIENT_AUTH         ((uint32_t)1 << 2)
+
+/**
+ * \brief 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,
  */
 static inline void
 br_ssl_engine_set_versions(br_ssl_engine_context *cc,
@@ -664,17 +977,35 @@ br_ssl_engine_set_versions(br_ssl_engine_context *cc,
        cc->version_max = version_max;
 }
 
        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);
 
  */
 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)
  */
 static inline void
 br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx)
@@ -682,8 +1013,17 @@ br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx)
        cc->x509ctx = x509ctx;
 }
 
        cc->x509ctx = x509ctx;
 }
 
-/*
- * Set a hash function implementation (by ID).
+/**
+ * \brief Set a hash function implementation (by ID).
+ *
+ * Hash functions set with this call will be used for SSL/TLS specific
+ * usages, not X.509 certificate validation. Only "standard" hash functions
+ * may be set (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512). If `impl`
+ * is `NULL`, then the hash function support is removed, not added.
+ *
+ * \param ctx    SSL engine context.
+ * \param id     hash function identifier.
+ * \param impl   hash function implementation (or `NULL`).
  */
 static inline void
 br_ssl_engine_set_hash(br_ssl_engine_context *ctx,
  */
 static inline void
 br_ssl_engine_set_hash(br_ssl_engine_context *ctx,
@@ -692,8 +1032,15 @@ br_ssl_engine_set_hash(br_ssl_engine_context *ctx,
        br_multihash_setimpl(&ctx->mhash, id, impl);
 }
 
        br_multihash_setimpl(&ctx->mhash, id, impl);
 }
 
-/*
- * Get a hash function implementation (by ID).
+/**
+ * \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)
  */
 static inline const br_hash_class *
 br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id)
@@ -701,8 +1048,14 @@ br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id)
        return br_multihash_getimpl(&ctx->mhash, id);
 }
 
        return br_multihash_getimpl(&ctx->mhash, id);
 }
 
-/*
- * Set the PRF implementation (for TLS 1.0 and 1.1).
+/**
+ * \brief Set the PRF implementation (for TLS 1.0 and 1.1).
+ *
+ * This function sets (or removes, if `impl` is `NULL`) the implemenation
+ * 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)
  */
 static inline void
 br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl)
@@ -710,8 +1063,14 @@ br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl)
        cc->prf10 = 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 implemenation
+ * 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)
  */
 static inline void
 br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl)
@@ -719,8 +1078,14 @@ br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl)
        cc->prf_sha256 = 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 implemenation
+ * 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)
  */
 static inline void
 br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl)
@@ -728,8 +1093,12 @@ br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl)
        cc->prf_sha384 = 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,
  */
 static inline void
 br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc,
@@ -740,8 +1109,11 @@ br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc,
        cc->iaes_cbcdec = impl_dec;
 }
 
        cc->iaes_cbcdec = impl_dec;
 }
 
-/*
- * Set the AES/CTR implementation.
+/**
+ * \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,
  */
 static inline void
 br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc,
@@ -750,8 +1122,12 @@ br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc,
        cc->iaes_ctr = impl;
 }
 
        cc->iaes_ctr = impl;
 }
 
-/*
- * Set the 3DES/CBC implementations.
+/**
+ * \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,
  */
 static inline void
 br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc,
@@ -762,8 +1138,11 @@ br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc,
        cc->ides_cbcdec = impl_dec;
 }
 
        cc->ides_cbcdec = impl_dec;
 }
 
-/*
- * Set the GHASH implementation (for GCM).
+/**
+ * \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)
  */
 static inline void
 br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl)
@@ -771,8 +1150,12 @@ br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl)
        cc->ighash = impl;
 }
 
        cc->ighash = impl;
 }
 
-/*
- * Set the CBC+HMAC record processor implementations.
+/**
+ * \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,
  */
 static inline void
 br_ssl_engine_set_cbc(br_ssl_engine_context *cc,
@@ -783,8 +1166,12 @@ br_ssl_engine_set_cbc(br_ssl_engine_context *cc,
        cc->icbc_out = impl_out;
 }
 
        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,
  */
 static inline void
 br_ssl_engine_set_gcm(br_ssl_engine_context *cc,
@@ -795,9 +1182,14 @@ br_ssl_engine_set_gcm(br_ssl_engine_context *cc,
        cc->igcm_out = impl_out;
 }
 
        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 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)
  */
 static inline void
 br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec)
@@ -805,44 +1197,105 @@ br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec)
        cc->iec = iec;
 }
 
        cc->iec = 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;
+}
+
 /*
 /*
- * 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 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);
 
  */
 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.
+ *
+ * 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.
  *
  *
- * 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.
+ * \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);
 
  */
 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.
  *
  * This function may be called several times; all injected entropy chunks
  * are cumulatively mixed.
@@ -864,64 +1317,158 @@ 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).
  * 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);
 
  */
 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 *
  */
 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;
 }
 
 {
        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 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:
  *
  * 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
  *
  * 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.
  * 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.
  * 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
 #define BR_SSL_CLOSED    0x0001
+/** \brief SSL engine state: record data is ready to be sent to the peer. */
 #define BR_SSL_SENDREC   0x0002
 #define BR_SSL_SENDREC   0x0002
+/** \brief SSL engine state: engine may receive records from the peer. */
 #define BR_SSL_RECVREC   0x0004
 #define BR_SSL_RECVREC   0x0004
+/** \brief SSL engine state: engine may accept application data to send. */
 #define BR_SSL_SENDAPP   0x0008
 #define BR_SSL_SENDAPP   0x0008
+/** \brief SSL engine state: engine has received application data. */
 #define BR_SSL_RECVAPP   0x0010
 
 #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)
  */
 static inline int
 br_ssl_engine_last_error(const br_ssl_engine_context *cc)
@@ -965,69 +1512,588 @@ br_ssl_engine_last_error(const br_ssl_engine_context *cc)
  *      call.
  */
 
  *      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);
 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);
 
 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);
 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);
 
 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);
 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);
 
 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);
 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);
 
 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
  * 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.
  * 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);
 
  */
 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);
 
  */
 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, 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);
 
 /*
  */
 int br_ssl_engine_renegotiate(br_ssl_engine_context *cc);
 
 /*
- * 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 {
  */
 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 1
+        * (therefore, writing back the complete encoded point works).
+        *
+        * 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    server public key point length (in bytes).
+        * \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;
 
         */
        br_ssl_engine_context eng;
 
+#ifndef BR_DOXYGEN_IGNORE
+       /*
+        * Minimum ClientHello length; padding with an extension (RFC
+        * 7685) is added if necessary to match at least that length.
+        * Such padding is nominally unnecessary, but it has been used
+        * to work around some server implementation bugs.
+        */
+       uint16_t min_clienthello_len;
+
+       /*
+        * Bit field for algoithms (hash + signature) supported by the
+        * server when requesting a client certificate.
+        */
+       uint16_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;
        /*
         * 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 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. This information is conveyed by the server when requesting
+ * a client certificate.
+ *
+ * \param cc   client context.
+ * \return  the server-supported hash functions (for signatures).
+ */
+static inline uint16_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
 
 /*
  * Each br_ssl_client_init_xxx() function sets the list of supported
@@ -1035,75 +2101,133 @@ typedef struct {
  * name 'xxx'. Defined profile names are:
  *
  *    full    all supported versions and suites; constant-time implementations
  * 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);
 
 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);
 
  */
 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
  */
 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
  */
 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 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
  */
 static inline void
-br_ssl_client_set_ecdsa(br_ssl_client_context *cc, br_ecdsa_vrfy iecdsa)
+br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len)
 {
 {
-       cc->iecdsa = iecdsa;
+       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.
  *
  *
- * If 'resume_session' is non-zero and the context was previously used
+ * The `server_name` parameter is used to fill the SNI extension; the
+ * X.509 "minimal" engine will also match that name against the server
+ * names included in the server's certificate. If the parameter is
+ * `NULL` then no SNI extension will be sent, and the X.509 "minimal"
+ * engine (if used for server certificate validation) will not check
+ * presence of any specific name in the received certificate.
+ *
+ * Therefore, setting the `server_name` to `NULL` shall be reserved
+ * to cases where alternate or additional methods are used to ascertain
+ * that the right server public key is used (e.g. a "known key" model).
+ *
+ * If `resume_session` is non-zero and the context was previously used
  * then the session parameters may be reused (depending on whether the
  * server previously sent a non-empty session ID, and accepts the session
  * 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).
  *
  * 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);
 
  */
 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)
  */
 static inline void
 br_ssl_client_forget_session(br_ssl_client_context *cc)
@@ -1111,40 +2235,131 @@ br_ssl_client_forget_session(br_ssl_client_context *cc)
        cc->eng.session.session_id_len = 0;
 }
 
        cc->eng.session.session_id_len = 0;
 }
 
-/*
- * 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 client certificate chain and key (single RSA case).
+ *
+ * This function sets a client certificate chain, that the client will
+ * send to the server whenever a client certificate is requested. This
+ * certificate uses an RSA public key; the corresponding private key is
+ * invoked for authentication. Trust anchor names sent by the server are
+ * ignored.
+ *
+ * The provided chain and private key are linked in the client context;
+ * they must remain valid as long as they may be used, i.e. normally
+ * for the duration of the connection, since they might be invoked
+ * again upon renegotiations.
+ *
+ * \param cc          SSL client context.
+ * \param chain       client certificate chain (SSL order: EE comes first).
+ * \param chain_len   client chain length (number of certificates).
+ * \param sk          client private key.
+ * \param irsasign    RSA signature implementation (PKCS#1 v1.5).
+ */
+void br_ssl_client_set_single_rsa(br_ssl_client_context *cc,
+       const br_x509_certificate *chain, size_t chain_len,
+       const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign);
+
+/*
+ * \brief Set the client certificate chain and key (single EC case).
+ *
+ * This function sets a client certificate chain, that the client will
+ * send to the server whenever a client certificate is requested. This
+ * certificate uses an EC public key; the corresponding private key is
+ * invoked for authentication. Trust anchor names sent by the server are
+ * ignored.
+ *
+ * The provided chain and private key are linked in the client context;
+ * they must remain valid as long as they may be used, i.e. normally
+ * for the duration of the connection, since they might be invoked
+ * again upon renegotiations.
+ *
+ * The `allowed_usages` is a combination of usages, namely
+ * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX`
+ * value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value
+ * allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA
+ * signature implementation must be provided; otherwise, the `iecdsa`
+ * parameter may be 0.
+ *
+ * The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or
+ * `BR_KEYTYPE_EC`; it is the type of the public key used the the CA
+ * that issued (signed) the client certificate. That value is used with
+ * full static ECDH: support of the certificate by the server depends
+ * on how the certificate was signed. (Note: when using TLS 1.2, this
+ * parameter is ignored; but its value matters for TLS 1.0 and 1.1.)
+ *
+ * \param cc                     server context.
+ * \param chain                  server certificate chain to send.
+ * \param chain_len              chain length (number of certificates).
+ * \param sk                     server private key (EC).
+ * \param allowed_usages         allowed private key usages.
+ * \param cert_issuer_key_type   issuing CA's key type.
+ * \param iec                    EC core implementation.
+ * \param iecdsa                 ECDSA signature implementation ("asn1" format).
+ */
+void br_ssl_client_set_single_ec(br_ssl_client_context *cc,
+       const br_x509_certificate *chain, size_t chain_len,
+       const br_ec_private_key *sk, unsigned allowed_usages,
+       unsigned cert_issuer_key_type,
+       const br_ec_impl *iec, br_ecdsa_sign iecdsa);
+
+/**
+ * \brief Type for a "translated cipher suite", as an array of two
+ * 16-bit integers.
+ *
+ * The first element is the cipher suite identifier (as used on the wire).
+ * The second element is the concatenation of four 4-bit elements which
  * characterise the cipher suite contents. In most to least significant
  * order, these 4-bit elements are:
  *
  * 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];
 
  */
 typedef uint16_t br_suite_translated[2];
 
+#ifndef BR_DOXYGEN_IGNORE
+/*
+ * Constants are already documented in the br_suite_translated type.
+ */
+
 #define BR_SSLKEYX_RSA           0
 #define BR_SSLKEYX_ECDHE_RSA     1
 #define BR_SSLKEYX_ECDHE_ECDSA   2
 #define BR_SSLKEYX_RSA           0
 #define BR_SSLKEYX_ECDHE_RSA     1
 #define BR_SSLKEYX_ECDHE_ECDSA   2
@@ -1166,122 +2381,235 @@ typedef uint16_t br_suite_translated[2];
 #define BR_SSLPRF_SHA256         br_sha256_ID
 #define BR_SSLPRF_SHA384         br_sha384_ID
 
 #define BR_SSLPRF_SHA256         br_sha256_ID
 #define BR_SSLPRF_SHA384         br_sha384_ID
 
+#endif
+
 /*
  * Pre-declaration for the SSL server context.
  */
 typedef struct br_ssl_server_context_ br_ssl_server_context;
 
 /*
  * 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 {
  */
 typedef struct {
+       /**
+        * \brief Cipher suite to use with that client.
+        */
        uint16_t cipher_suite;
        uint16_t cipher_suite;
+
+       /**
+        * \brief Hash function for signing the ServerKeyExchange.
+        *
+        * This is the symbolic identifier for the hash function that
+        * will be used to sign the ServerKeyExchange message, for ECDHE
+        * cipher suites. This is ignored for RSA and ECDH cipher suites.
+        *
+        * 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;
        int hash_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;
        const br_x509_certificate *chain;
+
+       /**
+        * \brief Certificate chain length (number of certificates).
+        */
        size_t chain_len;
        size_t chain_len;
+
 } br_ssl_server_choices;
 
 } br_ssl_server_choices;
 
-/*
- * Type for the certificate and private key handler on the server: an
- * object with the following methods:
+/**
+ * \brief Class type for a policy handler (server side).
  *
  *
- *   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).
+ * 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.
  *
  *
- *   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).
- *
- * In both cases, returned value is 1 on success, 0 on error.
- *
- *
- * 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_ {
  */
 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;
        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);
        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 1
+        * (thus, simply encoding the point in compressed or uncompressed
+        * format in `data` is fine).
+        *
+        *   - 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);
        uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx,
                unsigned char *data, size_t len);
+
+       /**
+        * \brief Perform a signature (for a ServerKeyExchange message).
+        *
+        * This callback function is invoked for ECDHE cipher suites.
+        * On input, the hash value 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.
+        *
+        * Returned value is the signature length (in bytes), or 0 on error.
+        *
+        * \param pctx      policy 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_server_policy_class **pctx,
                int hash_id, size_t hv_len, unsigned char *data, size_t len);
 };
 
        size_t (*do_sign)(const br_ssl_server_policy_class **pctx,
                int hash_id, size_t hv_len, unsigned char *data, 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 {
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        const br_ssl_server_policy_class *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;
        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;
 
 } 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 {
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        const br_ssl_server_policy_class *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;
        const br_x509_certificate *chain;
        size_t chain_len;
        const br_ec_private_key *sk;
@@ -1290,74 +2618,117 @@ typedef struct {
        const br_multihash_context *mhash;
        const br_ec_impl *iec;
        br_ecdsa_sign iecdsa;
        const br_multihash_context *mhash;
        const br_ec_impl *iec;
        br_ecdsa_sign iecdsa;
+#endif
 } br_ssl_server_policy_ec_context;
 
 } 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).
- *
- *  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.
+/**
+ * \brief Class type for a session parameter cache.
  *
  *
- * 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_ {
  */
 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;
        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);
        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);
 };
 
        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 {
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        const br_ssl_session_cache_class *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;
        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;
 
 } 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);
 
  */
 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 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_ {
  */
 struct br_ssl_server_context_ {
-       /*
-        * The encapsulated engine context.
+       /**
+        * \brief The encapsulated engine context.
         */
        br_ssl_engine_context eng;
 
         */
        br_ssl_engine_context eng;
 
-       /*
-        * Flags.
-        */
-       uint32_t flags;
-
+#ifndef BR_DOXYGEN_IGNORE
        /*
         * Maximum version from the client.
         */
        /*
         * Maximum version from the client.
         */
@@ -1393,10 +2764,6 @@ struct br_ssl_server_context_ {
         * Context for chain handler.
         */
        const br_ssl_server_policy_class **policy_vtable;
         * 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;
 
        /*
        unsigned char sign_hash_id;
 
        /*
@@ -1416,54 +2783,30 @@ struct br_ssl_server_context_ {
        size_t ecdhe_key_len;
 
        /*
        size_t ecdhe_key_len;
 
        /*
-        * Server-specific implementations.
+        * Trust anchor names for client authentication. "ta_names" and
+        * "tas" cannot be both non-NULL.
         */
         */
-};
-
-/*
- * Get currently defined server behavioural flags.
- */
-static inline uint32_t
-br_ssl_server_get_flags(br_ssl_server_context *cc)
-{
-       return cc->flags;
-}
-
-/*
- * Set all server flags. Flags which are not in the 'flags' argument
- * are cleared.
- */
-static inline void
-br_ssl_server_set_all_flags(br_ssl_server_context *cc, uint32_t flags)
-{
-       cc->flags = flags;
-}
+       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;
 
 
-/*
- * Add some server flags. The provided flags are set in the server context,
- * but other flags are untouched.
- */
-static inline void
-br_ssl_server_add_flags(br_ssl_server_context *cc, uint32_t flags)
-{
-       cc->flags |= flags;
-}
-
-/*
- * Remove some server flags. The provided flags are cleared from the
- * server context, but other flags are untouched.
- */
-static inline void
-br_ssl_server_remove_flags(br_ssl_server_context *cc, uint32_t flags)
-{
-       cc->flags &= ~flags;
-}
+       /*
+        * 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 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)
+       /*
+        * Server-specific implementations.
+        * (none for now)
+        */
+#endif
+};
 
 /*
  * Each br_ssl_server_init_xxx() function sets the list of supported
 
 /*
  * Each br_ssl_server_init_xxx() function sets the list of supported
@@ -1472,7 +2815,7 @@ br_ssl_server_remove_flags(br_ssl_server_context *cc, uint32_t flags)
  *
  *    full_rsa    all supported algorithm, server key type is RSA
  *    full_ec     all supported algorithm, server key type is EC
  *
  *    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
  *
  *
  * Naming scheme for "minimal" profiles: min123
  *
@@ -1492,33 +2835,156 @@ br_ssl_server_remove_flags(br_ssl_server_context *cc, uint32_t flags)
  *      d = 3DES/CBC
  */
 
  *      d = 3DES/CBC
  */
 
+/**
+ * \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);
 
 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);
 
 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);
 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);
 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);
 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);
 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);
 
 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 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)
  */
 static inline const br_suite_translated *
 br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num)
@@ -1527,10 +2993,15 @@ br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num)
        return cc->client_suites;
 }
 
        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 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.
+ *
+ * \param cc   server context.
+ * \return  the client-supported hash functions (for signatures).
  */
 static inline uint16_t
 br_ssl_server_get_client_hashes(const br_ssl_server_context *cc)
  */
 static inline uint16_t
 br_ssl_server_get_client_hashes(const br_ssl_server_context *cc)
@@ -1538,9 +3009,13 @@ br_ssl_server_get_client_hashes(const br_ssl_server_context *cc)
        return cc->hashes;
 }
 
        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)
  */
 static inline uint32_t
 br_ssl_server_get_client_curves(const br_ssl_server_context *cc)
@@ -1548,15 +3023,26 @@ br_ssl_server_get_client_curves(const br_ssl_server_context *cc)
        return cc->curves;
 }
 
        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);
 
  */
 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,
  */
 static inline void
 br_ssl_server_set_policy(br_ssl_server_context *cc,
@@ -1565,30 +3051,122 @@ br_ssl_server_set_policy(br_ssl_server_context *cc,
        cc->policy_vtable = pctx;
 }
 
        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,
  */
 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);
 
        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,
  */
 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);
 
        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,
  */
 static inline void
 br_ssl_server_set_cache(br_ssl_server_context *cc,
@@ -1597,8 +3175,11 @@ br_ssl_server_set_cache(br_ssl_server_context *cc,
        cc->cache_vtable = vtable;
 }
 
        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);
 
  */
 int br_ssl_server_reset(br_ssl_server_context *cc);
 
@@ -1630,7 +3211,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.
  */
  * 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 {
 typedef struct {
+#ifndef BR_DOXYGEN_IGNORE
        br_ssl_engine_context *engine;
        int (*low_read)(void *read_context,
                unsigned char *data, size_t len);
        br_ssl_engine_context *engine;
        int (*low_read)(void *read_context,
                unsigned char *data, size_t len);
@@ -1638,11 +3226,55 @@ typedef struct {
        int (*low_write)(void *write_context,
                const unsigned char *data, size_t len);
        void *write_context;
        int (*low_write)(void *write_context,
                const unsigned char *data, size_t len);
        void *write_context;
+#endif
 } br_sslio_context;
 
 } 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,
  */
 void br_sslio_init(br_sslio_context *ctx,
        br_ssl_engine_context *engine,
@@ -1653,64 +3285,123 @@ void br_sslio_init(br_sslio_context *ctx,
                const unsigned char *data, size_t len),
        void *write_context);
 
                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.
  *
  * 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);
 
  */
 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);
 
  */
 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.
+ *
+ * If `len` is zero, then this function returns 0 immediately. In
+ * all other cases, it never returns 0.
  *
  *
- * Note that some written bytes may be buffered; use br_sslio_flush()
- * to make sure that the data is sent to the transport stream.
+ * 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);
 
  */
 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);
 
  */
 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.
  *
  * 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);
 
  */
 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);
 
  */
 int br_sslio_close(br_sslio_context *cc);
 
@@ -1827,6 +3518,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
 
 #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.
  */
 /*
  * Symbolic constants for alerts.
  */