1 /* $OpenBSD: bss_bio.c,v 1.29 2024/07/09 06:14:59 beck Exp $ */ 2 /* ==================================================================== 3 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. All advertising materials mentioning features or use of this 18 * software must display the following acknowledgment: 19 * "This product includes software developed by the OpenSSL Project 20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21 * 22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 * endorse or promote products derived from this software without 24 * prior written permission. For written permission, please contact 25 * openssl-core@openssl.org. 26 * 27 * 5. Products derived from this software may not be called "OpenSSL" 28 * nor may "OpenSSL" appear in their names without prior written 29 * permission of the OpenSSL Project. 30 * 31 * 6. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by the OpenSSL Project 34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 * OF THE POSSIBILITY OF SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This product includes cryptographic software written by Eric Young 51 * (eay@cryptsoft.com). This product includes software written by Tim 52 * Hudson (tjh@cryptsoft.com). 53 * 54 */ 55 56 /* Special method for a BIO where the other endpoint is also a BIO 57 * of this kind, handled by the same thread (i.e. the "peer" is actually 58 * ourselves, wearing a different hat). 59 * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces 60 * for which no specific BIO method is available. 61 * See ssl/ssltest.c for some hints on how this can be used. */ 62 63 /* BIO_DEBUG implies BIO_PAIR_DEBUG */ 64 #ifdef BIO_DEBUG 65 # ifndef BIO_PAIR_DEBUG 66 # define BIO_PAIR_DEBUG 67 # endif 68 #endif 69 70 /* disable assert() unless BIO_PAIR_DEBUG has been defined */ 71 #ifndef BIO_PAIR_DEBUG 72 # ifndef NDEBUG 73 # define NDEBUG 74 # endif 75 #endif 76 77 #include <assert.h> 78 #include <limits.h> 79 #include <stdlib.h> 80 #include <string.h> 81 #include <sys/types.h> 82 83 #include <openssl/bio.h> 84 #include <openssl/err.h> 85 #include <openssl/crypto.h> 86 87 #include "bio_local.h" 88 89 static int bio_new(BIO *bio); 90 static int bio_free(BIO *bio); 91 static int bio_read(BIO *bio, char *buf, int size); 92 static int bio_write(BIO *bio, const char *buf, int num); 93 static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); 94 static int bio_puts(BIO *bio, const char *str); 95 96 static int bio_make_pair(BIO *bio1, BIO *bio2); 97 static void bio_destroy_pair(BIO *bio); 98 99 static const BIO_METHOD methods_biop = { 100 .type = BIO_TYPE_BIO, 101 .name = "BIO pair", 102 .bwrite = bio_write, 103 .bread = bio_read, 104 .bputs = bio_puts, 105 .ctrl = bio_ctrl, 106 .create = bio_new, 107 .destroy = bio_free 108 }; 109 110 const BIO_METHOD * 111 BIO_s_bio(void) 112 { 113 return &methods_biop; 114 } 115 LCRYPTO_ALIAS(BIO_s_bio); 116 117 struct bio_bio_st { 118 BIO *peer; /* NULL if buf == NULL. 119 * If peer != NULL, then peer->ptr is also a bio_bio_st, 120 * and its "peer" member points back to us. 121 * peer != NULL iff init != 0 in the BIO. */ 122 123 /* This is for what we write (i.e. reading uses peer's struct): */ 124 int closed; /* valid iff peer != NULL */ 125 size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ 126 size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ 127 size_t size; 128 char *buf; /* "size" elements (if != NULL) */ 129 130 size_t request; /* valid iff peer != NULL; 0 if len != 0, 131 * otherwise set by peer to number of bytes 132 * it (unsuccessfully) tried to read, 133 * never more than buffer space (size-len) warrants. */ 134 }; 135 136 static int 137 bio_new(BIO *bio) 138 { 139 struct bio_bio_st *b; 140 141 b = malloc(sizeof *b); 142 if (b == NULL) 143 return 0; 144 145 b->peer = NULL; 146 b->size = 17 * 1024; /* enough for one TLS record (just a default) */ 147 b->buf = NULL; 148 149 bio->ptr = b; 150 return 1; 151 } 152 153 static int 154 bio_free(BIO *bio) 155 { 156 struct bio_bio_st *b; 157 158 if (bio == NULL) 159 return 0; 160 b = bio->ptr; 161 162 assert(b != NULL); 163 164 if (b->peer) 165 bio_destroy_pair(bio); 166 167 free(b->buf); 168 free(b); 169 return 1; 170 } 171 172 173 174 static int 175 bio_read(BIO *bio, char *buf, int size_) 176 { 177 size_t size = size_; 178 size_t rest; 179 struct bio_bio_st *b, *peer_b; 180 181 BIO_clear_retry_flags(bio); 182 183 if (!bio->init) 184 return 0; 185 186 b = bio->ptr; 187 assert(b != NULL); 188 assert(b->peer != NULL); 189 peer_b = b->peer->ptr; 190 assert(peer_b != NULL); 191 assert(peer_b->buf != NULL); 192 193 peer_b->request = 0; /* will be set in "retry_read" situation */ 194 195 if (buf == NULL || size == 0) 196 return 0; 197 198 if (peer_b->len == 0) { 199 if (peer_b->closed) 200 return 0; /* writer has closed, and no data is left */ 201 else { 202 BIO_set_retry_read(bio); /* buffer is empty */ 203 if (size <= peer_b->size) 204 peer_b->request = size; 205 else 206 /* don't ask for more than the peer can 207 * deliver in one write */ 208 peer_b->request = peer_b->size; 209 return -1; 210 } 211 } 212 213 /* we can read */ 214 if (peer_b->len < size) 215 size = peer_b->len; 216 217 /* now read "size" bytes */ 218 219 rest = size; 220 221 assert(rest > 0); 222 do /* one or two iterations */ 223 { 224 size_t chunk; 225 226 assert(rest <= peer_b->len); 227 if (peer_b->offset + rest <= peer_b->size) 228 chunk = rest; 229 else 230 /* wrap around ring buffer */ 231 chunk = peer_b->size - peer_b->offset; 232 assert(peer_b->offset + chunk <= peer_b->size); 233 234 memcpy(buf, peer_b->buf + peer_b->offset, chunk); 235 236 peer_b->len -= chunk; 237 if (peer_b->len) { 238 peer_b->offset += chunk; 239 assert(peer_b->offset <= peer_b->size); 240 if (peer_b->offset == peer_b->size) 241 peer_b->offset = 0; 242 buf += chunk; 243 } else { 244 /* buffer now empty, no need to advance "buf" */ 245 assert(chunk == rest); 246 peer_b->offset = 0; 247 } 248 rest -= chunk; 249 } while (rest); 250 251 return size; 252 } 253 254 static int 255 bio_write(BIO *bio, const char *buf, int num_) 256 { 257 size_t num = num_; 258 size_t rest; 259 struct bio_bio_st *b; 260 261 BIO_clear_retry_flags(bio); 262 263 if (!bio->init || buf == NULL || num == 0) 264 return 0; 265 266 b = bio->ptr; 267 268 assert(b != NULL); 269 assert(b->peer != NULL); 270 assert(b->buf != NULL); 271 272 b->request = 0; 273 if (b->closed) { 274 /* we already closed */ 275 BIOerror(BIO_R_BROKEN_PIPE); 276 return -1; 277 } 278 279 assert(b->len <= b->size); 280 281 if (b->len == b->size) { 282 BIO_set_retry_write(bio); /* buffer is full */ 283 return -1; 284 } 285 286 /* we can write */ 287 if (num > b->size - b->len) 288 num = b->size - b->len; 289 290 /* now write "num" bytes */ 291 292 rest = num; 293 294 assert(rest > 0); 295 do /* one or two iterations */ 296 { 297 size_t write_offset; 298 size_t chunk; 299 300 assert(b->len + rest <= b->size); 301 302 write_offset = b->offset + b->len; 303 if (write_offset >= b->size) 304 write_offset -= b->size; 305 /* b->buf[write_offset] is the first byte we can write to. */ 306 307 if (write_offset + rest <= b->size) 308 chunk = rest; 309 else 310 /* wrap around ring buffer */ 311 chunk = b->size - write_offset; 312 313 memcpy(b->buf + write_offset, buf, chunk); 314 315 b->len += chunk; 316 317 assert(b->len <= b->size); 318 319 rest -= chunk; 320 buf += chunk; 321 } while (rest); 322 323 return num; 324 } 325 326 static long 327 bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 328 { 329 long ret; 330 struct bio_bio_st *b = bio->ptr; 331 332 assert(b != NULL); 333 334 switch (cmd) { 335 /* specific CTRL codes */ 336 337 case BIO_C_SET_WRITE_BUF_SIZE: 338 if (b->peer) { 339 BIOerror(BIO_R_IN_USE); 340 ret = 0; 341 } else if (num == 0) { 342 BIOerror(BIO_R_INVALID_ARGUMENT); 343 ret = 0; 344 } else { 345 size_t new_size = num; 346 347 if (b->size != new_size) { 348 free(b->buf); 349 b->buf = NULL; 350 b->size = new_size; 351 } 352 ret = 1; 353 } 354 break; 355 356 case BIO_C_GET_WRITE_BUF_SIZE: 357 ret = (long) b->size; 358 break; 359 360 case BIO_C_MAKE_BIO_PAIR: 361 { 362 BIO *other_bio = ptr; 363 364 if (bio_make_pair(bio, other_bio)) 365 ret = 1; 366 else 367 ret = 0; 368 } 369 break; 370 371 case BIO_C_DESTROY_BIO_PAIR: 372 /* Affects both BIOs in the pair -- call just once! 373 * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ 374 bio_destroy_pair(bio); 375 ret = 1; 376 break; 377 378 case BIO_C_GET_WRITE_GUARANTEE: 379 /* How many bytes can the caller feed to the next write 380 * without having to keep any? */ 381 if (b->peer == NULL || b->closed) 382 ret = 0; 383 else 384 ret = (long) b->size - b->len; 385 break; 386 387 case BIO_C_GET_READ_REQUEST: 388 /* If the peer unsuccessfully tried to read, how many bytes 389 * were requested? (As with BIO_CTRL_PENDING, that number 390 * can usually be treated as boolean.) */ 391 ret = (long) b->request; 392 break; 393 394 case BIO_C_RESET_READ_REQUEST: 395 /* Reset request. (Can be useful after read attempts 396 * at the other side that are meant to be non-blocking, 397 * e.g. when probing SSL_read to see if any data is 398 * available.) */ 399 b->request = 0; 400 ret = 1; 401 break; 402 403 case BIO_C_SHUTDOWN_WR: 404 /* similar to shutdown(..., SHUT_WR) */ 405 b->closed = 1; 406 ret = 1; 407 break; 408 409 /* standard CTRL codes follow */ 410 411 case BIO_CTRL_RESET: 412 if (b->buf != NULL) { 413 b->len = 0; 414 b->offset = 0; 415 } 416 ret = 0; 417 break; 418 419 420 case BIO_CTRL_GET_CLOSE: 421 ret = bio->shutdown; 422 break; 423 424 case BIO_CTRL_SET_CLOSE: 425 bio->shutdown = (int) num; 426 ret = 1; 427 break; 428 429 case BIO_CTRL_PENDING: 430 if (b->peer != NULL) { 431 struct bio_bio_st *peer_b = b->peer->ptr; 432 433 ret = (long) peer_b->len; 434 } else 435 ret = 0; 436 break; 437 438 case BIO_CTRL_WPENDING: 439 if (b->buf != NULL) 440 ret = (long) b->len; 441 else 442 ret = 0; 443 break; 444 445 case BIO_CTRL_DUP: 446 /* See BIO_dup_chain for circumstances we have to expect. */ 447 { 448 BIO *other_bio = ptr; 449 struct bio_bio_st *other_b; 450 451 assert(other_bio != NULL); 452 other_b = other_bio->ptr; 453 assert(other_b != NULL); 454 455 assert(other_b->buf == NULL); /* other_bio is always fresh */ 456 457 other_b->size = b->size; 458 } 459 460 ret = 1; 461 break; 462 463 case BIO_CTRL_FLUSH: 464 ret = 1; 465 break; 466 467 case BIO_CTRL_EOF: 468 { 469 BIO *other_bio = ptr; 470 471 if (other_bio) { 472 struct bio_bio_st *other_b = other_bio->ptr; 473 474 assert(other_b != NULL); 475 ret = other_b->len == 0 && other_b->closed; 476 } else 477 ret = 1; 478 } 479 break; 480 481 default: 482 ret = 0; 483 } 484 return ret; 485 } 486 487 static int 488 bio_puts(BIO *bio, const char *str) 489 { 490 return bio_write(bio, str, strlen(str)); 491 } 492 493 494 static int 495 bio_make_pair(BIO *bio1, BIO *bio2) 496 { 497 struct bio_bio_st *b1, *b2; 498 499 assert(bio1 != NULL); 500 assert(bio2 != NULL); 501 502 b1 = bio1->ptr; 503 b2 = bio2->ptr; 504 505 if (b1->peer != NULL || b2->peer != NULL) { 506 BIOerror(BIO_R_IN_USE); 507 return 0; 508 } 509 510 if (b1->buf == NULL) { 511 b1->buf = malloc(b1->size); 512 if (b1->buf == NULL) { 513 BIOerror(ERR_R_MALLOC_FAILURE); 514 return 0; 515 } 516 b1->len = 0; 517 b1->offset = 0; 518 } 519 520 if (b2->buf == NULL) { 521 b2->buf = malloc(b2->size); 522 if (b2->buf == NULL) { 523 BIOerror(ERR_R_MALLOC_FAILURE); 524 return 0; 525 } 526 b2->len = 0; 527 b2->offset = 0; 528 } 529 530 b1->peer = bio2; 531 b1->closed = 0; 532 b1->request = 0; 533 b2->peer = bio1; 534 b2->closed = 0; 535 b2->request = 0; 536 537 bio1->init = 1; 538 bio2->init = 1; 539 540 return 1; 541 } 542 543 static void 544 bio_destroy_pair(BIO *bio) 545 { 546 struct bio_bio_st *b = bio->ptr; 547 548 if (b != NULL) { 549 BIO *peer_bio = b->peer; 550 551 if (peer_bio != NULL) { 552 struct bio_bio_st *peer_b = peer_bio->ptr; 553 554 assert(peer_b != NULL); 555 assert(peer_b->peer == bio); 556 557 peer_b->peer = NULL; 558 peer_bio->init = 0; 559 assert(peer_b->buf != NULL); 560 peer_b->len = 0; 561 peer_b->offset = 0; 562 563 b->peer = NULL; 564 bio->init = 0; 565 assert(b->buf != NULL); 566 b->len = 0; 567 b->offset = 0; 568 } 569 } 570 } 571 572 573 /* Exported convenience functions */ 574 int 575 BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, BIO **bio2_p, size_t writebuf2) 576 { 577 BIO *bio1 = NULL, *bio2 = NULL; 578 long r; 579 int ret = 0; 580 581 bio1 = BIO_new(BIO_s_bio()); 582 if (bio1 == NULL) 583 goto err; 584 bio2 = BIO_new(BIO_s_bio()); 585 if (bio2 == NULL) 586 goto err; 587 588 if (writebuf1) { 589 r = BIO_set_write_buf_size(bio1, writebuf1); 590 if (!r) 591 goto err; 592 } 593 if (writebuf2) { 594 r = BIO_set_write_buf_size(bio2, writebuf2); 595 if (!r) 596 goto err; 597 } 598 599 r = BIO_make_bio_pair(bio1, bio2); 600 if (!r) 601 goto err; 602 ret = 1; 603 604 err: 605 if (ret == 0) { 606 if (bio1) { 607 BIO_free(bio1); 608 bio1 = NULL; 609 } 610 if (bio2) { 611 BIO_free(bio2); 612 bio2 = NULL; 613 } 614 } 615 616 *bio1_p = bio1; 617 *bio2_p = bio2; 618 return ret; 619 } 620 LCRYPTO_ALIAS(BIO_new_bio_pair); 621 622 size_t 623 BIO_ctrl_get_write_guarantee(BIO *bio) 624 { 625 return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 626 } 627 LCRYPTO_ALIAS(BIO_ctrl_get_write_guarantee); 628 629 size_t 630 BIO_ctrl_get_read_request(BIO *bio) 631 { 632 return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 633 } 634 LCRYPTO_ALIAS(BIO_ctrl_get_read_request); 635 636 int 637 BIO_ctrl_reset_read_request(BIO *bio) 638 { 639 return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); 640 } 641 LCRYPTO_ALIAS(BIO_ctrl_reset_read_request); 642