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