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