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