xref: /openbsd-src/regress/lib/libcrypto/bio/bio_mem.c (revision 720505cf7dda7a37320557697e38f275bbb49ae5)
1 /*	$OpenBSD: bio_mem.c,v 1.1 2022/12/08 17:49:02 tb Exp $	*/
2 /*
3  * Copyright (c) 2022 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 <err.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include <openssl/bio.h>
25 #include <openssl/buffer.h>
26 
27 static int
bio_mem_test(void)28 bio_mem_test(void)
29 {
30 	uint8_t *data = NULL;
31 	size_t data_len;
32 	uint8_t *rodata;
33 	long rodata_len;
34 	BUF_MEM *pbuf;
35 	BUF_MEM *buf = NULL;
36 	BIO *bio = NULL;
37 	int ret;
38 	int failed = 1;
39 
40 	data_len = 4096;
41 	if ((data = malloc(data_len)) == NULL)
42 		err(1, "malloc");
43 
44 	memset(data, 0xdb, data_len);
45 	data[0] = 0x01;
46 	data[data_len - 1] = 0xff;
47 
48 	if ((bio = BIO_new(BIO_s_mem())) == NULL) {
49 		fprintf(stderr, "FAIL: BIO_new() returned NULL\n");
50 		goto failure;
51 	}
52 	if ((ret = BIO_write(bio, data, data_len)) != (int)data_len) {
53 		fprintf(stderr, "FAIL: BIO_write() = %d, want %zu\n", ret,
54 		    data_len);
55 		goto failure;
56 	}
57 	if ((rodata_len = BIO_get_mem_data(bio, &rodata)) != (long)data_len) {
58 		fprintf(stderr, "FAIL: BIO_get_mem_data() = %ld, want %zu\n",
59 		    rodata_len, data_len);
60 		goto failure;
61 	}
62 	if (rodata[0] != 0x01) {
63 		fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", rodata[0], 0x01);
64 		goto failure;
65 	}
66 	if (rodata[rodata_len - 1] != 0xff) {
67 		fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n",
68 		    rodata[rodata_len - 1], 0xff);
69 		goto failure;
70 	}
71 
72 	if (!BIO_get_mem_ptr(bio, &pbuf)) {
73 		fprintf(stderr, "FAIL: BIO_get_mem_ptr() failed\n");
74 		goto failure;
75 	}
76 	if (pbuf->length != data_len) {
77 		fprintf(stderr, "FAIL: Got buffer with length %zu, want %zu\n",
78 		    pbuf->length, data_len);
79 		goto failure;
80 	}
81 	if (memcmp(pbuf->data, data, data_len) != 0) {
82 		fprintf(stderr, "FAIL: Got buffer with differing data\n");
83 		goto failure;
84 	}
85 	pbuf = NULL;
86 
87 	if ((buf = BUF_MEM_new()) == NULL) {
88 		fprintf(stderr, "FAIL: BUF_MEM_new() returned NULL\n");
89 		goto failure;
90 	}
91 	if (!BIO_set_mem_buf(bio, buf, BIO_NOCLOSE)) {
92 		fprintf(stderr, "FAIL: BUF_set_mem_buf() failed\n");
93 		goto failure;
94 	}
95 	if ((ret = BIO_puts(bio, "Hello\n")) != 6) {
96 		fprintf(stderr, "FAIL: BUF_puts() = %d, want %d\n", ret, 6);
97 		goto failure;
98 	}
99 	if ((ret = BIO_puts(bio, "World\n")) != 6) {
100 		fprintf(stderr, "FAIL: BUF_puts() = %d, want %d\n", ret, 6);
101 		goto failure;
102 	}
103 	if (buf->length != 12) {
104 		fprintf(stderr, "FAIL: buffer has length %zu, want %d\n",
105 		    buf->length, 12);
106 		goto failure;
107 	}
108 	buf->length = 11;
109 	if ((ret = BIO_gets(bio, data, data_len)) != 6) {
110 		fprintf(stderr, "FAIL: BUF_gets() = %d, want %d\n", ret, 6);
111 		goto failure;
112 	}
113 	if (strcmp(data, "Hello\n") != 0) {
114 		fprintf(stderr, "FAIL: BUF_gets() returned '%s', want '%s'\n",
115 		    data, "Hello\\n");
116 		goto failure;
117 	}
118 	if ((ret = BIO_gets(bio, data, data_len)) != 5) {
119 		fprintf(stderr, "FAIL: BUF_gets() = %d, want %d\n", ret, 5);
120 		goto failure;
121 	}
122 	if (strcmp(data, "World") != 0) {
123 		fprintf(stderr, "FAIL: BUF_gets() returned '%s', want '%s'\n",
124 		    data, "World");
125 		goto failure;
126 	}
127 
128 	if (!BIO_eof(bio)) {
129 		fprintf(stderr, "FAIL: BIO is not EOF\n");
130 		goto failure;
131 	}
132 	if ((ret = BIO_read(bio, data, data_len)) != -1) {
133 		fprintf(stderr, "FAIL: BIO_read() = %d, want -1\n", ret);
134 		goto failure;
135 	}
136 	if (!BIO_set_mem_eof_return(bio, -2)) {
137 		fprintf(stderr, "FAIL: BIO_set_mem_eof_return() failed\n");
138 		goto failure;
139 	}
140 	if ((ret = BIO_read(bio, data, data_len)) != -2) {
141 		fprintf(stderr, "FAIL: BIO_read() = %d, want -2\n", ret);
142 		goto failure;
143 	}
144 
145 	failed = 0;
146 
147  failure:
148 	free(data);
149 	BUF_MEM_free(buf);
150 	BIO_free(bio);
151 
152 	return failed;
153 }
154 
155 static int
bio_mem_small_io_test(void)156 bio_mem_small_io_test(void)
157 {
158 	uint8_t buf[2];
159 	int i, j, ret;
160 	BIO *bio;
161 	int failed = 1;
162 
163 	memset(buf, 0xdb, sizeof(buf));
164 
165 	if ((bio = BIO_new(BIO_s_mem())) == NULL) {
166 		fprintf(stderr, "FAIL: BIO_new() returned NULL\n");
167 		goto failure;
168 	}
169 
170 	for (i = 0; i < 100; i++) {
171 		if (!BIO_reset(bio)) {
172 			fprintf(stderr, "FAIL: BIO_reset() failed\n");
173 			goto failure;
174 		}
175 		for (j = 0; j < 25000; j++) {
176 			ret = BIO_write(bio, buf, sizeof(buf));
177 			if (ret != sizeof(buf)) {
178 				fprintf(stderr, "FAIL: BIO_write() = %d, "
179 				    "want %zu\n", ret, sizeof(buf));
180 				goto failure;
181 			}
182 		}
183 		for (j = 0; j < 25000; j++) {
184 			ret = BIO_read(bio, buf, sizeof(buf));
185 			if (ret != sizeof(buf)) {
186 				fprintf(stderr, "FAIL: BIO_read() = %d, "
187 				    "want %zu\n", ret, sizeof(buf));
188 				goto failure;
189 			}
190 			ret = BIO_write(bio, buf, sizeof(buf));
191 			if (ret != sizeof(buf)) {
192 				fprintf(stderr, "FAIL: BIO_write() = %d, "
193 				    "want %zu\n", ret, sizeof(buf));
194 				goto failure;
195 			}
196 		}
197 		for (j = 0; j < 25000; j++) {
198 			ret = BIO_read(bio, buf, sizeof(buf));
199 			if (ret != sizeof(buf)) {
200 				fprintf(stderr, "FAIL: BIO_read() = %d, "
201 				    "want %zu\n", ret, sizeof(buf));
202 				goto failure;
203 			}
204 		}
205 		if (!BIO_eof(bio)) {
206 			fprintf(stderr, "FAIL: BIO not EOF\n");
207 			goto failure;
208 		}
209 	}
210 
211 	if (buf[0] != 0xdb || buf[1] != 0xdb) {
212 		fprintf(stderr, "FAIL: buf = {0x%x, 0x%x}, want {0xdb, 0xdb}\n",
213 		    buf[0], buf[1]);
214 		goto failure;
215 	}
216 
217 	failed = 0;
218 
219  failure:
220 	BIO_free(bio);
221 
222 	return failed;
223 }
224 
225 static int
bio_mem_readonly_test(void)226 bio_mem_readonly_test(void)
227 {
228 	uint8_t *data = NULL;
229 	size_t data_len;
230 	uint8_t buf[2048];
231 	BIO *bio = NULL;
232 	int ret;
233 	int failed = 1;
234 
235 	data_len = 4096;
236 	if ((data = malloc(data_len)) == NULL)
237 		err(1, "malloc");
238 
239 	memset(data, 0xdb, data_len);
240 	data[0] = 0x01;
241 	data[data_len - 1] = 0xff;
242 
243 	if ((bio = BIO_new_mem_buf(data, data_len)) == NULL) {
244 		fprintf(stderr, "FAIL: BIO_new_mem_buf failed\n");
245 		goto failure;
246 	}
247 	if ((ret = BIO_read(bio, buf, 1)) != 1) {
248 		fprintf(stderr, "FAIL: BIO_read() = %d, want %zu\n", ret,
249 		    sizeof(buf));
250 		goto failure;
251 	}
252 	if (buf[0] != 0x01) {
253 		fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[0], 0x01);
254 		goto failure;
255 	}
256 	if ((ret = BIO_read(bio, buf, sizeof(buf))) != sizeof(buf)) {
257 		fprintf(stderr, "FAIL: BIO_read() = %d, want %zu\n", ret,
258 		    sizeof(buf));
259 		goto failure;
260 	}
261 	if (buf[0] != 0xdb) {
262 		fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[0], 0xdb);
263 		goto failure;
264 	}
265 	if ((ret = BIO_write(bio, buf, 1)) != -1) {
266 		fprintf(stderr, "FAIL: BIO_write() = %d, want -1\n", ret);
267 		goto failure;
268 	}
269 	if (BIO_eof(bio)) {
270 		fprintf(stderr, "FAIL: BIO is EOF\n");
271 		goto failure;
272 	}
273 	if (BIO_ctrl_pending(bio) != 2047) {
274 		fprintf(stderr, "FAIL: BIO_ctrl_pending() = %zu, want 2047\n",
275 		    BIO_ctrl_pending(bio));
276 		goto failure;
277 	}
278 	if ((ret = BIO_read(bio, buf, sizeof(buf))) != 2047) {
279 		fprintf(stderr, "FAIL: BIO_read() = %d, want 2047\n", ret);
280 		goto failure;
281 	}
282 	if (buf[2045] != 0xdb) {
283 		fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[2045], 0xdb);
284 		goto failure;
285 	}
286 	if (buf[2046] != 0xff) {
287 		fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[2046], 0xff);
288 		goto failure;
289 	}
290 	if (!BIO_eof(bio)) {
291 		fprintf(stderr, "FAIL: BIO is not EOF\n");
292 		goto failure;
293 	}
294 	if (BIO_ctrl_pending(bio) != 0) {
295 		fprintf(stderr, "FAIL: BIO_ctrl_pending() = %zu, want 0\n",
296 		    BIO_ctrl_pending(bio));
297 		goto failure;
298 	}
299 
300 	if (!BIO_reset(bio)) {
301 		fprintf(stderr, "FAIL: failed to reset bio\n");
302 		goto failure;
303 	}
304 	if (BIO_eof(bio)) {
305 		fprintf(stderr, "FAIL: BIO is EOF\n");
306 		goto failure;
307 	}
308 	if (BIO_ctrl_pending(bio) != 4096) {
309 		fprintf(stderr, "FAIL: BIO_ctrl_pending() = %zu, want 4096\n",
310 		    BIO_ctrl_pending(bio));
311 		goto failure;
312 	}
313 	if ((ret = BIO_read(bio, buf, 2)) != 2) {
314 		fprintf(stderr, "FAIL: BIO_read() = %d, want 2\n", ret);
315 		goto failure;
316 	}
317 	if (buf[0] != 0x01) {
318 		fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[0], 0x01);
319 		goto failure;
320 	}
321 	if (buf[1] != 0xdb) {
322 		fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[1], 0xdb);
323 		goto failure;
324 	}
325 
326 	failed = 0;
327 
328  failure:
329 	BIO_free(bio);
330 	free(data);
331 
332 	return failed;
333 }
334 
335 int
main(int argc,char ** argv)336 main(int argc, char **argv)
337 {
338 	int failed = 0;
339 
340 	failed |= bio_mem_test();
341 	failed |= bio_mem_small_io_test();
342 	failed |= bio_mem_readonly_test();
343 
344 	return failed;
345 }
346