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