From d2535f6d6c56956061dc8da2a8a2bfdd6b98a0a4 Mon Sep 17 00:00:00 2001 From: jsing <> Date: Wed, 22 Jan 2020 01:02:28 +0000 Subject: Implement close-notify and SSL_shutdown() handling for the TLSv1.3 client. ok beck@ inoguchi@ tb@ --- src/lib/libssl/tls13_internal.h | 7 ++++- src/lib/libssl/tls13_lib.c | 52 ++++++++++++++++++++++++++++++++++++- src/lib/libssl/tls13_record_layer.c | 26 ++++++++++++++----- 3 files changed, 76 insertions(+), 9 deletions(-) (limited to 'src/lib') diff --git a/src/lib/libssl/tls13_internal.h b/src/lib/libssl/tls13_internal.h index 3ee73782ec..7fee37f5dd 100644 --- a/src/lib/libssl/tls13_internal.h +++ b/src/lib/libssl/tls13_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_internal.h,v 1.39 2020/01/21 12:08:04 jsing Exp $ */ +/* $OpenBSD: tls13_internal.h,v 1.40 2020/01/22 01:02:28 jsing Exp $ */ /* * Copyright (c) 2018 Bob Beck * Copyright (c) 2018 Theo Buehler @@ -126,6 +126,7 @@ int tls13_record_layer_set_read_traffic_key(struct tls13_record_layer *rl, struct tls13_secret *read_key); int tls13_record_layer_set_write_traffic_key(struct tls13_record_layer *rl, struct tls13_secret *write_key); +ssize_t tls13_record_layer_send_pending(struct tls13_record_layer *rl); ssize_t tls13_record_layer_phh(struct tls13_record_layer *rl, CBS *cbs); ssize_t tls13_read_handshake_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n); @@ -181,6 +182,9 @@ struct tls13_ctx { struct tls13_handshake_stage handshake_stage; int handshake_completed; + int close_notify_sent; + int close_notify_recv; + const EVP_AEAD *aead; const EVP_MD *hash; @@ -215,6 +219,7 @@ ssize_t tls13_legacy_wire_write_cb(const void *buf, size_t n, void *arg); int tls13_legacy_read_bytes(SSL *ssl, int type, unsigned char *buf, int len, int peek); int tls13_legacy_write_bytes(SSL *ssl, int type, const void *buf, int len); +int tls13_legacy_shutdown(SSL *ssl); /* * Message Types - RFC 8446, Section B.3. diff --git a/src/lib/libssl/tls13_lib.c b/src/lib/libssl/tls13_lib.c index 451e798cb8..bb749a9b68 100644 --- a/src/lib/libssl/tls13_lib.c +++ b/src/lib/libssl/tls13_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_lib.c,v 1.16 2020/01/21 05:19:02 jsing Exp $ */ +/* $OpenBSD: tls13_lib.c,v 1.17 2020/01/22 01:02:28 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * Copyright (c) 2019 Bob Beck @@ -69,6 +69,7 @@ tls13_alert_received_cb(uint8_t alert_desc, void *arg) SSL *s = ctx->ssl; if (alert_desc == SSL_AD_CLOSE_NOTIFY) { + ctx->close_notify_recv = 1; ctx->ssl->internal->shutdown |= SSL_RECEIVED_SHUTDOWN; S3I(ctx->ssl)->warn_alert = alert_desc; return; @@ -482,3 +483,52 @@ tls13_legacy_write_bytes(SSL *ssl, int type, const void *vbuf, int len) n -= ret; } } + +int +tls13_legacy_shutdown(SSL *ssl) +{ + struct tls13_ctx *ctx = ssl->internal->tls13; + uint8_t buf[512]; /* XXX */ + ssize_t ret; + + /* + * We need to return 0 when we have sent a close-notify but have not + * yet received one. We return 1 only once we have sent and received + * close-notify alerts. All other cases return -1 and set internal + * state appropriately. + */ + if (ctx == NULL || ssl->internal->quiet_shutdown) { + ssl->internal->shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN; + return 1; + } + + /* Send close notify. */ + if (!ctx->close_notify_sent) { + ctx->close_notify_sent = 1; + if ((ret = tls13_send_alert(ctx->rl, SSL_AD_CLOSE_NOTIFY)) < 0) + return tls13_legacy_return_code(ssl, ret); + } + + /* Ensure close notify has been sent. */ + if ((ret = tls13_record_layer_send_pending(ctx->rl)) != TLS13_IO_SUCCESS) + return tls13_legacy_return_code(ssl, ret); + + /* Receive close notify. */ + if (!ctx->close_notify_recv) { + /* + * If there is still application data pending then we have no + * option but to discard it here. The application should have + * continued to call SSL_read() instead of SSL_shutdown(). + */ + /* XXX - tls13_drain_application_data()? */ + if ((ret = tls13_read_application_data(ctx->rl, buf, sizeof(buf))) > 0) + ret = TLS13_IO_WANT_POLLIN; + if (ret != TLS13_IO_EOF) + return tls13_legacy_return_code(ssl, ret); + } + + if (ctx->close_notify_recv) + return 1; + + return 0; +} diff --git a/src/lib/libssl/tls13_record_layer.c b/src/lib/libssl/tls13_record_layer.c index a6b00a83b3..dff5cd2bbe 100644 --- a/src/lib/libssl/tls13_record_layer.c +++ b/src/lib/libssl/tls13_record_layer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_record_layer.c,v 1.18 2020/01/21 12:08:04 jsing Exp $ */ +/* $OpenBSD: tls13_record_layer.c,v 1.19 2020/01/22 01:02:28 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * @@ -51,6 +51,8 @@ struct tls13_record_layer { /* Pending alert messages. */ uint8_t *alert_data; size_t alert_len; + uint8_t alert_level; + uint8_t alert_desc; /* Pending post-handshake handshake messages (RFC 8446, section 4.6). */ CBS phh_cbs; @@ -281,12 +283,19 @@ tls13_record_layer_send_alert(struct tls13_record_layer *rl) rl->alert_data = NULL; rl->alert_len = 0; - /* XXX - only close write channel when sending close notify. */ - rl->read_closed = 1; - rl->write_closed = 1; + if (rl->alert_desc == SSL_AD_CLOSE_NOTIFY) { + rl->write_closed = 1; + ret = TLS13_IO_SUCCESS; + } else if (rl->alert_desc == SSL_AD_USER_CANCELLED) { + /* Ignored at the record layer. */ + ret = TLS13_IO_SUCCESS; + } else { + rl->read_closed = 1; + rl->write_closed = 1; + ret = TLS13_IO_SUCCESS; /* XXX - ALERT? */ + } - /* XXX - we may want a TLS13_IO_ALERT (or handle as errors). */ - return TLS13_IO_FAILURE; + return ret; } static ssize_t @@ -314,7 +323,7 @@ tls13_record_layer_send_phh(struct tls13_record_layer *rl) return TLS13_IO_SUCCESS; } -static ssize_t +ssize_t tls13_record_layer_send_pending(struct tls13_record_layer *rl) { /* @@ -354,6 +363,9 @@ tls13_record_layer_alert(struct tls13_record_layer *rl, if (!CBB_finish(&cbb, &rl->alert_data, &rl->alert_len)) goto err; + rl->alert_level = alert_level; + rl->alert_desc = alert_desc; + return tls13_record_layer_send_pending(rl); err: -- cgit v1.2.3-55-g6feb