xref: /freebsd/crypto/openssl/test/bio_callback_test.c (revision b59017c5cad90d0f09a59e68c00457b7faf93e7c)
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