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