More Doxygen-compatible documentation (SSL API).
authorThomas Pornin <pornin@bolet.org>
Wed, 23 Nov 2016 15:59:44 +0000 (16:59 +0100)
committerThomas Pornin <pornin@bolet.org>
Wed, 23 Nov 2016 15:59:44 +0000 (16:59 +0100)
Doxyfile
inc/bearssl_ssl.h
src/ssl/ssl_io.c
tools/server.c

index dd0a60f..8d0030e 100644 (file)
--- a/Doxyfile
+++ b/Doxyfile
@@ -771,7 +771,7 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = inc/bearssl.h inc/bearssl_block.h inc/bearssl_ec.h inc/bearssl_hash.h inc/bearssl_hmac.h inc/bearssl_pem.h inc/bearssl_prf.h inc/bearssl_rand.h inc/bearssl_rsa.h inc/bearssl_x509.h
+INPUT                  = inc/bearssl.h inc/bearssl_block.h inc/bearssl_ec.h inc/bearssl_hash.h inc/bearssl_hmac.h inc/bearssl_pem.h inc/bearssl_prf.h inc/bearssl_rand.h inc/bearssl_rsa.h inc/bearssl_ssl.h inc/bearssl_x509.h
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
index 0876ff9..463e616 100644 (file)
 #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)
 
-/* Optimal output buffer size. */
+/** \brief Optimal output buffer size. */
 #define BR_SSL_BUFSIZE_OUTPUT   (16384 + 85)
 
-/* Optimal buffer size for monodirectional engine
-   (shared input/output buffer). */
+/** \brief Optimal buffer size for monodirectional engine
+    (shared input/output buffer). */
 #define BR_SSL_BUFSIZE_MONO     BR_SSL_BUFSIZE_INPUT
 
-/* Optimal buffer size for bidirectional engine
-   (single buffer split into two separate input/output buffers). */
+/** \brief Optimal buffer size for bidirectional engine
+    (single buffer split into two separate input/output buffers). */
 #define BR_SSL_BUFSIZE_BIDI     (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT)
 
 /*
  * and TLS 1.2). Note that though there is a constant for SSL 3.0, that
  * protocol version is not actually supported.
  */
+
+/** \brief Protocol version: SSL 3.0 (unsupported). */
 #define BR_SSL30   0x0300
+/** \brief Protocol version: TLS 1.0. */
 #define BR_TLS10   0x0301
+/** \brief Protocol version: TLS 1.1. */
 #define BR_TLS11   0x0302
+/** \brief Protocol version: TLS 1.2. */
 #define BR_TLS12   0x0303
 
 /*
  * errors. Received fatal alerts imply an error code in the 256..511 range.
  */
 
-/* No error so far (0). */
+/** \brief SSL status: no error so far (0). */
 #define BR_ERR_OK                      0
 
-/* Caller-provided parameter is incorrect. */
+/** \brief SSL status: caller-provided parameter is incorrect. */
 #define BR_ERR_BAD_PARAM               1
 
-/* Operation requested by the caller cannot be applied with the current
-   context state (e.g. reading data while outgoing data is waiting to
-   be sent). */
+/** \brief SSL status: operation requested by the caller cannot be applied
+    with the current context state (e.g. reading data while outgoing data
+    is waiting to be sent). */
 #define BR_ERR_BAD_STATE               2
 
-/* Incoming protocol or record version is unsupported. */
+/** \brief SSL status: incoming protocol or record version is unsupported. */
 #define BR_ERR_UNSUPPORTED_VERSION     3
 
-/* Incoming record version does not match the expected version. */
+/** \brief SSL status: incoming record version does not match the expected
+    version. */
 #define BR_ERR_BAD_VERSION             4
 
-/* Incoming record length is invalid. */
+/** \brief SSL status: incoming record length is invalid. */
 #define BR_ERR_BAD_LENGTH              5
 
-/* Incoming record is too large to be processed, or buffer is too small
-   for the handshake message to send. */
+/** \brief SSL status: incoming record is too large to be processed, or
+    buffer is too small for the handshake message to send. */
 #define BR_ERR_TOO_LARGE               6
 
-/* Decryption found an invalid padding, or the record MAC is not correct. */
+/** \brief SSL status: decryption found an invalid padding, or the record
+    MAC is not correct. */
 #define BR_ERR_BAD_MAC                 7
 
-/* No initial entropy was provided, and none can be obtained from the OS. */
+/** \brief SSL status: no initial entropy was provided, and none can be
+    obtained from the OS. */
 #define BR_ERR_NO_RANDOM               8
 
-/* Incoming record type is unknown. */
+/** \brief SSL status: incoming record type is unknown. */
 #define BR_ERR_UNKNOWN_TYPE            9
 
-/* Incoming record or message has wrong type with regards to the
-   current engine state. */
+/** \brief SSL status: incoming record or message has wrong type with
+    regards to the current engine state. */
 #define BR_ERR_UNEXPECTED             10
 
-/* ChangeCipherSpec message from the peer has invalid contents. */
+/** \brief SSL status: ChangeCipherSpec message from the peer has invalid
+    contents. */
 #define BR_ERR_BAD_CCS                12
 
-/* Alert message from the peer has invalid contents (odd length). */
+/** \brief SSL status: alert message from the peer has invalid contents
+    (odd length). */
 #define BR_ERR_BAD_ALERT              13
 
-/* Incoming handshake message decoding failed. */
+/** \brief SSL status: incoming handshake message decoding failed. */
 #define BR_ERR_BAD_HANDSHAKE          14
 
-/* ServerHello contains a session ID which is larger than 32 bytes. */
+/** \brief SSL status: ServerHello contains a session ID which is larger
+    than 32 bytes. */
 #define BR_ERR_OVERSIZED_ID           15
 
-/* Server wants to use a cipher suite that we did not claim to support.
-   This is also reported if we tried to advertise a cipher suite that
-   we do not support. */
+/** \brief SSL status: server wants to use a cipher suite that we did
+    not claim to support. This is also reported if we tried to advertise
+    a cipher suite that we do not support. */
 #define BR_ERR_BAD_CIPHER_SUITE       16
 
-/* Server wants to use a compression that we did not claim to support. */
+/** \brief SSL status: server wants to use a compression that we did not
+    claim to support. */
 #define BR_ERR_BAD_COMPRESSION        17
 
-/* Server's max fragment length does not match client's. */
+/** \brief SSL status: server's max fragment length does not match
+    client's. */
 #define BR_ERR_BAD_FRAGLEN            18
 
-/* Secure renegotiation failed. */
+/** \brief SSL status: secure renegotiation failed. */
 #define BR_ERR_BAD_SECRENEG           19
 
-/* Server sent an extension type that we did not announce, or used the
-   same extension type several times in a single ServerHello. */
+/** \brief SSL status: server sent an extension type that we did not
+    announce, or used the same extension type several times in a single
+    ServerHello. */
 #define BR_ERR_EXTRA_EXTENSION        20
 
-/* Invalid Server Name Indication contents (when used by the server,
-   this extension shall be empty). */
+/** \brief SSL status: invalid Server Name Indication contents (when
+    used by the server, this extension shall be empty). */
 #define BR_ERR_BAD_SNI                21
 
-/* Invalid ServerHelloDone from the server (length is not 0). */
+/** \brief SSL status: invalid ServerHelloDone from the server (length
+    is not 0). */
 #define BR_ERR_BAD_HELLO_DONE         22
 
-/* Internal limit exceeded (e.g. server's public key is too large). */
+/** \brief SSL status: internal limit exceeded (e.g. server's public key
+    is too large). */
 #define BR_ERR_LIMIT_EXCEEDED         23
 
-/* Finished message from peer does not match the expected value. */
+/** \brief SSL status: Finished message from peer does not match the
+    expected value. */
 #define BR_ERR_BAD_FINISHED           24
 
-/* Session resumption attempt with distinct version or cipher suite. */
+/** \brief SSL status: session resumption attempt with distinct version
+    or cipher suite. */
 #define BR_ERR_RESUME_MISMATCH        25
 
-/* Unsupported or invalid algorithm (ECDHE curve, signature algorithm,
-   hash function). */
+/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve,
+    signature algorithm, hash function). */
 #define BR_ERR_INVALID_ALGORITHM      26
 
-/* Invalid signature on ServerKeyExchange message. */
+/** \brief SSL status: invalid signature on ServerKeyExchange message. */
 #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: I/O error or premature close on underlying
+    transport stream. This error code is set only by the simplified
+    I/O API ("br_sslio_*"). */
 #define BR_ERR_IO                     31
 
-/* When a fatal alert is received from the peer, the alert value is added
-   to this constant. */
+/** \brief SSL status: base value for a received fatal alert.
+
+    When a fatal alert is received from the peer, the alert value
+    is added to this constant. */
 #define BR_ERR_RECV_FATAL_ALERT      256
 
-/* When a fatal alert is sent to the peer, the alert value is added
-   to this constant. */
+/** \brief SSL status: base value for a sent fatal alert.
+
+    When a fatal alert is sent to the peer, the alert value is added
+    to this constant. */
 #define BR_ERR_SEND_FATAL_ALERT      512
 
 /* ===================================================================== */
 
-/*
- * The decryption engine for incoming records is an object that implements
- * the following functions:
+/**
+ * \brief Decryption engine for SSL.
  *
- *   check_length   test whether the provided record length is valid
- *   decrypt        decrypt and verify the provided record
+ * When processing incoming records, the SSL engine will use a decryption
+ * engine that uses a specific context structure, and has a set of
+ * methods (a vtable) that follows this template.
  *
- * The decrypt() function receives as parameters a pointer to its context
- * structure, the record type, the record version, a pointer to the
- * start of the record payload, and a pointer to a word containing the
- * payload length. The decrypt() function may assume that the length is
- * proper (check_length() was called and returned 1). On success, a
- * pointer to the first plaintext byte is returned, and *len is adjusted
- * to contain the plaintext length; on error, NULL is returned.
- *
- * The decryption engine is responsible for keeping track of the record
- * sequence number.
+ * The decryption engine is responsible for applying decryption, verifying
+ * MAC, and keeping track of the record sequence number.
  */
 typedef struct br_sslrec_in_class_ br_sslrec_in_class;
 struct br_sslrec_in_class_ {
+       /**
+        * \brief Context size (in bytes).
+        */
        size_t context_size;
+
+       /**
+        * \brief Test validity of the incoming record length.
+        *
+        * This function returns 1 if the announced length for an
+        * incoming record is valid, 0 otherwise,
+        *
+        * \param ctx          decryption engine context.
+        * \param record_len   incoming record length.
+        * \return  1 of a valid length, 0 otherwise.
+        */
        int (*check_length)(const br_sslrec_in_class *const *ctx,
                size_t record_len);
+
+       /**
+        * \brief Decrypt the incoming record.
+        *
+        * This function may assume that the record length is valid
+        * (it has been previously tested with `check_length()`).
+        * Decryption is done in place; `*len` is updated with the
+        * cleartext length, and the address of the first plaintext
+        * byte is returned. If the record is correct but empty, then
+        * `*len` is set to 0 and a non-`NULL` pointer is returned.
+        *
+        * On decryption/MAC error, `NULL` is returned.
+        *
+        * \param ctx           decryption engine context.
+        * \param record_type   record type (23 for application data, etc).
+        * \param version       record version.
+        * \param payload       address of encrypted payload.
+        * \param len           pointer to payload length (updated).
+        * \return  pointer to plaintext, or `NULL` on error.
+        */
        unsigned char *(*decrypt)(const br_sslrec_in_class **ctx,
                int record_type, unsigned version,
                void *payload, size_t *len);
 };
 
-/*
- * The encryption engine for outgoing records is an object that implements
- * the following functions:
- *
- *   max_plaintext   get start and end offsets for payload
- *   encrypt         encrypt and apply MAC on current record
- *
- * The max_plaintext() function receives as inputs the start and end
- * of the buffer where the payload will be stored; this function assumes
- * that there will be room for a record header (5 bytes) BEFORE the
- * offset specified by *start. The max_plaintext() function then adjusts
- * the two offsets to designate the area for the plaintext.
- *
- * The encrypt() function assumes that the provided plaintext data is
- * in a buffer with enough room before and after the data chunk to
- * receive the needed headers (i.e. the plaintext is at offsets which
- * were computed by an earlier call to max_plaintext()). It returns
- * a pointer to the start of the encrypted record, and writes the
- * encrypted record length in '*len' (that length includes the record
- * header).
- *
- * The encryption engine MUST fill the record header. If the engine
- * performs a "split" into several records, then the successive records
- * MUST be consecutive in RAM; the returned length is thus the sum of
- * the individual record lengths.
- *
- * The encryption engine is responsible for keeping track of the record
- * sequence number.
+/**
+ * \brief Encryption engine for SSL.
+ *
+ * When building outgoing records, the SSL engine will use an encryption
+ * engine that uses a specific context structure, and has a set of
+ * methods (a vtable) that follows this template.
+ *
+ * The encryption engine is responsible for applying encryption and MAC,
+ * and keeping track of the record sequence number.
  */
 typedef struct br_sslrec_out_class_ br_sslrec_out_class;
 struct br_sslrec_out_class_ {
+       /**
+        * \brief Context size (in bytes).
+        */
        size_t context_size;
+
+       /**
+        * \brief Compute maximum plaintext sizes and offsets.
+        *
+        * When this function is called, the `*start` and `*end`
+        * values contain offsets designating the free area in the
+        * outgoing buffer for plaintext data; that free area is
+        * preceded by a 5-byte space which will receive the record
+        * header.
+        *
+        * The `max_plaintext()` function is responsible for adjusting
+        * both `*start` and `*end` to make room for any record-specific
+        * header, MAC, padding, and possible split.
+        *
+        * \param ctx     encryption engine context.
+        * \param start   pointer to start of plaintext offset (updated).
+        * \param end     pointer to start of plaintext offset (updated).
+        */
        void (*max_plaintext)(const br_sslrec_out_class *const *ctx,
                size_t *start, size_t *end);
+
+       /**
+        * \brief Perform record encryption.
+        *
+        * This function encrypts the record. The plaintext address and
+        * length are provided. Returned value is the start of the
+        * encrypted record (or sequence of records, if a split was
+        * performed), _including_ the 5-byte header, and `*len` is
+        * adjusted to the total size of the record(s), there again
+        * including the header(s).
+        *
+        * \param ctx           decryption engine context.
+        * \param record_type   record type (23 for application data, etc).
+        * \param version       record version.
+        * \param plaintext     address of plaintext.
+        * \param len           pointer to plaintext length (updated).
+        * \return  pointer to start of built record.
+        */
        unsigned char *(*encrypt)(const br_sslrec_out_class **ctx,
                int record_type, unsigned version,
                void *plaintext, size_t *len);
 };
 
-/*
- * An outgoing no-encryption engine is defined, to process outgoing
- * records before completion of the initial handshake.
+/**
+ * \brief Context for a no-encryption engine.
+ *
+ * The no-encryption engine processes outgoing records during the initial
+ * handshake, before encryption is applied.
  */
 typedef struct {
+       /** \brief No-encryption engine vtable. */
        const br_sslrec_out_class *vtable;
 } br_sslrec_out_clear_context;
+
+/** \brief Static, constant vtable for the no-encryption engine. */
 extern const br_sslrec_out_class br_sslrec_out_clear_vtable;
 
 /* ===================================================================== */
 
-/*
- * An engine for processing incoming records with a block cipher in
- * CBC mode has an extra initialization function, that takes as inputs:
- * -- a block cipher (CBC decryption) and its key;
- * -- a hash function for HMAC, with the MAC key and output length;
- * -- an optional initial IV.
- * If the IV is not provided (the 'iv' parameter is NULL), then the
- * engine will use an explicit per-record IV (as is mandated in TLS 1.1+).
+/**
+ * \brief Record decryption engine class, for CBC mode.
  *
- * The initialization function is responsible for setting the 'vtable'
- * field of the context.
+ * This class type extends the decryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for CBC processing: block cipher implementation, block cipher key,
+ * HMAC parameters (hash function, key, MAC length), and IV. If the
+ * IV is `NULL`, then a per-record IV will be used (TLS 1.1+).
  */
 typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class;
 struct br_sslrec_in_cbc_class_ {
+       /**
+        * \brief Superclass, as first vtable field.
+        */
        br_sslrec_in_class inner;
+
+       /**
+        * \brief Engine initialisation method.
+        *
+        * This method sets the vtable field in the context.
+        *
+        * \param ctx           context to initialise.
+        * \param bc_impl       block cipher implementation (CBC decryption).
+        * \param bc_key        block cipher key.
+        * \param bc_key_len    block cipher key length (in bytes).
+        * \param dig_impl      hash function for HMAC.
+        * \param mac_key       HMAC key.
+        * \param mac_key_len   HMAC key length (in bytes).
+        * \param mac_out_len   HMAC output length (in bytes).
+        * \param iv            initial IV (or `NULL`).
+        */
        void (*init)(const br_sslrec_in_cbc_class **ctx,
                const br_block_cbcdec_class *bc_impl,
                const void *bc_key, size_t bc_key_len,
@@ -279,21 +381,37 @@ struct br_sslrec_in_cbc_class_ {
                const void *iv);
 };
 
-/*
- * An engine for processing outgoing records with a block cipher in
- * CBC mode has an extra initialization function, that takes as inputs:
- * -- a block cipher (CBC encryption) and its key;
- * -- a hash function for HMAC, with the MAC key and output length;
- * -- an optional initial IV.
- * If the IV is not provided (the 'iv' parameter is NULL), then the
- * engine will use an explicit per-record IV (as is mandated in TLS 1.1+).
+/**
+ * \brief Record encryption engine class, for CBC mode.
  *
- * The initialization function is responsible for setting the 'vtable'
- * field of the context.
+ * This class type extends the encryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for CBC processing: block cipher implementation, block cipher key,
+ * HMAC parameters (hash function, key, MAC length), and IV. If the
+ * IV is `NULL`, then a per-record IV will be used (TLS 1.1+).
  */
 typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class;
 struct br_sslrec_out_cbc_class_ {
+       /**
+        * \brief Superclass, as first vtable field.
+        */
        br_sslrec_out_class inner;
+
+       /**
+        * \brief Engine initialisation method.
+        *
+        * This method sets the vtable field in the context.
+        *
+        * \param ctx           context to initialise.
+        * \param bc_impl       block cipher implementation (CBC encryption).
+        * \param bc_key        block cipher key.
+        * \param bc_key_len    block cipher key length (in bytes).
+        * \param dig_impl      hash function for HMAC.
+        * \param mac_key       HMAC key.
+        * \param mac_key_len   HMAC key length (in bytes).
+        * \param mac_out_len   HMAC output length (in bytes).
+        * \param iv            initial IV (or `NULL`).
+        */
        void (*init)(const br_sslrec_out_cbc_class **ctx,
                const br_block_cbcenc_class *bc_impl,
                const void *bc_key, size_t bc_key_len,
@@ -302,11 +420,17 @@ struct br_sslrec_out_cbc_class_ {
                const void *iv);
 };
 
-/*
- * Context structure for decrypting incoming records with CBC + HMAC.
+/**
+ * \brief Context structure for decrypting incoming records with
+ * CBC + HMAC.
+ *
+ * The first field points to the vtable. The other fields are opaque
+ * and shall not be accessed directly.
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        const br_sslrec_in_cbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
        uint64_t seq;
        union {
                const br_block_cbcdec_class *vtable;
@@ -317,14 +441,25 @@ typedef struct {
        size_t mac_len;
        unsigned char iv[16];
        int explicit_IV;
+#endif
 } br_sslrec_in_cbc_context;
+
+/**
+ * \brief Static, constant vtable for record decryption with CBC.
+ */
 extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable;
 
-/*
- * Context structure for encrypting outgoing records with CBC + HMAC.
+/**
+ * \brief Context structure for encrypting outgoing records with
+ * CBC + HMAC.
+ *
+ * The first field points to the vtable. The other fields are opaque
+ * and shall not be accessed directly.
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        const br_sslrec_out_cbc_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
        uint64_t seq;
        union {
                const br_block_cbcenc_class *vtable;
@@ -335,24 +470,43 @@ typedef struct {
        size_t mac_len;
        unsigned char iv[16];
        int explicit_IV;
+#endif
 } br_sslrec_out_cbc_context;
+
+/**
+ * \brief Static, constant vtable for record encryption with CBC.
+ */
 extern const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable;
 
 /* ===================================================================== */
 
-/*
- * An engine for processing incoming records with a block cipher in
- * GCM mode has an extra initialization function, that takes as inputs:
- * -- a block cipher (CTR) and its key;
- * -- a GHASH implementation;
- * -- an initial IV (4 bytes).
+/**
+ * \brief Record decryption engine class, for GCM mode.
  *
- * The initialization function is responsible for setting the 'vtable'
- * field of the context.
+ * This class type extends the decryption engine class with an
+ * initialisation method that receives the parameters needed
+ * for GCM processing: block cipher implementation, block cipher key,
+ * GHASH implementtion, and 4-byte IV.
  */
 typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class;
 struct br_sslrec_in_gcm_class_ {
+       /**
+        * \brief Superclass, as first vtable field.
+        */
        br_sslrec_in_class inner;
+
+       /**
+        * \brief Engine initialisation method.
+        *
+        * This method sets the vtable field in the context.
+        *
+        * \param ctx           context to initialise.
+        * \param bc_impl       block cipher implementation (CTR).
+        * \param key           block cipher key.
+        * \param key_len       block cipher key length (in bytes).
+        * \param gh_impl       GHASH implementation.
+        * \param iv            static IV (4 bytes).
+        */
        void (*init)(const br_sslrec_in_gcm_class **ctx,
                const br_block_ctr_class *bc_impl,
                const void *key, size_t key_len,
@@ -360,19 +514,33 @@ struct br_sslrec_in_gcm_class_ {
                const void *iv);
 };
 
-/*
- * An engine for processing outgoing records with a block cipher in
- * GCM mode has an extra initialization function, that takes as inputs:
- * -- a block cipher (CTR) and its key;
- * -- a GHASH implementation;
- * -- an initial IV (4 bytes).
+/**
+ * \brief Record 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_ {
+       /**
+        * \brief Superclass, as first vtable field.
+        */
        br_sslrec_out_class inner;
+
+       /**
+        * \brief Engine initialisation method.
+        *
+        * This method sets the vtable field in the context.
+        *
+        * \param ctx           context to initialise.
+        * \param bc_impl       block cipher implementation (CTR).
+        * \param key           block cipher key.
+        * \param key_len       block cipher key length (in bytes).
+        * \param gh_impl       GHASH implementation.
+        * \param iv            static IV (4 bytes).
+        */
        void (*init)(const br_sslrec_out_gcm_class **ctx,
                const br_block_ctr_class *bc_impl,
                const void *key, size_t key_len,
@@ -380,16 +548,22 @@ struct br_sslrec_out_gcm_class_ {
                const void *iv);
 };
 
-/*
- * We use the same context structure for incoming and outgoing records
- * with GCM, because it allows internal code sharing.
+/**
+ * \brief Context structure for processing records with GCM.
+ *
+ * The same context structure is used for encrypting and decrypting.
+ *
+ * The first field points to the vtable. The other fields are opaque
+ * and shall not be accessed directly.
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        union {
                const void *gen;
                const br_sslrec_in_gcm_class *in;
                const br_sslrec_out_gcm_class *out;
        } vtable;
+#ifndef BR_DOXYGEN_IGNORE
        uint64_t seq;
        union {
                const br_block_ctr_class *vtable;
@@ -398,39 +572,61 @@ typedef struct {
        br_ghash gh;
        unsigned char iv[4];
        unsigned char h[16];
+#endif
 } br_sslrec_gcm_context;
 
+/**
+ * \brief Static, constant vtable for record decryption with GCM.
+ */
 extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable;
+
+/**
+ * \brief Static, constant vtable for record encryption with GCM.
+ */
 extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable;
 
 /* ===================================================================== */
 
-/*
- * Type for session parameters, to be saved for session resumption.
+/**
+ * \brief Type for session parameters, to be saved for session resumption.
  */
 typedef struct {
+       /** \brief Session ID buffer. */
        unsigned char session_id[32];
+       /** \brief Session ID length (in bytes, at most 32). */
        unsigned char session_id_len;
+       /** \brief Protocol version. */
        uint16_t version;
+       /** \brief Cipher suite. */
        uint16_t cipher_suite;
+       /** \brief Master secret. */
        unsigned char master_secret[48];
 } br_ssl_session_parameters;
 
+#ifndef BR_DOXYGEN_IGNORE
 /*
  * Maximum numnber of cipher suites supported by a client or server.
  */
 #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
- * should not be used directly, but is meant to be included as first
- * field of the context structures for SSL clients and servers.
+ * should not be used directly.
+ *
+ * Structure contents are opaque and shall not be accessed directly.
  */
 typedef struct {
-
+#ifndef BR_DOXYGEN_IGNORE
        /*
         * The error code. When non-zero, then the state is "failed" and
         * no I/O may occur until reset.
@@ -648,11 +844,14 @@ typedef struct {
        const br_sslrec_in_gcm_class *igcm_in;
        const br_sslrec_out_gcm_class *igcm_out;
        const br_ec_impl *iec;
-
+#endif
 } br_ssl_engine_context;
 
-/*
- * Get currently defined engine behavioural flags.
+/**
+ * \brief Get currently defined engine behavioural flags.
+ *
+ * \param cc   SSL engine context.
+ * \return  the flags.
  */
 static inline uint32_t
 br_ssl_engine_get_flags(br_ssl_engine_context *cc)
@@ -660,9 +859,11 @@ br_ssl_engine_get_flags(br_ssl_engine_context *cc)
        return cc->flags;
 }
 
-/*
- * Set all engine flags. Flags which are not in the 'flags' argument
- * are cleared.
+/**
+ * \brief Set all engine behavioural flags.
+ *
+ * \param cc      SSL engine context.
+ * \param flags   new value for all flags.
  */
 static inline void
 br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags)
@@ -670,9 +871,14 @@ br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags)
        cc->flags = flags;
 }
 
-/*
- * Add some engine flags. The provided flags are set in the engine context,
- * but other flags are untouched.
+/**
+ * \brief Set some engine behavioural flags.
+ *
+ * The flags set in the `flags` parameter are set in the context; other
+ * flags are untouched.
+ *
+ * \param cc      SSL engine context.
+ * \param flags   additional set flags.
  */
 static inline void
 br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags)
@@ -680,9 +886,14 @@ br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags)
        cc->flags |= flags;
 }
 
-/*
- * Remove some engine flags. The provided flags are cleared from the
- * engine context, but other flags are untouched.
+/**
+ * \brief Clear some engine behavioural flags.
+ *
+ * The flags set in the `flags` parameter are cleared from the context; other
+ * flags are untouched.
+ *
+ * \param cc      SSL engine context.
+ * \param flags   flags to remove.
  */
 static inline void
 br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)
@@ -690,8 +901,33 @@ 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)
+
 /*
- * Set the minimum and maximum supported protocol versions.
+ * \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 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,
@@ -701,17 +937,35 @@ br_ssl_engine_set_versions(br_ssl_engine_context *cc,
        cc->version_max = version_max;
 }
 
-/*
- * Set the list of cipher suites advertised by this context. The provided
- * array is copied into the context. It is the caller responsibility
- * to ensure that all provided suites will be supported by the context.
+/**
+ * \brief Set the list of cipher suites advertised by this context.
+ *
+ * The provided array is copied into the context. It is the caller
+ * responsibility to ensure that all provided suites will be supported
+ * by the context. The engine context has enough room to receive _all_
+ * suites supported by the implementation. The provided array MUST NOT
+ * contain duplicates.
+ *
+ * If the engine is for a client, the "signaling" pseudo-cipher suite
+ * `TLS_FALLBACK_SCSV` can be added at the end of the list, if the
+ * calling application is performing a voluntary downgrade (voluntary
+ * downgrades are not recommended, but if such a downgrade is done, then
+ * adding the fallback pseudo-suite is a good idea).
+ *
+ * \param cc           SSL engine context.
+ * \param suites       cipher suites.
+ * \param suites_num   number of cipher suites.
  */
 void br_ssl_engine_set_suites(br_ssl_engine_context *cc,
        const uint16_t *suites, size_t suites_num);
 
-/*
- * Set the X.509 engine. The context should be already initialized and
- * ready to process a new chain.
+/**
+ * \brief Set the X.509 engine.
+ *
+ * The caller shall ensure that the X.509 engine is properly initialised.
+ *
+ * \param cc        SSL engine context.
+ * \param x509ctx   X.509 certificate validation context.
  */
 static inline void
 br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx)
@@ -719,8 +973,17 @@ br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx)
        cc->x509ctx = x509ctx;
 }
 
-/*
- * Set a hash function implementation (by ID).
+/**
+ * \brief Set 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,
@@ -729,8 +992,15 @@ br_ssl_engine_set_hash(br_ssl_engine_context *ctx,
        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)
@@ -738,8 +1008,14 @@ br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int 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)
@@ -747,8 +1023,14 @@ br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl)
        cc->prf10 = impl;
 }
 
-/*
- * Set the PRF implementation (for TLS 1.2, with SHA-256).
+/**
+ * \brief Set the PRF implementation with SHA-256 (for TLS 1.2).
+ *
+ * This function sets (or removes, if `impl` is `NULL`) the 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)
@@ -756,8 +1038,14 @@ br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl)
        cc->prf_sha256 = impl;
 }
 
-/*
- * Set the PRF implementation (for TLS 1.2, with SHA-384).
+/**
+ * \brief Set the PRF implementation with SHA-384 (for TLS 1.2).
+ *
+ * This function sets (or removes, if `impl` is `NULL`) the 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)
@@ -765,8 +1053,12 @@ br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl)
        cc->prf_sha384 = impl;
 }
 
-/*
- * Set the AES/CBC implementations.
+/**
+ * \brief Set the AES/CBC implementations.
+ *
+ * \param cc         SSL engine context.
+ * \param impl_enc   AES/CBC encryption implementation (or `NULL`).
+ * \param impl_dec   AES/CBC decryption implementation (or `NULL`).
  */
 static inline void
 br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc,
@@ -777,8 +1069,11 @@ br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc,
        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,
@@ -787,8 +1082,12 @@ br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc,
        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,
@@ -799,8 +1098,11 @@ br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc,
        cc->ides_cbcdec = impl_dec;
 }
 
-/*
- * Set the GHASH implementation (for GCM).
+/**
+ * \brief Set the 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)
@@ -808,8 +1110,12 @@ br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl)
        cc->ighash = impl;
 }
 
-/*
- * Set the CBC+HMAC record processor implementations.
+/**
+ * \brief Set the 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,
@@ -820,8 +1126,12 @@ br_ssl_engine_set_cbc(br_ssl_engine_context *cc,
        cc->icbc_out = impl_out;
 }
 
-/*
- * Set the GCM record processor implementations.
+/**
+ * \brief Set the record encryption and decryption engines for GCM.
+ *
+ * \param cc         SSL engine context.
+ * \param impl_in    record GCM decryption implementation (or `NULL`).
+ * \param impl_out   record GCM encryption implementation (or `NULL`).
  */
 static inline void
 br_ssl_engine_set_gcm(br_ssl_engine_context *cc,
@@ -832,9 +1142,14 @@ br_ssl_engine_set_gcm(br_ssl_engine_context *cc,
        cc->igcm_out = impl_out;
 }
 
-/*
- * Set the ECC core operations implementation. The 'iec' parameter
- * points to the core EC code used for both ECDHE and ECDSA.
+/**
+ * \brief Set the 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)
@@ -842,44 +1157,67 @@ br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec)
        cc->iec = iec;
 }
 
-/*
- * 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 I/O buffer for the SSL engine.
+ *
+ * Once this call has been made, `br_ssl_client_reset()` or
+ * `br_ssl_server_reset()` MUST be called before using the context.
+ *
+ * The provided buffer will be used as long as the engine context is
+ * used. The caller is responsible for keeping it available.
+ *
+ * If `bidi` is 0, then the engine will operate in half-duplex mode
+ * (it won't be able to send data while there is unprocessed incoming
+ * data in the buffer, and it won't be able to receive data while there
+ * is unsent data in the buffer). The optimal buffer size in half-duplex
+ * mode is `BR_SSL_BUFSIZE_MONO`; if the buffer is larger, then extra
+ * bytes are ignored. If the buffer is smaller, then this limits the
+ * capacity of the engine to support all allowed record sizes.
+ *
+ * If `bidi` is 1, then the engine will split the buffer into two
+ * parts, for separate handling of outgoing and incoming data. This
+ * enables full-duplex processing, but requires more RAM. The optimal
+ * buffer size in full-duplex mode is `BR_SSL_BUFSIZE_BIDI`; if the
+ * buffer is larger, then extra bytes are ignored. If the buffer is
+ * smaller, then the split will favour the incoming part, so that
+ * interoperability is maximised.
+ *
+ * \param cc          SSL engine context
+ * \param iobuf       I/O buffer.
+ * \param iobuf_len   I/O buffer length (in bytes).
+ * \param bidi        non-zero for full-duplex mode.
  */
 void br_ssl_engine_set_buffer(br_ssl_engine_context *cc,
        void *iobuf, size_t iobuf_len, int bidi);
 
-/*
- * Set the I/O buffers for a SSL engine. This call sets two buffers, for
- * concurrent input and output. The two buffers MUST be disjoint. Once
- * this call has been made, br_ssl_client_reset() or
- * br_ssl_server_reset() must be called before using the context.
+/**
+ * \brief Set the I/O buffers for the SSL engine.
+ *
+ * Once this call has been made, `br_ssl_client_reset()` or
+ * `br_ssl_server_reset()` MUST be called before using the context.
+ *
+ * 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 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.
+ * The macros `BR_SSL_BUFSIZE_INPUT` and `BR_SSL_BUFSIZE_OUTPUT`
+ * evaluate to the optimal (maximum) sizes for the input and output
+ * buffer, respectively.
+ *
+ * \param cc         SSL engine context
+ * \param ibuf       input buffer.
+ * \param ibuf_len   input buffer length (in bytes).
+ * \param obuf       output buffer.
+ * \param obuf_len   output buffer length (in bytes).
  */
 void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc,
        void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len);
 
-/*
- * Inject some "initial entropy" in the context. This entropy will be added
- * to what can be obtained from the underlying operating system, if that
- * OS is supported.
+/**
+ * \brief Inject some "initial entropy" in the context.
+ *
+ * This entropy will be added to what can be obtained from the
+ * underlying operating system, if that OS is supported.
  *
  * This function may be called several times; all injected entropy chunks
  * are cumulatively mixed.
@@ -901,28 +1239,66 @@ void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc,
  * asymmetric private key that you also store on the system) AND a
  * non-repeating value (e.g. current time, provided that the local clock
  * cannot be reset or altered by the attacker).
+ *
+ * \param cc     SSL engine context.
+ * \param data   extra entropy to inject.
+ * \param len    length of the extra data (in bytes).
  */
 void br_ssl_engine_inject_entropy(br_ssl_engine_context *cc,
        const void *data, size_t len);
 
-/*
- * Get the "server name" in this engine. For clients, this is the name
- * provided with br_ssl_client_reset(); for servers, this is the name
- * received from the client as part of the ClientHello message. If there
- * is no such name (e.g. the client did not send an SNI extension) then
- * the returned string is empty (returned pointer points to a byte of
- * value 0).
+/**
+ * \brief Get the "server name" in this engine.
+ *
+ * For clients, this is the name provided with `br_ssl_client_reset()`;
+ * for servers, this is the name received from the client as part of the
+ * ClientHello message. If there is no such name (e.g. the client did
+ * not send an SNI extension) then the returned string is empty
+ * (returned pointer points to a byte of value 0).
+ *
+ * The returned pointer refers to a buffer inside the context, which may
+ * be overwritten as part of normal SSL activity (even within the same
+ * connection, if a renegotiation occurs).
+ *
+ * \param cc   SSL engine context.
+ * \return  the server name (possibly empty).
  */
 static inline const char *
-br_ssl_engine_get_server_name(br_ssl_engine_context *cc)
+br_ssl_engine_get_server_name(const br_ssl_engine_context *cc)
 {
        return cc->server_name;
 }
 
-/*
- * 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.
+/**
+ * \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,
@@ -931,11 +1307,15 @@ br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc,
        memcpy(pp, &cc->session, sizeof *pp);
 }
 
-/*
- * Set the session parameters to the provided value. 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.
+/**
+ * \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,
@@ -944,46 +1324,73 @@ br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc,
        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:
  *
- *   BR_SSL_CLOSED    engine is finished, no more I/O (until next reset)
- *   BR_SSL_SENDREC   engine has some bytes to send to the peer
- *   BR_SSL_RECVREC   engine expects some bytes from the peer
- *   BR_SSL_SENDAPP   engine may receive application data to send (or flush)
- *   BR_SSL_RECVAPP   engine has obtained some application data from the peer,
- *                    that should be read by the caller
+ *   - `BR_SSL_CLOSED`
+ *
+ *     Engine is finished, no more I/O (until next reset).
+ *
+ *   - `BR_SSL_SENDREC`
+ *
+ *     Engine has some bytes to send to the peer.
+ *
+ *   - `BR_SSL_RECVREC`
+ *
+ *     Engine expects some bytes from the peer.
+ *
+ *   - `BR_SSL_SENDAPP`
+ *
+ *     Engine may receive application data to send (or flush).
+ *
+ *   - `BR_SSL_RECVAPP`
+ *
+ *     Engine has obtained some application data from the peer,
+ *     that should be read by the caller.
  *
  * If no flag at all is set (state value is 0), then the engine is not
- * fully initialized yet.
+ * fully initialised yet.
  *
- * The BR_SSL_CLOSED flag is exclusive; when it is set, no other flag is set.
- * To distinguish between a normal closure and an error, use
- * br_ssl_engine_last_error().
+ * The `BR_SSL_CLOSED` flag is exclusive; when it is set, no other flag
+ * is set. To distinguish between a normal closure and an error, use
+ * `br_ssl_engine_last_error()`.
  *
- * Generally speaking, BR_SSL_SENDREC and BR_SSL_SENDAPP are mutually
+ * Generally speaking, `BR_SSL_SENDREC` and `BR_SSL_SENDAPP` are mutually
  * exclusive: the input buffer, at any point, either accumulates
  * plaintext data, or contains an assembled record that is being sent.
- * Similarly, BR_SSL_RECVREC and BR_SSL_RECVAPP are mutually exclusive.
+ * Similarly, `BR_SSL_RECVREC` and `BR_SSL_RECVAPP` are mutually exclusive.
  * This may change in a future library version.
+ *
+ * \param cc   SSL engine context.
+ * \return  the current engine state.
  */
+unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc);
 
+/** \brief SSL engine state: closed or failed. */
 #define BR_SSL_CLOSED    0x0001
+/** \brief SSL engine state: record data is ready to be sent to the peer. */
 #define BR_SSL_SENDREC   0x0002
+/** \brief SSL engine state: engine may receive records from the peer. */
 #define BR_SSL_RECVREC   0x0004
+/** \brief SSL engine state: engine may accept application data to send. */
 #define BR_SSL_SENDAPP   0x0008
+/** \brief SSL engine state: engine has received application data. */
 #define BR_SSL_RECVAPP   0x0010
 
-/*
- * Get the current engine state.
- */
-unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc);
-
-/*
- * Get the engine error indicator. This is BR_ERR_OK (0) if no error was
- * encountered since the last call to br_ssl_client_reset() or
- * br_ssl_server_reset(). Only these calls clear the error indicator.
+/**
+ * \brief Get the engine error indicator.
+ *
+ * The error indicator is `BR_ERR_OK` (0) if no error was encountered
+ * since the last call to `br_ssl_client_reset()` or
+ * `br_ssl_server_reset()`. Other status values are "sticky": they
+ * remain set, and prevent all I/O activity, until cleared. Only the
+ * reset calls clear the error indicator.
+ *
+ * \param cc   SSL engine context.
+ * \return  0, or a non-zero error code.
  */
 static inline int
 br_ssl_engine_last_error(const br_ssl_engine_context *cc)
@@ -1027,61 +1434,184 @@ br_ssl_engine_last_error(const br_ssl_engine_context *cc)
  *      call.
  */
 
+/**
+ * \brief Get buffer for application data to send.
+ *
+ * If the engine is ready to accept application data to send to the
+ * peer, then this call returns a pointer to the buffer where such
+ * data shall be written, and its length is written in `*len`.
+ * Otherwise, `*len` is set to 0 and `NULL` is returned.
+ *
+ * \param cc    SSL engine context.
+ * \param len   receives the application data output buffer length, or 0.
+ * \return  the application data output buffer, or `NULL`.
+ */
 unsigned char *br_ssl_engine_sendapp_buf(
        const br_ssl_engine_context *cc, size_t *len);
+
+/**
+ * \brief Inform the engine of some new application data.
+ *
+ * After writing `len` bytes in the buffer returned by
+ * `br_ssl_engine_sendapp_buf()`, the application shall call this
+ * function to trigger any relevant processing. The `len` parameter
+ * MUST NOT be 0, and MUST NOT exceed the value obtained in the
+ * `br_ssl_engine_sendapp_buf()` call.
+ *
+ * \param cc    SSL engine context.
+ * \param len   number of bytes pushed (not zero).
+ */
 void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len);
 
+/**
+ * \brief Get buffer for received application data.
+ *
+ * If the engine has received application data from the peer, hen this
+ * call returns a pointer to the buffer from where such data shall be
+ * read, and its length is written in `*len`. Otherwise, `*len` is set
+ * to 0 and `NULL` is returned.
+ *
+ * \param cc    SSL engine context.
+ * \param len   receives the application data input buffer length, or 0.
+ * \return  the application data input buffer, or `NULL`.
+ */
 unsigned char *br_ssl_engine_recvapp_buf(
        const br_ssl_engine_context *cc, size_t *len);
+
+/**
+ * \brief Acknowledge some received application data.
+ *
+ * After reading `len` bytes from the buffer returned by
+ * `br_ssl_engine_recvapp_buf()`, the application shall call this
+ * function to trigger any relevant processing. The `len` parameter
+ * MUST NOT be 0, and MUST NOT exceed the value obtained in the
+ * `br_ssl_engine_recvapp_buf()` call.
+ *
+ * \param cc    SSL engine context.
+ * \param len   number of bytes read (not zero).
+ */
 void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len);
 
+/**
+ * \brief Get buffer for record data to send.
+ *
+ * If the engine has prepared some records to send to the peer, then this
+ * call returns a pointer to the buffer from where such data shall be
+ * read, and its length is written in `*len`. Otherwise, `*len` is set
+ * to 0 and `NULL` is returned.
+ *
+ * \param cc    SSL engine context.
+ * \param len   receives the record data output buffer length, or 0.
+ * \return  the record data output buffer, or `NULL`.
+ */
 unsigned char *br_ssl_engine_sendrec_buf(
        const br_ssl_engine_context *cc, size_t *len);
+
+/**
+ * \brief Acknowledge some sent record data.
+ *
+ * After reading `len` bytes from the buffer returned by
+ * `br_ssl_engine_sendrec_buf()`, the application shall call this
+ * function to trigger any relevant processing. The `len` parameter
+ * MUST NOT be 0, and MUST NOT exceed the value obtained in the
+ * `br_ssl_engine_sendrec_buf()` call.
+ *
+ * \param cc    SSL engine context.
+ * \param len   number of bytes read (not zero).
+ */
 void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len);
 
+/**
+ * \brief Get buffer for incoming records.
+ *
+ * If the engine is ready to accept records from the peer, then this
+ * call returns a pointer to the buffer where such data shall be
+ * written, and its length is written in `*len`. Otherwise, `*len` is
+ * set to 0 and `NULL` is returned.
+ *
+ * \param cc    SSL engine context.
+ * \param len   receives the record data input buffer length, or 0.
+ * \return  the record data input buffer, or `NULL`.
+ */
 unsigned char *br_ssl_engine_recvrec_buf(
        const br_ssl_engine_context *cc, size_t *len);
+
+/**
+ * \brief Inform the engine of some new record data.
+ *
+ * After writing `len` bytes in the buffer returned by
+ * `br_ssl_engine_recvrec_buf()`, the application shall call this
+ * function to trigger any relevant processing. The `len` parameter
+ * MUST NOT be 0, and MUST NOT exceed the value obtained in the
+ * `br_ssl_engine_recvrec_buf()` call.
+ *
+ * \param cc    SSL engine context.
+ * \param len   number of bytes pushed (not zero).
+ */
 void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len);
 
-/*
+/**
+ * \brief Flush buffered application data.
+ *
  * If some application data has been buffered in the engine, then wrap
  * it into a record and mark it for sending. If no application data has
  * been buffered but the engine would be ready to accept some, AND the
- * 'force' parameter is non-zero, then an empty record is assembled and
+ * `force` parameter is non-zero, then an empty record is assembled and
  * marked for sending. In all other cases, this function does nothing.
  *
  * Empty records are technically legal, but not all existing SSL/TLS
  * implementations support them. Empty records can be useful as a
  * transparent "keep-alive" mechanism to maintain some low-level
  * network activity.
+ *
+ * \param cc      SSL engine context.
+ * \param force   non-zero to force sending an empty record.
  */
 void br_ssl_engine_flush(br_ssl_engine_context *cc, int force);
 
-/*
- * Close the context. If, at that point, the context is open and in
- * ready state, then a close_notify alert is assembled and marked for
- * sending. Otherwise, no such alert is assembled.
+/**
+ * \brief Initiate a closure.
+ *
+ * If, at that point, the context is open and in ready state, then a
+ * `close_notify` alert is assembled and marked for sending; this
+ * triggers the closure protocol. Otherwise, no such alert is assembled.
+ *
+ * \param cc   SSL engine context.
  */
 void br_ssl_engine_close(br_ssl_engine_context *cc);
 
-/*
- * Initiate a renegotiation. If the engine is failed or closed, or if
- * the peer is known not to support secure renegotiation (RFC 5746),
- * then this function returns 0. Otherwise, this function returns 1 and
- * a renegotiation attempt is triggered, unless a handshake is already
- * taking place, in which case the call is ignored.
+/**
+ * \brief Initiate a renegotiation.
+ *
+ * If the engine is failed or closed, or if the peer is known not to
+ * support secure renegotiation (RFC 5746), or if renegotiations have
+ * been disabled with the `BR_OPT_NO_RENEGOTIATION` flag, 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);
 
-/*
- * Context structure for a SSL client.
+/**
+ * \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.
  */
 typedef struct {
-       /*
-        * The encapsulated engine context.
+       /**
+        * \brief The encapsulated engine context.
         */
        br_ssl_engine_context eng;
 
+#ifndef BR_DOXYGEN_IGNORE
        /*
         * Minimum ClientHello length; padding with an extension (RFC
         * 7685) is added if necessary to match at least that length.
@@ -1096,7 +1626,7 @@ typedef struct {
        br_rsa_public irsapub;
        br_rsa_pkcs1_vrfy irsavrfy;
        br_ecdsa_vrfy iecdsa;
-
+#endif
 } br_ssl_client_context;
 
 /*
@@ -1105,24 +1635,46 @@ typedef struct {
  * name 'xxx'. Defined profile names are:
  *
  *    full    all supported versions and suites; constant-time implementations
- *    FIXME: add other profiles
+ *    TODO: add other profiles
  */
 
+/**
+ * \brief SSL client profile: full.
+ *
+ * This function initialises the provided SSL client context with
+ * all supported algorithms and cipher suites. It also initialises
+ * a companion X.509 validation engine with all supported algorithms,
+ * and the provided trust anchors; the X.509 engine will be used by
+ * the client context to validate the server's certificate.
+ *
+ * \param cc                  client context to initialise.
+ * \param xc                  X.509 validation context to initialise.
+ * \param trust_anchors       trust anchors to use.
+ * \param trust_anchors_num   number of trust anchors.
+ */
 void br_ssl_client_init_full(br_ssl_client_context *cc,
        br_x509_minimal_context *xc,
        const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num);
 
-/*
- * Clear the complete contents of a SSL client context, including the
- * reference to the configured buffer, implementations, cipher suites
- * and state.
+/**
+ * \brief Clear the complete contents of a SSL client context.
+ *
+ * Everything is cleared, including the reference to the configured buffer,
+ * implementations, cipher suites and state. This is a preparatory step
+ * to assembling a custom profile.
+ *
+ * \param cc   client context to clear.
  */
 void br_ssl_client_zero(br_ssl_client_context *cc);
 
-/*
- * Set the RSA public-key operations implementation. This will be used
- * to encrypt the pre-master secret with the server's RSA public key
- * (RSA-encryption cipher suites only).
+/**
+ * \brief Set the RSA public-key operations implementation.
+ *
+ * This will be used to encrypt the pre-master secret with the server's
+ * RSA public key (RSA-encryption cipher suites only).
+ *
+ * \param cc        client context.
+ * \param irsapub   RSA public-key encryption implementation.
  */
 static inline void
 br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)
@@ -1130,10 +1682,14 @@ br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)
        cc->irsapub = irsapub;
 }
 
-/*
- * 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 signature verification implementation.
+ *
+ * This will be used to verify the server's signature on its
+ * ServerKeyExchange message (ECDHE_RSA cipher suites only).
+ *
+ * \param cc         client context.
+ * \param irsavrfy   RSA signature verification implementation.
  */
 static inline void
 br_ssl_client_set_rsavrfy(br_ssl_client_context *cc, br_rsa_pkcs1_vrfy irsavrfy)
@@ -1142,8 +1698,13 @@ br_ssl_client_set_rsavrfy(br_ssl_client_context *cc, br_rsa_pkcs1_vrfy irsavrfy)
 }
 
 /*
- * Set the ECDSA implementation (signature verification). The ECC core
- * implementation must also have been set.
+ * \brief Set the ECDSA implementation (signature verification).
+ *
+ * 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_client_set_ecdsa(br_ssl_client_context *cc, br_ecdsa_vrfy iecdsa)
@@ -1151,8 +1712,22 @@ br_ssl_client_set_ecdsa(br_ssl_client_context *cc, br_ecdsa_vrfy iecdsa)
        cc->iecdsa = iecdsa;
 }
 
-/*
- * Set the minimum ClientHello length (RFC 7685 padding).
+/**
+ * \brief Set the minimum ClientHello length (RFC 7685 padding).
+ *
+ * If this value is set and the ClientHello would be shorter, then
+ * the Pad ClientHello extension will be added with enough padding bytes
+ * to reach the target size. Because of the extension header, the resulting
+ * size will sometimes be slightly more than `len` bytes if the target
+ * size cannot be exactly met.
+ *
+ * The target length relates to the _contents_ of the ClientHello, not
+ * counting its 4-byte header. For instance, if `len` is set to 512,
+ * then the padding will bring the ClientHello size to 516 bytes with its
+ * header, and 521 bytes when counting the 5-byte record header.
+ *
+ * \param cc    client context.
+ * \param len   minimum ClientHello length (in bytes).
  */
 static inline void
 br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len)
@@ -1160,29 +1735,47 @@ br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len)
        cc->min_clienthello_len = len;
 }
 
-/*
- * Prepare or reset a client context for connecting with a server of
- * name 'server_name'. The 'server_name' parameter is used to fill the
- * SNI extension; if the parameter is NULL then no SNI extension will
- * be sent.
+/**
+ * \brief Prepare or reset a client context for a new connection.
+ *
+ * The `server_name` parameter is used to fill the SNI extension; the
+ * X.509 "minimal" engine will also match that name against the server
+ * names included in the server's certificate. If the parameter is
+ * `NULL` then no SNI extension will be sent, and the X.509 "minimal"
+ * engine (if used for server certificate validation) will not check
+ * presence of any specific name in the received certificate.
  *
- * If 'resume_session' is non-zero and the context was previously used
+ * Therefore, setting the `server_name` to `NULL` shall be reserved
+ * to cases where alternate or additional methods are used to ascertain
+ * that the right server public key is used (e.g. a "known key" model).
+ *
+ * If `resume_session` is non-zero and the context was previously used
  * then the session parameters may be reused (depending on whether the
  * server previously sent a non-empty session ID, and accepts the session
- * resumption).
+ * resumption). The session parameters for session resumption can also
+ * be set explicitly with `br_ssl_engine_set_session_parameters()`.
  *
  * On failure, the context is marked as failed, and this function
  * returns 0. A possible failure condition is when no initial entropy
  * was injected, and none could be obtained from the OS (either OS
  * randomness gathering is not supported, or it failed).
+ *
+ * \param cc               client context.
+ * \param server_name      target server name, or `NULL`.
+ * \param resume_session   non-zero to try session resumption.
+ * \return  0 on failure, 1 on success.
  */
 int br_ssl_client_reset(br_ssl_client_context *cc,
        const char *server_name, int resume_session);
 
-/*
- * Forget any session in the context. This means that the next handshake
- * that uses this context will necessarily be a full handshake (this
- * applies both to new connections and to renegotiations).
+/**
+ * \brief Forget any session in the context.
+ *
+ * This means that the next handshake that uses this context will
+ * necessarily be a full handshake (this applies both to new connections
+ * and to renegotiations).
+ *
+ * \param cc   client context.
  */
 static inline void
 br_ssl_client_forget_session(br_ssl_client_context *cc)
@@ -1190,40 +1783,64 @@ br_ssl_client_forget_session(br_ssl_client_context *cc)
        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 Type for a "translated cipher suite", as an array of two
+ * 16-bit integers.
+ *
+ * The first element is the cipher suite identifier (as used on the wire).
+ * The second element is the concatenation of four 4-bit elements which
  * characterise the cipher suite contents. In most to least significant
  * order, these 4-bit elements are:
  *
- *   Bits 12 to 15: key exchange + server key type
- *      0   RSA            RSA key exchange, key is RSA (encryption)
- *      1   ECDHE-RSA      ECDHE key exchange, key is RSA (signature)
- *      2   ECDHE-ECDSA    ECDHE key exchange, key is EC (signature)
- *      3   ECDH-RSA       Key is EC (key exchange), cert is signed with RSA
- *      4   ECDH-ECDSA     Key is EC (key exchange), cert is signed with ECDSA
- *
- *   Bits 8 to 11: symmetric encryption algorithm
- *      0   3DES/CBC
- *      1   AES-128/CBC
- *      2   AES-256/CBC
- *      3   AES-128/GCM
- *      4   AES-256/GCM
- *      5   ChaCha20/Poly1305
- *
- *   Bits 4 to 7: MAC algorithm
- *      0   AEAD           No dedicated MAC because encryption is AEAD
- *      2   HMAC/SHA-1     Value matches br_sha1_ID
- *      4   HMAC/SHA-256   Value matches br_sha256_ID
- *      5   HMAC/SHA-384   Value matches br_sha384_ID
- *
- *   Bits 0 to 3: hash function for PRF when used with TLS-1.2
- *      4   SHA-256        Value matches br_sha256_ID
- *      5   SHA-384        Value matches br_sha384_ID
+ *   - Bits 12 to 15: key exchange + server key type
+ *
+ *     | val | symbolic constant        | suite type  | details                                          |
+ *     | :-- | :----------------------- | :---------- | :----------------------------------------------- |
+ *     |  0  | `BR_SSLKEYX_RSA`         | RSA         | RSA key exchange, key is RSA (encryption)        |
+ *     |  1  | `BR_SSLKEYX_ECDHE_RSA`   | ECDHE_RSA   | ECDHE key exchange, key is RSA (signature)       |
+ *     |  2  | `BR_SSLKEYX_ECDHE_ECDSA` | ECDHE_ECDSA | ECDHE key exchange, key is EC (signature)        |
+ *     |  3  | `BR_SSLKEYX_ECDH_RSA`    | ECDH_RSA    | Key is EC (key exchange), cert signed with RSA   |
+ *     |  4  | `BR_SSLKEYX_ECDH_ECDSA`  | ECDH_ECDSA  | Key is EC (key exchange), cert signed with ECDSA |
+ *
+ *   - Bits 8 to 11: symmetric encryption algorithm
+ *
+ *     | val | symbolic constant      | symmetric encryption | key strength (bits) |
+ *     | :-- | :--------------------- | :------------------- | :------------------ |
+ *     |  0  | `BR_SSLENC_3DES_CBC`   | 3DES/CBC             | 168                 |
+ *     |  1  | `BR_SSLENC_AES128_CBC` | AES-128/CBC          | 128                 |
+ *     |  2  | `BR_SSLENC_AES256_CBC` | AES-256/CBC          | 256                 |
+ *     |  3  | `BR_SSLENC_AES128_GCM` | AES-128/GCM          | 128                 |
+ *     |  4  | `BR_SSLENC_AES256_GCM` | AES-256/GCM          | 256                 |
+ *     |  5  | `BR_SSLENC_CHACHA20`   | ChaCha20/Poly1305    | 256                 |
+ *
+ *   - Bits 4 to 7: MAC algorithm
+ *
+ *     | val | symbolic constant  | MAC type     | details                               |
+ *     | :-- | :----------------- | :----------- | :------------------------------------ |
+ *     |  0  | `BR_SSLMAC_AEAD`   | AEAD         | No dedicated MAC (encryption is AEAD) |
+ *     |  2  | `BR_SSLMAC_SHA1`   | HMAC/SHA-1   | Value matches `br_sha1_ID`            |
+ *     |  4  | `BR_SSLMAC_SHA256` | HMAC/SHA-256 | Value matches `br_sha256_ID`          |
+ *     |  5  | `BR_SSLMAC_SHA384` | HMAC/SHA-384 | Value matches `br_sha384_ID`          |
+ *
+ *   - Bits 0 to 3: hash function for PRF when used with TLS-1.2
+ *
+ *     | val | symbolic constant  | hash function | details                              |
+ *     | :-- | :----------------- | :------------ | :----------------------------------- |
+ *     |  4  | `BR_SSLPRF_SHA256` | SHA-256       | Value matches `br_sha256_ID`         |
+ *     |  5  | `BR_SSLPRF_SHA384` | SHA-384       | Value matches `br_sha384_ID`         |
+ *
+ * For instance, cipher suite `TLS_RSA_WITH_AES_128_GCM_SHA256` has
+ * standard identifier 0x009C, and is translated to 0x0304, for, in
+ * that order: RSA key exchange (0), AES-128/GCM (3), AEAD integrity (0),
+ * SHA-256 in the TLS PRF (4).
  */
 typedef uint16_t br_suite_translated[2];
 
+#ifndef BR_DOXYGEN_IGNORE
+/*
+ * Constants are already documented in the br_suite_translated type.
+ */
+
 #define BR_SSLKEYX_RSA           0
 #define BR_SSLKEYX_ECDHE_RSA     1
 #define BR_SSLKEYX_ECDHE_ECDSA   2
@@ -1245,122 +1862,234 @@ typedef uint16_t br_suite_translated[2];
 #define BR_SSLPRF_SHA256         br_sha256_ID
 #define BR_SSLPRF_SHA384         br_sha384_ID
 
+#endif
+
 /*
  * Pre-declaration for the SSL server context.
  */
 typedef struct br_ssl_server_context_ br_ssl_server_context;
 
-/*
- * Type for the server policy choices, taken after analysis of the client
- * message:
- *
- *     cipher_suite   Cipher suite to use.
- *
- *     hash_id        Signature hash function identifier (hash function
- *                    to use for signing the ServerKeyExchange, when the
- *                    suite uses ECDHE).
- *
- *     chain          The certificate chain to send (number of certificates
- *     chain_len      is in chain_length). The certificates are send "as is"
- *                    and shall be in standard SSL/TLS order (i.e. end-entity
- *                    first, each subsequent certificate signs the previous).
+/**
+ * \brief Type for the server policy choices, taken after analysis of
+ * the client message (ClientHello).
  */
 typedef struct {
+       /**
+        * \brief Cipher suite to use with that client.
+        */
        uint16_t cipher_suite;
+
+       /**
+        * \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;
+
+       /**
+        * \brief Certificate chain to send to the client.
+        *
+        * This is an array of `br_x509_certificate` objects, each
+        * normally containing a DER-encoded certificate. The server
+        * code does not try to decode these elements.
+        */
        const br_x509_certificate *chain;
+
+       /**
+        * \brief Certificate chain length (number of certificates).
+        */
        size_t chain_len;
 } br_ssl_server_choices;
 
-/*
- * Type for the certificate and private key handler on the server: an
- * object with the following methods:
- *
- *   choose    Select the parameters for this connection (cipher suite,
- *             certificate chain...). The selection is written into the
- *             '*choices' structure. Returned value is 1 on success, or
- *             0 on error (an error here means that the handshake will
- *             fail, and a handshake_failure alert will be sent to the
- *             client).
- *
- *   do_keyx   Perform the server-side key exchange operation. Returned
- *             value is 1 on success, 0 on error (see below). This is
- *             called only when the selected cipher suite calls for a
- *             RSA or ECDH key exchange involving the server key.
- *
- *   do_sign   Perform the server-side signature operation. Returned
- *             value is the signature length, or 0 on error (see below).
- *             This is called only when the selected cipher suite calls
- *             for an ECDHE key exchange, signed by the server with its key.
- *
- *
- * The do_keyx() method shall apply the following semantics:
- *
- * -- For RSA key exchange, it shall decrypt the incoming data along
- * the rules of PKCS#1 v1.5. The method must verify the proper padding
- * and also that the decrypted message length is exactly 48 bytes.
- * IMPORTANT: these operations MUST be constant-time (or adequatly blinded).
- * The decrypted message is written in the first 48 bytes of data[]. The
- * caller makes sure that the data[] buffer is large enough, and that 'len'
- * is at least 59 bytes.
- *
- * -- For ECDH key exchange, the provided data is an EC point (uncompressed
- * format); the method shall multiply that point with the server private
- * key, and write the X coordinate of the resulting point in the data[]
- * buffer, starting at offset 1 (so if the method produces a compressed or
- * uncompressed point, form offset 0, then everything is fine).
- *
- * In both cases, returned value is 1 on success, 0 on error.
+/**
+ * \brief Class type for a policy handler (server side).
  *
+ * A policy handler selects the policy parameters for a connection
+ * (cipher suite and other algorithms, and certificate chain to send to
+ * the client); it also performs the server-side computations involving
+ * its permanent private key.
  *
- * The do_sign() method shall compute the signature on the hash value
- * provided in the data[] buffer. The 'hv_len' value contains the hash
- * value length, while the 'len' parameter is the total size of the
- * buffer. The method must verify that the signature length is no more
- * than 'len' bytes, and report an error otherwise.
- *
- * The hash identifier is either 0 for the MD5+SHA-1 method in TLS-1.0 and
- * 1.1, or a non-zero hash function identifier in TLS-1.2 and later. In
- * the MD5+SHA-1 method, the hash value has length 36 bytes and there is
- * no hash function identifying header to add in the padding.
- *
- * Returned value is the signature length (in bytes). On error, this method
- * shall return 0.
+ * The SSL server engine will invoke first `choose()`, once the
+ * ClientHello message has been received, then either `do_keyx()`
+ * `do_sign()`, depending on the cipher suite.
  */
 typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class;
 struct br_ssl_server_policy_class_ {
+       /**
+        * \brief Context size (in bytes).
+        */
        size_t context_size;
+
+       /**
+        * \brief Select algorithms and certificates for this connection.
+        *
+        * This callback function shall fill the provided `choices`
+        * structure with the policy choices for this connection. This
+        * entails selecting the cipher suite, hash function for signing
+        * the ServerKeyExchange (applicable only to ECDHE cipher suites),
+        * and certificate chain to send.
+        *
+        * The callback receives a pointer to the server context that
+        * contains the relevant data. In particular, the functions
+        * `br_ssl_server_get_client_suites()`,
+        * `br_ssl_server_get_client_hashes()` and
+        * `br_ssl_server_get_client_curves()` can be used to obtain
+        * the cipher suites, hash functions and elliptic curves
+        * supported by both the client and server, respectively. The
+        * `br_ssl_engine_get_version()` and `br_ssl_engine_get_server_name()`
+        * functions yield the protocol version and requested server name
+        * (SNI), respectively.
+        *
+        * This function may modify its context structure (`pctx`) in
+        * arbitrary ways to keep track of its own choices.
+        *
+        * This function shall return 1 if appropriate policy choices
+        * could be made, or 0 if this connection cannot be pursued.
+        *
+        * \param pctx      policy context.
+        * \param cc        SSL server context.
+        * \param choices   destination structure for the policy choices.
+        * \return  1 on success, 0 on error.
+        */
        int (*choose)(const br_ssl_server_policy_class **pctx,
                const br_ssl_server_context *cc,
                br_ssl_server_choices *choices);
+
+       /**
+        * \brief Perform key exchange (server part).
+        *
+        * This callback is invoked to perform the server-side cryptographic
+        * operation for a key exchange that is not ECDHE. This callback
+        * uses the private key.
+        *
+        * **For RSA key exchange**, the provided `data` (of length `len`
+        * bytes) shall be decrypted with the server's private key, and
+        * the 48-byte premaster secret copied back to the first 48 bytes
+        * of `data`.
+        *
+        *   - The caller makes sure that `len` is at least 59 bytes.
+        *
+        *   - This callback MUST check that the provided length matches
+        *     that of the key modulus; it shall report an error otherwise.
+        *
+        *   - If the length matches that of the RSA key modulus, then
+        *     processing MUST be constant-time, even if decryption fails,
+        *     or the padding is incorrect, or the plaintext message length
+        *     is not exactly 48 bytes.
+        *
+        *   - This callback needs not check the two first bytes of the
+        *     obtained pre-master secret (the caller will do that).
+        *
+        *   - If an error is reported (0), then what the callback put
+        *     in the first 48 bytes of `data` is unimportant (the caller
+        *     will use random bytes instead).
+        *
+        * **For ECDH key exchange**, the provided `data` (of length `len`
+        * bytes) is the elliptic curve point from the client. The
+        * callback shall multiply it with its private key, and store
+        * the resulting X coordinate in `data`, starting at offset 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);
+
+       /**
+        * \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);
 };
 
-/*
- * A single-chain RSA policy handler, that always uses a single chain and
- * a RSA key. It may be restricted to do only signatures or only key
- * exchange.
+/**
+ * \brief A single-chain RSA policy handler.
+ *
+ * This policy context uses a single certificate chain, and a RSA
+ * private key. The context can be restricted to only signatures or
+ * only key exchange.
+ *
+ * Apart from the first field (vtable pointer), its contents are
+ * opaque and shall not be accessed directly.
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        const br_ssl_server_policy_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
        const br_x509_certificate *chain;
        size_t chain_len;
        const br_rsa_private_key *sk;
        unsigned allowed_usages;
        br_rsa_private irsacore;
        br_rsa_pkcs1_sign irsasign;
+#endif
 } br_ssl_server_policy_rsa_context;
 
-/*
- * A single-chain EC policy handler, that always uses a single chain and
- * an EC key. It may be restricted to do only signatures or only key
- * exchange.
+/**
+ * \brief A single-chain EC policy handler.
+ *
+ * This policy context uses a single certificate chain, and an EC
+ * private key. The context can be restricted to only signatures or
+ * only key exchange.
+ *
+ * Due to how TLS is defined, this context must be made aware whether
+ * the server certificate was itself signed with RSA or ECDSA. The code
+ * does not try to decode the certificate to obtain that information.
+ *
+ * Apart from the first field (vtable pointer), its contents are
+ * opaque and shall not be accessed directly.
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        const br_ssl_server_policy_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
        const br_x509_certificate *chain;
        size_t chain_len;
        const br_ec_private_key *sk;
@@ -1369,69 +2098,117 @@ typedef struct {
        const br_multihash_context *mhash;
        const br_ec_impl *iec;
        br_ecdsa_sign iecdsa;
+#endif
 } br_ssl_server_policy_ec_context;
 
-/*
- * Class type for a session parameter cache.
+/**
+ * \brief 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.
- *
- * Note that the requesting server context is provided. Implementations
- * may used some of the resources of that context, e.g. random number
- * generator or implementations of some cryptographic algorithms.
+ * Session parameters are saved in the cache with `save()`, and
+ * retrieved with `load()`. The cache implementation can apply any
+ * storage and eviction strategy that it sees fit. The SSL server
+ * context that performs the request is provided, so that its
+ * functionalities may be used by the implementation (e.g. hash
+ * functions or random number generation).
  */
 typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class;
 struct br_ssl_session_cache_class_ {
+       /**
+        * \brief Context size (in bytes).
+        */
        size_t context_size;
+
+       /**
+        * \brief Record a session.
+        *
+        * This callback should record the provided session parameters.
+        * The `params` structure is transient, so its contents shall
+        * be copied into the cache. The session ID has been randomly
+        * generated and always has length exactly 32 bytes.
+        *
+        * \param ctx          session cache context.
+        * \param server_ctx   SSL server context.
+        * \param params       session parameters to save.
+        */
        void (*save)(const br_ssl_session_cache_class **ctx,
                br_ssl_server_context *server_ctx,
                const br_ssl_session_parameters *params);
+
+       /**
+        * \brief Lookup a session in the cache.
+        *
+        * The session ID to lookup is in `params` and always has length
+        * exactly 32 bytes. If the session parameters are found in the
+        * cache, then the parameters shall be copied into the `params`
+        * structure. Returned value is 1 on successful lookup, 0
+        * otherwise.
+        *
+        * \param ctx          session cache context.
+        * \param server_ctx   SSL server context.
+        * \param params       destination for session parameters.
+        * \return  1 if found, 0 otherwise.
+        */
        int (*load)(const br_ssl_session_cache_class **ctx,
                br_ssl_server_context *server_ctx,
                br_ssl_session_parameters *params);
 };
 
-/*
- * Context for a very basic cache system that uses a linked list, managed
- * with an LRU algorithm (when the cache is full and a new set of parameters
- * must be saved, the least recently used entry is evicted). The storage
- * buffer is externally provided. Internally, an index tree is used to
- * speed up operations.
+/**
+ * \brief Context for a basic cache system.
+ *
+ * The system stores session parameters in a buffer provided at
+ * initialisation time. Each entry uses exactly 100 bytes, and
+ * buffer sizes up to 4294967295 bytes are supported.
+ *
+ * Entries are evicted with a LRU (Least Recently Used) policy. A
+ * search tree is maintained to keep lookups fast even with large
+ * caches.
+ *
+ * Apart from the first field (vtable pointer), the structure
+ * contents are opaque and shall not be accessed directly.
  */
 typedef struct {
+       /** \brief Pointer to vtable. */
        const br_ssl_session_cache_class *vtable;
+#ifndef BR_DOXYGEN_IGNORE
        unsigned char *store;
        size_t store_len, store_ptr;
        unsigned char index_key[32];
        const br_hash_class *hash;
        int init_done;
        uint32_t head, tail, root;
+#endif
 } br_ssl_session_cache_lru;
 
-/*
- * Initialise a LRU session cache with the provided storage space.
+/**
+ * \brief Initialise a LRU session cache with the provided storage space.
+ *
+ * The provided storage space must remain valid as long as the cache
+ * is used. Arbitrary lengths are supported, up to 4294967295 bytes;
+ * each entry uses up exactly 100 bytes.
+ *
+ * \param cc          session cache context.
+ * \param store       storage space for cached entries.
+ * \param store_len   storage space length (in bytes).
  */
 void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc,
        unsigned char *store, size_t store_len);
 
-/*
- * Context structure for a SSL server.
+/**
+ * \brief Context structure for a SSL server.
+ *
+ * The first field (called `eng`) is the SSL engine; all functions that
+ * work on a `br_ssl_engine_context` structure shall take as parameter
+ * a pointer to that field. The other structure fields are opaque and
+ * must not be accessed directly.
  */
 struct br_ssl_server_context_ {
-       /*
-        * The encapsulated engine context.
+       /**
+        * \brief The encapsulated engine context.
         */
        br_ssl_engine_context eng;
 
+#ifndef BR_DOXYGEN_IGNORE
        /*
         * Maximum version from the client.
         */
@@ -1491,22 +2268,11 @@ struct br_ssl_server_context_ {
 
        /*
         * Server-specific implementations.
+        * (none for now)
         */
+#endif
 };
 
-/*
- * 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)
-
-/*
- * 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)
-
 /*
  * Each br_ssl_server_init_xxx() function sets the list of supported
  * cipher suites and used implementations, as specified by the profile
@@ -1514,7 +2280,7 @@ struct br_ssl_server_context_ {
  *
  *    full_rsa    all supported algorithm, server key type is RSA
  *    full_ec     all supported algorithm, server key type is EC
- *    FIXME: add other profiles
+ *    TODO: add other profiles
  *
  * Naming scheme for "minimal" profiles: min123
  *
@@ -1534,33 +2300,156 @@ struct br_ssl_server_context_ {
  *      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);
 
+/**
+ * \brief SSL server profile: full_ec.
+ *
+ * This function initialises the provided SSL server context with
+ * all supported algorithms and cipher suites that rely on an EC
+ * key pair.
+ *
+ * The key type of the CA that issued the server's certificate must
+ * be provided, since it matters for ECDH cipher suites (ECDH_RSA
+ * suites require a RSA-powered CA). The key type is either
+ * `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`.
+ *
+ * \param cc                     server context to initialise.
+ * \param chain                  server certificate chain.
+ * \param chain_len              chain length (number of certificates).
+ * \param cert_issuer_key_type   certificate issuer's key type.
+ * \param sk                     EC private key.
+ */
 void br_ssl_server_init_full_ec(br_ssl_server_context *cc,
        const br_x509_certificate *chain, size_t chain_len,
        unsigned cert_issuer_key_type, const br_ec_private_key *sk);
 
+/**
+ * \brief SSL server profile: minr2g.
+ *
+ * This profile uses only TLS_RSA_WITH_AES_128_GCM_SHA256. Server key is
+ * RSA, and RSA key exchange is used (not forward secure, but uses little
+ * CPU in the client).
+ *
+ * \param cc          server context to initialise.
+ * \param chain       server certificate chain.
+ * \param chain_len   certificate chain length (number of certificate).
+ * \param sk          RSA private key.
+ */
 void br_ssl_server_init_minr2g(br_ssl_server_context *cc,
        const br_x509_certificate *chain, size_t chain_len,
        const br_rsa_private_key *sk);
+
+/**
+ * \brief SSL server profile: mine2g.
+ *
+ * This profile uses only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Server key
+ * is RSA, and ECDHE key exchange is used. This suite provides forward
+ * security, with a higher CPU expense on the client, and a somewhat
+ * larger code footprint (compared to "minr2g").
+ *
+ * \param cc          server context to initialise.
+ * \param chain       server certificate chain.
+ * \param chain_len   certificate chain length (number of certificate).
+ * \param sk          RSA private key.
+ */
 void br_ssl_server_init_mine2g(br_ssl_server_context *cc,
        const br_x509_certificate *chain, size_t chain_len,
        const br_rsa_private_key *sk);
+
+/**
+ * \brief SSL server profile: minf2g.
+ *
+ * This profile uses only TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
+ * Server key is EC, and ECDHE key exchange is used. This suite provides
+ * forward security, with a higher CPU expense on the client and server
+ * (by a factor of about 3 to 4), and a somewhat larger code footprint
+ * (compared to "minu2g" and "minv2g").
+ *
+ * \param cc          server context to initialise.
+ * \param chain       server certificate chain.
+ * \param chain_len   certificate chain length (number of certificate).
+ * \param sk          EC private key.
+ */
 void br_ssl_server_init_minf2g(br_ssl_server_context *cc,
        const br_x509_certificate *chain, size_t chain_len,
        const br_ec_private_key *sk);
+
+/**
+ * \brief SSL server profile: minu2g.
+ *
+ * This profile uses only TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256.
+ * Server key is EC, and ECDH key exchange is used; the issuing CA used
+ * a RSA key.
+ *
+ * The "minu2g" and "minv2g" profiles do not provide forward secrecy,
+ * but are the lightest on the server (for CPU usage), and are rather
+ * inexpensive on the client as well.
+ *
+ * \param cc          server context to initialise.
+ * \param chain       server certificate chain.
+ * \param chain_len   certificate chain length (number of certificate).
+ * \param sk          EC private key.
+ */
 void br_ssl_server_init_minu2g(br_ssl_server_context *cc,
        const br_x509_certificate *chain, size_t chain_len,
        const br_ec_private_key *sk);
+
+/**
+ * \brief SSL server profile: minv2g.
+ *
+ * This profile uses only TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256.
+ * Server key is EC, and ECDH key exchange is used; the issuing CA used
+ * an EC key.
+ *
+ * The "minu2g" and "minv2g" profiles do not provide forward secrecy,
+ * but are the lightest on the server (for CPU usage), and are rather
+ * inexpensive on the client as well.
+ *
+ * \param cc          server context to initialise.
+ * \param chain       server certificate chain.
+ * \param chain_len   certificate chain length (number of certificate).
+ * \param sk          EC private key.
+ */
 void br_ssl_server_init_minv2g(br_ssl_server_context *cc,
        const br_x509_certificate *chain, size_t chain_len,
        const br_ec_private_key *sk);
 
-/*
- * Get the supported client suites. The returned array is ordered by
- * client or server preferences, depending on the relevant flag.
+/**
+ * \brief 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)
@@ -1569,10 +2458,15 @@ br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num)
        return cc->client_suites;
 }
 
-/*
- * Get the hash functions supported by the client. This is a field of
- * bits: for hash function of ID x, bit x is set if the hash function
- * is supported in RSA signatures, 8+x if it is supported with ECDSA.
+/**
+ * \brief Get the hash functions 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)
@@ -1580,9 +2474,13 @@ br_ssl_server_get_client_hashes(const br_ssl_server_context *cc)
        return cc->hashes;
 }
 
-/*
- * Get the elliptic curves supported by the client. This is a bit field
- * (bit x is set if curve of ID x is supported).
+/**
+ * \brief Get the elliptic curves supported by the client.
+ *
+ * This is a bit field (bit x is set if curve of ID x is supported).
+ *
+ * \param cc   server context.
+ * \return  the client-supported elliptic curves.
  */
 static inline uint32_t
 br_ssl_server_get_client_curves(const br_ssl_server_context *cc)
@@ -1590,15 +2488,26 @@ br_ssl_server_get_client_curves(const br_ssl_server_context *cc)
        return cc->curves;
 }
 
-/*
- * Clear the complete contents of a SSL server context, including the
- * reference to the configured buffer, implementations, cipher suites
- * and state.
+/**
+ * \brief Clear the complete contents of a SSL server context.
+ *
+ * Everything is cleared, including the reference to the configured buffer,
+ * implementations, cipher suites and state. This is a preparatory step
+ * to assembling a custom profile.
+ *
+ * \param cc   server context to clear.
  */
 void br_ssl_server_zero(br_ssl_server_context *cc);
 
-/*
- * Set an externally provided policy context.
+/**
+ * \brief Set an externally provided policy context.
+ *
+ * The policy context's methods are invoked to decide the cipher suite
+ * and certificate chain, and to perform operations involving the server's
+ * private key.
+ *
+ * \param cc     server context.
+ * \param pctx   policy context (pointer to its vtable field).
  */
 static inline void
 br_ssl_server_set_policy(br_ssl_server_context *cc,
@@ -1607,30 +2516,67 @@ br_ssl_server_set_policy(br_ssl_server_context *cc,
        cc->policy_vtable = pctx;
 }
 
-/*
- * Set the server certificate chain and key (single RSA case).
- * The 'allowed_usages' is a combination of usages, namely
- * BR_KEYTYPE_KEYX and/or BR_KEYTYPE_SIGN.
+/**
+ * \brief Set the server certificate chain and key (single RSA case).
+ *
+ * This function uses a policy context included in the server context.
+ * It configures use of a single server certificate chain with a RSA
+ * private key. The `allowed_usages` is a combination of usages, namely
+ * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables
+ * the corresponding cipher suites (i.e. `TLS_RSA_*` use the RSA key for
+ * key exchange, while `TLS_ECDHE_RSA_*` use the RSA key for signatures).
+ *
+ * \param cc               server context.
+ * \param chain            server certificate chain to send to the client.
+ * \param chain_len        chain length (number of certificates).
+ * \param sk               server private key (RSA).
+ * \param allowed_usages   allowed private key usages.
+ * \param irsacore         RSA core implementation.
+ * \param irsasign         RSA signature implementation (PKCS#1 v1.5).
  */
 void br_ssl_server_set_single_rsa(br_ssl_server_context *cc,
-       const br_x509_certificate *chain, size_t chain_length,
+       const br_x509_certificate *chain, size_t chain_len,
        const br_rsa_private_key *sk, unsigned allowed_usages,
        br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign);
 
 /*
- * Set the server certificate chain and key (single EC case).
- * The 'allowed_usages' is a combination of usages, namely
- * BR_KEYTYPE_KEYX and/or BR_KEYTYPE_SIGN.
+ * \brief Set the server certificate chain and key (single EC case).
+ *
+ * This function uses a policy context included in the server context.
+ * It configures use of a single server certificate chain with an EC
+ * private key. The `allowed_usages` is a combination of usages, namely
+ * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables
+ * the corresponding cipher suites (i.e. `TLS_ECDH_*` use the EC key for
+ * key exchange, while `TLS_ECDHE_ECDSA_*` use the EC key for signatures).
+ *
+ * In order to support `TLS_ECDH_*` cipher suites (non-ephemeral ECDH),
+ * the algorithm type of the key used by the issuing CA to sign the
+ * server's certificate must be provided, as `cert_issuer_key_type`
+ * parameter (this value is either `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`).
+ *
+ * \param cc                     server context.
+ * \param chain                  server certificate chain to send.
+ * \param chain_len              chain length (number of certificates).
+ * \param sk                     server private key (EC).
+ * \param allowed_usages         allowed private key usages.
+ * \param cert_issuer_key_type   issuing CA's key type.
+ * \param iec                    EC core implementation.
+ * \param iecdsa                 ECDSA signature implementation ("asn1" format).
  */
 void br_ssl_server_set_single_ec(br_ssl_server_context *cc,
-       const br_x509_certificate *chain, size_t chain_length,
+       const br_x509_certificate *chain, size_t chain_len,
        const br_ec_private_key *sk, unsigned allowed_usages,
        unsigned cert_issuer_key_type,
        const br_ec_impl *iec, br_ecdsa_sign iecdsa);
 
-/*
- * Configure the server context to use the provided cache for session
- * parameters.
+/**
+ * \brief 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,
@@ -1639,8 +2585,11 @@ br_ssl_server_set_cache(br_ssl_server_context *cc,
        cc->cache_vtable = vtable;
 }
 
-/*
- * Prepare or reset a server context for handling an incoming client.
+/**
+ * \brief Prepare or reset a server context for handling an incoming client.
+ *
+ * \param cc   server context.
+ * \return  1 on success, 0 on error.
  */
 int br_ssl_server_reset(br_ssl_server_context *cc);
 
@@ -1672,7 +2621,14 @@ int br_ssl_server_reset(br_ssl_server_context *cc);
  * The SSL engine naturally applies some buffering, so the callbacks need
  * not apply buffers of their own.
  */
+/**
+ * \brief Context structure for the simplified SSL I/O wrapper.
+ *
+ * This structure is initialised with `br_sslio_init()`. Its contents
+ * are opaque and shall not be accessed directly.
+ */
 typedef struct {
+#ifndef BR_DOXYGEN_IGNORE
        br_ssl_engine_context *engine;
        int (*low_read)(void *read_context,
                unsigned char *data, size_t len);
@@ -1680,11 +2636,55 @@ typedef struct {
        int (*low_write)(void *write_context,
                const unsigned char *data, size_t len);
        void *write_context;
+#endif
 } br_sslio_context;
 
-/*
- * Initialise a simplified I/O context over the provided engine and
- * I/O callbacks.
+/**
+ * \brief Initialise a simplified I/O wrapper context.
+ *
+ * The simplified I/O wrapper offers a simpler read/write API for a SSL
+ * engine (client or server), using the provided callback functions for
+ * reading data from, or writing data to, the transport medium.
+ *
+ * The callback functions have the following semantics:
+ *
+ *   - Each callback receives an opaque context value (of type `void *`)
+ *     that the callback may use arbitrarily (or possibly ignore).
+ *
+ *   - `low_read()` reads at least one byte, at most `len` bytes, from
+ *     the transport medium. Read bytes shall be written in `data`.
+ *
+ *   - `low_write()` writes at least one byte, at most `len` bytes, unto
+ *     the transport medium. The bytes to write are read from `data`.
+ *
+ *   - The `len` parameter is never zero, and is always lower than 20000.
+ *
+ *   - The number of processed bytes (read or written) is returned. Since
+ *     that number is less than 20000, it always fits on an `int`.
+ *
+ *   - On error, the callbacks return -1. Reaching end-of-stream is an
+ *     error. Errors are permanent: the SSL connection is terminated.
+ *
+ *   - Callbacks SHOULD NOT return 0. This is tolerated, as long as
+ *     callbacks endeavour to block for some non-negligible amount of
+ *     time until at least one byte can be sent or received (if a
+ *     callback returns 0, then the wrapper invokes it again
+ *     immediately).
+ *
+ *   - Callbacks MAY return as soon as at least one byte is processed;
+ *     they MAY also insist on reading or writing _all_ requested bytes.
+ *     Since SSL is a self-terminated protocol (each record has a length
+ *     header), this does not change semantics.
+ *
+ *   - Callbacks need not apply any buffering (for performance) since SSL
+ *     itself uses buffers.
+ *
+ * \param ctx             wrapper context to initialise.
+ * \param engine          SSL engine to wrap.
+ * \param low_read        callback for reading data from the transport.
+ * \param read_context    context pointer for `low_read()`.
+ * \param low_write       callback for writing data on the transport.
+ * \param write_context   context pointer for `low_write()`.
  */
 void br_sslio_init(br_sslio_context *ctx,
        br_ssl_engine_context *engine,
@@ -1695,64 +2695,123 @@ void br_sslio_init(br_sslio_context *ctx,
                const unsigned char *data, size_t len),
        void *write_context);
 
-/*
- * Read some application data from a SSL connection. This call returns
- * only when at least one byte has been obtained. Returned value is
- * the number of bytes read, or -1 on error. The number of bytes
- * always fits on an 'int' (data from a single SSL/TLS record is
- * returned).
+/**
+ * \brief Read some application data from a SSL connection.
+ *
+ * If `len` is zero, then this function returns 0 immediately. In
+ * all other cases, it never returns 0.
+ *
+ * This call returns only when at least one byte has been obtained.
+ * Returned value is the number of bytes read, or -1 on error. The
+ * number of bytes always fits on an 'int' (data from a single SSL/TLS
+ * record is returned).
  *
  * On error or SSL closure, this function returns -1. The caller should
  * inspect the error status on the SSL engine to distinguish between
  * normal closure and error.
+ *
+ * \param cc    SSL wrapper context.
+ * \param dst   destination buffer for application data.
+ * \param len   maximum number of bytes to obtain.
+ * \return  number of bytes obtained, or -1 on error.
  */
 int br_sslio_read(br_sslio_context *cc, void *dst, size_t len);
 
-/*
- * Read some application data from a SSL connection. This call returns
- * only when ALL requested bytes have been read. Returned value is 0
- * on success, -1 on error. A normal SSL closure before that many bytes
- * are obtained is reported as an error by this function.
+/**
+ * \brief Read application data from a SSL connection.
+ *
+ * This calls returns only when _all_ requested `len` bytes are read,
+ * or an error is reached. Returned value is 0 on success, -1 on error.
+ * A normal (verified) SSL closure before that many bytes are obtained
+ * is reported as an error by this function.
+ *
+ * \param cc    SSL wrapper context.
+ * \param dst   destination buffer for application data.
+ * \param len   number of bytes to obtain.
+ * \return  0 on success, or -1 on error.
  */
 int br_sslio_read_all(br_sslio_context *cc, void *dst, size_t len);
 
-/*
- * Write some application data onto a SSL connection. This call returns
- * only when at least one byte had been written onto the connection (but
- * not necessarily flushed). Returned value is the number of written
- * bytes, or -1 on error (error conditions include a closed connection).
- * It is guaranteed that the number of bytes written by such a call will
- * fit in an 'int' on all architectures.
+/**
+ * \brief Write some application data unto a SSL connection.
+ *
+ * If `len` is zero, then this function returns 0 immediately. In
+ * all other cases, it never returns 0.
+ *
+ * This call returns only when at least one byte has been written.
+ * Returned value is the number of bytes written, or -1 on error. The
+ * number of bytes always fits on an 'int' (less than 20000).
+ *
+ * On error or SSL closure, this function returns -1. The caller should
+ * inspect the error status on the SSL engine to distinguish between
+ * normal closure and error.
+ *
+ * **Important:** SSL is buffered; a "written" byte is a byte that was
+ * injected into the wrapped SSL engine, but this does not necessarily mean
+ * that it has been scheduled for sending. Use `br_sslio_flush()` to
+ * ensure that all pending data has been sent to the transport medium.
  *
- * Note that some written bytes may be buffered; use br_sslio_flush()
- * to make sure that the data is sent to the transport stream.
+ * \param cc    SSL wrapper context.
+ * \param src   source buffer for application data.
+ * \param len   maximum number of bytes to write.
+ * \return  number of bytes written, or -1 on error.
  */
 int br_sslio_write(br_sslio_context *cc, const void *src, size_t len);
 
-/*
- * Write some application data onto a SSL connection. This call returns
- * only when ALL the bytes have been written onto the connection (but
- * not necessarily flushed). Returned value is 0 on success, -1 on error.
- * 
- * Note that some written bytes may be buffered; use br_sslio_flush()
- * to make sure that the data is sent to the transport stream.
+/**
+ * \brief Write application data unto a SSL connection.
+ *
+ * This calls returns only when _all_ requested `len` bytes have been
+ * written, or an error is reached. Returned value is 0 on success, -1
+ * on error. A normal (verified) SSL closure before that many bytes are
+ * written is reported as an error by this function.
+ *
+ * **Important:** SSL is buffered; a "written" byte is a byte that was
+ * injected into the wrapped SSL engine, but this does not necessarily mean
+ * that it has been scheduled for sending. Use `br_sslio_flush()` to
+ * ensure that all pending data has been sent to the transport medium.
+ *
+ * \param cc    SSL wrapper context.
+ * \param src   source buffer for application data.
+ * \param len   number of bytes to write.
+ * \return  0 on success, or -1 on error.
  */
 int br_sslio_write_all(br_sslio_context *cc, const void *src, size_t len);
 
-/*
- * Make sure that any buffered application data in the provided context
- * get packed up and sent unto the low_write() callback method. If that
- * callback method represents a buffered system, it is up to the caller
- * to then "flush" that system too.
+/**
+ * \brief Flush pending data.
+ *
+ * This call makes sure that any buffered application data in the
+ * provided context (including the wrapped SSL engine) has been sent
+ * to the transport medium (i.e. accepted by the `low_write()` callback
+ * method). If there is no such pending data, then this function does
+ * nothing (and returns a success, i.e. 0).
+ *
+ * If the underlying transport medium has its own buffers, then it is
+ * up to the caller to ensure the corresponding flushing.
  *
  * Returned value is 0 on success, -1 on error.
+ *
+ * \param cc    SSL wrapper context.
+ * \return  0 on success, or -1 on error.
  */
 int br_sslio_flush(br_sslio_context *cc);
 
-/*
- * Perform a SSL close. This implies sending a close_notify, and reading
- * the response from the server. Returned value is 0 on success, -1 on
- * error.
+/**
+ * \brief Close the SSL connection.
+ *
+ * This call runs the SSL closure protocol (sending a `close_notify`,
+ * receiving the response `close_notify`). When it returns, the SSL
+ * connection is finished. It is still up to the caller to manage the
+ * possible transport-level termination, if applicable (alternatively,
+ * the underlying transport stream may be reused for non-SSL messages).
+ *
+ * Returned value is 0 on success, -1 on error. A failure by the peer
+ * to process the complete closure protocol (i.e. sending back the
+ * `close_notify`) is an error.
+ *
+ * \param cc    SSL wrapper context.
+ * \return  0 on success, or -1 on error.
  */
 int br_sslio_close(br_sslio_context *cc);
 
@@ -1869,6 +2928,9 @@ int br_sslio_close(br_sslio_context *cc);
 #define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256       0xCCAD
 #define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256       0xCCAE
 
+/* From RFC 7507 */
+#define BR_TLS_FALLBACK_SCSV                         0x5600
+
 /*
  * Symbolic constants for alerts.
  */
index b409636..1952615 100644 (file)
@@ -149,6 +149,9 @@ br_sslio_read(br_sslio_context *ctx, void *dst, size_t len)
        unsigned char *buf;
        size_t alen;
 
+       if (len == 0) {
+               return 0;
+       }
        if (run_until(ctx, BR_SSL_RECVAPP) < 0) {
                return -1;
        }
@@ -188,6 +191,9 @@ br_sslio_write(br_sslio_context *ctx, const void *src, size_t len)
        unsigned char *buf;
        size_t alen;
 
+       if (len == 0) {
+               return 0;
+       }
        if (run_until(ctx, BR_SSL_SENDAPP) < 0) {
                return -1;
        }
index ea247ab..b81ce07 100644 (file)
@@ -334,7 +334,9 @@ sp_choose(const br_ssl_server_policy_class **pctx,
                case BR_SSLKEYX_ECDHE_RSA:
                        if (pc->sk->key_type == BR_KEYTYPE_RSA) {
                                choices->cipher_suite = st[u][0];
-                               if (cc->eng.session.version < BR_TLS12) {
+                               if (br_ssl_engine_get_version(&cc->eng)
+                                       < BR_TLS12)
+                               {
                                        hash_id = 0;
                                }
                                choices->hash_id = hash_id;
@@ -344,7 +346,9 @@ sp_choose(const br_ssl_server_policy_class **pctx,
                case BR_SSLKEYX_ECDHE_ECDSA:
                        if (pc->sk->key_type == BR_KEYTYPE_EC) {
                                choices->cipher_suite = st[u][0];
-                               if (cc->eng.session.version < BR_TLS12) {
+                               if (br_ssl_engine_get_version(&cc->eng)
+                                       < BR_TLS12)
+                               {
                                        hash_id = br_sha1_ID;
                                }
                                choices->hash_id = hash_id;
@@ -507,7 +511,7 @@ sp_do_sign(const br_ssl_server_policy_class **pctx,
                hc = get_hash_impl(hash_id);
                if (hc == NULL) {
                        if (pc->verbose) {
-                               fprintf(stderr, "ERROR: cannot RSA-sign with"
+                               fprintf(stderr, "ERROR: cannot ECDSA-sign with"
                                        " unknown hash function: %d\n",
                                        hash_id);
                        }