1 /* $OpenBSD: tls13_record.c,v 1.3 2019/01/21 00:24:19 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 { 26 uint16_t version; 27 uint8_t content_type; 28 size_t rec_len; 29 uint8_t *data; 30 size_t data_len; 31 CBS cbs; 32 33 struct tls13_buffer *buf; 34 }; 35 36 struct tls13_record * 37 tls13_record_new(void) 38 { 39 struct tls13_record *rec = NULL; 40 41 if ((rec = calloc(1, sizeof(struct tls13_record))) == NULL) 42 goto err; 43 if ((rec->buf = tls13_buffer_new(TLS13_RECORD_MAX_LEN)) == NULL) 44 goto err; 45 46 return rec; 47 48 err: 49 tls13_record_free(rec); 50 51 return NULL; 52 } 53 54 void 55 tls13_record_free(struct tls13_record *rec) 56 { 57 if (rec == NULL) 58 return; 59 60 tls13_buffer_free(rec->buf); 61 62 freezero(rec->data, rec->data_len); 63 freezero(rec, sizeof(struct tls13_record)); 64 } 65 66 uint16_t 67 tls13_record_version(struct tls13_record *rec) 68 { 69 return rec->version; 70 } 71 72 uint8_t 73 tls13_record_content_type(struct tls13_record *rec) 74 { 75 return rec->content_type; 76 } 77 78 int 79 tls13_record_header(struct tls13_record *rec, CBS *cbs) 80 { 81 if (rec->data_len < TLS13_RECORD_HEADER_LEN) 82 return 0; 83 84 CBS_init(cbs, rec->data, TLS13_RECORD_HEADER_LEN); 85 86 return 1; 87 } 88 89 int 90 tls13_record_content(struct tls13_record *rec, CBS *cbs) 91 { 92 CBS content; 93 94 tls13_record_data(rec, &content); 95 96 if (!CBS_skip(&content, TLS13_RECORD_HEADER_LEN)) 97 return 0; 98 99 CBS_dup(&content, cbs); 100 101 return 1; 102 } 103 104 void 105 tls13_record_data(struct tls13_record *rec, CBS *cbs) 106 { 107 CBS_init(cbs, rec->data, rec->data_len); 108 } 109 110 int 111 tls13_record_set_data(struct tls13_record *rec, uint8_t *data, size_t data_len) 112 { 113 if (data_len > TLS13_RECORD_MAX_LEN) 114 return 0; 115 116 freezero(rec->data, rec->data_len); 117 rec->data = data; 118 rec->data_len = data_len; 119 CBS_init(&rec->cbs, rec->data, rec->data_len); 120 121 return 1; 122 } 123 124 ssize_t 125 tls13_record_recv(struct tls13_record *rec, tls13_read_cb wire_read, 126 void *wire_arg) 127 { 128 uint16_t rec_len, rec_version; 129 uint8_t content_type; 130 ssize_t ret; 131 CBS cbs; 132 133 if (rec->data != NULL) 134 return TLS13_IO_FAILURE; 135 136 if (rec->content_type == 0) { 137 if ((ret = tls13_buffer_extend(rec->buf, 138 TLS13_RECORD_HEADER_LEN, wire_read, wire_arg)) <= 0) 139 return ret; 140 141 tls13_buffer_cbs(rec->buf, &cbs); 142 143 if (!CBS_get_u8(&cbs, &content_type)) 144 return TLS13_IO_FAILURE; 145 if (!CBS_get_u16(&cbs, &rec_version)) 146 return TLS13_IO_FAILURE; 147 if (!CBS_get_u16(&cbs, &rec_len)) 148 return TLS13_IO_FAILURE; 149 150 /* XXX - record overflow alert. */ 151 if (rec_len > TLS13_RECORD_MAX_CIPHERTEXT_LEN) 152 return TLS13_IO_FAILURE; 153 154 rec->content_type = content_type; 155 rec->version = rec_version; 156 rec->rec_len = rec_len; 157 } 158 159 if ((ret = tls13_buffer_extend(rec->buf, 160 TLS13_RECORD_HEADER_LEN + rec->rec_len, wire_read, wire_arg)) <= 0) 161 return ret; 162 163 if (!tls13_buffer_finish(rec->buf, &rec->data, &rec->data_len)) 164 return TLS13_IO_FAILURE; 165 166 return rec->data_len; 167 } 168 169 ssize_t 170 tls13_record_send(struct tls13_record *rec, tls13_write_cb wire_write, 171 void *wire_arg) 172 { 173 ssize_t ret; 174 175 if (rec->data == NULL) 176 return TLS13_IO_FAILURE; 177 178 while (CBS_len(&rec->cbs) > 0) { 179 if ((ret = wire_write(CBS_data(&rec->cbs), 180 CBS_len(&rec->cbs), wire_arg)) <= 0) 181 return ret; 182 183 if (!CBS_skip(&rec->cbs, ret)) 184 return TLS13_IO_FAILURE; 185 } 186 187 return rec->data_len; 188 } 189