xref: /openbsd/regress/lib/libssl/buffer/buffertest.c (revision 25c4e8bd)
1*25c4e8bdSjsing /* $OpenBSD: buffertest.c,v 1.6 2022/07/22 19:34:55 jsing Exp $ */
2c90a81c5Sjsing /*
3*25c4e8bdSjsing  * Copyright (c) 2019, 2022 Joel Sing <jsing@openbsd.org>
4c90a81c5Sjsing  *
5c90a81c5Sjsing  * Permission to use, copy, modify, and distribute this software for any
6c90a81c5Sjsing  * purpose with or without fee is hereby granted, provided that the above
7c90a81c5Sjsing  * copyright notice and this permission notice appear in all copies.
8c90a81c5Sjsing  *
9c90a81c5Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10c90a81c5Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11c90a81c5Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12c90a81c5Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13c90a81c5Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14c90a81c5Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15c90a81c5Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16c90a81c5Sjsing  */
17c90a81c5Sjsing 
18c90a81c5Sjsing #include <err.h>
194e1ee078Sjsing #include <stdio.h>
204e1ee078Sjsing #include <stdlib.h>
21c90a81c5Sjsing #include <string.h>
22c90a81c5Sjsing 
234e1ee078Sjsing #include "tls_internal.h"
24c90a81c5Sjsing 
25c90a81c5Sjsing uint8_t testdata[] = {
26c90a81c5Sjsing 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
27c90a81c5Sjsing 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
28c90a81c5Sjsing };
29c90a81c5Sjsing 
30c90a81c5Sjsing struct read_state {
31c90a81c5Sjsing 	uint8_t *buf;
32c90a81c5Sjsing 	size_t len;
33c90a81c5Sjsing 	size_t offset;
34c90a81c5Sjsing };
35c90a81c5Sjsing 
36c90a81c5Sjsing static ssize_t
read_cb(void * buf,size_t buflen,void * cb_arg)37c90a81c5Sjsing read_cb(void *buf, size_t buflen, void *cb_arg)
38c90a81c5Sjsing {
39c90a81c5Sjsing 	struct read_state *rs = cb_arg;
40c90a81c5Sjsing 	ssize_t n;
41c90a81c5Sjsing 
42c90a81c5Sjsing 	if (rs->offset > rs->len)
434e1ee078Sjsing 		return TLS_IO_EOF;
44c90a81c5Sjsing 
45c90a81c5Sjsing 	if ((size_t)(n = buflen) > (rs->len - rs->offset))
46c90a81c5Sjsing 		n = rs->len - rs->offset;
47c90a81c5Sjsing 
48c90a81c5Sjsing 	if (n == 0)
494e1ee078Sjsing 		return TLS_IO_WANT_POLLIN;
50c90a81c5Sjsing 
51c90a81c5Sjsing 	memcpy(buf, &rs->buf[rs->offset], n);
52c90a81c5Sjsing 	rs->offset += n;
53c90a81c5Sjsing 
54c90a81c5Sjsing 	return n;
55c90a81c5Sjsing }
56c90a81c5Sjsing 
57c90a81c5Sjsing struct extend_test {
58c90a81c5Sjsing 	size_t extend_len;
59c90a81c5Sjsing 	size_t read_len;
60c90a81c5Sjsing 	ssize_t want_ret;
61c90a81c5Sjsing };
62c90a81c5Sjsing 
63*25c4e8bdSjsing const struct extend_test extend_tests[] = {
64c90a81c5Sjsing 	{
65c90a81c5Sjsing 		.extend_len = 4,
66c90a81c5Sjsing 		.read_len = 0,
674e1ee078Sjsing 		.want_ret = TLS_IO_WANT_POLLIN,
68c90a81c5Sjsing 	},
69c90a81c5Sjsing 	{
70c90a81c5Sjsing 		.extend_len = 4,
71c90a81c5Sjsing 		.read_len = 8,
72c90a81c5Sjsing 		.want_ret = 4,
73c90a81c5Sjsing 	},
74c90a81c5Sjsing 	{
75c90a81c5Sjsing 		.extend_len = 12,
76c90a81c5Sjsing 		.read_len = 8,
774e1ee078Sjsing 		.want_ret = TLS_IO_WANT_POLLIN,
78c90a81c5Sjsing 	},
79c90a81c5Sjsing 	{
80c90a81c5Sjsing 		.extend_len = 12,
81c90a81c5Sjsing 		.read_len = 10,
824e1ee078Sjsing 		.want_ret = TLS_IO_WANT_POLLIN,
83c90a81c5Sjsing 	},
84c90a81c5Sjsing 	{
85c90a81c5Sjsing 		.extend_len = 12,
86c90a81c5Sjsing 		.read_len = 12,
87c90a81c5Sjsing 		.want_ret = 12,
88c90a81c5Sjsing 	},
89c90a81c5Sjsing 	{
90c90a81c5Sjsing 		.extend_len = 16,
91c90a81c5Sjsing 		.read_len = 16,
92c90a81c5Sjsing 		.want_ret = 16,
93c90a81c5Sjsing 	},
94c90a81c5Sjsing 	{
95c90a81c5Sjsing 		.extend_len = 20,
96c90a81c5Sjsing 		.read_len = 1,
974e1ee078Sjsing 		.want_ret = TLS_IO_EOF,
98c90a81c5Sjsing 	},
99c90a81c5Sjsing };
100c90a81c5Sjsing 
101c90a81c5Sjsing #define N_EXTEND_TESTS (sizeof(extend_tests) / sizeof(extend_tests[0]))
102c90a81c5Sjsing 
103*25c4e8bdSjsing static int
tls_buffer_extend_test(void)104*25c4e8bdSjsing tls_buffer_extend_test(void)
105c90a81c5Sjsing {
106*25c4e8bdSjsing 	const struct extend_test *et;
1074e1ee078Sjsing 	struct tls_buffer *buf;
108c90a81c5Sjsing 	struct read_state rs;
109*25c4e8bdSjsing 	uint8_t *data = NULL;
110c90a81c5Sjsing 	size_t i, data_len;
111c90a81c5Sjsing 	ssize_t ret;
112c90a81c5Sjsing 	CBS cbs;
113*25c4e8bdSjsing 	int failed = 1;
114c90a81c5Sjsing 
115c90a81c5Sjsing 	rs.buf = testdata;
116ef566ea2Sbeck 	rs.offset = 0;
117c90a81c5Sjsing 
1184e1ee078Sjsing 	if ((buf = tls_buffer_new(0)) == NULL)
1194e1ee078Sjsing 		errx(1, "tls_buffer_new");
120c90a81c5Sjsing 
121c90a81c5Sjsing 	for (i = 0; i < N_EXTEND_TESTS; i++) {
122c90a81c5Sjsing 		et = &extend_tests[i];
123c90a81c5Sjsing 		rs.len = et->read_len;
124c90a81c5Sjsing 
1254e1ee078Sjsing 		ret = tls_buffer_extend(buf, et->extend_len, read_cb, &rs);
126c90a81c5Sjsing 		if (ret != extend_tests[i].want_ret) {
127c0a6a244Stb 			fprintf(stderr, "FAIL: Test %zd - extend returned %zd, "
128c0a6a244Stb 			    "want %zd\n", i, ret, et->want_ret);
129*25c4e8bdSjsing 			goto failed;
130c90a81c5Sjsing 		}
131c90a81c5Sjsing 
132*25c4e8bdSjsing 		if (!tls_buffer_data(buf, &cbs)) {
133*25c4e8bdSjsing 			fprintf(stderr, "FAIL: Test %zd - failed to get data\n",
134*25c4e8bdSjsing 			    i);
135*25c4e8bdSjsing 			goto failed;
136*25c4e8bdSjsing 		}
137c90a81c5Sjsing 
138c90a81c5Sjsing 		if (!CBS_mem_equal(&cbs, testdata, CBS_len(&cbs))) {
139c0a6a244Stb 			fprintf(stderr, "FAIL: Test %zd - extend buffer "
140c90a81c5Sjsing 			    "mismatch", i);
141*25c4e8bdSjsing 			goto failed;
142c90a81c5Sjsing 		}
143c90a81c5Sjsing 	}
144c90a81c5Sjsing 
1454e1ee078Sjsing 	if (!tls_buffer_finish(buf, &data, &data_len)) {
146c90a81c5Sjsing 		fprintf(stderr, "FAIL: failed to finish\n");
147*25c4e8bdSjsing 		goto failed;
148c90a81c5Sjsing 	}
149c90a81c5Sjsing 
1504e1ee078Sjsing 	tls_buffer_free(buf);
151*25c4e8bdSjsing 	buf = NULL;
152c90a81c5Sjsing 
153c90a81c5Sjsing 	if (data_len != sizeof(testdata)) {
154c90a81c5Sjsing 		fprintf(stderr, "FAIL: got data length %zu, want %zu\n",
155c90a81c5Sjsing 		    data_len, sizeof(testdata));
156*25c4e8bdSjsing 		goto failed;
157c90a81c5Sjsing 	}
158c90a81c5Sjsing 	if (memcmp(data, testdata, data_len) != 0) {
159c90a81c5Sjsing 		fprintf(stderr, "FAIL: data mismatch\n");
160*25c4e8bdSjsing 		goto failed;
161c90a81c5Sjsing 	}
162*25c4e8bdSjsing 
163*25c4e8bdSjsing 	failed = 0;
164*25c4e8bdSjsing 
165*25c4e8bdSjsing  failed:
166*25c4e8bdSjsing 	tls_buffer_free(buf);
167c90a81c5Sjsing 	free(data);
168c90a81c5Sjsing 
169*25c4e8bdSjsing 	return failed;
170*25c4e8bdSjsing }
171*25c4e8bdSjsing 
172*25c4e8bdSjsing struct read_write_test {
173*25c4e8bdSjsing 	uint8_t pattern;
174*25c4e8bdSjsing 	size_t read;
175*25c4e8bdSjsing 	size_t write;
176*25c4e8bdSjsing 	size_t append;
177*25c4e8bdSjsing 	ssize_t want;
178*25c4e8bdSjsing };
179*25c4e8bdSjsing 
180*25c4e8bdSjsing const struct read_write_test read_write_tests[] = {
181*25c4e8bdSjsing 	{
182*25c4e8bdSjsing 		.read = 2048,
183*25c4e8bdSjsing 		.want = TLS_IO_WANT_POLLIN,
184*25c4e8bdSjsing 	},
185*25c4e8bdSjsing 	{
186*25c4e8bdSjsing 		.pattern = 0xdb,
187*25c4e8bdSjsing 		.write = 2048,
188*25c4e8bdSjsing 		.want = 2048,
189*25c4e8bdSjsing 	},
190*25c4e8bdSjsing 	{
191*25c4e8bdSjsing 		.pattern = 0xbd,
192*25c4e8bdSjsing 		.append = 2048,
193*25c4e8bdSjsing 		.want = 1,
194*25c4e8bdSjsing 	},
195*25c4e8bdSjsing 	{
196*25c4e8bdSjsing 		.pattern = 0xdb,
197*25c4e8bdSjsing 		.read = 2048,
198*25c4e8bdSjsing 		.want = 2048,
199*25c4e8bdSjsing 	},
200*25c4e8bdSjsing 	{
201*25c4e8bdSjsing 		.pattern = 0xfe,
202*25c4e8bdSjsing 		.append = 1024,
203*25c4e8bdSjsing 		.want = 1,
204*25c4e8bdSjsing 	},
205*25c4e8bdSjsing 	{
206*25c4e8bdSjsing 		.pattern = 0xbd,
207*25c4e8bdSjsing 		.read = 1000,
208*25c4e8bdSjsing 		.want = 1000,
209*25c4e8bdSjsing 	},
210*25c4e8bdSjsing 	{
211*25c4e8bdSjsing 		.pattern = 0xbd,
212*25c4e8bdSjsing 		.read = 1048,
213*25c4e8bdSjsing 		.want = 1048,
214*25c4e8bdSjsing 	},
215*25c4e8bdSjsing 	{
216*25c4e8bdSjsing 		.pattern = 0xdb,
217*25c4e8bdSjsing 		.write = 2048,
218*25c4e8bdSjsing 		.want = 2048,
219*25c4e8bdSjsing 	},
220*25c4e8bdSjsing 	{
221*25c4e8bdSjsing 		.pattern = 0xbd,
222*25c4e8bdSjsing 		.append = 1024,
223*25c4e8bdSjsing 		.want = 1,
224*25c4e8bdSjsing 	},
225*25c4e8bdSjsing 	{
226*25c4e8bdSjsing 		.pattern = 0xee,
227*25c4e8bdSjsing 		.append = 4096,
228*25c4e8bdSjsing 		.want = 1,
229*25c4e8bdSjsing 	},
230*25c4e8bdSjsing 	{
231*25c4e8bdSjsing 		.pattern = 0xfe,
232*25c4e8bdSjsing 		.append = 1,
233*25c4e8bdSjsing 		.want = 0,
234*25c4e8bdSjsing 	},
235*25c4e8bdSjsing 	{
236*25c4e8bdSjsing 		.pattern = 0xfe,
237*25c4e8bdSjsing 		.write = 1,
238*25c4e8bdSjsing 		.want = TLS_IO_FAILURE,
239*25c4e8bdSjsing 	},
240*25c4e8bdSjsing 	{
241*25c4e8bdSjsing 		.pattern = 0xfe,
242*25c4e8bdSjsing 		.read = 1024,
243*25c4e8bdSjsing 		.want = 1024,
244*25c4e8bdSjsing 	},
245*25c4e8bdSjsing 	{
246*25c4e8bdSjsing 		.pattern = 0xdb,
247*25c4e8bdSjsing 		.read = 2048,
248*25c4e8bdSjsing 		.want = 2048,
249*25c4e8bdSjsing 	},
250*25c4e8bdSjsing 	{
251*25c4e8bdSjsing 		.pattern = 0xbd,
252*25c4e8bdSjsing 		.read = 1024,
253*25c4e8bdSjsing 		.want = 1024,
254*25c4e8bdSjsing 	},
255*25c4e8bdSjsing 	{
256*25c4e8bdSjsing 		.pattern = 0xee,
257*25c4e8bdSjsing 		.read = 1024,
258*25c4e8bdSjsing 		.want = 1024,
259*25c4e8bdSjsing 	},
260*25c4e8bdSjsing 	{
261*25c4e8bdSjsing 		.pattern = 0xee,
262*25c4e8bdSjsing 		.read = 4096,
263*25c4e8bdSjsing 		.want = 3072,
264*25c4e8bdSjsing 	},
265*25c4e8bdSjsing 	{
266*25c4e8bdSjsing 		.read = 2048,
267*25c4e8bdSjsing 		.want = TLS_IO_WANT_POLLIN,
268*25c4e8bdSjsing 	},
269*25c4e8bdSjsing };
270*25c4e8bdSjsing 
271*25c4e8bdSjsing #define N_READ_WRITE_TESTS (sizeof(read_write_tests) / sizeof(read_write_tests[0]))
272*25c4e8bdSjsing 
273*25c4e8bdSjsing static int
tls_buffer_read_write_test(void)274*25c4e8bdSjsing tls_buffer_read_write_test(void)
275*25c4e8bdSjsing {
276*25c4e8bdSjsing 	const struct read_write_test *rwt;
277*25c4e8bdSjsing 	struct tls_buffer *buf = NULL;
278*25c4e8bdSjsing 	uint8_t *rbuf = NULL, *wbuf = NULL;
279*25c4e8bdSjsing 	ssize_t n;
280*25c4e8bdSjsing 	size_t i;
281*25c4e8bdSjsing 	int ret;
282*25c4e8bdSjsing 	int failed = 1;
283*25c4e8bdSjsing 
284*25c4e8bdSjsing 	if ((buf = tls_buffer_new(0)) == NULL)
285*25c4e8bdSjsing 		errx(1, "tls_buffer_new");
286*25c4e8bdSjsing 
287*25c4e8bdSjsing 	tls_buffer_set_capacity_limit(buf, 8192);
288*25c4e8bdSjsing 
289*25c4e8bdSjsing 	for (i = 0; i < N_READ_WRITE_TESTS; i++) {
290*25c4e8bdSjsing 		rwt = &read_write_tests[i];
291*25c4e8bdSjsing 
292*25c4e8bdSjsing 		if (rwt->append > 0) {
293*25c4e8bdSjsing 			free(wbuf);
294*25c4e8bdSjsing 			if ((wbuf = malloc(rwt->append)) == NULL)
295*25c4e8bdSjsing 				errx(1, "malloc");
296*25c4e8bdSjsing 			memset(wbuf, rwt->pattern, rwt->append);
297*25c4e8bdSjsing 			if ((ret = tls_buffer_append(buf, wbuf, rwt->append)) !=
298*25c4e8bdSjsing 			    rwt->want) {
299*25c4e8bdSjsing 				fprintf(stderr, "FAIL: test %zu - "
300*25c4e8bdSjsing 				    "tls_buffer_append() = %d, want %zu\n",
301*25c4e8bdSjsing 				    i, ret, rwt->want);
302*25c4e8bdSjsing 				goto failed;
303*25c4e8bdSjsing 			}
304*25c4e8bdSjsing 		}
305*25c4e8bdSjsing 
306*25c4e8bdSjsing 		if (rwt->write > 0) {
307*25c4e8bdSjsing 			free(wbuf);
308*25c4e8bdSjsing 			if ((wbuf = malloc(rwt->write)) == NULL)
309*25c4e8bdSjsing 				errx(1, "malloc");
310*25c4e8bdSjsing 			memset(wbuf, rwt->pattern, rwt->write);
311*25c4e8bdSjsing 			if ((n = tls_buffer_write(buf, wbuf, rwt->write)) !=
312*25c4e8bdSjsing 			    rwt->want) {
313*25c4e8bdSjsing 				fprintf(stderr, "FAIL: test %zu - "
314*25c4e8bdSjsing 				    "tls_buffer_write() = %zi, want %zu\n",
315*25c4e8bdSjsing 				    i, n, rwt->want);
316*25c4e8bdSjsing 				goto failed;
317*25c4e8bdSjsing 			}
318*25c4e8bdSjsing 		}
319*25c4e8bdSjsing 
320*25c4e8bdSjsing 		if (rwt->read > 0) {
321*25c4e8bdSjsing 			free(rbuf);
322*25c4e8bdSjsing 			if ((rbuf = calloc(1, rwt->read)) == NULL)
323*25c4e8bdSjsing 				errx(1, "malloc");
324*25c4e8bdSjsing 			if ((n = tls_buffer_read(buf, rbuf, rwt->read)) !=
325*25c4e8bdSjsing 			    rwt->want) {
326*25c4e8bdSjsing 				fprintf(stderr, "FAIL: test %zu - "
327*25c4e8bdSjsing 				    "tls_buffer_read() = %zi, want %zu\n",
328*25c4e8bdSjsing 				    i, n, rwt->want);
329*25c4e8bdSjsing 				goto failed;
330*25c4e8bdSjsing 			}
331*25c4e8bdSjsing 			if (rwt->want > 0) {
332*25c4e8bdSjsing 				free(wbuf);
333*25c4e8bdSjsing 				if ((wbuf = malloc(rwt->want)) == NULL)
334*25c4e8bdSjsing 					errx(1, "malloc");
335*25c4e8bdSjsing 				memset(wbuf, rwt->pattern, rwt->want);
336*25c4e8bdSjsing 				if (memcmp(rbuf, wbuf, rwt->want) != 0) {
337*25c4e8bdSjsing 					fprintf(stderr, "FAIL: test %zu - "
338*25c4e8bdSjsing 					    "read byte mismatch\n", i);
339*25c4e8bdSjsing 					goto failed;
340*25c4e8bdSjsing 				}
341*25c4e8bdSjsing 			}
342*25c4e8bdSjsing 		}
343*25c4e8bdSjsing 	}
344*25c4e8bdSjsing 
345*25c4e8bdSjsing 	failed = 0;
346*25c4e8bdSjsing 
347*25c4e8bdSjsing  failed:
348*25c4e8bdSjsing 	tls_buffer_free(buf);
349*25c4e8bdSjsing 	free(rbuf);
350*25c4e8bdSjsing 	free(wbuf);
351*25c4e8bdSjsing 
352*25c4e8bdSjsing 	return failed;
353*25c4e8bdSjsing }
354*25c4e8bdSjsing 
355*25c4e8bdSjsing int
main(int argc,char ** argv)356*25c4e8bdSjsing main(int argc, char **argv)
357*25c4e8bdSjsing {
358*25c4e8bdSjsing 	int failed = 0;
359*25c4e8bdSjsing 
360*25c4e8bdSjsing 	failed |= tls_buffer_extend_test();
361*25c4e8bdSjsing 	failed |= tls_buffer_read_write_test();
362*25c4e8bdSjsing 
363*25c4e8bdSjsing 	return failed;
364c90a81c5Sjsing }
365