xref: /freebsd/crypto/openssl/test/bio_callback_test.c (revision dafba19e42e78cd3d7c9264ece49ddd3d7d70da5)
1 /*
2  * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 #define OPENSSL_SUPPRESS_DEPRECATED
10 #include <stdio.h>
11 #include <string.h>
12 #include <openssl/bio.h>
13 
14 #include "testutil.h"
15 
16 #define MAXCOUNT 5
17 static int my_param_count;
18 static BIO *my_param_b[MAXCOUNT];
19 static int my_param_oper[MAXCOUNT];
20 static const char *my_param_argp[MAXCOUNT];
21 static int my_param_argi[MAXCOUNT];
22 static long my_param_argl[MAXCOUNT];
23 static long my_param_ret[MAXCOUNT];
24 static size_t my_param_len[MAXCOUNT];
25 static size_t my_param_processed[MAXCOUNT];
26 
27 static long my_bio_cb_ex(BIO *b, int oper, const char *argp, size_t len,
28     int argi, long argl, int ret, size_t *processed)
29 {
30     if (my_param_count >= MAXCOUNT)
31         return -1;
32     my_param_b[my_param_count] = b;
33     my_param_oper[my_param_count] = oper;
34     my_param_argp[my_param_count] = argp;
35     my_param_argi[my_param_count] = argi;
36     my_param_argl[my_param_count] = argl;
37     my_param_ret[my_param_count] = ret;
38     my_param_len[my_param_count] = len;
39     my_param_processed[my_param_count] = processed != NULL ? *processed : 0;
40 
41     my_param_count++;
42     return ret;
43 }
44 
45 static int test_bio_callback_ex(void)
46 {
47     int ok = 0;
48     BIO *bio;
49     int i;
50     char test1[] = "test";
51     const size_t test1len = sizeof(test1) - 1;
52     char test2[] = "hello";
53     const size_t test2len = sizeof(test2) - 1;
54     char buf[16];
55 
56     my_param_count = 0;
57 
58     bio = BIO_new(BIO_s_mem());
59     if (bio == NULL)
60         goto err;
61 
62     BIO_set_callback_ex(bio, my_bio_cb_ex);
63     i = BIO_write(bio, test1, test1len);
64     if (!TEST_int_eq(i, test1len)
65         || !TEST_int_eq(my_param_count, 2)
66         || !TEST_ptr_eq(my_param_b[0], bio)
67         || !TEST_int_eq(my_param_oper[0], BIO_CB_WRITE)
68         || !TEST_ptr_eq(my_param_argp[0], test1)
69         || !TEST_size_t_eq(my_param_len[0], test1len)
70         || !TEST_long_eq(my_param_argl[0], 0L)
71         || !TEST_int_eq((int)my_param_ret[0], 1)
72         || !TEST_ptr_eq(my_param_b[1], bio)
73         || !TEST_int_eq(my_param_oper[1], BIO_CB_WRITE | BIO_CB_RETURN)
74         || !TEST_ptr_eq(my_param_argp[1], test1)
75         || !TEST_size_t_eq(my_param_len[1], test1len)
76         || !TEST_long_eq(my_param_argl[1], 0L)
77         || !TEST_size_t_eq(my_param_processed[1], test1len)
78         || !TEST_int_eq((int)my_param_ret[1], 1))
79         goto err;
80 
81     my_param_count = 0;
82     i = BIO_read(bio, buf, sizeof(buf));
83     if (!TEST_mem_eq(buf, i, test1, test1len)
84         || !TEST_int_eq(my_param_count, 2)
85         || !TEST_ptr_eq(my_param_b[0], bio)
86         || !TEST_int_eq(my_param_oper[0], BIO_CB_READ)
87         || !TEST_ptr_eq(my_param_argp[0], buf)
88         || !TEST_size_t_eq(my_param_len[0], sizeof(buf))
89         || !TEST_long_eq(my_param_argl[0], 0L)
90         || !TEST_int_eq((int)my_param_ret[0], 1)
91         || !TEST_ptr_eq(my_param_b[1], bio)
92         || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN)
93         || !TEST_ptr_eq(my_param_argp[1], buf)
94         || !TEST_size_t_eq(my_param_len[1], sizeof(buf))
95         || !TEST_long_eq(my_param_argl[1], 0L)
96         || !TEST_size_t_eq(my_param_processed[1], test1len)
97         || !TEST_int_eq((int)my_param_ret[1], 1))
98         goto err;
99 
100     /* By default a mem bio returns -1 if it has run out of data */
101     my_param_count = 0;
102     i = BIO_read(bio, buf, sizeof(buf));
103     if (!TEST_int_eq(i, -1)
104         || !TEST_int_eq(my_param_count, 2)
105         || !TEST_ptr_eq(my_param_b[0], bio)
106         || !TEST_int_eq(my_param_oper[0], BIO_CB_READ)
107         || !TEST_ptr_eq(my_param_argp[0], buf)
108         || !TEST_size_t_eq(my_param_len[0], sizeof(buf))
109         || !TEST_long_eq(my_param_argl[0], 0L)
110         || !TEST_int_eq((int)my_param_ret[0], 1)
111         || !TEST_ptr_eq(my_param_b[1], bio)
112         || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN)
113         || !TEST_ptr_eq(my_param_argp[1], buf)
114         || !TEST_size_t_eq(my_param_len[1], sizeof(buf))
115         || !TEST_long_eq(my_param_argl[1], 0L)
116         || !TEST_size_t_eq(my_param_processed[1], 0)
117         || !TEST_int_eq((int)my_param_ret[1], -1))
118         goto err;
119 
120     /* Force the mem bio to return 0 if it has run out of data */
121     my_param_count = 0;
122     i = BIO_set_mem_eof_return(bio, 0);
123     if (!TEST_int_eq(i, 1)
124         || !TEST_int_eq(my_param_count, 2)
125         || !TEST_ptr_eq(my_param_b[0], bio)
126         || !TEST_int_eq(my_param_oper[0], BIO_CB_CTRL)
127         || !TEST_ptr_eq(my_param_argp[0], NULL)
128         || !TEST_int_eq(my_param_argi[0], BIO_C_SET_BUF_MEM_EOF_RETURN)
129         || !TEST_long_eq(my_param_argl[0], 0L)
130         || !TEST_int_eq((int)my_param_ret[0], 1)
131         || !TEST_ptr_eq(my_param_b[1], bio)
132         || !TEST_int_eq(my_param_oper[1], BIO_CB_CTRL | BIO_CB_RETURN)
133         || !TEST_ptr_eq(my_param_argp[1], NULL)
134         || !TEST_int_eq(my_param_argi[1], BIO_C_SET_BUF_MEM_EOF_RETURN)
135         || !TEST_long_eq(my_param_argl[1], 0L)
136         || !TEST_int_eq((int)my_param_ret[1], 1))
137         goto err;
138     my_param_count = 0;
139     i = BIO_read(bio, buf, sizeof(buf));
140     if (!TEST_int_eq(i, 0)
141         || !TEST_int_eq(my_param_count, 2)
142         || !TEST_ptr_eq(my_param_b[0], bio)
143         || !TEST_int_eq(my_param_oper[0], BIO_CB_READ)
144         || !TEST_ptr_eq(my_param_argp[0], buf)
145         || !TEST_size_t_eq(my_param_len[0], sizeof(buf))
146         || !TEST_long_eq(my_param_argl[0], 0L)
147         || !TEST_int_eq((int)my_param_ret[0], 1)
148         || !TEST_ptr_eq(my_param_b[1], bio)
149         || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN)
150         || !TEST_ptr_eq(my_param_argp[1], buf)
151         || !TEST_size_t_eq(my_param_len[1], sizeof(buf))
152         || !TEST_long_eq(my_param_argl[1], 0L)
153         || !TEST_size_t_eq(my_param_processed[1], 0)
154         || !TEST_int_eq((int)my_param_ret[1], 0))
155         goto err;
156 
157     my_param_count = 0;
158     i = BIO_puts(bio, test2);
159     if (!TEST_int_eq(i, 5)
160         || !TEST_int_eq(my_param_count, 2)
161         || !TEST_ptr_eq(my_param_b[0], bio)
162         || !TEST_int_eq(my_param_oper[0], BIO_CB_PUTS)
163         || !TEST_ptr_eq(my_param_argp[0], test2)
164         || !TEST_int_eq(my_param_argi[0], 0)
165         || !TEST_long_eq(my_param_argl[0], 0L)
166         || !TEST_int_eq((int)my_param_ret[0], 1)
167         || !TEST_ptr_eq(my_param_b[1], bio)
168         || !TEST_int_eq(my_param_oper[1], BIO_CB_PUTS | BIO_CB_RETURN)
169         || !TEST_ptr_eq(my_param_argp[1], test2)
170         || !TEST_int_eq(my_param_argi[1], 0)
171         || !TEST_long_eq(my_param_argl[1], 0L)
172         || !TEST_size_t_eq(my_param_processed[1], test2len)
173         || !TEST_int_eq((int)my_param_ret[1], 1))
174         goto err;
175 
176     my_param_count = 0;
177     i = BIO_free(bio);
178     if (!TEST_int_eq(i, 1)
179         || !TEST_int_eq(my_param_count, 1)
180         || !TEST_ptr_eq(my_param_b[0], bio)
181         || !TEST_int_eq(my_param_oper[0], BIO_CB_FREE)
182         || !TEST_ptr_eq(my_param_argp[0], NULL)
183         || !TEST_int_eq(my_param_argi[0], 0)
184         || !TEST_long_eq(my_param_argl[0], 0L)
185         || !TEST_int_eq((int)my_param_ret[0], 1))
186         goto finish;
187 
188     ok = 1;
189     goto finish;
190 
191 err:
192     BIO_free(bio);
193 
194 finish:
195     /* This helps finding memory leaks with ASAN */
196     memset(my_param_b, 0, sizeof(my_param_b));
197     memset(my_param_argp, 0, sizeof(my_param_argp));
198     return ok;
199 }
200 
201 #ifndef OPENSSL_NO_DEPRECATED_3_0
202 static long my_bio_callback(BIO *b, int oper, const char *argp, int argi,
203     long argl, long ret)
204 {
205     if (my_param_count >= MAXCOUNT)
206         return -1;
207     my_param_b[my_param_count] = b;
208     my_param_oper[my_param_count] = oper;
209     my_param_argp[my_param_count] = argp;
210     my_param_argi[my_param_count] = argi;
211     my_param_argl[my_param_count] = argl;
212     my_param_ret[my_param_count] = ret;
213     my_param_count++;
214     return ret;
215 }
216 
217 static int test_bio_callback(void)
218 {
219     int ok = 0;
220     BIO *bio;
221     int i;
222     char test1[] = "test";
223     const int test1len = sizeof(test1) - 1;
224     char test2[] = "hello";
225     const int test2len = sizeof(test2) - 1;
226     char buf[16];
227 
228     my_param_count = 0;
229 
230     bio = BIO_new(BIO_s_mem());
231     if (bio == NULL)
232         goto err;
233 
234     BIO_set_callback(bio, my_bio_callback);
235     i = BIO_write(bio, test1, test1len);
236     if (!TEST_int_eq(i, test1len)
237         || !TEST_int_eq(my_param_count, 2)
238         || !TEST_ptr_eq(my_param_b[0], bio)
239         || !TEST_int_eq(my_param_oper[0], BIO_CB_WRITE)
240         || !TEST_ptr_eq(my_param_argp[0], test1)
241         || !TEST_int_eq(my_param_argi[0], test1len)
242         || !TEST_long_eq(my_param_argl[0], 0L)
243         || !TEST_long_eq(my_param_ret[0], 1L)
244         || !TEST_ptr_eq(my_param_b[1], bio)
245         || !TEST_int_eq(my_param_oper[1], BIO_CB_WRITE | BIO_CB_RETURN)
246         || !TEST_ptr_eq(my_param_argp[1], test1)
247         || !TEST_int_eq(my_param_argi[1], test1len)
248         || !TEST_long_eq(my_param_argl[1], 0L)
249         || !TEST_long_eq(my_param_ret[1], (long)test1len))
250         goto err;
251 
252     my_param_count = 0;
253     i = BIO_read(bio, buf, sizeof(buf));
254     if (!TEST_mem_eq(buf, i, test1, test1len)
255         || !TEST_int_eq(my_param_count, 2)
256         || !TEST_ptr_eq(my_param_b[0], bio)
257         || !TEST_int_eq(my_param_oper[0], BIO_CB_READ)
258         || !TEST_ptr_eq(my_param_argp[0], buf)
259         || !TEST_int_eq(my_param_argi[0], sizeof(buf))
260         || !TEST_long_eq(my_param_argl[0], 0L)
261         || !TEST_long_eq(my_param_ret[0], 1L)
262         || !TEST_ptr_eq(my_param_b[1], bio)
263         || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN)
264         || !TEST_ptr_eq(my_param_argp[1], buf)
265         || !TEST_int_eq(my_param_argi[1], sizeof(buf))
266         || !TEST_long_eq(my_param_argl[1], 0L)
267         || !TEST_long_eq(my_param_ret[1], (long)test1len))
268         goto err;
269 
270     /* By default a mem bio returns -1 if it has run out of data */
271     my_param_count = 0;
272     i = BIO_read(bio, buf, sizeof(buf));
273     if (!TEST_int_eq(i, -1)
274         || !TEST_int_eq(my_param_count, 2)
275         || !TEST_ptr_eq(my_param_b[0], bio)
276         || !TEST_int_eq(my_param_oper[0], BIO_CB_READ)
277         || !TEST_ptr_eq(my_param_argp[0], buf)
278         || !TEST_int_eq(my_param_argi[0], sizeof(buf))
279         || !TEST_long_eq(my_param_argl[0], 0L)
280         || !TEST_long_eq(my_param_ret[0], 1L)
281         || !TEST_ptr_eq(my_param_b[1], bio)
282         || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN)
283         || !TEST_ptr_eq(my_param_argp[1], buf)
284         || !TEST_int_eq(my_param_argi[1], sizeof(buf))
285         || !TEST_long_eq(my_param_argl[1], 0L)
286         || !TEST_long_eq(my_param_ret[1], -1L))
287         goto err;
288 
289     /* Force the mem bio to return 0 if it has run out of data */
290     BIO_set_mem_eof_return(bio, 0);
291     my_param_count = 0;
292     i = BIO_read(bio, buf, sizeof(buf));
293     if (!TEST_int_eq(i, 0)
294         || !TEST_int_eq(my_param_count, 2)
295         || !TEST_ptr_eq(my_param_b[0], bio)
296         || !TEST_int_eq(my_param_oper[0], BIO_CB_READ)
297         || !TEST_ptr_eq(my_param_argp[0], buf)
298         || !TEST_int_eq(my_param_argi[0], sizeof(buf))
299         || !TEST_long_eq(my_param_argl[0], 0L)
300         || !TEST_long_eq(my_param_ret[0], 1L)
301         || !TEST_ptr_eq(my_param_b[1], bio)
302         || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN)
303         || !TEST_ptr_eq(my_param_argp[1], buf)
304         || !TEST_int_eq(my_param_argi[1], sizeof(buf))
305         || !TEST_long_eq(my_param_argl[1], 0L)
306         || !TEST_long_eq(my_param_ret[1], 0L))
307         goto err;
308 
309     my_param_count = 0;
310     i = BIO_puts(bio, test2);
311     if (!TEST_int_eq(i, 5)
312         || !TEST_int_eq(my_param_count, 2)
313         || !TEST_ptr_eq(my_param_b[0], bio)
314         || !TEST_int_eq(my_param_oper[0], BIO_CB_PUTS)
315         || !TEST_ptr_eq(my_param_argp[0], test2)
316         || !TEST_int_eq(my_param_argi[0], 0)
317         || !TEST_long_eq(my_param_argl[0], 0L)
318         || !TEST_long_eq(my_param_ret[0], 1L)
319         || !TEST_ptr_eq(my_param_b[1], bio)
320         || !TEST_int_eq(my_param_oper[1], BIO_CB_PUTS | BIO_CB_RETURN)
321         || !TEST_ptr_eq(my_param_argp[1], test2)
322         || !TEST_int_eq(my_param_argi[1], 0)
323         || !TEST_long_eq(my_param_argl[1], 0L)
324         || !TEST_long_eq(my_param_ret[1], (long)test2len))
325         goto err;
326 
327     my_param_count = 0;
328     i = BIO_free(bio);
329     if (!TEST_int_eq(i, 1)
330         || !TEST_int_eq(my_param_count, 1)
331         || !TEST_ptr_eq(my_param_b[0], bio)
332         || !TEST_int_eq(my_param_oper[0], BIO_CB_FREE)
333         || !TEST_ptr_eq(my_param_argp[0], NULL)
334         || !TEST_int_eq(my_param_argi[0], 0)
335         || !TEST_long_eq(my_param_argl[0], 0L)
336         || !TEST_long_eq(my_param_ret[0], 1L))
337         goto finish;
338 
339     ok = 1;
340     goto finish;
341 
342 err:
343     BIO_free(bio);
344 
345 finish:
346     /* This helps finding memory leaks with ASAN */
347     memset(my_param_b, 0, sizeof(my_param_b));
348     memset(my_param_argp, 0, sizeof(my_param_argp));
349     return ok;
350 }
351 #endif
352 
353 int setup_tests(void)
354 {
355     ADD_TEST(test_bio_callback_ex);
356 #ifndef OPENSSL_NO_DEPRECATED_3_0
357     ADD_TEST(test_bio_callback);
358 #endif
359     return 1;
360 }
361