#include <haproxy/quic_ack-t.h>
#include <haproxy/openssl-compat.h>
+/* Use EVP_CIPHER or EVP_AEAD API depending on the library */
+#if defined(USE_OPENSSL_AWSLC)
+
+# define QUIC_AEAD_API
+
+# define QUIC_AEAD EVP_AEAD
+# define QUIC_AEAD_CTX EVP_AEAD_CTX
+
+# define QUIC_AEAD_CTX_free EVP_AEAD_CTX_free
+# define QUIC_AEAD_key_length EVP_AEAD_key_length
+# define QUIC_AEAD_iv_length EVP_AEAD_nonce_length
+
+#else
+
+# define QUIC_AEAD EVP_CIPHER
+# define QUIC_AEAD_CTX EVP_CIPHER_CTX
+
+# define QUIC_AEAD_CTX_free EVP_CIPHER_CTX_free
+# define QUIC_AEAD_key_length EVP_CIPHER_key_length
+# define QUIC_AEAD_iv_length EVP_CIPHER_iv_length
+
+#endif
+
+
/* It seems TLS 1.3 ciphersuites macros differ between openssl and boringssl */
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
/* Key phase used for Key Update */
struct quic_tls_kp {
- EVP_CIPHER_CTX *ctx;
+ QUIC_AEAD_CTX *ctx;
unsigned char *secret;
size_t secretlen;
unsigned char *iv;
#define QUIC_FL_TLS_KP_BIT_SET (1 << 0)
struct quic_tls_secrets {
- EVP_CIPHER_CTX *ctx;
- const EVP_CIPHER *aead;
+ QUIC_AEAD_CTX *ctx;
+ const QUIC_AEAD *aead;
const EVP_MD *md;
EVP_CIPHER_CTX *hp_ctx;
const EVP_CIPHER *hp;
int quic_tls_encrypt(unsigned char *buf, size_t len,
const unsigned char *aad, size_t aad_len,
- EVP_CIPHER_CTX *ctx, const EVP_CIPHER *aead,
+ QUIC_AEAD_CTX *ctx, const QUIC_AEAD *aead,
const unsigned char *iv);
int quic_tls_decrypt2(unsigned char *out,
unsigned char *in, size_t ilen,
unsigned char *aad, size_t aad_len,
- EVP_CIPHER_CTX *ctx, const EVP_CIPHER *aead,
+ QUIC_AEAD_CTX *ctx, const QUIC_AEAD *aead,
const unsigned char *key, const unsigned char *iv);
int quic_tls_decrypt(unsigned char *buf, size_t len,
unsigned char *aad, size_t aad_len,
- EVP_CIPHER_CTX *tls_ctx, const EVP_CIPHER *aead,
+ QUIC_AEAD_CTX *tls_ctx, const QUIC_AEAD *aead,
const unsigned char *key, const unsigned char *iv);
int quic_tls_generate_retry_integrity_tag(unsigned char *odcid, unsigned char odcid_len,
unsigned char *buf, size_t len,
const struct quic_version *qv);
-int quic_tls_derive_keys(const EVP_CIPHER *aead, const EVP_CIPHER *hp,
+int quic_tls_derive_keys(const QUIC_AEAD *aead, const EVP_CIPHER *hp,
const EVP_MD *md, const struct quic_version *qv,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
const unsigned char *salt, size_t saltlen,
const unsigned char *label, size_t labellen);
-int quic_tls_rx_ctx_init(EVP_CIPHER_CTX **rx_ctx,
- const EVP_CIPHER *aead, unsigned char *key);
-int quic_tls_tx_ctx_init(EVP_CIPHER_CTX **tx_ctx,
- const EVP_CIPHER *aead, unsigned char *key);
+int quic_tls_rx_ctx_init(QUIC_AEAD_CTX **rx_ctx,
+ const QUIC_AEAD *aead, unsigned char *key);
+int quic_tls_tx_ctx_init(QUIC_AEAD_CTX **tx_ctx,
+ const QUIC_AEAD *aead, unsigned char *key);
int quic_tls_sec_update(const EVP_MD *md, const struct quic_version *qv,
unsigned char *new_sec, size_t new_seclen,
int quic_tls_key_update(struct quic_conn *qc);
void quic_tls_rotate_keys(struct quic_conn *qc);
-static inline const EVP_CIPHER *tls_aead(const SSL_CIPHER *cipher)
+static inline const QUIC_AEAD *tls_aead(const SSL_CIPHER *cipher)
{
switch (SSL_CIPHER_get_id(cipher)) {
case TLS1_3_CK_AES_128_GCM_SHA256:
+#ifdef QUIC_AEAD_API
+ return EVP_aead_aes_128_gcm();
+#else
return EVP_aes_128_gcm();
+#endif
+
case TLS1_3_CK_AES_256_GCM_SHA384:
+#ifdef QUIC_AEAD_API
+ return EVP_aead_aes_256_gcm();
+#else
return EVP_aes_256_gcm();
+#endif
+
#if !defined(OPENSSL_IS_AWSLC) && (!defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x4000000fL)
/* WT: LibreSSL has an issue with CHACHA20 running in-place till 3.9.2
* included, but the fix is already identified and will be merged
/* RX HP protection */
EVP_CIPHER_CTX_free(ctx->rx.hp_ctx);
/* RX AEAD decryption */
- EVP_CIPHER_CTX_free(ctx->rx.ctx);
+ QUIC_AEAD_CTX_free(ctx->rx.ctx);
pool_free(pool_head_quic_tls_iv, ctx->rx.iv);
pool_free(pool_head_quic_tls_key, ctx->rx.key);
/* TX HP protection */
EVP_CIPHER_CTX_free(ctx->tx.hp_ctx);
/* TX AEAD encryption */
- EVP_CIPHER_CTX_free(ctx->tx.ctx);
+ QUIC_AEAD_CTX_free(ctx->tx.ctx);
pool_free(pool_head_quic_tls_iv, ctx->tx.iv);
pool_free(pool_head_quic_tls_key, ctx->tx.key);
/* HP protection */
EVP_CIPHER_CTX_free(secs->hp_ctx);
/* AEAD decryption */
- EVP_CIPHER_CTX_free(secs->ctx);
+ QUIC_AEAD_CTX_free(secs->ctx);
pool_free(pool_head_quic_tls_iv, secs->iv);
pool_free(pool_head_quic_tls_key, secs->key);
/* Initialize a TLS cryptographic context for the Initial encryption level. */
static inline int quic_initial_tls_ctx_init(struct quic_tls_ctx *ctx)
{
+#ifdef QUIC_AEAD_API
+ ctx->rx.aead = ctx->tx.aead = EVP_aead_aes_128_gcm();
+#else
ctx->rx.aead = ctx->tx.aead = EVP_aes_128_gcm();
+#endif
ctx->rx.md = ctx->tx.md = EVP_sha256();
ctx->rx.hp = ctx->tx.hp = EVP_aes_128_ctr();
*/
static inline void quic_tls_ku_free(struct quic_conn *qc)
{
- EVP_CIPHER_CTX_free(qc->ku.prv_rx.ctx);
+ QUIC_AEAD_CTX_free(qc->ku.prv_rx.ctx);
pool_free(pool_head_quic_tls_secret, qc->ku.prv_rx.secret);
pool_free(pool_head_quic_tls_iv, qc->ku.prv_rx.iv);
pool_free(pool_head_quic_tls_key, qc->ku.prv_rx.key);
quic_tls_ku_reset(&qc->ku.prv_rx);
- EVP_CIPHER_CTX_free(qc->ku.nxt_rx.ctx);
+ QUIC_AEAD_CTX_free(qc->ku.nxt_rx.ctx);
pool_free(pool_head_quic_tls_secret, qc->ku.nxt_rx.secret);
pool_free(pool_head_quic_tls_iv, qc->ku.nxt_rx.iv);
pool_free(pool_head_quic_tls_key, qc->ku.nxt_rx.key);
quic_tls_ku_reset(&qc->ku.nxt_rx);
- EVP_CIPHER_CTX_free(qc->ku.nxt_tx.ctx);
+ QUIC_AEAD_CTX_free(qc->ku.nxt_tx.ctx);
pool_free(pool_head_quic_tls_secret, qc->ku.nxt_tx.secret);
pool_free(pool_head_quic_tls_iv, qc->ku.nxt_tx.iv);
pool_free(pool_head_quic_tls_key, qc->ku.nxt_tx.key);
unsigned char iv[QUIC_TLS_IV_LEN];
const unsigned char *sec = global.cluster_secret;
size_t seclen = sizeof global.cluster_secret;
- EVP_CIPHER_CTX *ctx = NULL;
- const EVP_CIPHER *aead = EVP_aes_128_gcm();
+ QUIC_AEAD_CTX *ctx = NULL;
+#ifdef QUIC_AEAD_API
+ const QUIC_AEAD *aead = EVP_aead_aes_128_gcm();
+#else
+ const QUIC_AEAD *aead = EVP_aes_128_gcm();
+#endif
uint32_t timestamp = (uint32_t)date.tv_sec;
TRACE_ENTER(QUIC_EV_CONN_TXPKT);
p += QUIC_TLS_TAG_LEN;
memcpy(p, salt, sizeof salt);
p += sizeof salt;
- EVP_CIPHER_CTX_free(ctx);
+ QUIC_AEAD_CTX_free(ctx);
ret = p - token;
leave:
err:
if (ctx)
- EVP_CIPHER_CTX_free(ctx);
+ QUIC_AEAD_CTX_free(ctx);
goto leave;
}
unsigned char iv[QUIC_TLS_IV_LEN];
const unsigned char *sec = global.cluster_secret;
size_t seclen = sizeof global.cluster_secret;
- EVP_CIPHER_CTX *ctx = NULL;
- const EVP_CIPHER *aead = EVP_aes_128_gcm();
+ QUIC_AEAD_CTX *ctx = NULL;
const struct quic_version *qv = qc ? qc->original_version :
pkt->version;
+#ifdef QUIC_AEAD_API
+ const QUIC_AEAD *aead = EVP_aead_aes_128_gcm();
+#else
+ const QUIC_AEAD *aead = EVP_aes_128_gcm();
+#endif
TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
goto err;
}
- EVP_CIPHER_CTX_free(ctx);
+ QUIC_AEAD_CTX_free(ctx);
ret = 1;
HA_ATOMIC_INC(&prx_counters->retry_validated);
err:
HA_ATOMIC_INC(&prx_counters->retry_error);
if (ctx)
- EVP_CIPHER_CTX_free(ctx);
+ QUIC_AEAD_CTX_free(ctx);
goto leave;
}
unsigned char iv[QUIC_TLS_IV_LEN];
struct quic_tls_ctx *tls_ctx =
qc_select_tls_ctx(qc, qel, pkt->type, pkt->version);
- EVP_CIPHER_CTX *rx_ctx = tls_ctx->rx.ctx;
+ QUIC_AEAD_CTX *rx_ctx = tls_ctx->rx.ctx;
unsigned char *rx_iv = tls_ctx->rx.iv;
size_t rx_iv_sz = tls_ctx->rx.ivlen;
unsigned char *rx_key = tls_ctx->rx.key;
if (!secs->aead || !secs->hp)
return;
-
- aead_keylen = (size_t)EVP_CIPHER_key_length(secs->aead);
- aead_ivlen = (size_t)EVP_CIPHER_iv_length(secs->aead);
+ aead_keylen = (size_t)QUIC_AEAD_key_length(secs->aead);
+ aead_ivlen = (size_t)QUIC_AEAD_iv_length(secs->aead);
hp_len = (size_t)EVP_CIPHER_key_length(secs->hp);
chunk_appendf(buf, "\n key=");
* ->hp_key is the key to be derived for header protection.
* Obviouly these keys have the same size becaused derived with the same TLS cryptographic context.
*/
-int quic_tls_derive_keys(const EVP_CIPHER *aead, const EVP_CIPHER *hp,
+int quic_tls_derive_keys(const QUIC_AEAD *aead, const EVP_CIPHER *hp,
const EVP_MD *md, const struct quic_version *qv,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen,
unsigned char *hp_key, size_t hp_keylen,
const unsigned char *secret, size_t secretlen)
{
- size_t aead_keylen = (size_t)EVP_CIPHER_key_length(aead);
- size_t aead_ivlen = (size_t)EVP_CIPHER_iv_length(aead);
+ size_t aead_keylen = (size_t)QUIC_AEAD_key_length(aead);
+ size_t aead_ivlen = (size_t)QUIC_AEAD_iv_length(aead);
size_t hp_len = hp ? (size_t)EVP_CIPHER_key_length(hp) : 0;
if (aead_keylen > keylen || aead_ivlen > ivlen || hp_len > hp_keylen)
/* Initialize the cipher context for RX part of <tls_ctx> QUIC TLS context.
* Return 1 if succeeded, 0 if not.
*/
-int quic_tls_rx_ctx_init(EVP_CIPHER_CTX **rx_ctx,
- const EVP_CIPHER *aead, unsigned char *key)
+int quic_tls_rx_ctx_init(QUIC_AEAD_CTX **rx_ctx,
+ const QUIC_AEAD *aead, unsigned char *key)
{
- EVP_CIPHER_CTX *ctx;
- int aead_nid = EVP_CIPHER_nid(aead);
- ctx = EVP_CIPHER_CTX_new();
+#ifdef QUIC_AEAD_API
+ QUIC_AEAD_CTX *ctx = EVP_AEAD_CTX_new(aead, key, EVP_AEAD_key_length(aead), EVP_AEAD_DEFAULT_TAG_LENGTH);
+ if (!ctx)
+ return 0;
+
+#else
+ int aead_nid = EVP_CIPHER_nid(aead);
+ QUIC_AEAD_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx)
return 0;
!EVP_DecryptInit_ex(ctx, NULL, NULL, key, NULL))
goto err;
+#endif
*rx_ctx = ctx;
-
return 1;
err:
- EVP_CIPHER_CTX_free(ctx);
+ QUIC_AEAD_CTX_free(ctx);
return 0;
}
/* Initialize the cipher context for TX part of <tls_ctx> QUIC TLS context.
* Return 1 if succeeded, 0 if not.
*/
-int quic_tls_tx_ctx_init(EVP_CIPHER_CTX **tx_ctx,
- const EVP_CIPHER *aead, unsigned char *key)
+int quic_tls_tx_ctx_init(QUIC_AEAD_CTX **tx_ctx,
+ const QUIC_AEAD *aead, unsigned char *key)
{
- EVP_CIPHER_CTX *ctx;
+#ifdef QUIC_AEAD_API
+ QUIC_AEAD_CTX *ctx = EVP_AEAD_CTX_new(aead, key, EVP_AEAD_key_length(aead), EVP_AEAD_DEFAULT_TAG_LENGTH);
+ if (!ctx)
+ return 0;
+
+#else
int aead_nid = EVP_CIPHER_nid(aead);
+ QUIC_AEAD_CTX *ctx = EVP_CIPHER_CTX_new();
- ctx = EVP_CIPHER_CTX_new();
if (!ctx)
return 0;
!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, QUIC_TLS_TAG_LEN, NULL)) ||
!EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL))
goto err;
+#endif
*tx_ctx = ctx;
-
return 1;
err:
- EVP_CIPHER_CTX_free(ctx);
+ QUIC_AEAD_CTX_free(ctx);
return 0;
}
*/
int quic_tls_encrypt(unsigned char *buf, size_t len,
const unsigned char *aad, size_t aad_len,
- EVP_CIPHER_CTX *ctx, const EVP_CIPHER *aead,
+ QUIC_AEAD_CTX *ctx, const QUIC_AEAD *aead,
const unsigned char *iv)
{
+#ifdef QUIC_AEAD_API
+ size_t outlen;
+
+ if (!EVP_AEAD_CTX_seal(ctx, buf, &outlen, len + EVP_AEAD_max_overhead(aead),
+ iv, QUIC_TLS_IV_LEN,
+ buf, len,
+ aad, aad_len))
+ return 0;
+#else
int outlen;
int aead_nid = EVP_CIPHER_nid(aead);
!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, QUIC_TLS_TAG_LEN, buf + len))
return 0;
+
+#endif
+
return 1;
}
*/
int quic_tls_decrypt(unsigned char *buf, size_t len,
unsigned char *aad, size_t aad_len,
- EVP_CIPHER_CTX *ctx, const EVP_CIPHER *aead,
+ QUIC_AEAD_CTX *ctx, const QUIC_AEAD *aead,
const unsigned char *key, const unsigned char *iv)
{
+#ifdef QUIC_AEAD_API
+ size_t outlen;
+
+ if (!EVP_AEAD_CTX_open(ctx, buf, &outlen, len,
+ iv, QUIC_TLS_IV_LEN,
+ buf, len,
+ aad, aad_len))
+ return 0;
+
+#else
+
int outlen;
int aead_nid = EVP_CIPHER_nid(aead);
!EVP_DecryptFinal_ex(ctx, buf + outlen, &outlen)))
return 0;
+#endif
+
return 1;
}
int quic_tls_decrypt2(unsigned char *out,
unsigned char *in, size_t len,
unsigned char *aad, size_t aad_len,
- EVP_CIPHER_CTX *ctx, const EVP_CIPHER *aead,
+ QUIC_AEAD_CTX *ctx, const QUIC_AEAD *aead,
const unsigned char *key, const unsigned char *iv)
{
+#ifdef QUIC_AEAD_API
+ size_t outlen;
+
+ if (!EVP_AEAD_CTX_open(ctx, out, &outlen, len,
+ iv, QUIC_TLS_IV_LEN,
+ in, len,
+ aad, aad_len))
+ return 0;
+
+#else
+
int outlen;
int aead_nid = EVP_CIPHER_nid(aead);
(aead_nid != NID_aes_128_ccm &&
!EVP_DecryptFinal_ex(ctx, out + outlen, &outlen)))
return 0;
+#endif
return 1;
}
kp_trace.tx = nxt_tx;
if (nxt_rx->ctx) {
- EVP_CIPHER_CTX_free(nxt_rx->ctx);
+ QUIC_AEAD_CTX_free(nxt_rx->ctx);
nxt_rx->ctx = NULL;
}
}
if (nxt_tx->ctx) {
- EVP_CIPHER_CTX_free(nxt_tx->ctx);
+ QUIC_AEAD_CTX_free(nxt_tx->ctx);
nxt_tx->ctx = NULL;
}
{
struct quic_tls_ctx *tls_ctx = &qc->ael->tls_ctx;
unsigned char *curr_secret, *curr_iv, *curr_key;
- EVP_CIPHER_CTX *curr_ctx;
+ QUIC_AEAD_CTX *curr_ctx;
TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);