mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 13:51:26 +02:00
MEDIUM: ssl: Add support for ktls on TLS 1.3 with AWS-LC
AWS-LC added a new API in AWS-LC 1.54 that allows the user to retrieve the keys for TLS 1.3 connections with SSL_get_read_traffic_secret(), so use it to be able to use ktls with TLS 1.3 too.
This commit is contained in:
parent
5c8fa50966
commit
fefc1cce20
134
src/ssl_sock.c
134
src/ssl_sock.c
@ -6032,6 +6032,44 @@ static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremo
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HA_USE_KTLS
|
#ifdef HA_USE_KTLS
|
||||||
|
#if defined(OPENSSL_IS_AWSLC) && AWSLC_API_VERSION >= 34 & !defined(HA_DISABLE_AWSLC_TLS13)
|
||||||
|
static int ssl_sock_hkdf_expand_label(struct ssl_sock_ctx *ctx, uint8_t *secret, size_t secret_len, uint8_t *label, size_t label_len, uint8_t *out, size_t out_len)
|
||||||
|
{
|
||||||
|
SSL *ssl = ctx->ssl;
|
||||||
|
/* 2 for length, 1 for the string length, label_len + 6 ("tls13 ") + 1 for the empty context string. */
|
||||||
|
int buf_len = 2 + 1 + label_len + 6 + 1;
|
||||||
|
/*
|
||||||
|
* As we only labels we use are "salt" or "key", consider label_len
|
||||||
|
* can only be 4 max.
|
||||||
|
*/
|
||||||
|
unsigned char buf[2 + 1 + 4 + 6 + 1];
|
||||||
|
const EVP_MD *digest;
|
||||||
|
uint16_t len = htons(out_len);
|
||||||
|
|
||||||
|
digest = SSL_CIPHER_get_handshake_digest(SSL_get_current_cipher(ssl));
|
||||||
|
|
||||||
|
BUG_ON(label_len > 4);
|
||||||
|
if (digest == NULL)
|
||||||
|
return -1;
|
||||||
|
/*
|
||||||
|
* The label looks like :
|
||||||
|
* 2 bytes for the length (in big engian)
|
||||||
|
* 1 byte for the label length, and then the string
|
||||||
|
* 1 byte for the context length, and then the context (we have no
|
||||||
|
* context so it will always be 0
|
||||||
|
*/
|
||||||
|
memcpy(buf, &len, sizeof(len));
|
||||||
|
len = label_len + 6;
|
||||||
|
memcpy(&buf[2], &len, 1);
|
||||||
|
memcpy(&buf[3], "tls13 ", 6);
|
||||||
|
memcpy(&buf[9], label, label_len);
|
||||||
|
len = 0;
|
||||||
|
memcpy(&buf[9 + label_len], &len, 1);
|
||||||
|
|
||||||
|
return (HKDF_expand(out, out_len, digest, secret, secret_len, buf, buf_len) == 1 ? 0 : - 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(OPENSSL_IS_AWSLC) || defined(OPENSSL_IS_BORINGSSL)
|
#if defined(OPENSSL_IS_AWSLC) || defined(OPENSSL_IS_BORINGSSL)
|
||||||
static void ssl_sock_setup_ktls(struct ssl_sock_ctx *ctx)
|
static void ssl_sock_setup_ktls(struct ssl_sock_ctx *ctx)
|
||||||
{
|
{
|
||||||
@ -6093,6 +6131,20 @@ static void ssl_sock_setup_ktls(struct ssl_sock_ctx *ctx)
|
|||||||
case TLS_1_2_VERSION:
|
case TLS_1_2_VERSION:
|
||||||
is_tls_12 = 1;
|
is_tls_12 = 1;
|
||||||
break;
|
break;
|
||||||
|
#if defined(OPENSSL_IS_AWSLC) && AWSLC_API_VERSION >= 34 & !defined(HA_DISABLE_AWSLC_TLS13)
|
||||||
|
/*
|
||||||
|
* For now only AWS-LC >= 1.54 supports the API to export
|
||||||
|
* TLS 1.3 secrets.
|
||||||
|
* Unfortunately, AWSLC_API_VERSION hasn't been bumped when
|
||||||
|
* those were added, so use the latest one. It will match
|
||||||
|
* AWS-LC 1.52 and 1.53 too, but there's not much we
|
||||||
|
* can do about it, one can define HA_DISABLE_AWSLC_TLS13
|
||||||
|
* to build with AWS-LC 1.52 or 1.53.
|
||||||
|
*/
|
||||||
|
case TLS_1_3_VERSION:
|
||||||
|
is_tls_12 = 0;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
return;
|
return;
|
||||||
@ -6213,6 +6265,88 @@ static void ssl_sock_setup_ktls(struct ssl_sock_ctx *ctx)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ctx->flags |= SSL_SOCK_F_KTLS_SEND | SSL_SOCK_F_KTLS_RECV;
|
ctx->flags |= SSL_SOCK_F_KTLS_SEND | SSL_SOCK_F_KTLS_RECV;
|
||||||
|
} else {
|
||||||
|
#if defined(OPENSSL_IS_AWSLC) && AWSLC_API_VERSION >= 34 & !defined(HA_DISABLE_AWSLC_TLS13)
|
||||||
|
unsigned char iv[12];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 12 is the maximum size for iv + salt currently supported
|
||||||
|
* in Linux, if a new cipher is added that expands that,
|
||||||
|
* then the buffer should be expanded.
|
||||||
|
*/
|
||||||
|
BUG_ON(iv_size + salt_size > sizeof(iv));
|
||||||
|
if (SSL_get_read_traffic_secret(ctx->ssl, NULL, &len) != 1) {
|
||||||
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* We may have to increase buf size if a new cipher is
|
||||||
|
* added and its secret size is too big.
|
||||||
|
*/
|
||||||
|
BUG_ON(len > sizeof(buf));
|
||||||
|
|
||||||
|
if (SSL_get_read_traffic_secret(ctx->ssl, buf, &len) != 1) {
|
||||||
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssl_sock_hkdf_expand_label(ctx, buf, len, (unsigned char *)"key", 3, &info.buf[iv_size], key_size) != 0) {
|
||||||
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (ssl_sock_hkdf_expand_label(ctx, buf, len, (unsigned char *)"iv", 2, iv, iv_size + salt_size) != 0) {
|
||||||
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* iv contains both what should go to "iv" and "salt",
|
||||||
|
* salt first, then iv.
|
||||||
|
*/
|
||||||
|
memcpy(&info.buf[0], iv + salt_size, iv_size);
|
||||||
|
memcpy(&info.buf[iv_size + key_size], iv, salt_size);
|
||||||
|
seq = SSL_get_read_sequence(ssl);
|
||||||
|
seq = my_htonll(seq);
|
||||||
|
memcpy(&info.buf[iv_size + key_size + salt_size], &seq, seq_size);
|
||||||
|
if (ktls_set_key(ctx, &info, info_size, 0) != 0) {
|
||||||
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (SSL_get_write_traffic_secret(ctx->ssl, NULL, &len) != 1) {
|
||||||
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
BUG_ON(len > sizeof(buf));
|
||||||
|
|
||||||
|
if (SSL_get_write_traffic_secret(ctx->ssl, buf, &len) != 1) {
|
||||||
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssl_sock_hkdf_expand_label(ctx, buf, len, (unsigned char *)"key", 3, &info.buf[iv_size], key_size) != 0) {
|
||||||
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (ssl_sock_hkdf_expand_label(ctx, buf, len, (unsigned char *)"iv", 2, iv, iv_size + salt_size) != 0) {
|
||||||
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* iv contains both what should go to "iv" and "salt",
|
||||||
|
* salt first, then iv.
|
||||||
|
*/
|
||||||
|
memcpy(&info.buf[0], iv + salt_size, iv_size);
|
||||||
|
memcpy(&info.buf[iv_size + key_size], iv, salt_size);
|
||||||
|
seq = SSL_get_write_sequence(ssl);
|
||||||
|
seq = my_htonll(seq);
|
||||||
|
memcpy(&info.buf[iv_size + key_size + salt_size], &seq, seq_size);
|
||||||
|
if (ktls_set_key(ctx, &info, info_size, 1) != 0) {
|
||||||
|
ctx->flags &= ~SSL_SOCK_F_KTLS_ENABLED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ctx->flags |= SSL_SOCK_F_KTLS_RECV | SSL_SOCK_F_KTLS_SEND;
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user