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