1 /* $OpenBSD: tls13_buffer.c,v 1.5 2021/05/16 14:19:04 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 "bytestring.h"
19 #include "tls13_internal.h"
20 
21 struct tls13_buffer {
22 	size_t capacity;
23 	uint8_t *data;
24 	size_t len;
25 	size_t offset;
26 };
27 
28 static int tls13_buffer_resize(struct tls13_buffer *buf, size_t capacity);
29 
30 struct tls13_buffer *
tls13_buffer_new(size_t init_size)31 tls13_buffer_new(size_t init_size)
32 {
33 	struct tls13_buffer *buf = NULL;
34 
35 	if ((buf = calloc(1, sizeof(struct tls13_buffer))) == NULL)
36 		goto err;
37 
38 	if (!tls13_buffer_resize(buf, init_size))
39 		goto err;
40 
41 	return buf;
42 
43  err:
44 	tls13_buffer_free(buf);
45 
46 	return NULL;
47 }
48 
49 void
tls13_buffer_free(struct tls13_buffer * buf)50 tls13_buffer_free(struct tls13_buffer *buf)
51 {
52 	if (buf == NULL)
53 		return;
54 
55 	freezero(buf->data, buf->capacity);
56 	freezero(buf, sizeof(struct tls13_buffer));
57 }
58 
59 static int
tls13_buffer_resize(struct tls13_buffer * buf,size_t capacity)60 tls13_buffer_resize(struct tls13_buffer *buf, size_t capacity)
61 {
62 	uint8_t *data;
63 
64 	if (buf->capacity == capacity)
65 		return 1;
66 
67 	if ((data = recallocarray(buf->data, buf->capacity, capacity, 1)) == NULL)
68 		return 0;
69 
70 	buf->data = data;
71 	buf->capacity = capacity;
72 
73 	return 1;
74 }
75 
76 int
tls13_buffer_set_data(struct tls13_buffer * buf,CBS * data)77 tls13_buffer_set_data(struct tls13_buffer *buf, CBS *data)
78 {
79 	if (!tls13_buffer_resize(buf, CBS_len(data)))
80 		return 0;
81 	memcpy(buf->data, CBS_data(data), CBS_len(data));
82 	return 1;
83 }
84 
85 ssize_t
tls13_buffer_extend(struct tls13_buffer * buf,size_t len,tls13_read_cb read_cb,void * cb_arg)86 tls13_buffer_extend(struct tls13_buffer *buf, size_t len,
87     tls13_read_cb read_cb, void *cb_arg)
88 {
89 	ssize_t ret;
90 
91 	if (len == buf->len)
92 		return buf->len;
93 
94 	if (len < buf->len)
95 		return TLS13_IO_FAILURE;
96 
97 	if (!tls13_buffer_resize(buf, len))
98 		return TLS13_IO_FAILURE;
99 
100 	for (;;) {
101 		if ((ret = read_cb(&buf->data[buf->len],
102 		    buf->capacity - buf->len, cb_arg)) <= 0)
103 			return ret;
104 
105 		if (ret > buf->capacity - buf->len)
106 			return TLS13_IO_FAILURE;
107 
108 		buf->len += ret;
109 
110 		if (buf->len == buf->capacity)
111 			return buf->len;
112 	}
113 }
114 
115 void
tls13_buffer_cbs(struct tls13_buffer * buf,CBS * cbs)116 tls13_buffer_cbs(struct tls13_buffer *buf, CBS *cbs)
117 {
118 	CBS_init(cbs, buf->data, buf->len);
119 }
120 
121 int
tls13_buffer_finish(struct tls13_buffer * buf,uint8_t ** out,size_t * out_len)122 tls13_buffer_finish(struct tls13_buffer *buf, uint8_t **out, size_t *out_len)
123 {
124 	if (out == NULL || out_len == NULL)
125 		return 0;
126 
127 	*out = buf->data;
128 	*out_len = buf->len;
129 
130 	buf->capacity = 0;
131 	buf->data = NULL;
132 	buf->len = 0;
133 
134 	return 1;
135 }
136