1*e0c4386eSCy Schubert /*
2*e0c4386eSCy Schubert * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
3*e0c4386eSCy Schubert *
4*e0c4386eSCy Schubert * Licensed under the Apache License 2.0 (the "License"). You may not use
5*e0c4386eSCy Schubert * this file except in compliance with the License. You can obtain a copy
6*e0c4386eSCy Schubert * in the file LICENSE in the source distribution or at
7*e0c4386eSCy Schubert * https://www.openssl.org/source/license.html
8*e0c4386eSCy Schubert */
9*e0c4386eSCy Schubert #include <stdio.h>
10*e0c4386eSCy Schubert #include <string.h>
11*e0c4386eSCy Schubert #include <openssl/buffer.h>
12*e0c4386eSCy Schubert #include <openssl/bio.h>
13*e0c4386eSCy Schubert
14*e0c4386eSCy Schubert #include "testutil.h"
15*e0c4386eSCy Schubert
test_bio_memleak(void)16*e0c4386eSCy Schubert static int test_bio_memleak(void)
17*e0c4386eSCy Schubert {
18*e0c4386eSCy Schubert int ok = 0;
19*e0c4386eSCy Schubert BIO *bio;
20*e0c4386eSCy Schubert BUF_MEM bufmem;
21*e0c4386eSCy Schubert static const char str[] = "BIO test\n";
22*e0c4386eSCy Schubert char buf[100];
23*e0c4386eSCy Schubert
24*e0c4386eSCy Schubert bio = BIO_new(BIO_s_mem());
25*e0c4386eSCy Schubert if (!TEST_ptr(bio))
26*e0c4386eSCy Schubert goto finish;
27*e0c4386eSCy Schubert bufmem.length = sizeof(str);
28*e0c4386eSCy Schubert bufmem.data = (char *) str;
29*e0c4386eSCy Schubert bufmem.max = bufmem.length;
30*e0c4386eSCy Schubert BIO_set_mem_buf(bio, &bufmem, BIO_NOCLOSE);
31*e0c4386eSCy Schubert BIO_set_flags(bio, BIO_FLAGS_MEM_RDONLY);
32*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio, buf, sizeof(buf)), sizeof(str)))
33*e0c4386eSCy Schubert goto finish;
34*e0c4386eSCy Schubert if (!TEST_mem_eq(buf, sizeof(str), str, sizeof(str)))
35*e0c4386eSCy Schubert goto finish;
36*e0c4386eSCy Schubert ok = 1;
37*e0c4386eSCy Schubert
38*e0c4386eSCy Schubert finish:
39*e0c4386eSCy Schubert BIO_free(bio);
40*e0c4386eSCy Schubert return ok;
41*e0c4386eSCy Schubert }
42*e0c4386eSCy Schubert
test_bio_get_mem(void)43*e0c4386eSCy Schubert static int test_bio_get_mem(void)
44*e0c4386eSCy Schubert {
45*e0c4386eSCy Schubert int ok = 0;
46*e0c4386eSCy Schubert BIO *bio = NULL;
47*e0c4386eSCy Schubert BUF_MEM *bufmem = NULL;
48*e0c4386eSCy Schubert
49*e0c4386eSCy Schubert bio = BIO_new(BIO_s_mem());
50*e0c4386eSCy Schubert if (!TEST_ptr(bio))
51*e0c4386eSCy Schubert goto finish;
52*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_puts(bio, "Hello World\n"), 12))
53*e0c4386eSCy Schubert goto finish;
54*e0c4386eSCy Schubert BIO_get_mem_ptr(bio, &bufmem);
55*e0c4386eSCy Schubert if (!TEST_ptr(bufmem))
56*e0c4386eSCy Schubert goto finish;
57*e0c4386eSCy Schubert if (!TEST_int_gt(BIO_set_close(bio, BIO_NOCLOSE), 0))
58*e0c4386eSCy Schubert goto finish;
59*e0c4386eSCy Schubert BIO_free(bio);
60*e0c4386eSCy Schubert bio = NULL;
61*e0c4386eSCy Schubert if (!TEST_mem_eq(bufmem->data, bufmem->length, "Hello World\n", 12))
62*e0c4386eSCy Schubert goto finish;
63*e0c4386eSCy Schubert ok = 1;
64*e0c4386eSCy Schubert
65*e0c4386eSCy Schubert finish:
66*e0c4386eSCy Schubert BIO_free(bio);
67*e0c4386eSCy Schubert BUF_MEM_free(bufmem);
68*e0c4386eSCy Schubert return ok;
69*e0c4386eSCy Schubert }
70*e0c4386eSCy Schubert
test_bio_new_mem_buf(void)71*e0c4386eSCy Schubert static int test_bio_new_mem_buf(void)
72*e0c4386eSCy Schubert {
73*e0c4386eSCy Schubert int ok = 0;
74*e0c4386eSCy Schubert BIO *bio;
75*e0c4386eSCy Schubert BUF_MEM *bufmem;
76*e0c4386eSCy Schubert char data[16];
77*e0c4386eSCy Schubert
78*e0c4386eSCy Schubert bio = BIO_new_mem_buf("Hello World\n", 12);
79*e0c4386eSCy Schubert if (!TEST_ptr(bio))
80*e0c4386eSCy Schubert goto finish;
81*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio, data, 5), 5))
82*e0c4386eSCy Schubert goto finish;
83*e0c4386eSCy Schubert if (!TEST_mem_eq(data, 5, "Hello", 5))
84*e0c4386eSCy Schubert goto finish;
85*e0c4386eSCy Schubert if (!TEST_int_gt(BIO_get_mem_ptr(bio, &bufmem), 0))
86*e0c4386eSCy Schubert goto finish;
87*e0c4386eSCy Schubert if (!TEST_int_lt(BIO_write(bio, "test", 4), 0))
88*e0c4386eSCy Schubert goto finish;
89*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio, data, 16), 7))
90*e0c4386eSCy Schubert goto finish;
91*e0c4386eSCy Schubert if (!TEST_mem_eq(data, 7, " World\n", 7))
92*e0c4386eSCy Schubert goto finish;
93*e0c4386eSCy Schubert if (!TEST_int_gt(BIO_reset(bio), 0))
94*e0c4386eSCy Schubert goto finish;
95*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio, data, 16), 12))
96*e0c4386eSCy Schubert goto finish;
97*e0c4386eSCy Schubert if (!TEST_mem_eq(data, 12, "Hello World\n", 12))
98*e0c4386eSCy Schubert goto finish;
99*e0c4386eSCy Schubert ok = 1;
100*e0c4386eSCy Schubert
101*e0c4386eSCy Schubert finish:
102*e0c4386eSCy Schubert BIO_free(bio);
103*e0c4386eSCy Schubert return ok;
104*e0c4386eSCy Schubert }
105*e0c4386eSCy Schubert
test_bio_rdonly_mem_buf(void)106*e0c4386eSCy Schubert static int test_bio_rdonly_mem_buf(void)
107*e0c4386eSCy Schubert {
108*e0c4386eSCy Schubert int ok = 0;
109*e0c4386eSCy Schubert BIO *bio, *bio2 = NULL;
110*e0c4386eSCy Schubert BUF_MEM *bufmem;
111*e0c4386eSCy Schubert char data[16];
112*e0c4386eSCy Schubert
113*e0c4386eSCy Schubert bio = BIO_new_mem_buf("Hello World\n", 12);
114*e0c4386eSCy Schubert if (!TEST_ptr(bio))
115*e0c4386eSCy Schubert goto finish;
116*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio, data, 5), 5))
117*e0c4386eSCy Schubert goto finish;
118*e0c4386eSCy Schubert if (!TEST_mem_eq(data, 5, "Hello", 5))
119*e0c4386eSCy Schubert goto finish;
120*e0c4386eSCy Schubert if (!TEST_int_gt(BIO_get_mem_ptr(bio, &bufmem), 0))
121*e0c4386eSCy Schubert goto finish;
122*e0c4386eSCy Schubert (void)BIO_set_close(bio, BIO_NOCLOSE);
123*e0c4386eSCy Schubert
124*e0c4386eSCy Schubert bio2 = BIO_new(BIO_s_mem());
125*e0c4386eSCy Schubert if (!TEST_ptr(bio2))
126*e0c4386eSCy Schubert goto finish;
127*e0c4386eSCy Schubert BIO_set_mem_buf(bio2, bufmem, BIO_CLOSE);
128*e0c4386eSCy Schubert BIO_set_flags(bio2, BIO_FLAGS_MEM_RDONLY);
129*e0c4386eSCy Schubert
130*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio2, data, 16), 7))
131*e0c4386eSCy Schubert goto finish;
132*e0c4386eSCy Schubert if (!TEST_mem_eq(data, 7, " World\n", 7))
133*e0c4386eSCy Schubert goto finish;
134*e0c4386eSCy Schubert if (!TEST_int_gt(BIO_reset(bio2), 0))
135*e0c4386eSCy Schubert goto finish;
136*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio2, data, 16), 7))
137*e0c4386eSCy Schubert goto finish;
138*e0c4386eSCy Schubert if (!TEST_mem_eq(data, 7, " World\n", 7))
139*e0c4386eSCy Schubert goto finish;
140*e0c4386eSCy Schubert ok = 1;
141*e0c4386eSCy Schubert
142*e0c4386eSCy Schubert finish:
143*e0c4386eSCy Schubert BIO_free(bio);
144*e0c4386eSCy Schubert BIO_free(bio2);
145*e0c4386eSCy Schubert return ok;
146*e0c4386eSCy Schubert }
147*e0c4386eSCy Schubert
test_bio_rdwr_rdonly(void)148*e0c4386eSCy Schubert static int test_bio_rdwr_rdonly(void)
149*e0c4386eSCy Schubert {
150*e0c4386eSCy Schubert int ok = 0;
151*e0c4386eSCy Schubert BIO *bio = NULL;
152*e0c4386eSCy Schubert char data[16];
153*e0c4386eSCy Schubert
154*e0c4386eSCy Schubert bio = BIO_new(BIO_s_mem());
155*e0c4386eSCy Schubert if (!TEST_ptr(bio))
156*e0c4386eSCy Schubert goto finish;
157*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_puts(bio, "Hello World\n"), 12))
158*e0c4386eSCy Schubert goto finish;
159*e0c4386eSCy Schubert
160*e0c4386eSCy Schubert BIO_set_flags(bio, BIO_FLAGS_MEM_RDONLY);
161*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio, data, 16), 12))
162*e0c4386eSCy Schubert goto finish;
163*e0c4386eSCy Schubert if (!TEST_mem_eq(data, 12, "Hello World\n", 12))
164*e0c4386eSCy Schubert goto finish;
165*e0c4386eSCy Schubert if (!TEST_int_gt(BIO_reset(bio), 0))
166*e0c4386eSCy Schubert goto finish;
167*e0c4386eSCy Schubert
168*e0c4386eSCy Schubert BIO_clear_flags(bio, BIO_FLAGS_MEM_RDONLY);
169*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_puts(bio, "Hi!\n"), 4))
170*e0c4386eSCy Schubert goto finish;
171*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio, data, 16), 16))
172*e0c4386eSCy Schubert goto finish;
173*e0c4386eSCy Schubert
174*e0c4386eSCy Schubert if (!TEST_mem_eq(data, 16, "Hello World\nHi!\n", 16))
175*e0c4386eSCy Schubert goto finish;
176*e0c4386eSCy Schubert
177*e0c4386eSCy Schubert ok = 1;
178*e0c4386eSCy Schubert
179*e0c4386eSCy Schubert finish:
180*e0c4386eSCy Schubert BIO_free(bio);
181*e0c4386eSCy Schubert return ok;
182*e0c4386eSCy Schubert }
183*e0c4386eSCy Schubert
test_bio_nonclear_rst(void)184*e0c4386eSCy Schubert static int test_bio_nonclear_rst(void)
185*e0c4386eSCy Schubert {
186*e0c4386eSCy Schubert int ok = 0;
187*e0c4386eSCy Schubert BIO *bio = NULL;
188*e0c4386eSCy Schubert char data[16];
189*e0c4386eSCy Schubert
190*e0c4386eSCy Schubert bio = BIO_new(BIO_s_mem());
191*e0c4386eSCy Schubert if (!TEST_ptr(bio))
192*e0c4386eSCy Schubert goto finish;
193*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_puts(bio, "Hello World\n"), 12))
194*e0c4386eSCy Schubert goto finish;
195*e0c4386eSCy Schubert
196*e0c4386eSCy Schubert BIO_set_flags(bio, BIO_FLAGS_NONCLEAR_RST);
197*e0c4386eSCy Schubert
198*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio, data, 16), 12))
199*e0c4386eSCy Schubert goto finish;
200*e0c4386eSCy Schubert if (!TEST_mem_eq(data, 12, "Hello World\n", 12))
201*e0c4386eSCy Schubert goto finish;
202*e0c4386eSCy Schubert if (!TEST_int_gt(BIO_reset(bio), 0))
203*e0c4386eSCy Schubert goto finish;
204*e0c4386eSCy Schubert
205*e0c4386eSCy Schubert if (!TEST_int_eq(BIO_read(bio, data, 16), 12))
206*e0c4386eSCy Schubert goto finish;
207*e0c4386eSCy Schubert if (!TEST_mem_eq(data, 12, "Hello World\n", 12))
208*e0c4386eSCy Schubert goto finish;
209*e0c4386eSCy Schubert
210*e0c4386eSCy Schubert BIO_clear_flags(bio, BIO_FLAGS_NONCLEAR_RST);
211*e0c4386eSCy Schubert if (!TEST_int_gt(BIO_reset(bio), 0))
212*e0c4386eSCy Schubert goto finish;
213*e0c4386eSCy Schubert
214*e0c4386eSCy Schubert if (!TEST_int_lt(BIO_read(bio, data, 16), 1))
215*e0c4386eSCy Schubert goto finish;
216*e0c4386eSCy Schubert
217*e0c4386eSCy Schubert ok = 1;
218*e0c4386eSCy Schubert
219*e0c4386eSCy Schubert finish:
220*e0c4386eSCy Schubert BIO_free(bio);
221*e0c4386eSCy Schubert return ok;
222*e0c4386eSCy Schubert }
223*e0c4386eSCy Schubert
224*e0c4386eSCy Schubert static int error_callback_fired;
BIO_error_callback(BIO * bio,int cmd,const char * argp,size_t len,int argi,long argl,int ret,size_t * processed)225*e0c4386eSCy Schubert static long BIO_error_callback(BIO *bio, int cmd, const char *argp,
226*e0c4386eSCy Schubert size_t len, int argi,
227*e0c4386eSCy Schubert long argl, int ret, size_t *processed)
228*e0c4386eSCy Schubert {
229*e0c4386eSCy Schubert if ((cmd & (BIO_CB_READ | BIO_CB_RETURN)) != 0) {
230*e0c4386eSCy Schubert error_callback_fired = 1;
231*e0c4386eSCy Schubert ret = 0; /* fail for read operations to simulate error in input BIO */
232*e0c4386eSCy Schubert }
233*e0c4386eSCy Schubert return ret;
234*e0c4386eSCy Schubert }
235*e0c4386eSCy Schubert
236*e0c4386eSCy Schubert /* Checks i2d_ASN1_bio_stream() is freeing all memory when input BIO ends unexpectedly. */
test_bio_i2d_ASN1_mime(void)237*e0c4386eSCy Schubert static int test_bio_i2d_ASN1_mime(void)
238*e0c4386eSCy Schubert {
239*e0c4386eSCy Schubert int ok = 0;
240*e0c4386eSCy Schubert BIO *bio = NULL, *out = NULL;
241*e0c4386eSCy Schubert BUF_MEM bufmem;
242*e0c4386eSCy Schubert static const char str[] = "BIO mime test\n";
243*e0c4386eSCy Schubert PKCS7 *p7 = NULL;
244*e0c4386eSCy Schubert
245*e0c4386eSCy Schubert if (!TEST_ptr(bio = BIO_new(BIO_s_mem())))
246*e0c4386eSCy Schubert goto finish;
247*e0c4386eSCy Schubert
248*e0c4386eSCy Schubert bufmem.length = sizeof(str);
249*e0c4386eSCy Schubert bufmem.data = (char *) str;
250*e0c4386eSCy Schubert bufmem.max = bufmem.length;
251*e0c4386eSCy Schubert BIO_set_mem_buf(bio, &bufmem, BIO_NOCLOSE);
252*e0c4386eSCy Schubert BIO_set_flags(bio, BIO_FLAGS_MEM_RDONLY);
253*e0c4386eSCy Schubert BIO_set_callback_ex(bio, BIO_error_callback);
254*e0c4386eSCy Schubert
255*e0c4386eSCy Schubert if (!TEST_ptr(out = BIO_new(BIO_s_mem())))
256*e0c4386eSCy Schubert goto finish;
257*e0c4386eSCy Schubert if (!TEST_ptr(p7 = PKCS7_new()))
258*e0c4386eSCy Schubert goto finish;
259*e0c4386eSCy Schubert if (!TEST_true(PKCS7_set_type(p7, NID_pkcs7_data)))
260*e0c4386eSCy Schubert goto finish;
261*e0c4386eSCy Schubert
262*e0c4386eSCy Schubert error_callback_fired = 0;
263*e0c4386eSCy Schubert
264*e0c4386eSCy Schubert if (!TEST_false(i2d_ASN1_bio_stream(out, (ASN1_VALUE*) p7, bio,
265*e0c4386eSCy Schubert SMIME_STREAM | SMIME_BINARY,
266*e0c4386eSCy Schubert ASN1_ITEM_rptr(PKCS7))))
267*e0c4386eSCy Schubert goto finish;
268*e0c4386eSCy Schubert
269*e0c4386eSCy Schubert if (!TEST_int_eq(error_callback_fired, 1))
270*e0c4386eSCy Schubert goto finish;
271*e0c4386eSCy Schubert
272*e0c4386eSCy Schubert ok = 1;
273*e0c4386eSCy Schubert
274*e0c4386eSCy Schubert finish:
275*e0c4386eSCy Schubert BIO_free(bio);
276*e0c4386eSCy Schubert BIO_free(out);
277*e0c4386eSCy Schubert PKCS7_free(p7);
278*e0c4386eSCy Schubert return ok;
279*e0c4386eSCy Schubert }
280*e0c4386eSCy Schubert
setup_tests(void)281*e0c4386eSCy Schubert int setup_tests(void)
282*e0c4386eSCy Schubert {
283*e0c4386eSCy Schubert ADD_TEST(test_bio_memleak);
284*e0c4386eSCy Schubert ADD_TEST(test_bio_get_mem);
285*e0c4386eSCy Schubert ADD_TEST(test_bio_new_mem_buf);
286*e0c4386eSCy Schubert ADD_TEST(test_bio_rdonly_mem_buf);
287*e0c4386eSCy Schubert ADD_TEST(test_bio_rdwr_rdonly);
288*e0c4386eSCy Schubert ADD_TEST(test_bio_nonclear_rst);
289*e0c4386eSCy Schubert ADD_TEST(test_bio_i2d_ASN1_mime);
290*e0c4386eSCy Schubert return 1;
291*e0c4386eSCy Schubert }
292