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