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