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