summaryrefslogtreecommitdiff
path: root/lib/libssl
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2019-11-17 17:20:17 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2019-11-17 17:20:17 +0000
commit1a9ef7e80acbe5dc8e9b18365db17c530ffae2e3 (patch)
treed0a380921ea74f4ebb9b70354bd10ec8e4d91f49 /lib/libssl
parent31509ae9391ef32a4bf9fe756ad7ed196670ea2b (diff)
Provide framework for sending alerts and post-handshake handshake messages.
Discussed at length with beck@ ok beck@ tb@
Diffstat (limited to 'lib/libssl')
-rw-r--r--lib/libssl/tls13_internal.h6
-rw-r--r--lib/libssl/tls13_record_layer.c183
2 files changed, 174 insertions, 15 deletions
diff --git a/lib/libssl/tls13_internal.h b/lib/libssl/tls13_internal.h
index 9ab72f4f3a7..05e108952a3 100644
--- a/lib/libssl/tls13_internal.h
+++ b/lib/libssl/tls13_internal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls13_internal.h,v 1.30 2019/11/17 06:35:30 jsing Exp $ */
+/* $OpenBSD: tls13_internal.h,v 1.31 2019/11/17 17:20:16 jsing Exp $ */
/*
* Copyright (c) 2018 Bob Beck <beck@openbsd.org>
* Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
@@ -120,6 +120,10 @@ 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_alert(struct tls13_record_layer *rl,
+ uint8_t alert_level, uint8_t alert_desc);
+ssize_t tls13_record_layer_phh(struct tls13_record_layer *rl, uint8_t *data,
+ size_t len);
ssize_t tls13_read_handshake_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n);
ssize_t tls13_write_handshake_data(struct tls13_record_layer *rl, const uint8_t *buf,
diff --git a/lib/libssl/tls13_record_layer.c b/lib/libssl/tls13_record_layer.c
index ff26b09d46d..8208ae508c5 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.10 2019/11/17 00:10:47 beck Exp $ */
+/* $OpenBSD: tls13_record_layer.c,v 1.11 2019/11/17 17:20:16 jsing Exp $ */
/*
* Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
*
@@ -22,6 +22,11 @@
#include "tls13_internal.h"
#include "tls13_record.h"
+static ssize_t tls13_record_layer_write_chunk(struct tls13_record_layer *rl,
+ uint8_t content_type, const uint8_t *buf, size_t n);
+static ssize_t tls13_record_layer_write_record(struct tls13_record_layer *rl,
+ uint8_t content_type, const uint8_t *content, size_t content_len);
+
struct tls13_record_layer {
int change_cipher_spec_seen;
int handshake_completed;
@@ -36,7 +41,20 @@ struct tls13_record_layer {
int write_closed;
struct tls13_record *rrec;
+
struct tls13_record *wrec;
+ uint8_t wrec_content_type;
+ size_t wrec_appdata_len;
+ size_t wrec_content_len;
+
+ /* Pending alert messages. */
+ uint8_t *alert_data;
+ size_t alert_len;
+
+ /* Pending post-handshake handshake messages. */
+ CBS phh_cbs;
+ uint8_t *phh_data;
+ size_t phh_len;
/* Buffer containing plaintext from opened records. */
uint8_t rbuf_content_type;
@@ -232,7 +250,7 @@ tls13_record_layer_process_alert(struct tls13_record_layer *rl)
} else if (alert_level == SSL3_AL_FATAL) {
rl->read_closed = 1;
rl->write_closed = 1;
- ret = TLS13_IO_EOF;
+ ret = TLS13_IO_FAILURE; /* XXX - ALERT? */
} else {
/* XXX - decode error alert. */
return TLS13_IO_FAILURE;
@@ -244,12 +262,112 @@ tls13_record_layer_process_alert(struct tls13_record_layer *rl)
return ret;
}
-int
-tls13_record_layer_send_alert(struct tls13_record_layer *rl,
+static ssize_t
+tls13_record_layer_send_alert(struct tls13_record_layer *rl)
+{
+ ssize_t ret;
+
+ /* This has to fit into a single record, per RFC 8446 section 5.1. */
+ if ((ret = tls13_record_layer_write_record(rl, SSL3_RT_ALERT,
+ rl->alert_data, rl->alert_len)) != rl->alert_len)
+ return ret;
+
+ freezero(rl->alert_data, rl->alert_len);
+ 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;
+
+ /* XXX - we may want a TLS13_IO_ALERT (or handle as errors). */
+ return TLS13_IO_FAILURE;
+}
+
+static ssize_t
+tls13_record_layer_send_phh(struct tls13_record_layer *rl)
+{
+ ssize_t ret;
+
+ /* Push out pending post-handshake handshake messages. */
+ if ((ret = tls13_record_layer_write_chunk(rl, SSL3_RT_HANDSHAKE,
+ CBS_data(&rl->phh_cbs), CBS_len(&rl->phh_cbs))) < 0)
+ return ret;
+ if (!CBS_skip(&rl->phh_cbs, ret))
+ return TLS13_IO_FAILURE;
+ if (CBS_len(&rl->phh_cbs) != 0)
+ return TLS13_IO_WANT_POLLOUT;
+
+ freezero(rl->phh_data, rl->phh_len);
+ rl->phh_data = NULL;
+ rl->phh_len = 0;
+
+ CBS_init(&rl->phh_cbs, rl->phh_data, rl->phh_len);
+
+ return TLS13_IO_SUCCESS;
+}
+
+static ssize_t
+tls13_record_layer_send_pending(struct tls13_record_layer *rl)
+{
+ /*
+ * If an alert is pending, then it needs to be sent. However,
+ * if we're already part of the way through sending post-handshake
+ * handshake messages, then we need to finish that first...
+ */
+
+ if (rl->phh_data != NULL && CBS_len(&rl->phh_cbs) != rl->phh_len)
+ return tls13_record_layer_send_phh(rl);
+
+ if (rl->alert_data != NULL)
+ return tls13_record_layer_send_alert(rl);
+
+ if (rl->phh_data != NULL)
+ return tls13_record_layer_send_phh(rl);
+
+ return TLS13_IO_SUCCESS;
+}
+
+ssize_t
+tls13_record_layer_alert(struct tls13_record_layer *rl,
uint8_t alert_level, uint8_t alert_desc)
{
- /* XXX - implement. */
- return -1;
+ CBB cbb;
+
+ if (rl->alert_data != NULL)
+ return TLS13_IO_FAILURE;
+
+ if (!CBB_init(&cbb, 0))
+ goto err;
+
+ if (!CBB_add_u8(&cbb, alert_level))
+ goto err;
+ if (!CBB_add_u8(&cbb, alert_desc))
+ goto err;
+ if (!CBB_finish(&cbb, &rl->alert_data, &rl->alert_len))
+ goto err;
+
+ return tls13_record_layer_send_pending(rl);
+
+ err:
+ CBB_cleanup(&cbb);
+
+ return TLS13_IO_FAILURE;
+}
+
+ssize_t
+tls13_record_layer_phh(struct tls13_record_layer *rl, uint8_t *data,
+ size_t len)
+{
+ if (rl->phh_data != NULL)
+ return TLS13_IO_FAILURE;
+
+ rl->phh_data = data;
+ rl->phh_len = len;
+
+ CBS_init(&rl->phh_cbs, rl->phh_data, rl->phh_len);
+
+ return tls13_record_layer_send_pending(rl);
}
static int
@@ -546,6 +664,9 @@ tls13_record_layer_seal_record_protected(struct tls13_record_layer *rl,
if (!tls13_record_set_data(rl->wrec, data, data_len))
goto err;
+ rl->wrec_content_len = content_len;
+ rl->wrec_content_type = content_type;
+
data = NULL;
data_len = 0;
@@ -673,12 +794,12 @@ tls13_record_layer_read(struct tls13_record_layer *rl, uint8_t content_type,
{
ssize_t ret;
+ if ((ret = tls13_record_layer_send_pending(rl)) != TLS13_IO_SUCCESS)
+ return ret;
+
if (rl->read_closed)
return TLS13_IO_EOF;
- /* XXX - loop here with record and byte limits. */
- /* XXX - send alert... */
-
/* If necessary, pull up the next record. */
if (CBS_len(&rl->rbuf_cbs) == 0) {
if ((ret = tls13_record_layer_read_record(rl)) <= 0)
@@ -737,16 +858,38 @@ tls13_record_layer_write_record(struct tls13_record_layer *rl,
if (rl->write_closed)
return TLS13_IO_EOF;
+ /*
+ * If we pushed out application data while handling other messages,
+ * we need to return content length on the next call.
+ */
+ if (content_type == SSL3_RT_APPLICATION_DATA &&
+ rl->wrec_appdata_len != 0) {
+ ret = rl->wrec_appdata_len;
+ rl->wrec_appdata_len = 0;
+ return ret;
+ }
+
/* See if there is an existing record and attempt to push it out... */
if (rl->wrec != NULL) {
if ((ret = tls13_record_send(rl->wrec, rl->wire_write,
rl->cb_arg)) <= 0)
return ret;
-
tls13_record_layer_wrec_free(rl);
- /* XXX - could be pushing out different data... */
- return content_len;
+ if (rl->wrec_content_type == content_type) {
+ ret = rl->wrec_content_len;
+ rl->wrec_content_len = 0;
+ rl->wrec_content_type = 0;
+ return ret;
+ }
+
+ /*
+ * The only partial record type should be application data.
+ * All other cases are handled to completion.
+ */
+ if (rl->wrec_content_type != SSL3_RT_APPLICATION_DATA)
+ return TLS13_IO_FAILURE;
+ rl->wrec_appdata_len = rl->wrec_content_len;
}
if (content_len > TLS13_RECORD_MAX_PLAINTEXT_LEN)
@@ -767,8 +910,8 @@ tls13_record_layer_write_record(struct tls13_record_layer *rl,
}
static ssize_t
-tls13_record_layer_write(struct tls13_record_layer *rl, uint8_t content_type,
- const uint8_t *buf, size_t n)
+tls13_record_layer_write_chunk(struct tls13_record_layer *rl,
+ uint8_t content_type, const uint8_t *buf, size_t n)
{
if (n > TLS13_RECORD_MAX_PLAINTEXT_LEN)
n = TLS13_RECORD_MAX_PLAINTEXT_LEN;
@@ -776,6 +919,18 @@ tls13_record_layer_write(struct tls13_record_layer *rl, uint8_t content_type,
return tls13_record_layer_write_record(rl, content_type, buf, n);
}
+static ssize_t
+tls13_record_layer_write(struct tls13_record_layer *rl, uint8_t content_type,
+ const uint8_t *buf, size_t n)
+{
+ ssize_t ret;
+
+ if ((ret = tls13_record_layer_send_pending(rl)) != TLS13_IO_SUCCESS)
+ return ret;
+
+ return tls13_record_layer_write_chunk(rl, content_type, buf, n);
+}
+
ssize_t
tls13_read_handshake_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n)
{