1 /* ==================================================================== 2 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * 3. All advertising materials mentioning features or use of this 17 * software must display the following acknowledgment: 18 * "This product includes software developed by the OpenSSL Project 19 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 20 * 21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22 * endorse or promote products derived from this software without 23 * prior written permission. For written permission, please contact 24 * openssl-core (at) openssl.org. 25 * 26 * 5. Products derived from this software may not be called "OpenSSL" 27 * nor may "OpenSSL" appear in their names without prior written 28 * permission of the OpenSSL Project. 29 * 30 * 6. Redistributions of any form whatsoever must retain the following 31 * acknowledgment: 32 * "This product includes software developed by the OpenSSL Project 33 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46 * OF THE POSSIBILITY OF SUCH DAMAGE. 47 * ==================================================================== 48 * 49 * This product includes cryptographic software written by Eric Young 50 * (eay (at) cryptsoft.com). This product includes software written by Tim 51 * Hudson (tjh (at) cryptsoft.com). */ 52 53 #include <openssl/bio.h> 54 55 #include <assert.h> 56 #include <string.h> 57 58 #include <openssl/buf.h> 59 #include <openssl/err.h> 60 #include <openssl/mem.h> 61 62 63 struct bio_bio_st { 64 BIO *peer; /* NULL if buf == NULL. 65 * If peer != NULL, then peer->ptr is also a bio_bio_st, 66 * and its "peer" member points back to us. 67 * peer != NULL iff init != 0 in the BIO. */ 68 69 /* This is for what we write (i.e. reading uses peer's struct): */ 70 int closed; /* valid iff peer != NULL */ 71 size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ 72 size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ 73 size_t size; 74 uint8_t *buf; /* "size" elements (if != NULL) */ 75 char buf_externally_allocated; /* true iff buf was externally allocated. */ 76 77 char zero_copy_read_lock; /* true iff a zero copy read operation 78 * is in progress. */ 79 char zero_copy_write_lock; /* true iff a zero copy write operation 80 * is in progress. */ 81 82 size_t request; /* valid iff peer != NULL; 0 if len != 0, 83 * otherwise set by peer to number of bytes 84 * it (unsuccessfully) tried to read, 85 * never more than buffer space (size-len) warrants. */ 86 }; 87 88 static int bio_new(BIO *bio) { 89 struct bio_bio_st *b; 90 91 b = OPENSSL_malloc(sizeof *b); 92 if (b == NULL) { 93 return 0; 94 } 95 memset(b, 0, sizeof(struct bio_bio_st)); 96 97 b->size = 17 * 1024; /* enough for one TLS record (just a default) */ 98 bio->ptr = b; 99 return 1; 100 } 101 102 static void bio_destroy_pair(BIO *bio) { 103 struct bio_bio_st *b = bio->ptr; 104 BIO *peer_bio; 105 struct bio_bio_st *peer_b; 106 107 if (b == NULL) { 108 return; 109 } 110 111 peer_bio = b->peer; 112 if (peer_bio == NULL) { 113 return; 114 } 115 116 peer_b = peer_bio->ptr; 117 118 assert(peer_b != NULL); 119 assert(peer_b->peer == bio); 120 121 peer_b->peer = NULL; 122 peer_bio->init = 0; 123 assert(peer_b->buf != NULL); 124 peer_b->len = 0; 125 peer_b->offset = 0; 126 127 b->peer = NULL; 128 bio->init = 0; 129 assert(b->buf != NULL); 130 b->len = 0; 131 b->offset = 0; 132 } 133 134 static int bio_free(BIO *bio) { 135 struct bio_bio_st *b; 136 137 if (bio == NULL) { 138 return 0; 139 } 140 b = bio->ptr; 141 142 assert(b != NULL); 143 144 if (b->peer) { 145 bio_destroy_pair(bio); 146 } 147 148 if (!b->buf_externally_allocated) { 149 OPENSSL_free(b->buf); 150 } 151 152 OPENSSL_free(b); 153 154 return 1; 155 } 156 157 static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b, 158 uint8_t** out_read_buf, 159 size_t* out_buf_offset) { 160 size_t max_available; 161 if (peer_b->len > peer_b->size - peer_b->offset) { 162 /* Only the first half of the ring buffer can be read. */ 163 max_available = peer_b->size - peer_b->offset; 164 } else { 165 max_available = peer_b->len; 166 } 167 168 *out_read_buf = peer_b->buf; 169 *out_buf_offset = peer_b->offset; 170 return max_available; 171 } 172 173 int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf, 174 size_t* out_buf_offset, 175 size_t* out_available_bytes) { 176 struct bio_bio_st* b; 177 struct bio_bio_st* peer_b; 178 size_t max_available; 179 *out_available_bytes = 0; 180 181 BIO_clear_retry_flags(bio); 182 183 if (!bio->init) { 184 OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED); 185 return 0; 186 } 187 188 b = bio->ptr; 189 190 if (!b || !b->peer) { 191 OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); 192 return 0; 193 } 194 195 peer_b = b->peer->ptr; 196 if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) { 197 OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); 198 return 0; 199 } 200 201 if (peer_b->zero_copy_read_lock) { 202 OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); 203 return 0; 204 } 205 206 peer_b->request = 0; /* Is not used by zero-copy API. */ 207 208 max_available = 209 bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset); 210 211 assert(peer_b->buf != NULL); 212 if (max_available > 0) { 213 peer_b->zero_copy_read_lock = 1; 214 } 215 216 *out_available_bytes = max_available; 217 return 1; 218 } 219 220 int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) { 221 struct bio_bio_st* b; 222 struct bio_bio_st* peer_b; 223 size_t max_available; 224 size_t dummy_read_offset; 225 uint8_t* dummy_read_buf; 226 227 assert(BIO_get_retry_flags(bio) == 0); 228 229 if (!bio->init) { 230 OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED); 231 return 0; 232 } 233 234 b = bio->ptr; 235 236 if (!b || !b->peer) { 237 OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); 238 return 0; 239 } 240 241 peer_b = b->peer->ptr; 242 if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) { 243 OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); 244 return 0; 245 } 246 247 if (!peer_b->zero_copy_read_lock) { 248 OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); 249 return 0; 250 } 251 252 max_available = 253 bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset); 254 if (bytes_read > max_available) { 255 OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); 256 return 0; 257 } 258 259 assert(peer_b->len >= bytes_read); 260 peer_b->len -= bytes_read; 261 assert(peer_b->offset + bytes_read <= peer_b->size); 262 263 /* Move read offset. If zero_copy_write_lock == 1 we must advance the 264 * offset even if buffer becomes empty, to make sure 265 * write_offset = (offset + len) mod size does not change. */ 266 if (peer_b->offset + bytes_read == peer_b->size || 267 (!peer_b->zero_copy_write_lock && peer_b->len == 0)) { 268 peer_b->offset = 0; 269 } else { 270 peer_b->offset += bytes_read; 271 } 272 273 bio->num_read += bytes_read; 274 peer_b->zero_copy_read_lock = 0; 275 return 1; 276 } 277 278 static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b, 279 uint8_t** out_write_buf, 280 size_t* out_buf_offset) { 281 size_t write_offset; 282 size_t max_available; 283 284 assert(b->len <= b->size); 285 286 write_offset = b->offset + b->len; 287 288 if (write_offset >= b->size) { 289 /* Only the first half of the ring buffer can be written to. */ 290 write_offset -= b->size; 291 /* write up to the start of the ring buffer. */ 292 max_available = b->offset - write_offset; 293 } else { 294 /* write up to the end the buffer. */ 295 max_available = b->size - write_offset; 296 } 297 298 *out_write_buf = b->buf; 299 *out_buf_offset = write_offset; 300 return max_available; 301 } 302 303 int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf, 304 size_t* out_buf_offset, 305 size_t* out_available_bytes) { 306 struct bio_bio_st* b; 307 struct bio_bio_st* peer_b; 308 size_t max_available; 309 310 *out_available_bytes = 0; 311 BIO_clear_retry_flags(bio); 312 313 if (!bio->init) { 314 OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED); 315 return 0; 316 } 317 318 b = bio->ptr; 319 320 if (!b || !b->buf || !b->peer) { 321 OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); 322 return 0; 323 } 324 peer_b = b->peer->ptr; 325 if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) { 326 OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); 327 return 0; 328 } 329 330 assert(b->buf != NULL); 331 332 if (b->zero_copy_write_lock) { 333 OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); 334 return 0; 335 } 336 337 b->request = 0; 338 if (b->closed) { 339 /* Bio is already closed. */ 340 OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE); 341 return 0; 342 } 343 344 max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset); 345 346 if (max_available > 0) { 347 b->zero_copy_write_lock = 1; 348 } 349 350 *out_available_bytes = max_available; 351 return 1; 352 } 353 354 int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) { 355 struct bio_bio_st* b; 356 struct bio_bio_st* peer_b; 357 358 size_t rest; 359 size_t dummy_write_offset; 360 uint8_t* dummy_write_buf; 361 362 if (!bio->init) { 363 OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED); 364 return 0; 365 } 366 367 b = bio->ptr; 368 369 if (!b || !b->buf || !b->peer) { 370 OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); 371 return 0; 372 } 373 peer_b = b->peer->ptr; 374 if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) { 375 OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD); 376 return 0; 377 } 378 379 b->request = 0; 380 if (b->closed) { 381 /* BIO is already closed. */ 382 OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE); 383 return 0; 384 } 385 386 if (!b->zero_copy_write_lock) { 387 OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); 388 return 0; 389 } 390 391 rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset); 392 393 if (bytes_written > rest) { 394 OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT); 395 return 0; 396 } 397 398 bio->num_write += bytes_written; 399 /* Move write offset. */ 400 b->len += bytes_written; 401 b->zero_copy_write_lock = 0; 402 return 1; 403 } 404 405 static int bio_read(BIO *bio, char *buf, int size_) { 406 size_t size = size_; 407 size_t rest; 408 struct bio_bio_st *b, *peer_b; 409 410 BIO_clear_retry_flags(bio); 411 412 if (!bio->init) { 413 return 0; 414 } 415 416 b = bio->ptr; 417 assert(b != NULL); 418 assert(b->peer != NULL); 419 peer_b = b->peer->ptr; 420 assert(peer_b != NULL); 421 assert(peer_b->buf != NULL); 422 423 peer_b->request = 0; /* will be set in "retry_read" situation */ 424 425 if (buf == NULL || size == 0 || peer_b->zero_copy_read_lock) { 426 return 0; 427 } 428 429 if (peer_b->len == 0) { 430 if (peer_b->closed) { 431 return 0; /* writer has closed, and no data is left */ 432 } else { 433 BIO_set_retry_read(bio); /* buffer is empty */ 434 if (size <= peer_b->size) { 435 peer_b->request = size; 436 } else { 437 /* don't ask for more than the peer can 438 * deliver in one write */ 439 peer_b->request = peer_b->size; 440 } 441 return -1; 442 } 443 } 444 445 /* we can read */ 446 if (peer_b->len < size) { 447 size = peer_b->len; 448 } 449 450 /* now read "size" bytes */ 451 rest = size; 452 453 assert(rest > 0); 454 /* one or two iterations */ 455 do { 456 size_t chunk; 457 458 assert(rest <= peer_b->len); 459 if (peer_b->offset + rest <= peer_b->size) { 460 chunk = rest; 461 } else { 462 /* wrap around ring buffer */ 463 chunk = peer_b->size - peer_b->offset; 464 } 465 assert(peer_b->offset + chunk <= peer_b->size); 466 467 memcpy(buf, peer_b->buf + peer_b->offset, chunk); 468 469 peer_b->len -= chunk; 470 /* If zero_copy_write_lock == 1 we must advance the offset even if buffer 471 * becomes empty, to make sure write_offset = (offset + len) % size 472 * does not change. */ 473 if (peer_b->len || peer_b->zero_copy_write_lock) { 474 peer_b->offset += chunk; 475 assert(peer_b->offset <= peer_b->size); 476 if (peer_b->offset == peer_b->size) { 477 peer_b->offset = 0; 478 } 479 buf += chunk; 480 } else { 481 /* buffer now empty, no need to advance "buf" */ 482 assert(chunk == rest); 483 peer_b->offset = 0; 484 } 485 rest -= chunk; 486 } while (rest); 487 488 return size; 489 } 490 491 static int bio_write(BIO *bio, const char *buf, int num_) { 492 size_t num = num_; 493 size_t rest; 494 struct bio_bio_st *b; 495 496 BIO_clear_retry_flags(bio); 497 498 if (!bio->init || buf == NULL || num == 0) { 499 return 0; 500 } 501 502 b = bio->ptr; 503 assert(b != NULL); 504 assert(b->peer != NULL); 505 assert(b->buf != NULL); 506 507 if (b->zero_copy_write_lock) { 508 return 0; 509 } 510 511 b->request = 0; 512 if (b->closed) { 513 /* we already closed */ 514 OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE); 515 return -1; 516 } 517 518 assert(b->len <= b->size); 519 520 if (b->len == b->size) { 521 BIO_set_retry_write(bio); /* buffer is full */ 522 return -1; 523 } 524 525 /* we can write */ 526 if (num > b->size - b->len) { 527 num = b->size - b->len; 528 } 529 530 /* now write "num" bytes */ 531 rest = num; 532 533 assert(rest > 0); 534 /* one or two iterations */ 535 do { 536 size_t write_offset; 537 size_t chunk; 538 539 assert(b->len + rest <= b->size); 540 541 write_offset = b->offset + b->len; 542 if (write_offset >= b->size) { 543 write_offset -= b->size; 544 } 545 /* b->buf[write_offset] is the first byte we can write to. */ 546 547 if (write_offset + rest <= b->size) { 548 chunk = rest; 549 } else { 550 /* wrap around ring buffer */ 551 chunk = b->size - write_offset; 552 } 553 554 memcpy(b->buf + write_offset, buf, chunk); 555 556 b->len += chunk; 557 558 assert(b->len <= b->size); 559 560 rest -= chunk; 561 buf += chunk; 562 } while (rest); 563 564 return num; 565 } 566 567 static int bio_make_pair(BIO* bio1, BIO* bio2, 568 size_t writebuf1_len, uint8_t* ext_writebuf1, 569 size_t writebuf2_len, uint8_t* ext_writebuf2) { 570 struct bio_bio_st *b1, *b2; 571 572 assert(bio1 != NULL); 573 assert(bio2 != NULL); 574 575 b1 = bio1->ptr; 576 b2 = bio2->ptr; 577 578 if (b1->peer != NULL || b2->peer != NULL) { 579 OPENSSL_PUT_ERROR(BIO, BIO_R_IN_USE); 580 return 0; 581 } 582 583 assert(b1->buf_externally_allocated == 0); 584 assert(b2->buf_externally_allocated == 0); 585 586 if (b1->buf == NULL) { 587 if (writebuf1_len) { 588 b1->size = writebuf1_len; 589 } 590 if (!ext_writebuf1) { 591 b1->buf_externally_allocated = 0; 592 b1->buf = OPENSSL_malloc(b1->size); 593 if (b1->buf == NULL) { 594 OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE); 595 return 0; 596 } 597 } else { 598 b1->buf = ext_writebuf1; 599 b1->buf_externally_allocated = 1; 600 } 601 b1->len = 0; 602 b1->offset = 0; 603 } 604 605 if (b2->buf == NULL) { 606 if (writebuf2_len) { 607 b2->size = writebuf2_len; 608 } 609 if (!ext_writebuf2) { 610 b2->buf_externally_allocated = 0; 611 b2->buf = OPENSSL_malloc(b2->size); 612 if (b2->buf == NULL) { 613 OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE); 614 return 0; 615 } 616 } else { 617 b2->buf = ext_writebuf2; 618 b2->buf_externally_allocated = 1; 619 } 620 b2->len = 0; 621 b2->offset = 0; 622 } 623 624 b1->peer = bio2; 625 b1->closed = 0; 626 b1->request = 0; 627 b1->zero_copy_read_lock = 0; 628 b1->zero_copy_write_lock = 0; 629 b2->peer = bio1; 630 b2->closed = 0; 631 b2->request = 0; 632 b2->zero_copy_read_lock = 0; 633 b2->zero_copy_write_lock = 0; 634 635 bio1->init = 1; 636 bio2->init = 1; 637 638 return 1; 639 } 640 641 static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) { 642 long ret; 643 struct bio_bio_st *b = bio->ptr; 644 645 assert(b != NULL); 646 647 switch (cmd) { 648 /* specific CTRL codes */ 649 650 case BIO_C_GET_WRITE_BUF_SIZE: 651 ret = (long)b->size; 652 break; 653 654 case BIO_C_GET_WRITE_GUARANTEE: 655 /* How many bytes can the caller feed to the next write 656 * without having to keep any? */ 657 if (b->peer == NULL || b->closed) { 658 ret = 0; 659 } else { 660 ret = (long)b->size - b->len; 661 } 662 break; 663 664 case BIO_C_GET_READ_REQUEST: 665 /* If the peer unsuccessfully tried to read, how many bytes 666 * were requested? (As with BIO_CTRL_PENDING, that number 667 * can usually be treated as boolean.) */ 668 ret = (long)b->request; 669 break; 670 671 case BIO_C_RESET_READ_REQUEST: 672 /* Reset request. (Can be useful after read attempts 673 * at the other side that are meant to be non-blocking, 674 * e.g. when probing SSL_read to see if any data is 675 * available.) */ 676 b->request = 0; 677 ret = 1; 678 break; 679 680 case BIO_C_SHUTDOWN_WR: 681 /* similar to shutdown(..., SHUT_WR) */ 682 b->closed = 1; 683 ret = 1; 684 break; 685 686 /* standard CTRL codes follow */ 687 688 case BIO_CTRL_GET_CLOSE: 689 ret = bio->shutdown; 690 break; 691 692 case BIO_CTRL_SET_CLOSE: 693 bio->shutdown = (int)num; 694 ret = 1; 695 break; 696 697 case BIO_CTRL_PENDING: 698 if (b->peer != NULL) { 699 struct bio_bio_st *peer_b = b->peer->ptr; 700 ret = (long)peer_b->len; 701 } else { 702 ret = 0; 703 } 704 break; 705 706 case BIO_CTRL_WPENDING: 707 ret = 0; 708 if (b->buf != NULL) { 709 ret = (long)b->len; 710 } 711 break; 712 713 case BIO_CTRL_FLUSH: 714 ret = 1; 715 break; 716 717 case BIO_CTRL_EOF: { 718 BIO *other_bio = ptr; 719 720 if (other_bio) { 721 struct bio_bio_st *other_b = other_bio->ptr; 722 assert(other_b != NULL); 723 ret = other_b->len == 0 && other_b->closed; 724 } else { 725 ret = 1; 726 } 727 } break; 728 729 default: 730 ret = 0; 731 } 732 return ret; 733 } 734 735 static int bio_puts(BIO *bio, const char *str) { 736 return bio_write(bio, str, strlen(str)); 737 } 738 739 static const BIO_METHOD methods_biop = { 740 BIO_TYPE_BIO, "BIO pair", bio_write, bio_read, 741 bio_puts, NULL /* no bio_gets */, bio_ctrl, bio_new, 742 bio_free, NULL /* no bio_callback_ctrl */ 743 }; 744 745 const BIO_METHOD *bio_s_bio(void) { return &methods_biop; } 746 747 int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1, 748 BIO** bio2_p, size_t writebuf2) { 749 return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p, 750 writebuf2, NULL); 751 } 752 753 int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len, 754 uint8_t* ext_writebuf1, 755 BIO** bio2_p, size_t writebuf2_len, 756 uint8_t* ext_writebuf2) { 757 BIO *bio1 = NULL, *bio2 = NULL; 758 int ret = 0; 759 760 /* External buffers must have sizes greater than 0. */ 761 if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) { 762 goto err; 763 } 764 765 bio1 = BIO_new(bio_s_bio()); 766 if (bio1 == NULL) { 767 goto err; 768 } 769 bio2 = BIO_new(bio_s_bio()); 770 if (bio2 == NULL) { 771 goto err; 772 } 773 774 if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len, 775 ext_writebuf2)) { 776 goto err; 777 } 778 ret = 1; 779 780 err: 781 if (ret == 0) { 782 BIO_free(bio1); 783 bio1 = NULL; 784 BIO_free(bio2); 785 bio2 = NULL; 786 } 787 788 *bio1_p = bio1; 789 *bio2_p = bio2; 790 return ret; 791 } 792 793 size_t BIO_ctrl_get_read_request(BIO *bio) { 794 return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 795 } 796 797 size_t BIO_ctrl_get_write_guarantee(BIO *bio) { 798 return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 799 } 800 801 int BIO_shutdown_wr(BIO *bio) { 802 return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL); 803 } 804