diff options
author | jsing <> | 2019-01-20 10:31:54 +0000 |
---|---|---|
committer | jsing <> | 2019-01-20 10:31:54 +0000 |
commit | 7d4c5df49f29866dec345d1ed3420715c776e9e1 (patch) | |
tree | e8897b82c6da0c5ad784ceab148eb15cf17a1d6c | |
parent | 109c1a3cd723529ce9ea6e4db6ce37493ed83034 (diff) | |
download | openbsd-7d4c5df49f29866dec345d1ed3420715c776e9e1.tar.gz openbsd-7d4c5df49f29866dec345d1ed3420715c776e9e1.tar.bz2 openbsd-7d4c5df49f29866dec345d1ed3420715c776e9e1.zip |
Provide an initial implementation of the TLS 1.3 record layer.
This is entirely self-contained and knows nothing about SSL or BIO. The
bottom of the stack is provided by wire read and write callbacks, with the
API to the record layer primarily being via
tls13_{read,write}_{application,handshake}_data().
This currently lacks some functionality, however will be worked on in tree.
ok tb@
-rw-r--r-- | src/lib/libssl/Makefile | 6 | ||||
-rw-r--r-- | src/lib/libssl/tls13_internal.h | 32 | ||||
-rw-r--r-- | src/lib/libssl/tls13_record_layer.c | 758 |
3 files changed, 790 insertions, 6 deletions
diff --git a/src/lib/libssl/Makefile b/src/lib/libssl/Makefile index b835d3f5ae..d23aaa7249 100644 --- a/src/lib/libssl/Makefile +++ b/src/lib/libssl/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: Makefile,v 1.48 2019/01/19 04:08:06 jsing Exp $ | 1 | # $OpenBSD: Makefile,v 1.49 2019/01/20 10:31:54 jsing Exp $ |
2 | 2 | ||
3 | .include <bsd.own.mk> | 3 | .include <bsd.own.mk> |
4 | .ifndef NOMAN | 4 | .ifndef NOMAN |
@@ -16,7 +16,6 @@ CFLAGS+= -Wall -Wundef | |||
16 | CFLAGS+= -Werror | 16 | CFLAGS+= -Werror |
17 | .endif | 17 | .endif |
18 | CFLAGS+= -DLIBRESSL_INTERNAL | 18 | CFLAGS+= -DLIBRESSL_INTERNAL |
19 | |||
20 | CFLAGS+= -I${.CURDIR} | 19 | CFLAGS+= -I${.CURDIR} |
21 | 20 | ||
22 | LDADD+= -L${BSDOBJDIR}/lib/libcrypto -lcrypto | 21 | LDADD+= -L${BSDOBJDIR}/lib/libcrypto -lcrypto |
@@ -65,7 +64,8 @@ SRCS= \ | |||
65 | tls13_buffer.c \ | 64 | tls13_buffer.c \ |
66 | tls13_handshake.c \ | 65 | tls13_handshake.c \ |
67 | tls13_key_schedule.c \ | 66 | tls13_key_schedule.c \ |
68 | tls13_record.c | 67 | tls13_record.c \ |
68 | tls13_record_layer.c | ||
69 | 69 | ||
70 | HDRS= dtls1.h srtp.h ssl.h ssl2.h ssl23.h ssl3.h tls1.h | 70 | HDRS= dtls1.h srtp.h ssl.h ssl2.h ssl23.h ssl3.h tls1.h |
71 | 71 | ||
diff --git a/src/lib/libssl/tls13_internal.h b/src/lib/libssl/tls13_internal.h index 876f339c80..496627c0cd 100644 --- a/src/lib/libssl/tls13_internal.h +++ b/src/lib/libssl/tls13_internal.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls13_internal.h,v 1.8 2019/01/19 03:32:03 jsing Exp $ */ | 1 | /* $OpenBSD: tls13_internal.h,v 1.9 2019/01/20 10:31:54 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2018 Bob Beck <beck@openbsd.org> | 3 | * Copyright (c) 2018 Bob Beck <beck@openbsd.org> |
4 | * Copyright (c) 2018 Theo Buehler <tb@openbsd.org> | 4 | * Copyright (c) 2018 Theo Buehler <tb@openbsd.org> |
@@ -31,8 +31,12 @@ __BEGIN_HIDDEN_DECLS | |||
31 | #define TLS13_IO_WANT_POLLIN -2 | 31 | #define TLS13_IO_WANT_POLLIN -2 |
32 | #define TLS13_IO_WANT_POLLOUT -3 | 32 | #define TLS13_IO_WANT_POLLOUT -3 |
33 | 33 | ||
34 | typedef int (*tls13_alert_cb)(uint8_t _alert_level, uint8_t _alert_desc, | ||
35 | void *_cb_arg); | ||
36 | typedef int (*tls13_post_handshake_cb)(void *_cb_arg); | ||
34 | typedef ssize_t (*tls13_read_cb)(void *_buf, size_t _buflen, void *_cb_arg); | 37 | typedef ssize_t (*tls13_read_cb)(void *_buf, size_t _buflen, void *_cb_arg); |
35 | typedef ssize_t (*tls13_write_cb)(const void *_buf, size_t _buflen, void *_cb_arg); | 38 | typedef ssize_t (*tls13_write_cb)(const void *_buf, size_t _buflen, |
39 | void *_cb_arg); | ||
36 | 40 | ||
37 | struct tls13_buffer; | 41 | struct tls13_buffer; |
38 | 42 | ||
@@ -41,7 +45,8 @@ void tls13_buffer_free(struct tls13_buffer *buf); | |||
41 | ssize_t tls13_buffer_extend(struct tls13_buffer *buf, size_t len, | 45 | ssize_t tls13_buffer_extend(struct tls13_buffer *buf, size_t len, |
42 | tls13_read_cb read_cb, void *cb_arg); | 46 | tls13_read_cb read_cb, void *cb_arg); |
43 | void tls13_buffer_cbs(struct tls13_buffer *buf, CBS *cbs); | 47 | void tls13_buffer_cbs(struct tls13_buffer *buf, CBS *cbs); |
44 | int tls13_buffer_finish(struct tls13_buffer *buf, uint8_t **out, size_t *out_len); | 48 | int tls13_buffer_finish(struct tls13_buffer *buf, uint8_t **out, |
49 | size_t *out_len); | ||
45 | 50 | ||
46 | struct tls13_secret { | 51 | struct tls13_secret { |
47 | uint8_t *data; | 52 | uint8_t *data; |
@@ -92,6 +97,27 @@ int tls13_derive_application_secrets(struct tls13_secrets *secrets, | |||
92 | 97 | ||
93 | struct tls13_ctx; | 98 | struct tls13_ctx; |
94 | 99 | ||
100 | struct tls13_record_layer; | ||
101 | |||
102 | struct tls13_record_layer *tls13_record_layer_new(tls13_read_cb wire_read, | ||
103 | tls13_write_cb wire_write, tls13_alert_cb alert_cb, | ||
104 | tls13_post_handshake_cb post_handshake_cb, void *cb_arg); | ||
105 | void tls13_record_layer_free(struct tls13_record_layer *rl); | ||
106 | void tls13_record_layer_set_aead(struct tls13_record_layer *rl, | ||
107 | const EVP_AEAD *aead); | ||
108 | void tls13_record_layer_set_hash(struct tls13_record_layer *rl, | ||
109 | const EVP_MD *hash); | ||
110 | void tls13_record_layer_handshake_completed(struct tls13_record_layer *rl); | ||
111 | int tls13_record_layer_set_traffic_keys(struct tls13_record_layer *rl, | ||
112 | struct tls13_secret *read_key, struct tls13_secret *write_key); | ||
113 | |||
114 | ssize_t tls13_read_handshake_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n); | ||
115 | ssize_t tls13_write_handshake_data(struct tls13_record_layer *rl, const uint8_t *buf, | ||
116 | size_t n); | ||
117 | ssize_t tls13_read_application_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n); | ||
118 | ssize_t tls13_write_application_data(struct tls13_record_layer *rl, const uint8_t *buf, | ||
119 | size_t n); | ||
120 | |||
95 | /* | 121 | /* |
96 | * RFC 8446, Section B.3 | 122 | * RFC 8446, Section B.3 |
97 | * | 123 | * |
diff --git a/src/lib/libssl/tls13_record_layer.c b/src/lib/libssl/tls13_record_layer.c new file mode 100644 index 0000000000..b70f9f174e --- /dev/null +++ b/src/lib/libssl/tls13_record_layer.c | |||
@@ -0,0 +1,758 @@ | |||
1 | /* $OpenBSD: tls13_record_layer.c,v 1.1 2019/01/20 10:31:54 jsing Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> | ||
4 | * | ||
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 | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include "ssl_locl.h" | ||
19 | |||
20 | #include <openssl/curve25519.h> | ||
21 | |||
22 | #include "tls13_internal.h" | ||
23 | #include "tls13_record.h" | ||
24 | |||
25 | struct tls13_record_layer { | ||
26 | int change_cipher_spec_seen; | ||
27 | int handshake_completed; | ||
28 | |||
29 | struct tls13_record *rrec; | ||
30 | struct tls13_record *wrec; | ||
31 | |||
32 | /* Buffer containing plaintext from opened records. */ | ||
33 | uint8_t rbuf_content_type; | ||
34 | uint8_t *rbuf; | ||
35 | size_t rbuf_len; | ||
36 | CBS rbuf_cbs; | ||
37 | |||
38 | /* Record protection. */ | ||
39 | const EVP_MD *hash; | ||
40 | const EVP_AEAD *aead; | ||
41 | EVP_AEAD_CTX read_aead_ctx; | ||
42 | EVP_AEAD_CTX write_aead_ctx; | ||
43 | struct tls13_secret read_iv; | ||
44 | struct tls13_secret write_iv; | ||
45 | struct tls13_secret read_nonce; | ||
46 | struct tls13_secret write_nonce; | ||
47 | uint8_t read_seq_num[TLS13_RECORD_SEQ_NUM_LEN]; | ||
48 | uint8_t write_seq_num[TLS13_RECORD_SEQ_NUM_LEN]; | ||
49 | |||
50 | /* Record callbacks. */ | ||
51 | tls13_alert_cb alert_cb; | ||
52 | tls13_post_handshake_cb post_handshake_cb; | ||
53 | |||
54 | /* Wire read/write callbacks. */ | ||
55 | tls13_read_cb wire_read; | ||
56 | tls13_write_cb wire_write; | ||
57 | void *cb_arg; | ||
58 | }; | ||
59 | |||
60 | static void | ||
61 | tls13_record_layer_rbuf_free(struct tls13_record_layer *rl) | ||
62 | { | ||
63 | CBS_init(&rl->rbuf_cbs, NULL, 0); | ||
64 | freezero(rl->rbuf, rl->rbuf_len); | ||
65 | rl->rbuf = NULL; | ||
66 | rl->rbuf_len = 0; | ||
67 | rl->rbuf_content_type = 0; | ||
68 | } | ||
69 | |||
70 | static void | ||
71 | tls13_record_layer_rrec_free(struct tls13_record_layer *rl) | ||
72 | { | ||
73 | tls13_record_free(rl->rrec); | ||
74 | rl->rrec = NULL; | ||
75 | } | ||
76 | |||
77 | static void | ||
78 | tls13_record_layer_wrec_free(struct tls13_record_layer *rl) | ||
79 | { | ||
80 | tls13_record_free(rl->wrec); | ||
81 | rl->wrec = NULL; | ||
82 | } | ||
83 | |||
84 | struct tls13_record_layer * | ||
85 | tls13_record_layer_new(tls13_read_cb wire_read, tls13_write_cb wire_write, | ||
86 | tls13_alert_cb alert_cb, tls13_post_handshake_cb post_handshake_cb, | ||
87 | void *cb_arg) | ||
88 | { | ||
89 | struct tls13_record_layer *rl; | ||
90 | |||
91 | if ((rl = calloc(1, sizeof(struct tls13_record_layer))) == NULL) | ||
92 | return NULL; | ||
93 | |||
94 | rl->wire_read = wire_read; | ||
95 | rl->wire_write = wire_write; | ||
96 | rl->alert_cb = alert_cb; | ||
97 | rl->post_handshake_cb = post_handshake_cb; | ||
98 | rl->cb_arg = cb_arg; | ||
99 | |||
100 | return rl; | ||
101 | } | ||
102 | |||
103 | void | ||
104 | tls13_record_layer_free(struct tls13_record_layer *rl) | ||
105 | { | ||
106 | if (rl == NULL) | ||
107 | return; | ||
108 | |||
109 | tls13_record_layer_rbuf_free(rl); | ||
110 | |||
111 | tls13_record_layer_rrec_free(rl); | ||
112 | tls13_record_layer_wrec_free(rl); | ||
113 | |||
114 | EVP_AEAD_CTX_cleanup(&rl->read_aead_ctx); | ||
115 | EVP_AEAD_CTX_cleanup(&rl->write_aead_ctx); | ||
116 | |||
117 | freezero(rl->read_iv.data, rl->read_iv.len); | ||
118 | freezero(rl->write_iv.data, rl->write_iv.len); | ||
119 | freezero(rl->read_nonce.data, rl->read_nonce.len); | ||
120 | freezero(rl->write_nonce.data, rl->write_nonce.len); | ||
121 | |||
122 | freezero(rl, sizeof(struct tls13_record_layer)); | ||
123 | } | ||
124 | |||
125 | static int | ||
126 | tls13_record_layer_inc_seq_num(uint8_t *seq_num) | ||
127 | { | ||
128 | size_t i; | ||
129 | |||
130 | for (i = TLS13_RECORD_SEQ_NUM_LEN - 1; i > 0; i--) { | ||
131 | if (++seq_num[i] != 0) | ||
132 | break; | ||
133 | } | ||
134 | |||
135 | /* RFC 8446 section 5.3 - sequence numbers must not wrap. */ | ||
136 | return (i != 0 || seq_num[0] != 0); | ||
137 | } | ||
138 | |||
139 | static int | ||
140 | tls13_record_layer_update_nonce(struct tls13_secret *nonce, | ||
141 | struct tls13_secret *iv, uint8_t *seq_num) | ||
142 | { | ||
143 | ssize_t i, j; | ||
144 | |||
145 | if (nonce->len != iv->len) | ||
146 | return 0; | ||
147 | |||
148 | /* | ||
149 | * RFC 8446 section 5.3 - sequence number is zero padded and XOR'd | ||
150 | * with the IV to produce a per-record nonce. The IV will also be | ||
151 | * at least 8-bytes in length. | ||
152 | */ | ||
153 | for (i = nonce->len - 1, j = TLS13_RECORD_SEQ_NUM_LEN - 1; i >= 0; i--, j--) | ||
154 | nonce->data[i] = iv->data[i] ^ (j >= 0 ? seq_num[j] : 0); | ||
155 | |||
156 | return 1; | ||
157 | } | ||
158 | |||
159 | void | ||
160 | tls13_record_layer_set_aead(struct tls13_record_layer *rl, | ||
161 | const EVP_AEAD *aead) | ||
162 | { | ||
163 | rl->aead = aead; | ||
164 | } | ||
165 | |||
166 | void | ||
167 | tls13_record_layer_set_hash(struct tls13_record_layer *rl, | ||
168 | const EVP_MD *hash) | ||
169 | { | ||
170 | rl->hash = hash; | ||
171 | } | ||
172 | |||
173 | void | ||
174 | tls13_record_layer_handshake_completed(struct tls13_record_layer *rl) | ||
175 | { | ||
176 | rl->handshake_completed = 1; | ||
177 | } | ||
178 | |||
179 | static int | ||
180 | tls13_record_layer_process_alert(struct tls13_record_layer *rl) | ||
181 | { | ||
182 | uint8_t alert_level, alert_desc; | ||
183 | |||
184 | /* | ||
185 | * A TLSv1.3 alert record can only contain a single alert - this means | ||
186 | * that processing the alert must consume all of the record. The alert | ||
187 | * will result in one of three things - continuation (user_cancelled), | ||
188 | * read channel closure (close_notify) or termination (all others). | ||
189 | */ | ||
190 | if (rl->rbuf == NULL) | ||
191 | return -1; | ||
192 | if (rl->rbuf_content_type != SSL3_RT_ALERT) | ||
193 | return -1; | ||
194 | |||
195 | if (!CBS_get_u8(&rl->rbuf_cbs, &alert_level)) | ||
196 | return -1; /* XXX - decode error alert. */ | ||
197 | if (!CBS_get_u8(&rl->rbuf_cbs, &alert_desc)) | ||
198 | return -1; /* XXX - decode error alert. */ | ||
199 | |||
200 | if (CBS_len(&rl->rbuf_cbs) != 0) | ||
201 | return -1; | ||
202 | |||
203 | tls13_record_layer_rbuf_free(rl); | ||
204 | |||
205 | return rl->alert_cb(alert_level, alert_desc, rl->cb_arg); | ||
206 | } | ||
207 | |||
208 | int | ||
209 | tls13_record_layer_send_alert(struct tls13_record_layer *rl, | ||
210 | uint8_t alert_level, uint8_t alert_desc) | ||
211 | { | ||
212 | /* XXX - implement. */ | ||
213 | return -1; | ||
214 | } | ||
215 | |||
216 | static int | ||
217 | tls13_record_layer_set_traffic_key(const EVP_AEAD *aead, EVP_AEAD_CTX *aead_ctx, | ||
218 | const EVP_MD *hash, struct tls13_secret *iv, struct tls13_secret *nonce, | ||
219 | struct tls13_secret *traffic_key) | ||
220 | { | ||
221 | struct tls13_secret context = { .data = "", .len = 0 }; | ||
222 | struct tls13_secret key = { .data = NULL, .len = 0 }; | ||
223 | int ret = 0; | ||
224 | |||
225 | freezero(iv->data, iv->len); | ||
226 | iv->data = NULL; | ||
227 | iv->len = 0; | ||
228 | |||
229 | freezero(nonce->data, nonce->len); | ||
230 | nonce->data = NULL; | ||
231 | nonce->len = 0; | ||
232 | |||
233 | if ((iv->data = calloc(1, EVP_AEAD_nonce_length(aead))) == NULL) | ||
234 | goto err; | ||
235 | iv->len = EVP_AEAD_nonce_length(aead); | ||
236 | |||
237 | if ((nonce->data = calloc(1, EVP_AEAD_nonce_length(aead))) == NULL) | ||
238 | goto err; | ||
239 | nonce->len = EVP_AEAD_nonce_length(aead); | ||
240 | |||
241 | if ((key.data = calloc(1, EVP_AEAD_key_length(aead))) == NULL) | ||
242 | goto err; | ||
243 | key.len = EVP_AEAD_key_length(aead); | ||
244 | |||
245 | if (!tls13_hkdf_expand_label(iv, hash, traffic_key, "iv", &context)) | ||
246 | goto err; | ||
247 | if (!tls13_hkdf_expand_label(&key, hash, traffic_key, "key", &context)) | ||
248 | goto err; | ||
249 | |||
250 | if (!EVP_AEAD_CTX_init(aead_ctx, aead, key.data, key.len, | ||
251 | EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) | ||
252 | goto err; | ||
253 | |||
254 | ret = 1; | ||
255 | |||
256 | err: | ||
257 | freezero(key.data, key.len); | ||
258 | |||
259 | return ret; | ||
260 | } | ||
261 | |||
262 | int | ||
263 | tls13_record_layer_set_traffic_keys(struct tls13_record_layer *rl, | ||
264 | struct tls13_secret *read_key, struct tls13_secret *write_key) | ||
265 | { | ||
266 | memset(rl->read_seq_num, 0, TLS13_RECORD_SEQ_NUM_LEN); | ||
267 | memset(rl->write_seq_num, 0, TLS13_RECORD_SEQ_NUM_LEN); | ||
268 | |||
269 | if (!tls13_record_layer_set_traffic_key(rl->aead, &rl->read_aead_ctx, | ||
270 | rl->hash, &rl->read_iv, &rl->read_nonce, read_key)) | ||
271 | return 0; | ||
272 | |||
273 | if (!tls13_record_layer_set_traffic_key(rl->aead, &rl->write_aead_ctx, | ||
274 | rl->hash, &rl->write_iv, &rl->write_nonce, write_key)) | ||
275 | return 0; | ||
276 | |||
277 | return 1; | ||
278 | } | ||
279 | |||
280 | static int | ||
281 | tls13_record_layer_open_record_plaintext(struct tls13_record_layer *rl) | ||
282 | { | ||
283 | CBS cbs; | ||
284 | |||
285 | if (rl->aead != NULL) | ||
286 | return 0; | ||
287 | |||
288 | /* | ||
289 | * We're still operating in plaintext mode, so just copy the | ||
290 | * content from the record to the plaintext buffer. | ||
291 | */ | ||
292 | if (!tls13_record_content(rl->rrec, &cbs)) | ||
293 | return 0; | ||
294 | |||
295 | tls13_record_layer_rbuf_free(rl); | ||
296 | |||
297 | if (!CBS_stow(&cbs, &rl->rbuf, &rl->rbuf_len)) | ||
298 | return 0; | ||
299 | |||
300 | rl->rbuf_content_type = tls13_record_content_type(rl->rrec); | ||
301 | |||
302 | CBS_init(&rl->rbuf_cbs, rl->rbuf, rl->rbuf_len); | ||
303 | |||
304 | return 1; | ||
305 | } | ||
306 | |||
307 | static int | ||
308 | tls13_record_layer_open_record_protected(struct tls13_record_layer *rl) | ||
309 | { | ||
310 | CBS header, enc_record; | ||
311 | uint8_t *content = NULL; | ||
312 | ssize_t content_len = 0; | ||
313 | uint8_t content_type; | ||
314 | size_t out_len; | ||
315 | |||
316 | if (rl->aead == NULL) | ||
317 | goto err; | ||
318 | |||
319 | if (!tls13_record_header(rl->rrec, &header)) | ||
320 | goto err; | ||
321 | if (!tls13_record_content(rl->rrec, &enc_record)) | ||
322 | goto err; | ||
323 | |||
324 | if ((content = calloc(1, CBS_len(&enc_record))) == NULL) | ||
325 | goto err; | ||
326 | content_len = CBS_len(&enc_record); | ||
327 | |||
328 | if (!tls13_record_layer_update_nonce(&rl->read_nonce, &rl->read_iv, | ||
329 | rl->read_seq_num)) | ||
330 | goto err; | ||
331 | |||
332 | if (!EVP_AEAD_CTX_open(&rl->read_aead_ctx, | ||
333 | content, &out_len, content_len, | ||
334 | rl->read_nonce.data, rl->read_nonce.len, | ||
335 | CBS_data(&enc_record), CBS_len(&enc_record), | ||
336 | CBS_data(&header), CBS_len(&header))) | ||
337 | goto err; | ||
338 | |||
339 | if (!tls13_record_layer_inc_seq_num(rl->read_seq_num)) | ||
340 | goto err; | ||
341 | |||
342 | /* | ||
343 | * The real content type is hidden at the end of the record content and | ||
344 | * it may be followed by padding that consists of one or more zeroes. | ||
345 | * Time to hunt for that elusive content type! | ||
346 | */ | ||
347 | /* XXX - CBS from end? CBS_get_end_u8()? */ | ||
348 | content_len = out_len - 1; | ||
349 | while (content_len >= 0 && content[content_len] == 0) | ||
350 | content_len--; | ||
351 | if (content_len < 0) | ||
352 | goto err; | ||
353 | content_type = content[content_len]; | ||
354 | |||
355 | tls13_record_layer_rbuf_free(rl); | ||
356 | |||
357 | rl->rbuf_content_type = content_type; | ||
358 | rl->rbuf = content; | ||
359 | rl->rbuf_len = content_len; | ||
360 | |||
361 | CBS_init(&rl->rbuf_cbs, rl->rbuf, rl->rbuf_len); | ||
362 | |||
363 | return 1; | ||
364 | |||
365 | err: | ||
366 | freezero(content, content_len); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int | ||
372 | tls13_record_layer_open_record(struct tls13_record_layer *rl) | ||
373 | { | ||
374 | if (rl->aead == NULL) | ||
375 | return tls13_record_layer_open_record_plaintext(rl); | ||
376 | |||
377 | return tls13_record_layer_open_record_protected(rl); | ||
378 | } | ||
379 | |||
380 | static int | ||
381 | tls13_record_layer_seal_record_plaintext(struct tls13_record_layer *rl, | ||
382 | uint8_t content_type, const uint8_t *content, size_t content_len) | ||
383 | { | ||
384 | uint8_t *data = NULL; | ||
385 | size_t data_len = 0; | ||
386 | uint16_t version; | ||
387 | CBB cbb, body; | ||
388 | |||
389 | if (rl->aead != NULL) | ||
390 | return 0; | ||
391 | |||
392 | /* XXX - TLS1_VERSION for first client hello... */ | ||
393 | version = TLS1_2_VERSION; | ||
394 | |||
395 | /* | ||
396 | * We're still operating in plaintext mode, so just copy the | ||
397 | * content into the record. | ||
398 | */ | ||
399 | if (!CBB_init(&cbb, TLS13_RECORD_HEADER_LEN + content_len)) | ||
400 | goto err; | ||
401 | |||
402 | if (!CBB_add_u8(&cbb, content_type)) | ||
403 | goto err; | ||
404 | if (!CBB_add_u16(&cbb, version)) | ||
405 | goto err; | ||
406 | if (!CBB_add_u16_length_prefixed(&cbb, &body)) | ||
407 | goto err; | ||
408 | if (!CBB_add_bytes(&body, content, content_len)) | ||
409 | goto err; | ||
410 | |||
411 | if (!CBB_finish(&cbb, &data, &data_len)) | ||
412 | goto err; | ||
413 | |||
414 | if (!tls13_record_set_data(rl->wrec, data, data_len)) | ||
415 | goto err; | ||
416 | |||
417 | return 1; | ||
418 | |||
419 | err: | ||
420 | CBB_cleanup(&cbb); | ||
421 | freezero(data, data_len); | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static int | ||
427 | tls13_record_layer_seal_record_protected(struct tls13_record_layer *rl, | ||
428 | uint8_t content_type, const uint8_t *content, size_t content_len) | ||
429 | { | ||
430 | uint8_t *data = NULL, *header = NULL, *inner = NULL; | ||
431 | size_t data_len = 0, header_len = 0, inner_len = 0; | ||
432 | uint8_t *enc_record; | ||
433 | size_t enc_record_len; | ||
434 | ssize_t ret = 0; | ||
435 | size_t out_len; | ||
436 | CBB cbb; | ||
437 | |||
438 | if (rl->aead == NULL) | ||
439 | return 0; | ||
440 | |||
441 | memset(&cbb, 0, sizeof(cbb)); | ||
442 | |||
443 | /* Build inner plaintext. */ | ||
444 | if (!CBB_init(&cbb, content_len + 1)) | ||
445 | goto err; | ||
446 | if (!CBB_add_bytes(&cbb, content, content_len)) | ||
447 | goto err; | ||
448 | if (!CBB_add_u8(&cbb, content_type)) | ||
449 | goto err; | ||
450 | /* XXX - padding? */ | ||
451 | if (!CBB_finish(&cbb, &inner, &inner_len)) | ||
452 | goto err; | ||
453 | |||
454 | if (inner_len > TLS13_RECORD_MAX_INNER_PLAINTEXT_LEN) | ||
455 | goto err; | ||
456 | |||
457 | /* XXX EVP_AEAD_max_tag_len vs EVP_AEAD_CTX_tag_len. */ | ||
458 | enc_record_len = inner_len + EVP_AEAD_max_tag_len(rl->aead); | ||
459 | if (enc_record_len > TLS13_RECORD_MAX_CIPHERTEXT_LEN) | ||
460 | goto err; | ||
461 | |||
462 | /* Build the record header. */ | ||
463 | if (!CBB_init(&cbb, TLS13_RECORD_HEADER_LEN)) | ||
464 | goto err; | ||
465 | if (!CBB_add_u8(&cbb, SSL3_RT_APPLICATION_DATA)) | ||
466 | goto err; | ||
467 | if (!CBB_add_u16(&cbb, TLS1_2_VERSION)) | ||
468 | goto err; | ||
469 | if (!CBB_add_u16(&cbb, enc_record_len)) | ||
470 | goto err; | ||
471 | if (!CBB_finish(&cbb, &header, &header_len)) | ||
472 | goto err; | ||
473 | |||
474 | /* Build the actual record. */ | ||
475 | if (!CBB_init(&cbb, TLS13_RECORD_HEADER_LEN + enc_record_len)) | ||
476 | goto err; | ||
477 | if (!CBB_add_bytes(&cbb, header, header_len)) | ||
478 | goto err; | ||
479 | if (!CBB_add_space(&cbb, &enc_record, enc_record_len)) | ||
480 | goto err; | ||
481 | if (!CBB_finish(&cbb, &data, &data_len)) | ||
482 | goto err; | ||
483 | |||
484 | if (!tls13_record_layer_update_nonce(&rl->write_nonce, | ||
485 | &rl->write_iv, rl->write_seq_num)) | ||
486 | goto err; | ||
487 | |||
488 | /* | ||
489 | * XXX - consider a EVP_AEAD_CTX_seal_iov() that takes an iovec... | ||
490 | * this would avoid a copy since the inner would be passed as two | ||
491 | * separate pieces. | ||
492 | */ | ||
493 | if (!EVP_AEAD_CTX_seal(&rl->write_aead_ctx, | ||
494 | enc_record, &out_len, enc_record_len, | ||
495 | rl->write_nonce.data, rl->write_nonce.len, | ||
496 | inner, inner_len, header, header_len)) | ||
497 | goto err; | ||
498 | |||
499 | if (out_len != enc_record_len) | ||
500 | goto err; | ||
501 | |||
502 | if (!tls13_record_layer_inc_seq_num(rl->write_seq_num)) | ||
503 | goto err; | ||
504 | |||
505 | if (!tls13_record_set_data(rl->wrec, data, data_len)) | ||
506 | goto err; | ||
507 | |||
508 | data = NULL; | ||
509 | data_len = 0; | ||
510 | |||
511 | ret = 1; | ||
512 | |||
513 | err: | ||
514 | CBB_cleanup(&cbb); | ||
515 | |||
516 | freezero(data, data_len); | ||
517 | freezero(header, header_len); | ||
518 | freezero(inner, inner_len); | ||
519 | |||
520 | return ret; | ||
521 | } | ||
522 | |||
523 | static int | ||
524 | tls13_record_layer_seal_record(struct tls13_record_layer *rl, | ||
525 | uint8_t content_type, const uint8_t *content, size_t content_len) | ||
526 | { | ||
527 | tls13_record_layer_wrec_free(rl); | ||
528 | |||
529 | if ((rl->wrec = tls13_record_new()) == NULL) | ||
530 | return 0; | ||
531 | |||
532 | if (rl->aead == NULL) | ||
533 | return tls13_record_layer_seal_record_plaintext(rl, | ||
534 | content_type, content, content_len); | ||
535 | |||
536 | return tls13_record_layer_seal_record_protected(rl, content_type, | ||
537 | content, content_len); | ||
538 | } | ||
539 | |||
540 | static ssize_t | ||
541 | tls13_record_layer_read_record(struct tls13_record_layer *rl) | ||
542 | { | ||
543 | uint8_t content_type, ccs; | ||
544 | ssize_t ret; | ||
545 | CBS cbs; | ||
546 | |||
547 | again: /* XXX */ | ||
548 | |||
549 | if (rl->rrec == NULL) { | ||
550 | if ((rl->rrec = tls13_record_new()) == NULL) | ||
551 | goto err; | ||
552 | } | ||
553 | |||
554 | if ((ret = tls13_record_recv(rl->rrec, rl->wire_read, rl->cb_arg)) <= 0) | ||
555 | return ret; | ||
556 | |||
557 | /* XXX - record version checks. */ | ||
558 | |||
559 | content_type = tls13_record_content_type(rl->rrec); | ||
560 | |||
561 | /* | ||
562 | * Bag of hacks ahead... after the first ClientHello message has been | ||
563 | * sent or received and before the peer's Finished message has been | ||
564 | * received, we may receive an unencrypted ChangeCipherSpec record | ||
565 | * (see RFC 8446 section 5 and appendix D.4). This record must be | ||
566 | * ignored. | ||
567 | */ | ||
568 | if (content_type == SSL3_RT_CHANGE_CIPHER_SPEC) { | ||
569 | /* XXX - need to check after ClientHello, before Finished. */ | ||
570 | if (rl->handshake_completed || rl->change_cipher_spec_seen) { | ||
571 | /* XXX - unexpected message alert. */ | ||
572 | goto err; | ||
573 | } | ||
574 | if (!tls13_record_content(rl->rrec, &cbs)) { | ||
575 | /* XXX - decode error alert. */ | ||
576 | goto err; | ||
577 | } | ||
578 | if (!CBS_get_u8(&cbs, &ccs)) { | ||
579 | /* XXX - decode error alert. */ | ||
580 | goto err; | ||
581 | } | ||
582 | if (ccs != 1) { | ||
583 | /* XXX - something alert. */ | ||
584 | goto err; | ||
585 | } | ||
586 | rl->change_cipher_spec_seen = 1; | ||
587 | tls13_record_layer_rrec_free(rl); | ||
588 | goto again; /* XXX */ | ||
589 | } | ||
590 | |||
591 | /* | ||
592 | * Once record protection is engaged, we should only receive | ||
593 | * protected application data messages (aside from the | ||
594 | * dummy ChangeCipherSpec messages, handled above). | ||
595 | */ | ||
596 | if (rl->aead != NULL && content_type != SSL3_RT_APPLICATION_DATA) { | ||
597 | /* XXX - unexpected message alert. */ | ||
598 | goto err; | ||
599 | } | ||
600 | |||
601 | if (!tls13_record_layer_open_record(rl)) | ||
602 | goto err; | ||
603 | |||
604 | tls13_record_layer_rrec_free(rl); | ||
605 | |||
606 | switch (rl->rbuf_content_type) { | ||
607 | case SSL3_RT_ALERT: | ||
608 | return tls13_record_layer_process_alert(rl); | ||
609 | |||
610 | case SSL3_RT_HANDSHAKE: | ||
611 | break; | ||
612 | |||
613 | case SSL3_RT_APPLICATION_DATA: | ||
614 | if (!rl->handshake_completed) { | ||
615 | /* XXX - unexpected message alert. */ | ||
616 | goto err; | ||
617 | } | ||
618 | break; | ||
619 | |||
620 | default: | ||
621 | /* XXX - unexpected message alert. */ | ||
622 | goto err; | ||
623 | } | ||
624 | |||
625 | return TLS13_IO_SUCCESS; | ||
626 | |||
627 | err: | ||
628 | return TLS13_IO_FAILURE; | ||
629 | } | ||
630 | |||
631 | ssize_t | ||
632 | tls13_record_layer_read(struct tls13_record_layer *rl, uint8_t content_type, | ||
633 | uint8_t *buf, size_t n) | ||
634 | { | ||
635 | int ret; | ||
636 | |||
637 | /* XXX - loop here with record and byte limits. */ | ||
638 | /* XXX - send alert... */ | ||
639 | |||
640 | again: /* XXX */ | ||
641 | |||
642 | /* If necessary, pull up the next record. */ | ||
643 | if (CBS_len(&rl->rbuf_cbs) == 0) { | ||
644 | if ((ret = tls13_record_layer_read_record(rl)) <= 0) | ||
645 | return ret; | ||
646 | |||
647 | /* XXX - need to check record version. */ | ||
648 | } | ||
649 | if (rl->rbuf_content_type != content_type) { | ||
650 | /* | ||
651 | * Handshake content can appear as post-handshake messages (yup, | ||
652 | * the RFC reused the same content type...), which means we can | ||
653 | * be trying to read application data and need to handle a | ||
654 | * post-handshake handshake message instead... | ||
655 | */ | ||
656 | if (rl->rbuf_content_type == SSL3_RT_HANDSHAKE) { | ||
657 | if (rl->handshake_completed) { | ||
658 | /* XXX - call callback, drop for now... */ | ||
659 | tls13_record_layer_rbuf_free(rl); | ||
660 | goto again; | ||
661 | } | ||
662 | } | ||
663 | |||
664 | /* XXX - unexpected message alert. */ | ||
665 | goto err; | ||
666 | } | ||
667 | |||
668 | if (n > CBS_len(&rl->rbuf_cbs)) | ||
669 | n = CBS_len(&rl->rbuf_cbs); | ||
670 | |||
671 | /* XXX - CBS_memcpy? CBS_copy_bytes? */ | ||
672 | memcpy(buf, CBS_data(&rl->rbuf_cbs), n); | ||
673 | if (!CBS_skip(&rl->rbuf_cbs, n)) | ||
674 | goto err; | ||
675 | |||
676 | if (CBS_len(&rl->rbuf_cbs) == 0) | ||
677 | tls13_record_layer_rbuf_free(rl); | ||
678 | |||
679 | return n; | ||
680 | |||
681 | err: | ||
682 | return TLS13_IO_FAILURE; | ||
683 | } | ||
684 | |||
685 | static ssize_t | ||
686 | tls13_record_layer_write_record(struct tls13_record_layer *rl, | ||
687 | uint8_t content_type, const uint8_t *content, size_t content_len) | ||
688 | { | ||
689 | ssize_t ret; | ||
690 | |||
691 | /* See if there is an existing record and attempt to push it out... */ | ||
692 | if (rl->wrec != NULL) { | ||
693 | if ((ret = tls13_record_send(rl->wrec, rl->wire_write, | ||
694 | rl->cb_arg)) <= 0) | ||
695 | return ret; | ||
696 | |||
697 | tls13_record_layer_wrec_free(rl); | ||
698 | |||
699 | /* XXX - could be pushing out different data... */ | ||
700 | return content_len; | ||
701 | } | ||
702 | |||
703 | if (content_len > TLS13_RECORD_MAX_PLAINTEXT_LEN) | ||
704 | goto err; | ||
705 | |||
706 | if (!tls13_record_layer_seal_record(rl, content_type, content, content_len)) | ||
707 | goto err; | ||
708 | |||
709 | if ((ret = tls13_record_send(rl->wrec, rl->wire_write, rl->cb_arg)) <= 0) | ||
710 | return ret; | ||
711 | |||
712 | tls13_record_layer_wrec_free(rl); | ||
713 | |||
714 | return content_len; | ||
715 | |||
716 | err: | ||
717 | return TLS13_IO_FAILURE; | ||
718 | } | ||
719 | |||
720 | static ssize_t | ||
721 | tls13_record_layer_write(struct tls13_record_layer *rl, uint8_t content_type, | ||
722 | const uint8_t *buf, size_t n) | ||
723 | { | ||
724 | /* XXX - handle fragmenting... */ | ||
725 | return tls13_record_layer_write_record(rl, content_type, buf, n); | ||
726 | } | ||
727 | |||
728 | ssize_t | ||
729 | tls13_read_handshake_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n) | ||
730 | { | ||
731 | return tls13_record_layer_read(rl, SSL3_RT_HANDSHAKE, buf, n); | ||
732 | } | ||
733 | |||
734 | ssize_t | ||
735 | tls13_write_handshake_data(struct tls13_record_layer *rl, const uint8_t *buf, | ||
736 | size_t n) | ||
737 | { | ||
738 | return tls13_record_layer_write(rl, SSL3_RT_HANDSHAKE, buf, n); | ||
739 | } | ||
740 | |||
741 | ssize_t | ||
742 | tls13_read_application_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n) | ||
743 | { | ||
744 | if (!rl->handshake_completed) | ||
745 | return TLS13_IO_FAILURE; | ||
746 | |||
747 | return tls13_record_layer_read(rl, SSL3_RT_APPLICATION_DATA, buf, n); | ||
748 | } | ||
749 | |||
750 | ssize_t | ||
751 | tls13_write_application_data(struct tls13_record_layer *rl, const uint8_t *buf, | ||
752 | size_t n) | ||
753 | { | ||
754 | if (!rl->handshake_completed) | ||
755 | return TLS13_IO_FAILURE; | ||
756 | |||
757 | return tls13_record_layer_write(rl, SSL3_RT_APPLICATION_DATA, buf, n); | ||
758 | } | ||