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