1 /* $OpenBSD: tls13_record.c,v 1.4 2020/02/15 14:36:58 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 /* XXX - record overflow alert. */ 149 if (rec_len > TLS13_RECORD_MAX_CIPHERTEXT_LEN) 150 return TLS13_IO_FAILURE; 151 152 rec->content_type = content_type; 153 rec->version = rec_version; 154 rec->rec_len = rec_len; 155 } 156 157 if ((ret = tls13_buffer_extend(rec->buf, 158 TLS13_RECORD_HEADER_LEN + rec->rec_len, wire_read, wire_arg)) <= 0) 159 return ret; 160 161 if (!tls13_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, tls13_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