diff options
Diffstat (limited to '')
| -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 | } | ||
