diff options
| author | jsing <> | 2022-07-22 19:33:53 +0000 |
|---|---|---|
| committer | jsing <> | 2022-07-22 19:33:53 +0000 |
| commit | 6612d759045c7571f6be2ff1366a704ba82eb216 (patch) | |
| tree | 621585d83424bc407b8aa48aef0a859751335e14 /src | |
| parent | eb96f22ae583afb63244c20ef4b563fcdd868d57 (diff) | |
| download | openbsd-6612d759045c7571f6be2ff1366a704ba82eb216.tar.gz openbsd-6612d759045c7571f6be2ff1366a704ba82eb216.tar.bz2 openbsd-6612d759045c7571f6be2ff1366a704ba82eb216.zip | |
Add read and write support to tls_buffer.
tls_buffer was original created for a specific use case, namely reading in
length prefixed messages. This adds read and write support, along with a
capacity limit, allowing it to be used in additional use cases.
ok beck@ tb@
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libssl/tls13_handshake_msg.c | 5 | ||||
| -rw-r--r-- | src/lib/libssl/tls13_record.c | 5 | ||||
| -rw-r--r-- | src/lib/libssl/tls_buffer.c | 133 | ||||
| -rw-r--r-- | src/lib/libssl/tls_internal.h | 9 |
4 files changed, 139 insertions, 13 deletions
diff --git a/src/lib/libssl/tls13_handshake_msg.c b/src/lib/libssl/tls13_handshake_msg.c index 946ccaccd6..134cfb2173 100644 --- a/src/lib/libssl/tls13_handshake_msg.c +++ b/src/lib/libssl/tls13_handshake_msg.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls13_handshake_msg.c,v 1.5 2022/07/20 06:32:24 jsing Exp $ */ | 1 | /* $OpenBSD: tls13_handshake_msg.c,v 1.6 2022/07/22 19:33:53 jsing Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -136,7 +136,8 @@ tls13_handshake_msg_recv(struct tls13_handshake_msg *msg, | |||
| 136 | tls13_handshake_msg_read_cb, rl)) <= 0) | 136 | tls13_handshake_msg_read_cb, rl)) <= 0) |
| 137 | return ret; | 137 | return ret; |
| 138 | 138 | ||
| 139 | tls_buffer_cbs(msg->buf, &cbs); | 139 | if (!tls_buffer_data(msg->buf, &cbs)) |
| 140 | return TLS13_IO_FAILURE; | ||
| 140 | 141 | ||
| 141 | if (!CBS_get_u8(&cbs, &msg_type)) | 142 | if (!CBS_get_u8(&cbs, &msg_type)) |
| 142 | return TLS13_IO_FAILURE; | 143 | return TLS13_IO_FAILURE; |
diff --git a/src/lib/libssl/tls13_record.c b/src/lib/libssl/tls13_record.c index 2c744668e5..dbc835c546 100644 --- a/src/lib/libssl/tls13_record.c +++ b/src/lib/libssl/tls13_record.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls13_record.c,v 1.9 2021/10/23 13:12:14 jsing Exp $ */ | 1 | /* $OpenBSD: tls13_record.c,v 1.10 2022/07/22 19:33:53 jsing Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -134,7 +134,8 @@ tls13_record_recv(struct tls13_record *rec, tls_read_cb wire_read, | |||
| 134 | TLS13_RECORD_HEADER_LEN, wire_read, wire_arg)) <= 0) | 134 | TLS13_RECORD_HEADER_LEN, wire_read, wire_arg)) <= 0) |
| 135 | return ret; | 135 | return ret; |
| 136 | 136 | ||
| 137 | tls_buffer_cbs(rec->buf, &cbs); | 137 | if (!tls_buffer_data(rec->buf, &cbs)) |
| 138 | return TLS13_IO_FAILURE; | ||
| 138 | 139 | ||
| 139 | if (!CBS_get_u8(&cbs, &content_type)) | 140 | if (!CBS_get_u8(&cbs, &content_type)) |
| 140 | return TLS13_IO_FAILURE; | 141 | return TLS13_IO_FAILURE; |
diff --git a/src/lib/libssl/tls_buffer.c b/src/lib/libssl/tls_buffer.c index 9bb6b62e51..f70cfbc1a0 100644 --- a/src/lib/libssl/tls_buffer.c +++ b/src/lib/libssl/tls_buffer.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* $OpenBSD: tls_buffer.c,v 1.2 2022/07/20 06:32:24 jsing Exp $ */ | 1 | /* $OpenBSD: tls_buffer.c,v 1.3 2022/07/22 19:33:53 jsing Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018, 2019, 2022 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| 5 | * Permission to use, copy, modify, and distribute this software for any | 5 | * Permission to use, copy, modify, and distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -21,8 +21,11 @@ | |||
| 21 | #include "bytestring.h" | 21 | #include "bytestring.h" |
| 22 | #include "tls_internal.h" | 22 | #include "tls_internal.h" |
| 23 | 23 | ||
| 24 | #define TLS_BUFFER_CAPACITY_LIMIT (1024 * 1024) | ||
| 25 | |||
| 24 | struct tls_buffer { | 26 | struct tls_buffer { |
| 25 | size_t capacity; | 27 | size_t capacity; |
| 28 | size_t capacity_limit; | ||
| 26 | uint8_t *data; | 29 | uint8_t *data; |
| 27 | size_t len; | 30 | size_t len; |
| 28 | size_t offset; | 31 | size_t offset; |
| @@ -38,6 +41,8 @@ tls_buffer_new(size_t init_size) | |||
| 38 | if ((buf = calloc(1, sizeof(struct tls_buffer))) == NULL) | 41 | if ((buf = calloc(1, sizeof(struct tls_buffer))) == NULL) |
| 39 | goto err; | 42 | goto err; |
| 40 | 43 | ||
| 44 | buf->capacity_limit = TLS_BUFFER_CAPACITY_LIMIT; | ||
| 45 | |||
| 41 | if (!tls_buffer_resize(buf, init_size)) | 46 | if (!tls_buffer_resize(buf, init_size)) |
| 42 | goto err; | 47 | goto err; |
| 43 | 48 | ||
| @@ -50,32 +55,76 @@ tls_buffer_new(size_t init_size) | |||
| 50 | } | 55 | } |
| 51 | 56 | ||
| 52 | void | 57 | void |
| 58 | tls_buffer_clear(struct tls_buffer *buf) | ||
| 59 | { | ||
| 60 | freezero(buf->data, buf->capacity); | ||
| 61 | |||
| 62 | buf->data = NULL; | ||
| 63 | buf->capacity = 0; | ||
| 64 | buf->len = 0; | ||
| 65 | buf->offset = 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | void | ||
| 53 | tls_buffer_free(struct tls_buffer *buf) | 69 | tls_buffer_free(struct tls_buffer *buf) |
| 54 | { | 70 | { |
| 55 | if (buf == NULL) | 71 | if (buf == NULL) |
| 56 | return; | 72 | return; |
| 57 | 73 | ||
| 58 | freezero(buf->data, buf->capacity); | 74 | tls_buffer_clear(buf); |
| 75 | |||
| 59 | freezero(buf, sizeof(struct tls_buffer)); | 76 | freezero(buf, sizeof(struct tls_buffer)); |
| 60 | } | 77 | } |
| 61 | 78 | ||
| 62 | static int | 79 | static int |
| 80 | tls_buffer_grow(struct tls_buffer *buf, size_t capacity) | ||
| 81 | { | ||
| 82 | if (buf->capacity >= capacity) | ||
| 83 | return 1; | ||
| 84 | |||
| 85 | return tls_buffer_resize(buf, capacity); | ||
| 86 | } | ||
| 87 | |||
| 88 | static int | ||
| 63 | tls_buffer_resize(struct tls_buffer *buf, size_t capacity) | 89 | tls_buffer_resize(struct tls_buffer *buf, size_t capacity) |
| 64 | { | 90 | { |
| 65 | uint8_t *data; | 91 | uint8_t *data; |
| 66 | 92 | ||
| 93 | /* | ||
| 94 | * XXX - Consider maintaining a minimum size and growing more | ||
| 95 | * intelligently (rather than exactly). | ||
| 96 | */ | ||
| 67 | if (buf->capacity == capacity) | 97 | if (buf->capacity == capacity) |
| 68 | return 1; | 98 | return 1; |
| 69 | 99 | ||
| 100 | if (capacity > buf->capacity_limit) | ||
| 101 | return 0; | ||
| 102 | |||
| 70 | if ((data = recallocarray(buf->data, buf->capacity, capacity, 1)) == NULL) | 103 | if ((data = recallocarray(buf->data, buf->capacity, capacity, 1)) == NULL) |
| 71 | return 0; | 104 | return 0; |
| 72 | 105 | ||
| 73 | buf->data = data; | 106 | buf->data = data; |
| 74 | buf->capacity = capacity; | 107 | buf->capacity = capacity; |
| 75 | 108 | ||
| 109 | /* Ensure that len and offset are valid if capacity decreased. */ | ||
| 110 | if (buf->len > buf->capacity) | ||
| 111 | buf->len = buf->capacity; | ||
| 112 | if (buf->offset > buf->len) | ||
| 113 | buf->offset = buf->len; | ||
| 114 | |||
| 76 | return 1; | 115 | return 1; |
| 77 | } | 116 | } |
| 78 | 117 | ||
| 118 | void | ||
| 119 | tls_buffer_set_capacity_limit(struct tls_buffer *buf, size_t limit) | ||
| 120 | { | ||
| 121 | /* | ||
| 122 | * XXX - do we want to force a resize if this limit is less than current | ||
| 123 | * capacity... and what do we do with existing data? Force a clear? | ||
| 124 | */ | ||
| 125 | buf->capacity_limit = limit; | ||
| 126 | } | ||
| 127 | |||
| 79 | ssize_t | 128 | ssize_t |
| 80 | tls_buffer_extend(struct tls_buffer *buf, size_t len, | 129 | tls_buffer_extend(struct tls_buffer *buf, size_t len, |
| 81 | tls_read_cb read_cb, void *cb_arg) | 130 | tls_read_cb read_cb, void *cb_arg) |
| @@ -106,10 +155,79 @@ tls_buffer_extend(struct tls_buffer *buf, size_t len, | |||
| 106 | } | 155 | } |
| 107 | } | 156 | } |
| 108 | 157 | ||
| 109 | void | 158 | ssize_t |
| 110 | tls_buffer_cbs(struct tls_buffer *buf, CBS *cbs) | 159 | tls_buffer_read(struct tls_buffer *buf, uint8_t *rbuf, size_t n) |
| 160 | { | ||
| 161 | if (buf->offset > buf->len) | ||
| 162 | return TLS_IO_FAILURE; | ||
| 163 | |||
| 164 | if (buf->offset == buf->len) | ||
| 165 | return TLS_IO_WANT_POLLIN; | ||
| 166 | |||
| 167 | if (n > buf->len - buf->offset) | ||
| 168 | n = buf->len - buf->offset; | ||
| 169 | |||
| 170 | memcpy(rbuf, &buf->data[buf->offset], n); | ||
| 171 | |||
| 172 | buf->offset += n; | ||
| 173 | |||
| 174 | return n; | ||
| 175 | } | ||
| 176 | |||
| 177 | ssize_t | ||
| 178 | tls_buffer_write(struct tls_buffer *buf, const uint8_t *wbuf, size_t n) | ||
| 179 | { | ||
| 180 | if (buf->offset > buf->len) | ||
| 181 | return TLS_IO_FAILURE; | ||
| 182 | |||
| 183 | /* | ||
| 184 | * To avoid continually growing the buffer, pull data up to the | ||
| 185 | * start of the buffer. If all data has been read then we can simply | ||
| 186 | * reset, otherwise wait until we're going to save at least 4KB of | ||
| 187 | * memory to reduce overhead. | ||
| 188 | */ | ||
| 189 | if (buf->offset == buf->len) { | ||
| 190 | buf->len = 0; | ||
| 191 | buf->offset = 0; | ||
| 192 | } | ||
| 193 | if (buf->offset >= 4096) { | ||
| 194 | memmove(buf->data, &buf->data[buf->offset], | ||
| 195 | buf->len - buf->offset); | ||
| 196 | buf->len -= buf->offset; | ||
| 197 | buf->offset = 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | if (buf->len > SIZE_MAX - n) | ||
| 201 | return TLS_IO_FAILURE; | ||
| 202 | if (!tls_buffer_grow(buf, buf->len + n)) | ||
| 203 | return TLS_IO_FAILURE; | ||
| 204 | |||
| 205 | memcpy(&buf->data[buf->len], wbuf, n); | ||
| 206 | |||
| 207 | buf->len += n; | ||
| 208 | |||
| 209 | return n; | ||
| 210 | } | ||
| 211 | |||
| 212 | int | ||
| 213 | tls_buffer_append(struct tls_buffer *buf, const uint8_t *wbuf, size_t n) | ||
| 214 | { | ||
| 215 | return tls_buffer_write(buf, wbuf, n) == n; | ||
| 216 | } | ||
| 217 | |||
| 218 | int | ||
| 219 | tls_buffer_data(struct tls_buffer *buf, CBS *out_cbs) | ||
| 111 | { | 220 | { |
| 112 | CBS_init(cbs, buf->data, buf->len); | 221 | CBS cbs; |
| 222 | |||
| 223 | CBS_init(&cbs, buf->data, buf->len); | ||
| 224 | |||
| 225 | if (!CBS_skip(&cbs, buf->offset)) | ||
| 226 | return 0; | ||
| 227 | |||
| 228 | CBS_dup(&cbs, out_cbs); | ||
| 229 | |||
| 230 | return 1; | ||
| 113 | } | 231 | } |
| 114 | 232 | ||
| 115 | int | 233 | int |
| @@ -121,9 +239,10 @@ tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len) | |||
| 121 | *out = buf->data; | 239 | *out = buf->data; |
| 122 | *out_len = buf->len; | 240 | *out_len = buf->len; |
| 123 | 241 | ||
| 124 | buf->capacity = 0; | ||
| 125 | buf->data = NULL; | 242 | buf->data = NULL; |
| 243 | buf->capacity = 0; | ||
| 126 | buf->len = 0; | 244 | buf->len = 0; |
| 245 | buf->offset = 0; | ||
| 127 | 246 | ||
| 128 | return 1; | 247 | return 1; |
| 129 | } | 248 | } |
diff --git a/src/lib/libssl/tls_internal.h b/src/lib/libssl/tls_internal.h index ac2d14da48..88dae9e67e 100644 --- a/src/lib/libssl/tls_internal.h +++ b/src/lib/libssl/tls_internal.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls_internal.h,v 1.7 2022/07/20 06:32:24 jsing Exp $ */ | 1 | /* $OpenBSD: tls_internal.h,v 1.8 2022/07/22 19:33:53 jsing Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2018, 2019, 2021 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018, 2019, 2021 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -47,10 +47,15 @@ typedef ssize_t (*tls_flush_cb)(void *_cb_arg); | |||
| 47 | struct tls_buffer; | 47 | struct tls_buffer; |
| 48 | 48 | ||
| 49 | struct tls_buffer *tls_buffer_new(size_t init_size); | 49 | struct tls_buffer *tls_buffer_new(size_t init_size); |
| 50 | void tls_buffer_clear(struct tls_buffer *buf); | ||
| 50 | void tls_buffer_free(struct tls_buffer *buf); | 51 | void tls_buffer_free(struct tls_buffer *buf); |
| 52 | void tls_buffer_set_capacity_limit(struct tls_buffer *buf, size_t limit); | ||
| 51 | ssize_t tls_buffer_extend(struct tls_buffer *buf, size_t len, | 53 | ssize_t tls_buffer_extend(struct tls_buffer *buf, size_t len, |
| 52 | tls_read_cb read_cb, void *cb_arg); | 54 | tls_read_cb read_cb, void *cb_arg); |
| 53 | void tls_buffer_cbs(struct tls_buffer *buf, CBS *cbs); | 55 | ssize_t tls_buffer_read(struct tls_buffer *buf, uint8_t *rbuf, size_t n); |
| 56 | ssize_t tls_buffer_write(struct tls_buffer *buf, const uint8_t *wbuf, size_t n); | ||
| 57 | int tls_buffer_append(struct tls_buffer *buf, const uint8_t *wbuf, size_t n); | ||
| 58 | int tls_buffer_data(struct tls_buffer *buf, CBS *cbs); | ||
| 54 | int tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len); | 59 | int tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len); |
| 55 | 60 | ||
| 56 | /* | 61 | /* |
