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 | |
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@
-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 | /* |