bss_bio.c revision 280297
155714Skris/* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ 2120631Snectar/* ==================================================================== 3120631Snectar * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 4120631Snectar * 5120631Snectar * Redistribution and use in source and binary forms, with or without 6120631Snectar * modification, are permitted provided that the following conditions 7120631Snectar * are met: 8120631Snectar * 9120631Snectar * 1. Redistributions of source code must retain the above copyright 10280297Sjkim * notice, this list of conditions and the following disclaimer. 11120631Snectar * 12120631Snectar * 2. Redistributions in binary form must reproduce the above copyright 13120631Snectar * notice, this list of conditions and the following disclaimer in 14120631Snectar * the documentation and/or other materials provided with the 15120631Snectar * distribution. 16120631Snectar * 17120631Snectar * 3. All advertising materials mentioning features or use of this 18120631Snectar * software must display the following acknowledgment: 19120631Snectar * "This product includes software developed by the OpenSSL Project 20120631Snectar * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21120631Snectar * 22120631Snectar * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23120631Snectar * endorse or promote products derived from this software without 24120631Snectar * prior written permission. For written permission, please contact 25120631Snectar * openssl-core@openssl.org. 26120631Snectar * 27120631Snectar * 5. Products derived from this software may not be called "OpenSSL" 28120631Snectar * nor may "OpenSSL" appear in their names without prior written 29120631Snectar * permission of the OpenSSL Project. 30120631Snectar * 31120631Snectar * 6. Redistributions of any form whatsoever must retain the following 32120631Snectar * acknowledgment: 33120631Snectar * "This product includes software developed by the OpenSSL Project 34120631Snectar * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35120631Snectar * 36120631Snectar * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37120631Snectar * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38120631Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39120631Snectar * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40120631Snectar * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41120631Snectar * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42120631Snectar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43120631Snectar * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44120631Snectar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45120631Snectar * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46120631Snectar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47120631Snectar * OF THE POSSIBILITY OF SUCH DAMAGE. 48120631Snectar * ==================================================================== 49120631Snectar * 50120631Snectar * This product includes cryptographic software written by Eric Young 51120631Snectar * (eay@cryptsoft.com). This product includes software written by Tim 52120631Snectar * Hudson (tjh@cryptsoft.com). 53120631Snectar * 54120631Snectar */ 5555714Skris 56280297Sjkim/* 57280297Sjkim * Special method for a BIO where the other endpoint is also a BIO of this 58280297Sjkim * kind, handled by the same thread (i.e. the "peer" is actually ourselves, 59280297Sjkim * wearing a different hat). Such "BIO pairs" are mainly for using the SSL 60280297Sjkim * library with I/O interfaces for which no specific BIO method is available. 61280297Sjkim * See ssl/ssltest.c for some hints on how this can be used. 62280297Sjkim */ 6355714Skris 64100936Snectar/* BIO_DEBUG implies BIO_PAIR_DEBUG */ 65100936Snectar#ifdef BIO_DEBUG 66100936Snectar# ifndef BIO_PAIR_DEBUG 67100936Snectar# define BIO_PAIR_DEBUG 68100936Snectar# endif 69100936Snectar#endif 70100936Snectar 71100936Snectar/* disable assert() unless BIO_PAIR_DEBUG has been defined */ 7255714Skris#ifndef BIO_PAIR_DEBUG 73100936Snectar# ifndef NDEBUG 74100936Snectar# define NDEBUG 75100936Snectar# endif 7655714Skris#endif 7755714Skris 7855714Skris#include <assert.h> 7959191Skris#include <limits.h> 8055714Skris#include <stdlib.h> 8155714Skris#include <string.h> 8255714Skris 8355714Skris#include <openssl/bio.h> 8455714Skris#include <openssl/err.h> 8555714Skris#include <openssl/crypto.h> 8655714Skris 87109998Smarkm#include "e_os.h" 88100928Snectar 89109998Smarkm/* VxWorks defines SSIZE_MAX with an empty value causing compile errors */ 90109998Smarkm#if defined(OPENSSL_SYS_VXWORKS) 91100928Snectar# undef SSIZE_MAX 92109998Smarkm#endif 93109998Smarkm#ifndef SSIZE_MAX 9459191Skris# define SSIZE_MAX INT_MAX 9559191Skris#endif 9659191Skris 9755714Skrisstatic int bio_new(BIO *bio); 9855714Skrisstatic int bio_free(BIO *bio); 9955714Skrisstatic int bio_read(BIO *bio, char *buf, int size); 10068651Skrisstatic int bio_write(BIO *bio, const char *buf, int num); 10155714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); 10268651Skrisstatic int bio_puts(BIO *bio, const char *str); 10355714Skris 10455714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2); 10555714Skrisstatic void bio_destroy_pair(BIO *bio); 10655714Skris 107280297Sjkimstatic BIO_METHOD methods_biop = { 108280297Sjkim BIO_TYPE_BIO, 109280297Sjkim "BIO pair", 110280297Sjkim bio_write, 111280297Sjkim bio_read, 112280297Sjkim bio_puts, 113280297Sjkim NULL /* no bio_gets */ , 114280297Sjkim bio_ctrl, 115280297Sjkim bio_new, 116280297Sjkim bio_free, 117280297Sjkim NULL /* no bio_callback_ctrl */ 11855714Skris}; 11955714Skris 12055714SkrisBIO_METHOD *BIO_s_bio(void) 12155714Skris{ 122280297Sjkim return &methods_biop; 123280297Sjkim} 12455714Skris 125280297Sjkimstruct bio_bio_st { 126280297Sjkim BIO *peer; /* NULL if buf == NULL. If peer != NULL, then 127280297Sjkim * peer->ptr is also a bio_bio_st, and its 128280297Sjkim * "peer" member points back to us. peer != 129280297Sjkim * NULL iff init != 0 in the BIO. */ 130280297Sjkim /* This is for what we write (i.e. reading uses peer's struct): */ 131280297Sjkim int closed; /* valid iff peer != NULL */ 132280297Sjkim size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ 133280297Sjkim size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ 134280297Sjkim size_t size; 135280297Sjkim char *buf; /* "size" elements (if != NULL) */ 136280297Sjkim size_t request; /* valid iff peer != NULL; 0 if len != 0, 137280297Sjkim * otherwise set by peer to number of bytes 138280297Sjkim * it (unsuccessfully) tried to read, never 139280297Sjkim * more than buffer space (size-len) 140280297Sjkim * warrants. */ 14155714Skris}; 14255714Skris 14355714Skrisstatic int bio_new(BIO *bio) 144280297Sjkim{ 145280297Sjkim struct bio_bio_st *b; 14655714Skris 147280297Sjkim b = OPENSSL_malloc(sizeof *b); 148280297Sjkim if (b == NULL) 149280297Sjkim return 0; 15055714Skris 151280297Sjkim b->peer = NULL; 152280297Sjkim /* enough for one TLS record (just a default) */ 153280297Sjkim b->size = 17 * 1024; 154280297Sjkim b->buf = NULL; 15555714Skris 156280297Sjkim bio->ptr = b; 157280297Sjkim return 1; 158280297Sjkim} 15955714Skris 16055714Skrisstatic int bio_free(BIO *bio) 161280297Sjkim{ 162280297Sjkim struct bio_bio_st *b; 16355714Skris 164280297Sjkim if (bio == NULL) 165280297Sjkim return 0; 166280297Sjkim b = bio->ptr; 16755714Skris 168280297Sjkim assert(b != NULL); 16955714Skris 170280297Sjkim if (b->peer) 171280297Sjkim bio_destroy_pair(bio); 17255714Skris 173280297Sjkim if (b->buf != NULL) { 174280297Sjkim OPENSSL_free(b->buf); 175280297Sjkim } 17655714Skris 177280297Sjkim OPENSSL_free(b); 17855714Skris 179280297Sjkim return 1; 180280297Sjkim} 18155714Skris 18255714Skrisstatic int bio_read(BIO *bio, char *buf, int size_) 183280297Sjkim{ 184280297Sjkim size_t size = size_; 185280297Sjkim size_t rest; 186280297Sjkim struct bio_bio_st *b, *peer_b; 18755714Skris 188280297Sjkim BIO_clear_retry_flags(bio); 18955714Skris 190280297Sjkim if (!bio->init) 191280297Sjkim return 0; 19255714Skris 193280297Sjkim b = bio->ptr; 194280297Sjkim assert(b != NULL); 195280297Sjkim assert(b->peer != NULL); 196280297Sjkim peer_b = b->peer->ptr; 197280297Sjkim assert(peer_b != NULL); 198280297Sjkim assert(peer_b->buf != NULL); 19955714Skris 200280297Sjkim peer_b->request = 0; /* will be set in "retry_read" situation */ 20155714Skris 202280297Sjkim if (buf == NULL || size == 0) 203280297Sjkim return 0; 20455714Skris 205280297Sjkim if (peer_b->len == 0) { 206280297Sjkim if (peer_b->closed) 207280297Sjkim return 0; /* writer has closed, and no data is left */ 208280297Sjkim else { 209280297Sjkim BIO_set_retry_read(bio); /* buffer is empty */ 210280297Sjkim if (size <= peer_b->size) 211280297Sjkim peer_b->request = size; 212280297Sjkim else 213280297Sjkim /* 214280297Sjkim * don't ask for more than the peer can deliver in one write 215280297Sjkim */ 216280297Sjkim peer_b->request = peer_b->size; 217280297Sjkim return -1; 218280297Sjkim } 219280297Sjkim } 22055714Skris 221280297Sjkim /* we can read */ 222280297Sjkim if (peer_b->len < size) 223280297Sjkim size = peer_b->len; 22455714Skris 225280297Sjkim /* now read "size" bytes */ 22655714Skris 227280297Sjkim rest = size; 228280297Sjkim 229280297Sjkim assert(rest > 0); 230280297Sjkim do { /* one or two iterations */ 231280297Sjkim size_t chunk; 232280297Sjkim 233280297Sjkim assert(rest <= peer_b->len); 234280297Sjkim if (peer_b->offset + rest <= peer_b->size) 235280297Sjkim chunk = rest; 236280297Sjkim else 237280297Sjkim /* wrap around ring buffer */ 238280297Sjkim chunk = peer_b->size - peer_b->offset; 239280297Sjkim assert(peer_b->offset + chunk <= peer_b->size); 240280297Sjkim 241280297Sjkim memcpy(buf, peer_b->buf + peer_b->offset, chunk); 242280297Sjkim 243280297Sjkim peer_b->len -= chunk; 244280297Sjkim if (peer_b->len) { 245280297Sjkim peer_b->offset += chunk; 246280297Sjkim assert(peer_b->offset <= peer_b->size); 247280297Sjkim if (peer_b->offset == peer_b->size) 248280297Sjkim peer_b->offset = 0; 249280297Sjkim buf += chunk; 250280297Sjkim } else { 251280297Sjkim /* buffer now empty, no need to advance "buf" */ 252280297Sjkim assert(chunk == rest); 253280297Sjkim peer_b->offset = 0; 254280297Sjkim } 255280297Sjkim rest -= chunk; 256280297Sjkim } 257280297Sjkim while (rest); 258280297Sjkim 259280297Sjkim return size; 260280297Sjkim} 261280297Sjkim 262280297Sjkim/*- 263280297Sjkim * non-copying interface: provide pointer to available data in buffer 26459191Skris * bio_nread0: return number of available bytes 26559191Skris * bio_nread: also advance index 26659191Skris * (example usage: bio_nread0(), read from buffer, bio_nread() 26759191Skris * or just bio_nread(), read from buffer) 26859191Skris */ 269280297Sjkim/* 270280297Sjkim * WARNING: The non-copying interface is largely untested as of yet and may 271280297Sjkim * contain bugs. 272280297Sjkim */ 273238405Sjkimstatic ossl_ssize_t bio_nread0(BIO *bio, char **buf) 274280297Sjkim{ 275280297Sjkim struct bio_bio_st *b, *peer_b; 276280297Sjkim ossl_ssize_t num; 27759191Skris 278280297Sjkim BIO_clear_retry_flags(bio); 27959191Skris 280280297Sjkim if (!bio->init) 281280297Sjkim return 0; 28259191Skris 283280297Sjkim b = bio->ptr; 284280297Sjkim assert(b != NULL); 285280297Sjkim assert(b->peer != NULL); 286280297Sjkim peer_b = b->peer->ptr; 287280297Sjkim assert(peer_b != NULL); 288280297Sjkim assert(peer_b->buf != NULL); 28959191Skris 290280297Sjkim peer_b->request = 0; 291280297Sjkim 292280297Sjkim if (peer_b->len == 0) { 293280297Sjkim char dummy; 294280297Sjkim 295280297Sjkim /* avoid code duplication -- nothing available for reading */ 296280297Sjkim return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ 297280297Sjkim } 298280297Sjkim 299280297Sjkim num = peer_b->len; 300280297Sjkim if (peer_b->size < peer_b->offset + num) 301280297Sjkim /* no ring buffer wrap-around for non-copying interface */ 302280297Sjkim num = peer_b->size - peer_b->offset; 303280297Sjkim assert(num > 0); 304280297Sjkim 305280297Sjkim if (buf != NULL) 306280297Sjkim *buf = peer_b->buf + peer_b->offset; 307280297Sjkim return num; 308280297Sjkim} 309280297Sjkim 310238405Sjkimstatic ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_) 311280297Sjkim{ 312280297Sjkim struct bio_bio_st *b, *peer_b; 313280297Sjkim ossl_ssize_t num, available; 31459191Skris 315280297Sjkim if (num_ > SSIZE_MAX) 316280297Sjkim num = SSIZE_MAX; 317280297Sjkim else 318280297Sjkim num = (ossl_ssize_t) num_; 31959191Skris 320280297Sjkim available = bio_nread0(bio, buf); 321280297Sjkim if (num > available) 322280297Sjkim num = available; 323280297Sjkim if (num <= 0) 324280297Sjkim return num; 32559191Skris 326280297Sjkim b = bio->ptr; 327280297Sjkim peer_b = b->peer->ptr; 32859191Skris 329280297Sjkim peer_b->len -= num; 330280297Sjkim if (peer_b->len) { 331280297Sjkim peer_b->offset += num; 332280297Sjkim assert(peer_b->offset <= peer_b->size); 333280297Sjkim if (peer_b->offset == peer_b->size) 334280297Sjkim peer_b->offset = 0; 335280297Sjkim } else 336280297Sjkim peer_b->offset = 0; 33759191Skris 338280297Sjkim return num; 339280297Sjkim} 34059191Skris 34168651Skrisstatic int bio_write(BIO *bio, const char *buf, int num_) 342280297Sjkim{ 343280297Sjkim size_t num = num_; 344280297Sjkim size_t rest; 345280297Sjkim struct bio_bio_st *b; 34655714Skris 347280297Sjkim BIO_clear_retry_flags(bio); 34855714Skris 349280297Sjkim if (!bio->init || buf == NULL || num == 0) 350280297Sjkim return 0; 35155714Skris 352280297Sjkim b = bio->ptr; 353280297Sjkim assert(b != NULL); 354280297Sjkim assert(b->peer != NULL); 355280297Sjkim assert(b->buf != NULL); 35655714Skris 357280297Sjkim b->request = 0; 358280297Sjkim if (b->closed) { 359280297Sjkim /* we already closed */ 360280297Sjkim BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); 361280297Sjkim return -1; 362280297Sjkim } 36355714Skris 364280297Sjkim assert(b->len <= b->size); 36555714Skris 366280297Sjkim if (b->len == b->size) { 367280297Sjkim BIO_set_retry_write(bio); /* buffer is full */ 368280297Sjkim return -1; 369280297Sjkim } 37055714Skris 371280297Sjkim /* we can write */ 372280297Sjkim if (num > b->size - b->len) 373280297Sjkim num = b->size - b->len; 37455714Skris 375280297Sjkim /* now write "num" bytes */ 37655714Skris 377280297Sjkim rest = num; 37855714Skris 379280297Sjkim assert(rest > 0); 380280297Sjkim do { /* one or two iterations */ 381280297Sjkim size_t write_offset; 382280297Sjkim size_t chunk; 38355714Skris 384280297Sjkim assert(b->len + rest <= b->size); 38555714Skris 386280297Sjkim write_offset = b->offset + b->len; 387280297Sjkim if (write_offset >= b->size) 388280297Sjkim write_offset -= b->size; 389280297Sjkim /* b->buf[write_offset] is the first byte we can write to. */ 39055714Skris 391280297Sjkim if (write_offset + rest <= b->size) 392280297Sjkim chunk = rest; 393280297Sjkim else 394280297Sjkim /* wrap around ring buffer */ 395280297Sjkim chunk = b->size - write_offset; 39655714Skris 397280297Sjkim memcpy(b->buf + write_offset, buf, chunk); 398280297Sjkim 399280297Sjkim b->len += chunk; 400280297Sjkim 401280297Sjkim assert(b->len <= b->size); 402280297Sjkim 403280297Sjkim rest -= chunk; 404280297Sjkim buf += chunk; 405280297Sjkim } 406280297Sjkim while (rest); 407280297Sjkim 408280297Sjkim return num; 409280297Sjkim} 410280297Sjkim 411280297Sjkim/*- 412280297Sjkim * non-copying interface: provide pointer to region to write to 41359191Skris * bio_nwrite0: check how much space is available 41459191Skris * bio_nwrite: also increase length 41559191Skris * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() 41659191Skris * or just bio_nwrite(), write to buffer) 41759191Skris */ 418238405Sjkimstatic ossl_ssize_t bio_nwrite0(BIO *bio, char **buf) 419280297Sjkim{ 420280297Sjkim struct bio_bio_st *b; 421280297Sjkim size_t num; 422280297Sjkim size_t write_offset; 42355714Skris 424280297Sjkim BIO_clear_retry_flags(bio); 42559191Skris 426280297Sjkim if (!bio->init) 427280297Sjkim return 0; 42859191Skris 429280297Sjkim b = bio->ptr; 430280297Sjkim assert(b != NULL); 431280297Sjkim assert(b->peer != NULL); 432280297Sjkim assert(b->buf != NULL); 43359191Skris 434280297Sjkim b->request = 0; 435280297Sjkim if (b->closed) { 436280297Sjkim BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); 437280297Sjkim return -1; 438280297Sjkim } 43959191Skris 440280297Sjkim assert(b->len <= b->size); 44159191Skris 442280297Sjkim if (b->len == b->size) { 443280297Sjkim BIO_set_retry_write(bio); 444280297Sjkim return -1; 445280297Sjkim } 44659191Skris 447280297Sjkim num = b->size - b->len; 448280297Sjkim write_offset = b->offset + b->len; 449280297Sjkim if (write_offset >= b->size) 450280297Sjkim write_offset -= b->size; 451280297Sjkim if (write_offset + num > b->size) 452280297Sjkim /* 453280297Sjkim * no ring buffer wrap-around for non-copying interface (to fulfil 454280297Sjkim * the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have 455280297Sjkim * to be called twice) 456280297Sjkim */ 457280297Sjkim num = b->size - write_offset; 45859191Skris 459280297Sjkim if (buf != NULL) 460280297Sjkim *buf = b->buf + write_offset; 461280297Sjkim assert(write_offset + num <= b->size); 46259191Skris 463280297Sjkim return num; 464280297Sjkim} 46559191Skris 466238405Sjkimstatic ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) 467280297Sjkim{ 468280297Sjkim struct bio_bio_st *b; 469280297Sjkim ossl_ssize_t num, space; 47059191Skris 471280297Sjkim if (num_ > SSIZE_MAX) 472280297Sjkim num = SSIZE_MAX; 473280297Sjkim else 474280297Sjkim num = (ossl_ssize_t) num_; 47559191Skris 476280297Sjkim space = bio_nwrite0(bio, buf); 477280297Sjkim if (num > space) 478280297Sjkim num = space; 479280297Sjkim if (num <= 0) 480280297Sjkim return num; 481280297Sjkim b = bio->ptr; 482280297Sjkim assert(b != NULL); 483280297Sjkim b->len += num; 484280297Sjkim assert(b->len <= b->size); 48559191Skris 486280297Sjkim return num; 487280297Sjkim} 48859191Skris 48955714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 490280297Sjkim{ 491280297Sjkim long ret; 492280297Sjkim struct bio_bio_st *b = bio->ptr; 49355714Skris 494280297Sjkim assert(b != NULL); 49555714Skris 496280297Sjkim switch (cmd) { 497280297Sjkim /* specific CTRL codes */ 49855714Skris 499280297Sjkim case BIO_C_SET_WRITE_BUF_SIZE: 500280297Sjkim if (b->peer) { 501280297Sjkim BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); 502280297Sjkim ret = 0; 503280297Sjkim } else if (num == 0) { 504280297Sjkim BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); 505280297Sjkim ret = 0; 506280297Sjkim } else { 507280297Sjkim size_t new_size = num; 50855714Skris 509280297Sjkim if (b->size != new_size) { 510280297Sjkim if (b->buf) { 511280297Sjkim OPENSSL_free(b->buf); 512280297Sjkim b->buf = NULL; 513280297Sjkim } 514280297Sjkim b->size = new_size; 515280297Sjkim } 516280297Sjkim ret = 1; 517280297Sjkim } 518280297Sjkim break; 51955714Skris 520280297Sjkim case BIO_C_GET_WRITE_BUF_SIZE: 521280297Sjkim ret = (long)b->size; 522280297Sjkim break; 52355714Skris 524280297Sjkim case BIO_C_MAKE_BIO_PAIR: 525280297Sjkim { 526280297Sjkim BIO *other_bio = ptr; 52755714Skris 528280297Sjkim if (bio_make_pair(bio, other_bio)) 529280297Sjkim ret = 1; 530280297Sjkim else 531280297Sjkim ret = 0; 532280297Sjkim } 533280297Sjkim break; 53455714Skris 535280297Sjkim case BIO_C_DESTROY_BIO_PAIR: 536280297Sjkim /* 537280297Sjkim * Affects both BIOs in the pair -- call just once! Or let 538280297Sjkim * BIO_free(bio1); BIO_free(bio2); do the job. 539280297Sjkim */ 540280297Sjkim bio_destroy_pair(bio); 541280297Sjkim ret = 1; 542280297Sjkim break; 54359191Skris 544280297Sjkim case BIO_C_GET_WRITE_GUARANTEE: 545280297Sjkim /* 546280297Sjkim * How many bytes can the caller feed to the next write without 547280297Sjkim * having to keep any? 548280297Sjkim */ 549280297Sjkim if (b->peer == NULL || b->closed) 550280297Sjkim ret = 0; 551280297Sjkim else 552280297Sjkim ret = (long)b->size - b->len; 553280297Sjkim break; 55455714Skris 555280297Sjkim case BIO_C_GET_READ_REQUEST: 556280297Sjkim /* 557280297Sjkim * If the peer unsuccessfully tried to read, how many bytes were 558280297Sjkim * requested? (As with BIO_CTRL_PENDING, that number can usually be 559280297Sjkim * treated as boolean.) 560280297Sjkim */ 561280297Sjkim ret = (long)b->request; 562280297Sjkim break; 56355714Skris 564280297Sjkim case BIO_C_RESET_READ_REQUEST: 565280297Sjkim /* 566280297Sjkim * Reset request. (Can be useful after read attempts at the other 567280297Sjkim * side that are meant to be non-blocking, e.g. when probing SSL_read 568280297Sjkim * to see if any data is available.) 569280297Sjkim */ 570280297Sjkim b->request = 0; 571280297Sjkim ret = 1; 572280297Sjkim break; 57359191Skris 574280297Sjkim case BIO_C_SHUTDOWN_WR: 575280297Sjkim /* similar to shutdown(..., SHUT_WR) */ 576280297Sjkim b->closed = 1; 577280297Sjkim ret = 1; 578280297Sjkim break; 57955714Skris 580280297Sjkim case BIO_C_NREAD0: 581280297Sjkim /* prepare for non-copying read */ 582280297Sjkim ret = (long)bio_nread0(bio, ptr); 583280297Sjkim break; 58455714Skris 585280297Sjkim case BIO_C_NREAD: 586280297Sjkim /* non-copying read */ 587280297Sjkim ret = (long)bio_nread(bio, ptr, (size_t)num); 588280297Sjkim break; 58955714Skris 590280297Sjkim case BIO_C_NWRITE0: 591280297Sjkim /* prepare for non-copying write */ 592280297Sjkim ret = (long)bio_nwrite0(bio, ptr); 593280297Sjkim break; 59455714Skris 595280297Sjkim case BIO_C_NWRITE: 596280297Sjkim /* non-copying write */ 597280297Sjkim ret = (long)bio_nwrite(bio, ptr, (size_t)num); 598280297Sjkim break; 59955714Skris 600280297Sjkim /* standard CTRL codes follow */ 60155714Skris 602280297Sjkim case BIO_CTRL_RESET: 603280297Sjkim if (b->buf != NULL) { 604280297Sjkim b->len = 0; 605280297Sjkim b->offset = 0; 606280297Sjkim } 607280297Sjkim ret = 0; 608280297Sjkim break; 60955714Skris 610280297Sjkim case BIO_CTRL_GET_CLOSE: 611280297Sjkim ret = bio->shutdown; 612280297Sjkim break; 61355714Skris 614280297Sjkim case BIO_CTRL_SET_CLOSE: 615280297Sjkim bio->shutdown = (int)num; 616280297Sjkim ret = 1; 617280297Sjkim break; 61855714Skris 619280297Sjkim case BIO_CTRL_PENDING: 620280297Sjkim if (b->peer != NULL) { 621280297Sjkim struct bio_bio_st *peer_b = b->peer->ptr; 62255714Skris 623280297Sjkim ret = (long)peer_b->len; 624280297Sjkim } else 625280297Sjkim ret = 0; 626280297Sjkim break; 62755714Skris 628280297Sjkim case BIO_CTRL_WPENDING: 629280297Sjkim if (b->buf != NULL) 630280297Sjkim ret = (long)b->len; 631280297Sjkim else 632280297Sjkim ret = 0; 633280297Sjkim break; 63455714Skris 635280297Sjkim case BIO_CTRL_DUP: 636280297Sjkim /* See BIO_dup_chain for circumstances we have to expect. */ 637280297Sjkim { 638280297Sjkim BIO *other_bio = ptr; 639280297Sjkim struct bio_bio_st *other_b; 640280297Sjkim 641280297Sjkim assert(other_bio != NULL); 642280297Sjkim other_b = other_bio->ptr; 643280297Sjkim assert(other_b != NULL); 644280297Sjkim 645280297Sjkim assert(other_b->buf == NULL); /* other_bio is always fresh */ 646280297Sjkim 647280297Sjkim other_b->size = b->size; 648280297Sjkim } 649280297Sjkim 650280297Sjkim ret = 1; 651280297Sjkim break; 652280297Sjkim 653280297Sjkim case BIO_CTRL_FLUSH: 654280297Sjkim ret = 1; 655280297Sjkim break; 656280297Sjkim 657280297Sjkim case BIO_CTRL_EOF: 658280297Sjkim { 659280297Sjkim BIO *other_bio = ptr; 660280297Sjkim 661280297Sjkim if (other_bio) { 662280297Sjkim struct bio_bio_st *other_b = other_bio->ptr; 663280297Sjkim 664280297Sjkim assert(other_b != NULL); 665280297Sjkim ret = other_b->len == 0 && other_b->closed; 666280297Sjkim } else 667280297Sjkim ret = 1; 668280297Sjkim } 669280297Sjkim break; 670280297Sjkim 671280297Sjkim default: 672280297Sjkim ret = 0; 673280297Sjkim } 674280297Sjkim return ret; 675280297Sjkim} 676280297Sjkim 67768651Skrisstatic int bio_puts(BIO *bio, const char *str) 678280297Sjkim{ 679280297Sjkim return bio_write(bio, str, strlen(str)); 680280297Sjkim} 68155714Skris 68255714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2) 683280297Sjkim{ 684280297Sjkim struct bio_bio_st *b1, *b2; 68555714Skris 686280297Sjkim assert(bio1 != NULL); 687280297Sjkim assert(bio2 != NULL); 68855714Skris 689280297Sjkim b1 = bio1->ptr; 690280297Sjkim b2 = bio2->ptr; 69155714Skris 692280297Sjkim if (b1->peer != NULL || b2->peer != NULL) { 693280297Sjkim BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); 694280297Sjkim return 0; 695280297Sjkim } 69655714Skris 697280297Sjkim if (b1->buf == NULL) { 698280297Sjkim b1->buf = OPENSSL_malloc(b1->size); 699280297Sjkim if (b1->buf == NULL) { 700280297Sjkim BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 701280297Sjkim return 0; 702280297Sjkim } 703280297Sjkim b1->len = 0; 704280297Sjkim b1->offset = 0; 705280297Sjkim } 70655714Skris 707280297Sjkim if (b2->buf == NULL) { 708280297Sjkim b2->buf = OPENSSL_malloc(b2->size); 709280297Sjkim if (b2->buf == NULL) { 710280297Sjkim BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 711280297Sjkim return 0; 712280297Sjkim } 713280297Sjkim b2->len = 0; 714280297Sjkim b2->offset = 0; 715280297Sjkim } 716280297Sjkim 717280297Sjkim b1->peer = bio2; 718280297Sjkim b1->closed = 0; 719280297Sjkim b1->request = 0; 720280297Sjkim b2->peer = bio1; 721280297Sjkim b2->closed = 0; 722280297Sjkim b2->request = 0; 723280297Sjkim 724280297Sjkim bio1->init = 1; 725280297Sjkim bio2->init = 1; 726280297Sjkim 727280297Sjkim return 1; 728280297Sjkim} 729280297Sjkim 73055714Skrisstatic void bio_destroy_pair(BIO *bio) 731280297Sjkim{ 732280297Sjkim struct bio_bio_st *b = bio->ptr; 73355714Skris 734280297Sjkim if (b != NULL) { 735280297Sjkim BIO *peer_bio = b->peer; 73655714Skris 737280297Sjkim if (peer_bio != NULL) { 738280297Sjkim struct bio_bio_st *peer_b = peer_bio->ptr; 73955714Skris 740280297Sjkim assert(peer_b != NULL); 741280297Sjkim assert(peer_b->peer == bio); 74255714Skris 743280297Sjkim peer_b->peer = NULL; 744280297Sjkim peer_bio->init = 0; 745280297Sjkim assert(peer_b->buf != NULL); 746280297Sjkim peer_b->len = 0; 747280297Sjkim peer_b->offset = 0; 74855714Skris 749280297Sjkim b->peer = NULL; 750280297Sjkim bio->init = 0; 751280297Sjkim assert(b->buf != NULL); 752280297Sjkim b->len = 0; 753280297Sjkim b->offset = 0; 754280297Sjkim } 755280297Sjkim } 756280297Sjkim} 757280297Sjkim 75855714Skris/* Exported convenience functions */ 75955714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, 760280297Sjkim BIO **bio2_p, size_t writebuf2) 761280297Sjkim{ 762280297Sjkim BIO *bio1 = NULL, *bio2 = NULL; 763280297Sjkim long r; 764280297Sjkim int ret = 0; 76555714Skris 766280297Sjkim bio1 = BIO_new(BIO_s_bio()); 767280297Sjkim if (bio1 == NULL) 768280297Sjkim goto err; 769280297Sjkim bio2 = BIO_new(BIO_s_bio()); 770280297Sjkim if (bio2 == NULL) 771280297Sjkim goto err; 77255714Skris 773280297Sjkim if (writebuf1) { 774280297Sjkim r = BIO_set_write_buf_size(bio1, writebuf1); 775280297Sjkim if (!r) 776280297Sjkim goto err; 777280297Sjkim } 778280297Sjkim if (writebuf2) { 779280297Sjkim r = BIO_set_write_buf_size(bio2, writebuf2); 780280297Sjkim if (!r) 781280297Sjkim goto err; 782280297Sjkim } 78355714Skris 784280297Sjkim r = BIO_make_bio_pair(bio1, bio2); 785280297Sjkim if (!r) 786280297Sjkim goto err; 787280297Sjkim ret = 1; 78855714Skris 78955714Skris err: 790280297Sjkim if (ret == 0) { 791280297Sjkim if (bio1) { 792280297Sjkim BIO_free(bio1); 793280297Sjkim bio1 = NULL; 794280297Sjkim } 795280297Sjkim if (bio2) { 796280297Sjkim BIO_free(bio2); 797280297Sjkim bio2 = NULL; 798280297Sjkim } 799280297Sjkim } 80055714Skris 801280297Sjkim *bio1_p = bio1; 802280297Sjkim *bio2_p = bio2; 803280297Sjkim return ret; 804280297Sjkim} 80555714Skris 80655714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio) 807280297Sjkim{ 808280297Sjkim return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 809280297Sjkim} 81055714Skris 81155714Skrissize_t BIO_ctrl_get_read_request(BIO *bio) 812280297Sjkim{ 813280297Sjkim return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 814280297Sjkim} 81559191Skris 81659191Skrisint BIO_ctrl_reset_read_request(BIO *bio) 817280297Sjkim{ 818280297Sjkim return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); 819280297Sjkim} 82059191Skris 821280297Sjkim/* 822280297Sjkim * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now 823280297Sjkim * (conceivably some other BIOs could allow non-copying reads and writes 824280297Sjkim * too.) 82559191Skris */ 82659191Skrisint BIO_nread0(BIO *bio, char **buf) 827280297Sjkim{ 828280297Sjkim long ret; 82959191Skris 830280297Sjkim if (!bio->init) { 831280297Sjkim BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); 832280297Sjkim return -2; 833280297Sjkim } 83459191Skris 835280297Sjkim ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); 836280297Sjkim if (ret > INT_MAX) 837280297Sjkim return INT_MAX; 838280297Sjkim else 839280297Sjkim return (int)ret; 840280297Sjkim} 84159191Skris 84259191Skrisint BIO_nread(BIO *bio, char **buf, int num) 843280297Sjkim{ 844280297Sjkim int ret; 84559191Skris 846280297Sjkim if (!bio->init) { 847280297Sjkim BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); 848280297Sjkim return -2; 849280297Sjkim } 85059191Skris 851280297Sjkim ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf); 852280297Sjkim if (ret > 0) 853280297Sjkim bio->num_read += ret; 854280297Sjkim return ret; 855280297Sjkim} 85659191Skris 85759191Skrisint BIO_nwrite0(BIO *bio, char **buf) 858280297Sjkim{ 859280297Sjkim long ret; 86059191Skris 861280297Sjkim if (!bio->init) { 862280297Sjkim BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); 863280297Sjkim return -2; 864280297Sjkim } 86559191Skris 866280297Sjkim ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); 867280297Sjkim if (ret > INT_MAX) 868280297Sjkim return INT_MAX; 869280297Sjkim else 870280297Sjkim return (int)ret; 871280297Sjkim} 87259191Skris 87359191Skrisint BIO_nwrite(BIO *bio, char **buf, int num) 874280297Sjkim{ 875280297Sjkim int ret; 87659191Skris 877280297Sjkim if (!bio->init) { 878280297Sjkim BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); 879280297Sjkim return -2; 880280297Sjkim } 88159191Skris 882280297Sjkim ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); 883280297Sjkim if (ret > 0) 884280297Sjkim bio->num_write += ret; 885280297Sjkim return ret; 886280297Sjkim} 887