From f7e8f89fb91b338377370418c53b6831a0023151 Mon Sep 17 00:00:00 2001 From: jsing Date: Sun, 24 Jul 2022 14:28:16 +0000 Subject: [PATCH] Provide record layer callbacks for QUIC. QUIC uses TLS to complete the handshake, however unlike normal TLS it does not use the TLS record layer, rather it provides its own transport. This means that we need to intercept all communication between the TLS handshake and the record layer. This allows TLS handshake message writes to be directed to QUIC, likewise for TLS handshake message reads. Alerts also need to be sent via QUIC, plus it needs to be provided with the traffic keys that are derived by TLS. ok tb@ --- lib/libssl/Makefile | 3 +- lib/libssl/ssl_locl.h | 6 +- lib/libssl/tls13_internal.h | 21 ++++- lib/libssl/tls13_lib.c | 23 +++--- lib/libssl/tls13_quic.c | 135 ++++++++++++++++++++++++++++++++ lib/libssl/tls13_record_layer.c | 31 +++++++- lib/libssl/tls_internal.h | 14 +++- 7 files changed, 217 insertions(+), 16 deletions(-) create mode 100644 lib/libssl/tls13_quic.c diff --git a/lib/libssl/Makefile b/lib/libssl/Makefile index e6930b0b9f6..d0d7bc4e02b 100644 --- a/lib/libssl/Makefile +++ b/lib/libssl/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.75 2022/06/28 20:40:24 tb Exp $ +# $OpenBSD: Makefile,v 1.76 2022/07/24 14:28:16 jsing Exp $ .include .ifndef NOMAN @@ -79,6 +79,7 @@ SRCS= \ tls13_key_schedule.c \ tls13_legacy.c \ tls13_lib.c \ + tls13_quic.c \ tls13_record.c \ tls13_record_layer.c \ tls13_server.c \ diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h index 7623daccf1e..18daf791f05 100644 --- a/lib/libssl/ssl_locl.h +++ b/lib/libssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.416 2022/07/22 19:54:46 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.417 2022/07/24 14:28:16 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -581,6 +581,10 @@ typedef struct ssl_handshake_tls13_st { EVP_MD_CTX *clienthello_md_ctx; unsigned char *clienthello_hash; unsigned int clienthello_hash_len; + + /* QUIC read/write encryption levels. */ + enum ssl_encryption_level_t quic_read_level; + enum ssl_encryption_level_t quic_write_level; } SSL_HANDSHAKE_TLS13; typedef struct ssl_handshake_st { diff --git a/lib/libssl/tls13_internal.h b/lib/libssl/tls13_internal.h index 6382f8b0483..f4b17bdf253 100644 --- a/lib/libssl/tls13_internal.h +++ b/lib/libssl/tls13_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_internal.h,v 1.100 2022/07/24 14:16:29 jsing Exp $ */ +/* $OpenBSD: tls13_internal.h,v 1.101 2022/07/24 14:28:16 jsing Exp $ */ /* * Copyright (c) 2018 Bob Beck * Copyright (c) 2018 Theo Buehler @@ -175,9 +175,19 @@ int tls13_update_server_traffic_secret(struct tls13_secrets *secrets); struct tls13_record_layer; struct tls13_record_layer_callbacks { + /* Wire callbacks. */ tls_read_cb wire_read; tls_write_cb wire_write; tls_flush_cb wire_flush; + + /* Interceptors. */ + tls_handshake_read_cb handshake_read; + tls_handshake_write_cb handshake_write; + tls_traffic_key_cb set_read_traffic_key; + tls_traffic_key_cb set_write_traffic_key; + tls_alert_send_cb alert_send; + + /* Notification callbacks. */ tls13_alert_cb alert_recv; tls13_alert_cb alert_sent; tls13_phh_recv_cb phh_recv; @@ -187,6 +197,8 @@ struct tls13_record_layer_callbacks { struct tls13_record_layer *tls13_record_layer_new( const struct tls13_record_layer_callbacks *callbacks, void *cb_arg); void tls13_record_layer_free(struct tls13_record_layer *rl); +void tls13_record_layer_set_callbacks(struct tls13_record_layer *rl, + const struct tls13_record_layer_callbacks *callbacks, void *cb_arg); void tls13_record_layer_allow_ccs(struct tls13_record_layer *rl, int allow); void tls13_record_layer_allow_legacy_alerts(struct tls13_record_layer *rl, int allow); void tls13_record_layer_rcontent(struct tls13_record_layer *rl, CBS *cbs); @@ -297,6 +309,13 @@ void tls13_ctx_free(struct tls13_ctx *ctx); const EVP_AEAD *tls13_cipher_aead(const SSL_CIPHER *cipher); const EVP_MD *tls13_cipher_hash(const SSL_CIPHER *cipher); +void tls13_alert_received_cb(uint8_t alert_desc, void *arg); +void tls13_alert_sent_cb(uint8_t alert_desc, void *arg); +ssize_t tls13_phh_received_cb(void *cb_arg); +void tls13_phh_done_cb(void *cb_arg); + +int tls13_quic_init(struct tls13_ctx *ctx); + /* * Legacy interfaces. */ diff --git a/lib/libssl/tls13_lib.c b/lib/libssl/tls13_lib.c index d63951a0ff3..57c58a3d305 100644 --- a/lib/libssl/tls13_lib.c +++ b/lib/libssl/tls13_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_lib.c,v 1.69 2022/07/24 14:19:45 jsing Exp $ */ +/* $OpenBSD: tls13_lib.c,v 1.70 2022/07/24 14:28:16 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * Copyright (c) 2019 Bob Beck @@ -103,7 +103,7 @@ tls13_cipher_hash(const SSL_CIPHER *cipher) return NULL; } -static void +void tls13_alert_received_cb(uint8_t alert_desc, void *arg) { struct tls13_ctx *ctx = arg; @@ -132,7 +132,7 @@ tls13_alert_received_cb(uint8_t alert_desc, void *arg) SSL_CTX_remove_session(ctx->ssl->ctx, ctx->ssl->session); } -static void +void tls13_alert_sent_cb(uint8_t alert_desc, void *arg) { struct tls13_ctx *ctx = arg; @@ -328,7 +328,7 @@ tls13_key_update_recv(struct tls13_ctx *ctx, CBS *cbs) return tls13_send_alert(ctx->rl, alert); } -static ssize_t +ssize_t tls13_phh_received_cb(void *cb_arg) { ssize_t ret = TLS13_IO_FAILURE; @@ -369,7 +369,7 @@ tls13_phh_received_cb(void *cb_arg) return ret; } -static void +void tls13_phh_done_cb(void *cb_arg) { struct tls13_ctx *ctx = cb_arg; @@ -380,10 +380,11 @@ tls13_phh_done_cb(void *cb_arg) } } -static const struct tls13_record_layer_callbacks rl_callbacks = { +static const struct tls13_record_layer_callbacks tls13_rl_callbacks = { .wire_read = tls13_legacy_wire_read_cb, .wire_write = tls13_legacy_wire_write_cb, .wire_flush = tls13_legacy_wire_flush_cb, + .alert_recv = tls13_alert_received_cb, .alert_sent = tls13_alert_sent_cb, .phh_recv = tls13_phh_received_cb, @@ -402,7 +403,7 @@ tls13_ctx_new(int mode, SSL *ssl) ctx->mode = mode; ctx->ssl = ssl; - if ((ctx->rl = tls13_record_layer_new(&rl_callbacks, ctx)) == NULL) + if ((ctx->rl = tls13_record_layer_new(&tls13_rl_callbacks, ctx)) == NULL) goto err; ctx->handshake_message_sent_cb = tls13_legacy_handshake_message_sent_cb; @@ -410,11 +411,15 @@ tls13_ctx_new(int mode, SSL *ssl) ctx->info_cb = tls13_legacy_info_cb; ctx->ocsp_status_recv_cb = tls13_legacy_ocsp_status_recv_cb; - if (!SSL_is_quic(ssl)) - ctx->middlebox_compat = 1; + ctx->middlebox_compat = 1; ssl->internal->tls13 = ctx; + if (SSL_is_quic(ssl)) { + if (!tls13_quic_init(ctx)) + goto err; + } + return ctx; err: diff --git a/lib/libssl/tls13_quic.c b/lib/libssl/tls13_quic.c new file mode 100644 index 00000000000..3f814188a74 --- /dev/null +++ b/lib/libssl/tls13_quic.c @@ -0,0 +1,135 @@ +/* $OpenBSD: tls13_quic.c,v 1.1 2022/07/24 14:28:16 jsing Exp $ */ +/* + * Copyright (c) 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "tls13_internal.h" + +static ssize_t +tls13_quic_wire_read_cb(void *buf, size_t n, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + SSLerror(ssl, ERR_R_INTERNAL_ERROR); + return TLS13_IO_FAILURE; +} + +static ssize_t +tls13_quic_wire_write_cb(const void *buf, size_t n, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + SSLerror(ssl, ERR_R_INTERNAL_ERROR); + return TLS13_IO_FAILURE; +} + +static ssize_t +tls13_quic_wire_flush_cb(void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + /* XXX - call flush_flight. */ + SSLerror(ssl, ERR_R_INTERNAL_ERROR); + return TLS13_IO_FAILURE; +} + +static ssize_t +tls13_quic_handshake_read_cb(void *buf, size_t n, void *arg) +{ + /* XXX - read handshake data. */ + return TLS13_IO_FAILURE; +} + +static ssize_t +tls13_quic_handshake_write_cb(const void *buf, size_t n, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + /* XXX - call add_handshake_data. */ + SSLerror(ssl, ERR_R_INTERNAL_ERROR); + return TLS13_IO_FAILURE; +} + +static int +tls13_quic_set_read_traffic_key(struct tls13_secret *read_key, + enum ssl_encryption_level_t read_level, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + ctx->hs->tls13.quic_read_level = read_level; + + /* XXX - call set_read_secret. */ + SSLerror(ssl, ERR_R_INTERNAL_ERROR); + return 0; +} + +static int +tls13_quic_set_write_traffic_key(struct tls13_secret *write_key, + enum ssl_encryption_level_t write_level, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + ctx->hs->tls13.quic_write_level = write_level; + + /* XXX - call set_write_secret. */ + SSLerror(ssl, ERR_R_INTERNAL_ERROR); + return 0; +} + +static int +tls13_quic_alert_send_cb(int alert_desc, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + /* XXX - call send_alert. */ + SSLerror(ssl, ERR_R_INTERNAL_ERROR); + return TLS13_IO_FAILURE; +} + +static const struct tls13_record_layer_callbacks quic_rl_callbacks = { + .wire_read = tls13_quic_wire_read_cb, + .wire_write = tls13_quic_wire_write_cb, + .wire_flush = tls13_quic_wire_flush_cb, + + .handshake_read = tls13_quic_handshake_read_cb, + .handshake_write = tls13_quic_handshake_write_cb, + .set_read_traffic_key = tls13_quic_set_read_traffic_key, + .set_write_traffic_key = tls13_quic_set_write_traffic_key, + .alert_send = tls13_quic_alert_send_cb, + + .alert_recv = tls13_alert_received_cb, + .alert_sent = tls13_alert_sent_cb, + .phh_recv = tls13_phh_received_cb, + .phh_sent = tls13_phh_done_cb, +}; + +int +tls13_quic_init(struct tls13_ctx *ctx) +{ + tls13_record_layer_set_callbacks(ctx->rl, &quic_rl_callbacks, ctx); + + ctx->middlebox_compat = 0; + + return 1; +} diff --git a/lib/libssl/tls13_record_layer.c b/lib/libssl/tls13_record_layer.c index c92fd8d193d..ac5b83bd341 100644 --- a/lib/libssl/tls13_record_layer.c +++ b/lib/libssl/tls13_record_layer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_record_layer.c,v 1.69 2022/07/24 14:16:29 jsing Exp $ */ +/* $OpenBSD: tls13_record_layer.c,v 1.70 2022/07/24 14:28:16 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * @@ -146,8 +146,8 @@ tls13_record_layer_new(const struct tls13_record_layer_callbacks *callbacks, goto err; rl->legacy_version = TLS1_2_VERSION; - rl->cb = *callbacks; - rl->cb_arg = cb_arg; + + tls13_record_layer_set_callbacks(rl, callbacks, cb_arg); return rl; @@ -177,6 +177,14 @@ tls13_record_layer_free(struct tls13_record_layer *rl) freezero(rl, sizeof(struct tls13_record_layer)); } +void +tls13_record_layer_set_callbacks(struct tls13_record_layer *rl, + const struct tls13_record_layer_callbacks *callbacks, void *cb_arg) +{ + rl->cb = *callbacks; + rl->cb_arg = cb_arg; +} + void tls13_record_layer_rcontent(struct tls13_record_layer *rl, CBS *cbs) { @@ -489,6 +497,10 @@ int tls13_record_layer_set_read_traffic_key(struct tls13_record_layer *rl, struct tls13_secret *read_key, enum ssl_encryption_level_t read_level) { + if (rl->cb.set_read_traffic_key != NULL) + return rl->cb.set_read_traffic_key(read_key, read_level, + rl->cb_arg); + return tls13_record_layer_set_traffic_key(rl->aead, rl->hash, rl->read, read_key); } @@ -497,6 +509,10 @@ int tls13_record_layer_set_write_traffic_key(struct tls13_record_layer *rl, struct tls13_secret *write_key, enum ssl_encryption_level_t write_level) { + if (rl->cb.set_write_traffic_key != NULL) + return rl->cb.set_write_traffic_key(write_key, write_level, + rl->cb_arg); + return tls13_record_layer_set_traffic_key(rl->aead, rl->hash, rl->write, write_key); } @@ -1128,6 +1144,9 @@ tls13_send_dummy_ccs(struct tls13_record_layer *rl) ssize_t tls13_read_handshake_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n) { + if (rl->cb.handshake_read != NULL) + return rl->cb.handshake_read(buf, n, rl->cb_arg); + return tls13_record_layer_read(rl, SSL3_RT_HANDSHAKE, buf, n); } @@ -1135,6 +1154,9 @@ ssize_t tls13_write_handshake_data(struct tls13_record_layer *rl, const uint8_t *buf, size_t n) { + if (rl->cb.handshake_write != NULL) + return rl->cb.handshake_write(buf, n, rl->cb_arg); + return tls13_record_layer_write(rl, SSL3_RT_HANDSHAKE, buf, n); } @@ -1181,6 +1203,9 @@ tls13_send_alert(struct tls13_record_layer *rl, uint8_t alert_desc) uint8_t alert_level = TLS13_ALERT_LEVEL_FATAL; ssize_t ret; + if (rl->cb.alert_send != NULL) + return rl->cb.alert_send(alert_desc, rl->cb_arg); + if (alert_desc == TLS13_ALERT_CLOSE_NOTIFY || alert_desc == TLS13_ALERT_USER_CANCELED) alert_level = TLS13_ALERT_LEVEL_WARNING; diff --git a/lib/libssl/tls_internal.h b/lib/libssl/tls_internal.h index 88dae9e67e4..1d3a8133cdf 100644 --- a/lib/libssl/tls_internal.h +++ b/lib/libssl/tls_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_internal.h,v 1.8 2022/07/22 19:33:53 jsing Exp $ */ +/* $OpenBSD: tls_internal.h,v 1.9 2022/07/24 14:28:16 jsing Exp $ */ /* * Copyright (c) 2018, 2019, 2021 Joel Sing * @@ -33,6 +33,10 @@ __BEGIN_HIDDEN_DECLS #define TLS_IO_WANT_POLLOUT -4 #define TLS_IO_WANT_RETRY -5 /* Retry the previous call immediately. */ +enum ssl_encryption_level_t; + +struct tls13_secret; + /* * Callbacks. */ @@ -41,6 +45,14 @@ typedef ssize_t (*tls_write_cb)(const void *_buf, size_t _buflen, void *_cb_arg); typedef ssize_t (*tls_flush_cb)(void *_cb_arg); +typedef ssize_t (*tls_handshake_read_cb)(void *_buf, size_t _buflen, + void *_cb_arg); +typedef ssize_t (*tls_handshake_write_cb)(const void *_buf, size_t _buflen, + void *_cb_arg); +typedef int (*tls_traffic_key_cb)(struct tls13_secret *key, + enum ssl_encryption_level_t level, void *_cb_arg); +typedef int (*tls_alert_send_cb)(int _alert_desc, void *_cb_arg); + /* * Buffers. */ -- 2.20.1