1 /* $OpenBSD: bio_mem.c,v 1.1 2022/12/08 17:49:02 tb Exp $ */ 2 /* 3 * Copyright (c) 2022 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <err.h> 19 #include <stdint.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 24 #include <openssl/bio.h> 25 #include <openssl/buffer.h> 26 27 static int 28 bio_mem_test(void) 29 { 30 uint8_t *data = NULL; 31 size_t data_len; 32 uint8_t *rodata; 33 long rodata_len; 34 BUF_MEM *pbuf; 35 BUF_MEM *buf = NULL; 36 BIO *bio = NULL; 37 int ret; 38 int failed = 1; 39 40 data_len = 4096; 41 if ((data = malloc(data_len)) == NULL) 42 err(1, "malloc"); 43 44 memset(data, 0xdb, data_len); 45 data[0] = 0x01; 46 data[data_len - 1] = 0xff; 47 48 if ((bio = BIO_new(BIO_s_mem())) == NULL) { 49 fprintf(stderr, "FAIL: BIO_new() returned NULL\n"); 50 goto failure; 51 } 52 if ((ret = BIO_write(bio, data, data_len)) != (int)data_len) { 53 fprintf(stderr, "FAIL: BIO_write() = %d, want %zu\n", ret, 54 data_len); 55 goto failure; 56 } 57 if ((rodata_len = BIO_get_mem_data(bio, &rodata)) != (long)data_len) { 58 fprintf(stderr, "FAIL: BIO_get_mem_data() = %ld, want %zu\n", 59 rodata_len, data_len); 60 goto failure; 61 } 62 if (rodata[0] != 0x01) { 63 fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", rodata[0], 0x01); 64 goto failure; 65 } 66 if (rodata[rodata_len - 1] != 0xff) { 67 fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", 68 rodata[rodata_len - 1], 0xff); 69 goto failure; 70 } 71 72 if (!BIO_get_mem_ptr(bio, &pbuf)) { 73 fprintf(stderr, "FAIL: BIO_get_mem_ptr() failed\n"); 74 goto failure; 75 } 76 if (pbuf->length != data_len) { 77 fprintf(stderr, "FAIL: Got buffer with length %zu, want %zu\n", 78 pbuf->length, data_len); 79 goto failure; 80 } 81 if (memcmp(pbuf->data, data, data_len) != 0) { 82 fprintf(stderr, "FAIL: Got buffer with differing data\n"); 83 goto failure; 84 } 85 pbuf = NULL; 86 87 if ((buf = BUF_MEM_new()) == NULL) { 88 fprintf(stderr, "FAIL: BUF_MEM_new() returned NULL\n"); 89 goto failure; 90 } 91 if (!BIO_set_mem_buf(bio, buf, BIO_NOCLOSE)) { 92 fprintf(stderr, "FAIL: BUF_set_mem_buf() failed\n"); 93 goto failure; 94 } 95 if ((ret = BIO_puts(bio, "Hello\n")) != 6) { 96 fprintf(stderr, "FAIL: BUF_puts() = %d, want %d\n", ret, 6); 97 goto failure; 98 } 99 if ((ret = BIO_puts(bio, "World\n")) != 6) { 100 fprintf(stderr, "FAIL: BUF_puts() = %d, want %d\n", ret, 6); 101 goto failure; 102 } 103 if (buf->length != 12) { 104 fprintf(stderr, "FAIL: buffer has length %zu, want %d\n", 105 buf->length, 12); 106 goto failure; 107 } 108 buf->length = 11; 109 if ((ret = BIO_gets(bio, data, data_len)) != 6) { 110 fprintf(stderr, "FAIL: BUF_gets() = %d, want %d\n", ret, 6); 111 goto failure; 112 } 113 if (strcmp(data, "Hello\n") != 0) { 114 fprintf(stderr, "FAIL: BUF_gets() returned '%s', want '%s'\n", 115 data, "Hello\\n"); 116 goto failure; 117 } 118 if ((ret = BIO_gets(bio, data, data_len)) != 5) { 119 fprintf(stderr, "FAIL: BUF_gets() = %d, want %d\n", ret, 5); 120 goto failure; 121 } 122 if (strcmp(data, "World") != 0) { 123 fprintf(stderr, "FAIL: BUF_gets() returned '%s', want '%s'\n", 124 data, "World"); 125 goto failure; 126 } 127 128 if (!BIO_eof(bio)) { 129 fprintf(stderr, "FAIL: BIO is not EOF\n"); 130 goto failure; 131 } 132 if ((ret = BIO_read(bio, data, data_len)) != -1) { 133 fprintf(stderr, "FAIL: BIO_read() = %d, want -1\n", ret); 134 goto failure; 135 } 136 if (!BIO_set_mem_eof_return(bio, -2)) { 137 fprintf(stderr, "FAIL: BIO_set_mem_eof_return() failed\n"); 138 goto failure; 139 } 140 if ((ret = BIO_read(bio, data, data_len)) != -2) { 141 fprintf(stderr, "FAIL: BIO_read() = %d, want -2\n", ret); 142 goto failure; 143 } 144 145 failed = 0; 146 147 failure: 148 free(data); 149 BUF_MEM_free(buf); 150 BIO_free(bio); 151 152 return failed; 153 } 154 155 static int 156 bio_mem_small_io_test(void) 157 { 158 uint8_t buf[2]; 159 int i, j, ret; 160 BIO *bio; 161 int failed = 1; 162 163 memset(buf, 0xdb, sizeof(buf)); 164 165 if ((bio = BIO_new(BIO_s_mem())) == NULL) { 166 fprintf(stderr, "FAIL: BIO_new() returned NULL\n"); 167 goto failure; 168 } 169 170 for (i = 0; i < 100; i++) { 171 if (!BIO_reset(bio)) { 172 fprintf(stderr, "FAIL: BIO_reset() failed\n"); 173 goto failure; 174 } 175 for (j = 0; j < 25000; j++) { 176 ret = BIO_write(bio, buf, sizeof(buf)); 177 if (ret != sizeof(buf)) { 178 fprintf(stderr, "FAIL: BIO_write() = %d, " 179 "want %zu\n", ret, sizeof(buf)); 180 goto failure; 181 } 182 } 183 for (j = 0; j < 25000; j++) { 184 ret = BIO_read(bio, buf, sizeof(buf)); 185 if (ret != sizeof(buf)) { 186 fprintf(stderr, "FAIL: BIO_read() = %d, " 187 "want %zu\n", ret, sizeof(buf)); 188 goto failure; 189 } 190 ret = BIO_write(bio, buf, sizeof(buf)); 191 if (ret != sizeof(buf)) { 192 fprintf(stderr, "FAIL: BIO_write() = %d, " 193 "want %zu\n", ret, sizeof(buf)); 194 goto failure; 195 } 196 } 197 for (j = 0; j < 25000; j++) { 198 ret = BIO_read(bio, buf, sizeof(buf)); 199 if (ret != sizeof(buf)) { 200 fprintf(stderr, "FAIL: BIO_read() = %d, " 201 "want %zu\n", ret, sizeof(buf)); 202 goto failure; 203 } 204 } 205 if (!BIO_eof(bio)) { 206 fprintf(stderr, "FAIL: BIO not EOF\n"); 207 goto failure; 208 } 209 } 210 211 if (buf[0] != 0xdb || buf[1] != 0xdb) { 212 fprintf(stderr, "FAIL: buf = {0x%x, 0x%x}, want {0xdb, 0xdb}\n", 213 buf[0], buf[1]); 214 goto failure; 215 } 216 217 failed = 0; 218 219 failure: 220 BIO_free(bio); 221 222 return failed; 223 } 224 225 static int 226 bio_mem_readonly_test(void) 227 { 228 uint8_t *data = NULL; 229 size_t data_len; 230 uint8_t buf[2048]; 231 BIO *bio = NULL; 232 int ret; 233 int failed = 1; 234 235 data_len = 4096; 236 if ((data = malloc(data_len)) == NULL) 237 err(1, "malloc"); 238 239 memset(data, 0xdb, data_len); 240 data[0] = 0x01; 241 data[data_len - 1] = 0xff; 242 243 if ((bio = BIO_new_mem_buf(data, data_len)) == NULL) { 244 fprintf(stderr, "FAIL: BIO_new_mem_buf failed\n"); 245 goto failure; 246 } 247 if ((ret = BIO_read(bio, buf, 1)) != 1) { 248 fprintf(stderr, "FAIL: BIO_read() = %d, want %zu\n", ret, 249 sizeof(buf)); 250 goto failure; 251 } 252 if (buf[0] != 0x01) { 253 fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[0], 0x01); 254 goto failure; 255 } 256 if ((ret = BIO_read(bio, buf, sizeof(buf))) != sizeof(buf)) { 257 fprintf(stderr, "FAIL: BIO_read() = %d, want %zu\n", ret, 258 sizeof(buf)); 259 goto failure; 260 } 261 if (buf[0] != 0xdb) { 262 fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[0], 0xdb); 263 goto failure; 264 } 265 if ((ret = BIO_write(bio, buf, 1)) != -1) { 266 fprintf(stderr, "FAIL: BIO_write() = %d, want -1\n", ret); 267 goto failure; 268 } 269 if (BIO_eof(bio)) { 270 fprintf(stderr, "FAIL: BIO is EOF\n"); 271 goto failure; 272 } 273 if (BIO_ctrl_pending(bio) != 2047) { 274 fprintf(stderr, "FAIL: BIO_ctrl_pending() = %zu, want 2047\n", 275 BIO_ctrl_pending(bio)); 276 goto failure; 277 } 278 if ((ret = BIO_read(bio, buf, sizeof(buf))) != 2047) { 279 fprintf(stderr, "FAIL: BIO_read() = %d, want 2047\n", ret); 280 goto failure; 281 } 282 if (buf[2045] != 0xdb) { 283 fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[2045], 0xdb); 284 goto failure; 285 } 286 if (buf[2046] != 0xff) { 287 fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[2046], 0xff); 288 goto failure; 289 } 290 if (!BIO_eof(bio)) { 291 fprintf(stderr, "FAIL: BIO is not EOF\n"); 292 goto failure; 293 } 294 if (BIO_ctrl_pending(bio) != 0) { 295 fprintf(stderr, "FAIL: BIO_ctrl_pending() = %zu, want 0\n", 296 BIO_ctrl_pending(bio)); 297 goto failure; 298 } 299 300 if (!BIO_reset(bio)) { 301 fprintf(stderr, "FAIL: failed to reset bio\n"); 302 goto failure; 303 } 304 if (BIO_eof(bio)) { 305 fprintf(stderr, "FAIL: BIO is EOF\n"); 306 goto failure; 307 } 308 if (BIO_ctrl_pending(bio) != 4096) { 309 fprintf(stderr, "FAIL: BIO_ctrl_pending() = %zu, want 4096\n", 310 BIO_ctrl_pending(bio)); 311 goto failure; 312 } 313 if ((ret = BIO_read(bio, buf, 2)) != 2) { 314 fprintf(stderr, "FAIL: BIO_read() = %d, want 2\n", ret); 315 goto failure; 316 } 317 if (buf[0] != 0x01) { 318 fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[0], 0x01); 319 goto failure; 320 } 321 if (buf[1] != 0xdb) { 322 fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[1], 0xdb); 323 goto failure; 324 } 325 326 failed = 0; 327 328 failure: 329 BIO_free(bio); 330 free(data); 331 332 return failed; 333 } 334 335 int 336 main(int argc, char **argv) 337 { 338 int failed = 0; 339 340 failed |= bio_mem_test(); 341 failed |= bio_mem_small_io_test(); 342 failed |= bio_mem_readonly_test(); 343 344 return failed; 345 } 346