BearSSL/inc/bearssl_ssl.h
2016-11-20 18:50:37 +01:00

1881 lines
63 KiB
C

/*
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_SSL_H__
#define BR_BEARSSL_SSL_H__
#include <stddef.h>
#include <stdint.h>
#include "bearssl_block.h"
#include "bearssl_hash.h"
#include "bearssl_hmac.h"
#include "bearssl_prf.h"
#include "bearssl_rand.h"
#include "bearssl_x509.h"
/*
* SSL
* ---
*
*/
/* Optimal input buffer size. */
#define BR_SSL_BUFSIZE_INPUT (16384 + 325)
/* Optimal output buffer size. */
#define BR_SSL_BUFSIZE_OUTPUT (16384 + 85)
/* 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). */
#define BR_SSL_BUFSIZE_BIDI (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT)
/*
* Constants for known SSL/TLS protocol versions (SSL 3.0, TLS 1.0, TLS 1.1
* and TLS 1.2). Note that though there is a constant for SSL 3.0, that
* protocol version is not actually supported.
*/
#define BR_SSL30 0x0300
#define BR_TLS10 0x0301
#define BR_TLS11 0x0302
#define BR_TLS12 0x0303
/*
* Error constants. They are used to report the reason why a context has
* been marked as failed.
*
* Implementation note: SSL-level error codes should be in the 1..31
* range. The 32..63 range is for certificate decoding and validation
* errors. Received fatal alerts imply an error code in the 256..511 range.
*/
/* No error so far (0). */
#define BR_ERR_OK 0
/* 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). */
#define BR_ERR_BAD_STATE 2
/* Incoming protocol or record version is unsupported. */
#define BR_ERR_UNSUPPORTED_VERSION 3
/* Incoming record version does not match the expected version. */
#define BR_ERR_BAD_VERSION 4
/* 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. */
#define BR_ERR_TOO_LARGE 6
/* 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. */
#define BR_ERR_NO_RANDOM 8
/* 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. */
#define BR_ERR_UNEXPECTED 10
/* ChangeCipherSpec message from the peer has invalid contents. */
#define BR_ERR_BAD_CCS 12
/* Alert message from the peer has invalid contents (odd length). */
#define BR_ERR_BAD_ALERT 13
/* Incoming handshake message decoding failed. */
#define BR_ERR_BAD_HANDSHAKE 14
/* 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. */
#define BR_ERR_BAD_CIPHER_SUITE 16
/* 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. */
#define BR_ERR_BAD_FRAGLEN 18
/* 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. */
#define BR_ERR_EXTRA_EXTENSION 20
/* 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). */
#define BR_ERR_BAD_HELLO_DONE 22
/* 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. */
#define BR_ERR_BAD_FINISHED 24
/* 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). */
#define BR_ERR_INVALID_ALGORITHM 26
/* 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_*"). */
#define BR_ERR_IO 31
/* 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. */
#define BR_ERR_SEND_FATAL_ALERT 512
/* ===================================================================== */
/*
* The decryption engine for incoming records is an object that implements
* the following functions:
*
* check_length test whether the provided record length is valid
* decrypt decrypt and verify the provided record
*
* 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.
*/
typedef struct br_sslrec_in_class_ br_sslrec_in_class;
struct br_sslrec_in_class_ {
size_t context_size;
int (*check_length)(const br_sslrec_in_class *const *ctx,
size_t record_len);
unsigned char *(*decrypt)(const br_sslrec_in_class **ctx,
int record_type, unsigned version,
void *payload, size_t *len);
};
/*
* The encryption engine for outgoing records is an object that implements
* the following functions:
*
* max_plaintext get start and end offsets for payload
* encrypt encrypt and apply MAC on current record
*
* The max_plaintext() function receives as inputs the start and end
* of the buffer where the payload will be stored; this function assumes
* that there will be room for a record header (5 bytes) BEFORE the
* offset specified by *start. The max_plaintext() function then adjusts
* the two offsets to designate the area for the plaintext.
*
* The encrypt() function assumes that the provided plaintext data is
* in a buffer with enough room before and after the data chunk to
* receive the needed headers (i.e. the plaintext is at offsets which
* were computed by an earlier call to max_plaintext()). It returns
* a pointer to the start of the encrypted record, and writes the
* encrypted record length in '*len' (that length includes the record
* header).
*
* The encryption engine MUST fill the record header. If the engine
* performs a "split" into several records, then the successive records
* MUST be consecutive in RAM; the returned length is thus the sum of
* the individual record lengths.
*
* The encryption engine is responsible for keeping track of the record
* sequence number.
*/
typedef struct br_sslrec_out_class_ br_sslrec_out_class;
struct br_sslrec_out_class_ {
size_t context_size;
void (*max_plaintext)(const br_sslrec_out_class *const *ctx,
size_t *start, size_t *end);
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.
*/
typedef struct {
const br_sslrec_out_class *vtable;
} br_sslrec_out_clear_context;
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+).
*
* The initialization function is responsible for setting the 'vtable'
* field of the context.
*/
typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class;
struct br_sslrec_in_cbc_class_ {
br_sslrec_in_class inner;
void (*init)(const br_sslrec_in_cbc_class **ctx,
const br_block_cbcdec_class *bc_impl,
const void *bc_key, size_t bc_key_len,
const br_hash_class *dig_impl,
const void *mac_key, size_t mac_key_len, size_t mac_out_len,
const void *iv);
};
/*
* 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+).
*
* The initialization function is responsible for setting the 'vtable'
* field of the context.
*/
typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class;
struct br_sslrec_out_cbc_class_ {
br_sslrec_out_class inner;
void (*init)(const br_sslrec_out_cbc_class **ctx,
const br_block_cbcenc_class *bc_impl,
const void *bc_key, size_t bc_key_len,
const br_hash_class *dig_impl,
const void *mac_key, size_t mac_key_len, size_t mac_out_len,
const void *iv);
};
/*
* Context structure for decrypting incoming records with CBC + HMAC.
*/
typedef struct {
const br_sslrec_in_cbc_class *vtable;
uint64_t seq;
union {
const br_block_cbcdec_class *vtable;
br_aes_gen_cbcdec_keys aes;
br_des_gen_cbcdec_keys des;
} bc;
br_hmac_key_context mac;
size_t mac_len;
unsigned char iv[16];
int explicit_IV;
} br_sslrec_in_cbc_context;
extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable;
/*
* Context structure for encrypting outgoing records with CBC + HMAC.
*/
typedef struct {
const br_sslrec_out_cbc_class *vtable;
uint64_t seq;
union {
const br_block_cbcenc_class *vtable;
br_aes_gen_cbcenc_keys aes;
br_des_gen_cbcenc_keys des;
} bc;
br_hmac_key_context mac;
size_t mac_len;
unsigned char iv[16];
int explicit_IV;
} br_sslrec_out_cbc_context;
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).
*
* The initialization function is responsible for setting the 'vtable'
* field of the context.
*/
typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class;
struct br_sslrec_in_gcm_class_ {
br_sslrec_in_class inner;
void (*init)(const br_sslrec_in_gcm_class **ctx,
const br_block_ctr_class *bc_impl,
const void *key, size_t key_len,
br_ghash gh_impl,
const void *iv);
};
/*
* 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).
*
* The initialization function is responsible for setting the 'vtable'
* field of the context.
*/
typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class;
struct br_sslrec_out_gcm_class_ {
br_sslrec_out_class inner;
void (*init)(const br_sslrec_out_gcm_class **ctx,
const br_block_ctr_class *bc_impl,
const void *key, size_t key_len,
br_ghash gh_impl,
const void *iv);
};
/*
* We use the same context structure for incoming and outgoing records
* with GCM, because it allows internal code sharing.
*/
typedef struct {
union {
const void *gen;
const br_sslrec_in_gcm_class *in;
const br_sslrec_out_gcm_class *out;
} vtable;
uint64_t seq;
union {
const br_block_ctr_class *vtable;
br_aes_gen_ctr_keys aes;
} bc;
br_ghash gh;
unsigned char iv[4];
unsigned char h[16];
} br_sslrec_gcm_context;
extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable;
extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable;
/* ===================================================================== */
/*
* Type for session parameters, to be saved for session resumption.
*/
typedef struct {
unsigned char session_id[32];
unsigned char session_id_len;
uint16_t version;
uint16_t cipher_suite;
unsigned char master_secret[48];
} br_ssl_session_parameters;
/*
* Maximum numnber of cipher suites supported by a client or server.
*/
#define BR_MAX_CIPHER_SUITES 40
/*
* Context structure for SSL engine. This is common to the client and
* server; the engine 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.
*/
typedef struct {
/*
* The error code. When non-zero, then the state is "failed" and
* no I/O may occur until reset.
*/
int err;
/*
* Configured I/O buffers. They are either disjoint, or identical.
*/
unsigned char *ibuf, *obuf;
size_t ibuf_len, obuf_len;
/*
* Maximum fragment length applies to outgoing records; incoming
* records can be processed as long as they fit in the input
* buffer. It is guaranteed that incoming records at least as big
* as max_frag_len can be processed.
*/
uint16_t max_frag_len;
unsigned char log_max_frag_len;
unsigned char peer_log_max_frag_len;
/*
* Buffering management registers.
*/
size_t ixa, ixb, ixc;
size_t oxa, oxb, oxc;
unsigned char iomode;
unsigned char incrypt;
/*
* Shutdown flag: when set to non-zero, incoming record bytes
* will not be accepted anymore. This is used after a close_notify
* has been received: afterwards, the engine no longer claims that
* it could receive bytes from the transport medium.
*/
unsigned char shutdown_recv;
/*
* 'record_type_in' is set to the incoming record type when the
* record header has been received.
* 'record_type_out' is used to make the next outgoing record
* header when it is ready to go.
*/
unsigned char record_type_in, record_type_out;
/*
* When a record is received, its version is extracted:
* -- if 'version_in' is 0, then it is set to the received version;
* -- otherwise, if the received version is not identical to
* the 'version_in' contents, then a failure is reported.
*
* This implements the SSL requirement that all records shall
* use the negotiated protocol version, once decided (in the
* ServerHello). It is up to the handshake handler to adjust this
* field when necessary.
*/
uint16_t version_in;
/*
* 'version_out' is used when the next outgoing record is ready
* to go.
*/
uint16_t version_out;
/*
* Record handler contexts.
*/
union {
const br_sslrec_in_class *vtable;
br_sslrec_in_cbc_context cbc;
br_sslrec_gcm_context gcm;
} in;
union {
const br_sslrec_out_class *vtable;
br_sslrec_out_clear_context clear;
br_sslrec_out_cbc_context cbc;
br_sslrec_gcm_context gcm;
} out;
/*
* The "application data" flag. It is set when application data
* can be exchanged, cleared otherwise.
*/
unsigned char application_data;
/*
* Context RNG.
*/
br_hmac_drbg_context rng;
int rng_init_done;
int rng_os_rand_done;
/*
* Supported minimum and maximum versions, and cipher suites.
*/
uint16_t version_min;
uint16_t version_max;
uint16_t suites_buf[BR_MAX_CIPHER_SUITES];
unsigned char suites_num;
/*
* For clients, the server name to send as a SNI extension. For
* servers, the name received in the SNI extension (if any).
*/
char server_name[256];
/*
* "Security parameters". These are filled by the handshake
* handler, and used when switching encryption state.
*/
unsigned char client_random[32];
unsigned char server_random[32];
/* obsolete
unsigned char session_id[32];
unsigned char session_id_len;
uint16_t version;
uint16_t cipher_suite;
unsigned char master_secret[48];
*/
br_ssl_session_parameters session;
/*
* ECDHE elements: curve and point from the peer. The server also
* uses that buffer for the point to send to the client.
*/
unsigned char ecdhe_curve;
unsigned char ecdhe_point[133];
unsigned char ecdhe_point_len;
/*
* Secure renegotiation (RFC 5746): 'reneg' can be:
* 0 first handshake (server support is not known)
* 1 server does not support secure renegotiation
* 2 server supports secure renegotiation
*
* The saved_finished buffer contains the client and the
* server "Finished" values from the last handshake, in
* that order (12 bytes each).
*/
unsigned char reneg;
unsigned char saved_finished[24];
/*
* Behavioural flags.
*/
uint32_t flags;
/*
* Context variables for the handshake processor.
* The 'pad' must be large enough to accommodate an
* RSA-encrypted pre-master secret, or a RSA signature on
* key exchange parameters; since we want to support up to
* RSA-4096, this means at least 512 bytes.
* (Other pad usages require its length to be at least 256.)
*/
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
unsigned char pad[512];
unsigned char *hbuf_in, *hbuf_out, *saved_hbuf_out;
size_t hlen_in, hlen_out;
void (*hsrun)(void *ctx);
/*
* The 'action' value communicates OOB information between the
* engine and the handshake processor.
*
* From the engine:
* 0 invocation triggered by I/O
* 1 invocation triggered by explicit close
* 2 invocation triggered by explicit renegotiation
*/
unsigned char action;
/*
* State for alert messages. Value is either 0, or the value of
* the alert level byte (level is either 1 for warning, or 2 for
* fatal; we convert all other values to 'fatal').
*/
unsigned char alert;
/*
* Closure flags. This flag is set when a close_notify has been
* received from the peer.
*/
unsigned char close_received;
/*
* Multi-hasher for the handshake messages. The handshake handler
* is responsible for resetting it when appropriate.
*/
br_multihash_context mhash;
/*
* Pointer to the X.509 engine. The engine is supposed to be
* already initialized. It is used to validate the peer's
* certificate.
*/
const br_x509_class **x509ctx;
/*
* Pointers to implementations; left to NULL for unsupported
* functions. For the raw hash functions, implementations are
* referenced from the multihasher (mhash field).
*/
br_tls_prf_impl prf10;
br_tls_prf_impl prf_sha256;
br_tls_prf_impl prf_sha384;
const br_block_cbcenc_class *iaes_cbcenc;
const br_block_cbcdec_class *iaes_cbcdec;
const br_block_ctr_class *iaes_ctr;
const br_block_cbcenc_class *ides_cbcenc;
const br_block_cbcdec_class *ides_cbcdec;
br_ghash ighash;
const br_sslrec_in_cbc_class *icbc_in;
const br_sslrec_out_cbc_class *icbc_out;
const br_sslrec_in_gcm_class *igcm_in;
const br_sslrec_out_gcm_class *igcm_out;
const br_ec_impl *iec;
} br_ssl_engine_context;
/*
* Get currently defined engine behavioural flags.
*/
static inline uint32_t
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.
*/
static inline void
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.
*/
static inline void
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.
*/
static inline void
br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)
{
cc->flags &= ~flags;
}
/*
* Set the minimum and maximum supported protocol versions.
*/
static inline void
br_ssl_engine_set_versions(br_ssl_engine_context *cc,
unsigned version_min, unsigned version_max)
{
cc->version_min = version_min;
cc->version_max = version_max;
}
/*
* 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.
*/
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.
*/
static inline void
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).
*/
static inline void
br_ssl_engine_set_hash(br_ssl_engine_context *ctx,
int id, const br_hash_class *impl)
{
br_multihash_setimpl(&ctx->mhash, id, impl);
}
/*
* Get a hash function implementation (by ID).
*/
static inline const br_hash_class *
br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id)
{
return br_multihash_getimpl(&ctx->mhash, id);
}
/*
* Set the PRF implementation (for TLS 1.0 and 1.1).
*/
static inline void
br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl)
{
cc->prf10 = impl;
}
/*
* Set the PRF implementation (for TLS 1.2, with SHA-256).
*/
static inline void
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).
*/
static inline void
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.
*/
static inline void
br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc,
const br_block_cbcenc_class *impl_enc,
const br_block_cbcdec_class *impl_dec)
{
cc->iaes_cbcenc = impl_enc;
cc->iaes_cbcdec = impl_dec;
}
/*
* Set the AES/CTR implementation.
*/
static inline void
br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc,
const br_block_ctr_class *impl)
{
cc->iaes_ctr = impl;
}
/*
* Set the 3DES/CBC implementations.
*/
static inline void
br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc,
const br_block_cbcenc_class *impl_enc,
const br_block_cbcdec_class *impl_dec)
{
cc->ides_cbcenc = impl_enc;
cc->ides_cbcdec = impl_dec;
}
/*
* Set the GHASH implementation (for GCM).
*/
static inline void
br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl)
{
cc->ighash = impl;
}
/*
* Set the CBC+HMAC record processor implementations.
*/
static inline void
br_ssl_engine_set_cbc(br_ssl_engine_context *cc,
const br_sslrec_in_cbc_class *impl_in,
const br_sslrec_out_cbc_class *impl_out)
{
cc->icbc_in = impl_in;
cc->icbc_out = impl_out;
}
/*
* Set the GCM record processor implementations.
*/
static inline void
br_ssl_engine_set_gcm(br_ssl_engine_context *cc,
const br_sslrec_in_gcm_class *impl_in,
const br_sslrec_out_gcm_class *impl_out)
{
cc->igcm_in = impl_in;
cc->igcm_out = impl_out;
}
/*
* Set the ECC core operations implementation. The 'iec' parameter
* points to the core EC code used for both ECDHE and ECDSA.
*/
static inline void
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.
*/
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.
*
* 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.
*/
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.
*
* This function may be called several times; all injected entropy chunks
* are cumulatively mixed.
*
* If entropy gathering from the OS is supported and compiled in, then this
* step is optional. Otherwise, it is mandatory to inject randomness, and
* the caller MUST take care to push (as one or several successive calls)
* enough entropy to achieve cryptographic resistance (at least 80 bits,
* preferably 128 or more). The engine will report an error if no entropy
* was provided and none can be obtained from the OS.
*
* Take care that this function cannot assess the cryptographic quality of
* the provided bytes.
*
* In all generality, "entropy" must here be considered to mean "that
* which the attacker cannot predict". If your OS/architecture does not
* have a suitable source of randomness, then you can make do with the
* combination of a large enough secret value (possibly a copy of an
* asymmetric private key that you also store on the system) AND a
* non-repeating value (e.g. current time, provided that the local clock
* cannot be reset or altered by the attacker).
*/
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).
*/
static inline const char *
br_ssl_engine_get_server_name(br_ssl_engine_context *cc)
{
return cc->server_name;
}
/*
* An SSL engine (client or server) has, at any time, a state which is
* the combination of zero, one or more of these flags:
*
* BR_SSL_CLOSED engine is finished, no more I/O (until next reset)
* BR_SSL_SENDREC engine has some bytes to send to the peer
* BR_SSL_RECVREC engine expects some bytes from the peer
* BR_SSL_SENDAPP engine may receive application data to send (or flush)
* BR_SSL_RECVAPP engine has obtained some application data from the peer,
* that should be read by the caller
*
* If no flag at all is set (state value is 0), then the engine is not
* fully initialized yet.
*
* The BR_SSL_CLOSED flag is exclusive; when it is set, no other flag is set.
* To distinguish between a normal closure and an error, use
* br_ssl_engine_last_error().
*
* Generally speaking, BR_SSL_SENDREC and BR_SSL_SENDAPP are mutually
* exclusive: the input buffer, at any point, either accumulates
* plaintext data, or contains an assembled record that is being sent.
* Similarly, BR_SSL_RECVREC and BR_SSL_RECVAPP are mutually exclusive.
* This may change in a future library version.
*/
#define BR_SSL_CLOSED 0x0001
#define BR_SSL_SENDREC 0x0002
#define BR_SSL_RECVREC 0x0004
#define BR_SSL_SENDAPP 0x0008
#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.
*/
static inline int
br_ssl_engine_last_error(const br_ssl_engine_context *cc)
{
return cc->err;
}
/*
* There are four I/O operations, each identified by a symbolic name:
*
* sendapp inject application data in the engine
* recvapp retrieving application data from the engine
* sendrec sending records on the transport medium
* recvrec receiving records from the transport medium
*
* Terminology works thus: in a layered model where the SSL engine sits
* between the application and the network, "send" designates operations
* where bytes flow from application to network, and "recv" for the
* reverse operation. Application data (the plaintext that is to be
* conveyed through SSL) is "app", while encrypted records are "rec".
* Note that from the SSL engine point of view, "sendapp" and "recvrec"
* designate bytes that enter the engine ("inject" operation), while
* "recvapp" and "sendrec" designate bytes that exit the engine
* ("extract" operation).
*
* For the operation 'xxx', two functions are defined:
*
* br_ssl_engine_xxx_buf
* Returns a pointer and length to the buffer to use for that
* operation. '*len' is set to the number of bytes that may be read
* from the buffer (extract operation) or written to the buffer
* (inject operation). If no byte may be exchanged for that operation
* at that point, then '*len' is set to zero, and NULL is returned.
* The engine state is unmodified by this call.
*
* br_ssl_engine_xxx_ack
* Informs the engine that 'len' bytes have been read from the buffer
* (extract operation) or written to the buffer (inject operation).
* The 'len' value MUST NOT be zero. The 'len' value MUST NOT exceed
* that which was obtained from a preceeding br_ssl_engine_xxx_buf()
* call.
*/
unsigned char *br_ssl_engine_sendapp_buf(
const br_ssl_engine_context *cc, size_t *len);
void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len);
unsigned char *br_ssl_engine_recvapp_buf(
const br_ssl_engine_context *cc, size_t *len);
void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len);
unsigned char *br_ssl_engine_sendrec_buf(
const br_ssl_engine_context *cc, size_t *len);
void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len);
unsigned char *br_ssl_engine_recvrec_buf(
const br_ssl_engine_context *cc, size_t *len);
void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len);
/*
* If some application data has been buffered in the engine, then wrap
* it into a record and mark it for sending. If no application data has
* been buffered but the engine would be ready to accept some, AND the
* 'force' parameter is non-zero, then an empty record is assembled and
* marked for sending. In all other cases, this function does nothing.
*
* Empty records are technically legal, but not all existing SSL/TLS
* implementations support them. Empty records can be useful as a
* transparent "keep-alive" mechanism to maintain some low-level
* network activity.
*/
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.
*/
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.
*/
int br_ssl_engine_renegotiate(br_ssl_engine_context *cc);
/*
* Context structure for a SSL client.
*/
typedef struct {
/*
* The encapsulated engine context.
*/
br_ssl_engine_context eng;
/*
* Minimum ClientHello length; padding with an extension (RFC
* 7685) is added if necessary to match at least that length.
* Such padding is nominally unnecessary, but it has been used
* to work around some server implementation bugs.
*/
uint16_t min_clienthello_len;
/*
* Implementations.
*/
br_rsa_public irsapub;
br_rsa_pkcs1_vrfy irsavrfy;
br_ecdsa_vrfy iecdsa;
} br_ssl_client_context;
/*
* Each br_ssl_client_init_xxx() function sets the list of supported
* cipher suites and used implementations, as specified by the profile
* name 'xxx'. Defined profile names are:
*
* full all supported versions and suites; constant-time implementations
* FIXME: add other profiles
*/
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.
*/
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).
*/
static inline void
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).
*/
static inline void
br_ssl_client_set_rsavrfy(br_ssl_client_context *cc, br_rsa_pkcs1_vrfy irsavrfy)
{
cc->irsavrfy = irsavrfy;
}
/*
* Set the ECDSA implementation (signature verification). The ECC core
* implementation must also have been set.
*/
static inline void
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).
*/
static inline void
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.
*
* 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).
*
* 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).
*/
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).
*/
static inline void
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
* 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
*/
typedef uint16_t br_suite_translated[2];
#define BR_SSLKEYX_RSA 0
#define BR_SSLKEYX_ECDHE_RSA 1
#define BR_SSLKEYX_ECDHE_ECDSA 2
#define BR_SSLKEYX_ECDH_RSA 3
#define BR_SSLKEYX_ECDH_ECDSA 4
#define BR_SSLENC_3DES_CBC 0
#define BR_SSLENC_AES128_CBC 1
#define BR_SSLENC_AES256_CBC 2
#define BR_SSLENC_AES128_GCM 3
#define BR_SSLENC_AES256_GCM 4
#define BR_SSLENC_CHACHA20 5
#define BR_SSLMAC_AEAD 0
#define BR_SSLMAC_SHA1 br_sha1_ID
#define BR_SSLMAC_SHA256 br_sha256_ID
#define BR_SSLMAC_SHA384 br_sha384_ID
#define BR_SSLPRF_SHA256 br_sha256_ID
#define BR_SSLPRF_SHA384 br_sha384_ID
/*
* 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).
*/
typedef struct {
uint16_t cipher_suite;
int hash_id;
const br_x509_certificate *chain;
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.
*
*
* 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.
*/
typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class;
struct br_ssl_server_policy_class_ {
size_t context_size;
int (*choose)(const br_ssl_server_policy_class **pctx,
const br_ssl_server_context *cc,
br_ssl_server_choices *choices);
uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx,
unsigned char *data, size_t len);
size_t (*do_sign)(const br_ssl_server_policy_class **pctx,
int hash_id, size_t hv_len, unsigned char *data, size_t len);
};
/*
* A single-chain RSA policy handler, that always uses a single chain and
* a RSA key. It may be restricted to do only signatures or only key
* exchange.
*/
typedef struct {
const br_ssl_server_policy_class *vtable;
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;
} 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.
*/
typedef struct {
const br_ssl_server_policy_class *vtable;
const br_x509_certificate *chain;
size_t chain_len;
const br_ec_private_key *sk;
unsigned allowed_usages;
unsigned cert_issuer_key_type;
const br_multihash_context *mhash;
const br_ec_impl *iec;
br_ecdsa_sign iecdsa;
} br_ssl_server_policy_ec_context;
/*
* Class type for a session parameter cache.
*
* save Record session parameters. The session ID has been randomly
* generated, and the session ID length is always 32 bytes.
* The method shall copy the provided information (the structure
* is transient).
*
* load Find session parameters by ID. The session ID is in the relevant
* field in the '*params' structure, and has always length exactly
* 32 bytes. The method shall fill in the other field with the
* session data, if found. Returned value is 1 when the session was
* found, 0 otherwise.
*
* 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.
*/
typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class;
struct br_ssl_session_cache_class_ {
size_t context_size;
void (*save)(const br_ssl_session_cache_class **ctx,
br_ssl_server_context *server_ctx,
const br_ssl_session_parameters *params);
int (*load)(const br_ssl_session_cache_class **ctx,
br_ssl_server_context *server_ctx,
br_ssl_session_parameters *params);
};
/*
* Context for a very basic cache system that uses a linked list, managed
* with an LRU algorithm (when the cache is full and a new set of parameters
* must be saved, the least recently used entry is evicted). The storage
* buffer is externally provided. Internally, an index tree is used to
* speed up operations.
*/
typedef struct {
const br_ssl_session_cache_class *vtable;
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;
} br_ssl_session_cache_lru;
/*
* Initialise a LRU session cache with the provided storage space.
*/
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.
*/
struct br_ssl_server_context_ {
/*
* The encapsulated engine context.
*/
br_ssl_engine_context eng;
/*
* Maximum version from the client.
*/
uint16_t client_max_version;
/*
* Session cache.
*/
const br_ssl_session_cache_class **cache_vtable;
/*
* Translated cipher suites supported by the client. The list
* is trimmed to include only the cipher suites that the
* server also supports; they are in the same order as in the
* client message.
*/
br_suite_translated client_suites[BR_MAX_CIPHER_SUITES];
unsigned char client_suites_num;
/*
* Hash functions supported by the client, with ECDSA and RSA
* (bit mask). For hash function with id 'x', set bit index is
* x for RSA, x+8 for ECDSA.
*/
uint16_t hashes;
/*
* Curves supported by the client (bit mask, for named curves).
*/
uint32_t curves;
/*
* Context for chain handler.
*/
const br_ssl_server_policy_class **policy_vtable;
const br_x509_certificate *chain;
size_t chain_len;
const unsigned char *cert_cur;
size_t cert_len;
unsigned char sign_hash_id;
/*
* For the core handlers, thus avoiding (in most cases) the
* need for an externally provided policy context.
*/
union {
const br_ssl_server_policy_class *vtable;
br_ssl_server_policy_rsa_context single_rsa;
br_ssl_server_policy_ec_context single_ec;
} chain_handler;
/*
* Buffer for the ECDHE private key.
*/
unsigned char ecdhe_key[70];
size_t ecdhe_key_len;
/*
* Server-specific implementations.
*/
};
/*
* 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
* name 'xxx'. Defined profile names are:
*
* full_rsa all supported algorithm, server key type is RSA
* full_ec all supported algorithm, server key type is EC
* FIXME: add other profiles
*
* Naming scheme for "minimal" profiles: min123
*
* -- character 1: key exchange
* r = RSA
* e = ECDHE_RSA
* f = ECDHE_ECDSA
* u = ECDH_RSA
* v = ECDH_ECDSA
* -- character 2: version / PRF
* 0 = TLS 1.0 / 1.1 with MD5+SHA-1
* 2 = TLS 1.2 with SHA-256
* 3 = TLS 1.2 with SHA-384
* -- character 3: encryption
* a = AES/CBC
* g = AES/GCM
* d = 3DES/CBC
*/
void br_ssl_server_init_full_rsa(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
void br_ssl_server_init_full_ec(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
unsigned cert_issuer_key_type, const br_ec_private_key *sk);
void br_ssl_server_init_minr2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
void br_ssl_server_init_mine2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
void br_ssl_server_init_minf2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk);
void br_ssl_server_init_minu2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk);
void br_ssl_server_init_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.
*/
static inline const br_suite_translated *
br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num)
{
*num = cc->client_suites_num;
return cc->client_suites;
}
/*
* 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.
*/
static inline uint16_t
br_ssl_server_get_client_hashes(const br_ssl_server_context *cc)
{
return cc->hashes;
}
/*
* Get the elliptic curves supported by the client. This is a bit field
* (bit x is set if curve of ID x is supported).
*/
static inline uint32_t
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.
*/
void br_ssl_server_zero(br_ssl_server_context *cc);
/*
* Set an externally provided policy context.
*/
static inline void
br_ssl_server_set_policy(br_ssl_server_context *cc,
const br_ssl_server_policy_class **pctx)
{
cc->policy_vtable = pctx;
}
/*
* Set the server certificate chain and key (single RSA case).
* The 'allowed_usages' is a combination of usages, namely
* BR_KEYTYPE_KEYX and/or BR_KEYTYPE_SIGN.
*/
void br_ssl_server_set_single_rsa(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_length,
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.
*/
void br_ssl_server_set_single_ec(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_length,
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.
*/
static inline void
br_ssl_server_set_cache(br_ssl_server_context *cc,
const br_ssl_session_cache_class **vtable)
{
cc->cache_vtable = vtable;
}
/*
* Prepare or reset a server context for handling an incoming client.
*/
int br_ssl_server_reset(br_ssl_server_context *cc);
/* ===================================================================== */
/*
* Context for the simplified I/O context. The transport medium is accessed
* through the low_read() and low_write() callback functions, each with
* its own opaque context pointer.
*
* low_read() read some bytes, at most 'len' bytes, into data[]. The
* returned value is the number of read bytes, or -1 on error.
* The 'len' parameter is guaranteed never to exceed 20000,
* so the length always fits in an 'int' on all platforms.
*
* low_write() write up to 'len' bytes, to be read from data[]. The
* returned value is the number of written bytes, or -1 on
* error. The 'len' parameter is guaranteed never to exceed
* 20000, so the length always fits in an 'int' on all
* parameters.
*
* A socket closure (if the transport medium is a socket) should be reported
* as an error (-1). The callbacks shall endeavour to block until at least
* one byte can be read or written; a callback returning 0 at times is
* acceptable, but this normally leads to the callback being immediately
* called again, so the callback should at least always try to block for
* some time if no I/O can take place.
*
* The SSL engine naturally applies some buffering, so the callbacks need
* not apply buffers of their own.
*/
typedef struct {
br_ssl_engine_context *engine;
int (*low_read)(void *read_context,
unsigned char *data, size_t len);
void *read_context;
int (*low_write)(void *write_context,
const unsigned char *data, size_t len);
void *write_context;
} br_sslio_context;
/*
* Initialise a simplified I/O context over the provided engine and
* I/O callbacks.
*/
void br_sslio_init(br_sslio_context *ctx,
br_ssl_engine_context *engine,
int (*low_read)(void *read_context,
unsigned char *data, size_t len),
void *read_context,
int (*low_write)(void *write_context,
const unsigned char *data, size_t len),
void *write_context);
/*
* 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).
*
* 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.
*/
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.
*/
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.
*
* Note that some written bytes may be buffered; use br_sslio_flush()
* to make sure that the data is sent to the transport stream.
*/
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.
*/
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.
*
* Returned value is 0 on success, -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.
*/
int br_sslio_close(br_sslio_context *cc);
/* ===================================================================== */
/*
* Symbolic constants for cipher suites.
*/
/* From RFC 5246 */
#define BR_TLS_NULL_WITH_NULL_NULL 0x0000
#define BR_TLS_RSA_WITH_NULL_MD5 0x0001
#define BR_TLS_RSA_WITH_NULL_SHA 0x0002
#define BR_TLS_RSA_WITH_NULL_SHA256 0x003B
#define BR_TLS_RSA_WITH_RC4_128_MD5 0x0004
#define BR_TLS_RSA_WITH_RC4_128_SHA 0x0005
#define BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A
#define BR_TLS_RSA_WITH_AES_128_CBC_SHA 0x002F
#define BR_TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
#define BR_TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C
#define BR_TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D
#define BR_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D
#define BR_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010
#define BR_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013
#define BR_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016
#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030
#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031
#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032
#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033
#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036
#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037
#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038
#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039
#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E
#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F
#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040
#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067
#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068
#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069
#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A
#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B
#define BR_TLS_DH_anon_WITH_RC4_128_MD5 0x0018
#define BR_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B
#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034
#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A
#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C
#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D
/* From RFC 4492 */
#define BR_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001
#define BR_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002
#define BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003
#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004
#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005
#define BR_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006
#define BR_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007
#define BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A
#define BR_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B
#define BR_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C
#define BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D
#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E
#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F
#define BR_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010
#define BR_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011
#define BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012
#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013
#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014
#define BR_TLS_ECDH_anon_WITH_NULL_SHA 0xC015
#define BR_TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016
#define BR_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017
#define BR_TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018
#define BR_TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019
/* From RFC 5288 */
#define BR_TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C
#define BR_TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D
#define BR_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E
#define BR_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F
#define BR_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0
#define BR_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1
#define BR_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2
#define BR_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3
#define BR_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4
#define BR_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5
#define BR_TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6
#define BR_TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7
/* From RFC 5289 */
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024
#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025
#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026
#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027
#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028
#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029
#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C
#define BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D
#define BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E
#define BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F
#define BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030
#define BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031
#define BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032
/* From RFC 7905 */
#define BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8
#define BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9
#define BR_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA
#define BR_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB
#define BR_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC
#define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD
#define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE
/*
* Symbolic constants for alerts.
*/
#define BR_ALERT_CLOSE_NOTIFY 0
#define BR_ALERT_UNEXPECTED_MESSAGE 10
#define BR_ALERT_BAD_RECORD_MAC 20
#define BR_ALERT_RECORD_OVERFLOW 22
#define BR_ALERT_DECOMPRESSION_FAILURE 30
#define BR_ALERT_HANDSHAKE_FAILURE 40
#define BR_ALERT_BAD_CERTIFICATE 42
#define BR_ALERT_UNSUPPORTED_CERTIFICATE 43
#define BR_ALERT_CERTIFICATE_REVOKED 44
#define BR_ALERT_CERTIFICATE_EXPIRED 45
#define BR_ALERT_CERTIFICATE_UNKNOWN 46
#define BR_ALERT_ILLEGAL_PARAMETER 47
#define BR_ALERT_UNKNOWN_CA 48
#define BR_ALERT_ACCESS_DENIED 49
#define BR_ALERT_DECODE_ERROR 50
#define BR_ALERT_DECRYPT_ERROR 51
#define BR_ALERT_PROTOCOL_VERSION 70
#define BR_ALERT_INSUFFICIENT_SECURITY 71
#define BR_ALERT_INTERNAL_ERROR 80
#define BR_ALERT_USER_CANCELED 90
#define BR_ALERT_NO_RENEGOTIATION 100
#define BR_ALERT_UNSUPPORTED_EXTENSION 110
#endif