summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libssl/tls13_handshake_msg.c5
-rw-r--r--lib/libssl/tls13_record.c5
-rw-r--r--lib/libssl/tls_buffer.c133
-rw-r--r--lib/libssl/tls_internal.h9
4 files changed, 139 insertions, 13 deletions
diff --git a/lib/libssl/tls13_handshake_msg.c b/lib/libssl/tls13_handshake_msg.c
index 946ccaccd6f..134cfb21739 100644
--- a/lib/libssl/tls13_handshake_msg.c
+++ b/lib/libssl/tls13_handshake_msg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls13_handshake_msg.c,v 1.5 2022/07/20 06:32:24 jsing Exp $ */
+/* $OpenBSD: tls13_handshake_msg.c,v 1.6 2022/07/22 19:33:53 jsing Exp $ */
/*
* Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
*
@@ -136,7 +136,8 @@ tls13_handshake_msg_recv(struct tls13_handshake_msg *msg,
tls13_handshake_msg_read_cb, rl)) <= 0)
return ret;
- tls_buffer_cbs(msg->buf, &cbs);
+ if (!tls_buffer_data(msg->buf, &cbs))
+ return TLS13_IO_FAILURE;
if (!CBS_get_u8(&cbs, &msg_type))
return TLS13_IO_FAILURE;
diff --git a/lib/libssl/tls13_record.c b/lib/libssl/tls13_record.c
index 2c744668e5b..dbc835c5463 100644
--- a/lib/libssl/tls13_record.c
+++ b/lib/libssl/tls13_record.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls13_record.c,v 1.9 2021/10/23 13:12:14 jsing Exp $ */
+/* $OpenBSD: tls13_record.c,v 1.10 2022/07/22 19:33:53 jsing Exp $ */
/*
* Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
*
@@ -134,7 +134,8 @@ tls13_record_recv(struct tls13_record *rec, tls_read_cb wire_read,
TLS13_RECORD_HEADER_LEN, wire_read, wire_arg)) <= 0)
return ret;
- tls_buffer_cbs(rec->buf, &cbs);
+ if (!tls_buffer_data(rec->buf, &cbs))
+ return TLS13_IO_FAILURE;
if (!CBS_get_u8(&cbs, &content_type))
return TLS13_IO_FAILURE;
diff --git a/lib/libssl/tls_buffer.c b/lib/libssl/tls_buffer.c
index 9bb6b62e511..f70cfbc1a0d 100644
--- a/lib/libssl/tls_buffer.c
+++ b/lib/libssl/tls_buffer.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: tls_buffer.c,v 1.2 2022/07/20 06:32:24 jsing Exp $ */
+/* $OpenBSD: tls_buffer.c,v 1.3 2022/07/22 19:33:53 jsing Exp $ */
/*
- * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
+ * Copyright (c) 2018, 2019, 2022 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -21,8 +21,11 @@
#include "bytestring.h"
#include "tls_internal.h"
+#define TLS_BUFFER_CAPACITY_LIMIT (1024 * 1024)
+
struct tls_buffer {
size_t capacity;
+ size_t capacity_limit;
uint8_t *data;
size_t len;
size_t offset;
@@ -38,6 +41,8 @@ tls_buffer_new(size_t init_size)
if ((buf = calloc(1, sizeof(struct tls_buffer))) == NULL)
goto err;
+ buf->capacity_limit = TLS_BUFFER_CAPACITY_LIMIT;
+
if (!tls_buffer_resize(buf, init_size))
goto err;
@@ -50,32 +55,76 @@ tls_buffer_new(size_t init_size)
}
void
+tls_buffer_clear(struct tls_buffer *buf)
+{
+ freezero(buf->data, buf->capacity);
+
+ buf->data = NULL;
+ buf->capacity = 0;
+ buf->len = 0;
+ buf->offset = 0;
+}
+
+void
tls_buffer_free(struct tls_buffer *buf)
{
if (buf == NULL)
return;
- freezero(buf->data, buf->capacity);
+ tls_buffer_clear(buf);
+
freezero(buf, sizeof(struct tls_buffer));
}
static int
+tls_buffer_grow(struct tls_buffer *buf, size_t capacity)
+{
+ if (buf->capacity >= capacity)
+ return 1;
+
+ return tls_buffer_resize(buf, capacity);
+}
+
+static int
tls_buffer_resize(struct tls_buffer *buf, size_t capacity)
{
uint8_t *data;
+ /*
+ * XXX - Consider maintaining a minimum size and growing more
+ * intelligently (rather than exactly).
+ */
if (buf->capacity == capacity)
return 1;
+ if (capacity > buf->capacity_limit)
+ return 0;
+
if ((data = recallocarray(buf->data, buf->capacity, capacity, 1)) == NULL)
return 0;
buf->data = data;
buf->capacity = capacity;
+ /* Ensure that len and offset are valid if capacity decreased. */
+ if (buf->len > buf->capacity)
+ buf->len = buf->capacity;
+ if (buf->offset > buf->len)
+ buf->offset = buf->len;
+
return 1;
}
+void
+tls_buffer_set_capacity_limit(struct tls_buffer *buf, size_t limit)
+{
+ /*
+ * XXX - do we want to force a resize if this limit is less than current
+ * capacity... and what do we do with existing data? Force a clear?
+ */
+ buf->capacity_limit = limit;
+}
+
ssize_t
tls_buffer_extend(struct tls_buffer *buf, size_t len,
tls_read_cb read_cb, void *cb_arg)
@@ -106,10 +155,79 @@ tls_buffer_extend(struct tls_buffer *buf, size_t len,
}
}
-void
-tls_buffer_cbs(struct tls_buffer *buf, CBS *cbs)
+ssize_t
+tls_buffer_read(struct tls_buffer *buf, uint8_t *rbuf, size_t n)
+{
+ if (buf->offset > buf->len)
+ return TLS_IO_FAILURE;
+
+ if (buf->offset == buf->len)
+ return TLS_IO_WANT_POLLIN;
+
+ if (n > buf->len - buf->offset)
+ n = buf->len - buf->offset;
+
+ memcpy(rbuf, &buf->data[buf->offset], n);
+
+ buf->offset += n;
+
+ return n;
+}
+
+ssize_t
+tls_buffer_write(struct tls_buffer *buf, const uint8_t *wbuf, size_t n)
+{
+ if (buf->offset > buf->len)
+ return TLS_IO_FAILURE;
+
+ /*
+ * To avoid continually growing the buffer, pull data up to the
+ * start of the buffer. If all data has been read then we can simply
+ * reset, otherwise wait until we're going to save at least 4KB of
+ * memory to reduce overhead.
+ */
+ if (buf->offset == buf->len) {
+ buf->len = 0;
+ buf->offset = 0;
+ }
+ if (buf->offset >= 4096) {
+ memmove(buf->data, &buf->data[buf->offset],
+ buf->len - buf->offset);
+ buf->len -= buf->offset;
+ buf->offset = 0;
+ }
+
+ if (buf->len > SIZE_MAX - n)
+ return TLS_IO_FAILURE;
+ if (!tls_buffer_grow(buf, buf->len + n))
+ return TLS_IO_FAILURE;
+
+ memcpy(&buf->data[buf->len], wbuf, n);
+
+ buf->len += n;
+
+ return n;
+}
+
+int
+tls_buffer_append(struct tls_buffer *buf, const uint8_t *wbuf, size_t n)
+{
+ return tls_buffer_write(buf, wbuf, n) == n;
+}
+
+int
+tls_buffer_data(struct tls_buffer *buf, CBS *out_cbs)
{
- CBS_init(cbs, buf->data, buf->len);
+ CBS cbs;
+
+ CBS_init(&cbs, buf->data, buf->len);
+
+ if (!CBS_skip(&cbs, buf->offset))
+ return 0;
+
+ CBS_dup(&cbs, out_cbs);
+
+ return 1;
}
int
@@ -121,9 +239,10 @@ tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len)
*out = buf->data;
*out_len = buf->len;
- buf->capacity = 0;
buf->data = NULL;
+ buf->capacity = 0;
buf->len = 0;
+ buf->offset = 0;
return 1;
}
diff --git a/lib/libssl/tls_internal.h b/lib/libssl/tls_internal.h
index ac2d14da48d..88dae9e67e4 100644
--- a/lib/libssl/tls_internal.h
+++ b/lib/libssl/tls_internal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls_internal.h,v 1.7 2022/07/20 06:32:24 jsing Exp $ */
+/* $OpenBSD: tls_internal.h,v 1.8 2022/07/22 19:33:53 jsing Exp $ */
/*
* Copyright (c) 2018, 2019, 2021 Joel Sing <jsing@openbsd.org>
*
@@ -47,10 +47,15 @@ typedef ssize_t (*tls_flush_cb)(void *_cb_arg);
struct tls_buffer;
struct tls_buffer *tls_buffer_new(size_t init_size);
+void tls_buffer_clear(struct tls_buffer *buf);
void tls_buffer_free(struct tls_buffer *buf);
+void tls_buffer_set_capacity_limit(struct tls_buffer *buf, size_t limit);
ssize_t tls_buffer_extend(struct tls_buffer *buf, size_t len,
tls_read_cb read_cb, void *cb_arg);
-void tls_buffer_cbs(struct tls_buffer *buf, CBS *cbs);
+ssize_t tls_buffer_read(struct tls_buffer *buf, uint8_t *rbuf, size_t n);
+ssize_t tls_buffer_write(struct tls_buffer *buf, const uint8_t *wbuf, size_t n);
+int tls_buffer_append(struct tls_buffer *buf, const uint8_t *wbuf, size_t n);
+int tls_buffer_data(struct tls_buffer *buf, CBS *cbs);
int tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len);
/*