1295009Sjkim/* crypto/bio/bss_bio.c */ 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 147331638Sjkim b = OPENSSL_malloc(sizeof(*b)); 148280297Sjkim if (b == NULL) 149280297Sjkim return 0; 15055714Skris 151280297Sjkim b->peer = NULL; 152306195Sjkim b->closed = 0; 153306195Sjkim b->len = 0; 154306195Sjkim b->offset = 0; 155280297Sjkim /* enough for one TLS record (just a default) */ 156280297Sjkim b->size = 17 * 1024; 157280297Sjkim b->buf = NULL; 158306195Sjkim b->request = 0; 15955714Skris 160280297Sjkim bio->ptr = b; 161280297Sjkim return 1; 162280297Sjkim} 16355714Skris 16455714Skrisstatic int bio_free(BIO *bio) 165280297Sjkim{ 166280297Sjkim struct bio_bio_st *b; 16755714Skris 168280297Sjkim if (bio == NULL) 169280297Sjkim return 0; 170280297Sjkim b = bio->ptr; 17155714Skris 172280297Sjkim assert(b != NULL); 17355714Skris 174280297Sjkim if (b->peer) 175280297Sjkim bio_destroy_pair(bio); 17655714Skris 177280297Sjkim if (b->buf != NULL) { 178280297Sjkim OPENSSL_free(b->buf); 179280297Sjkim } 18055714Skris 181280297Sjkim OPENSSL_free(b); 18255714Skris 183280297Sjkim return 1; 184280297Sjkim} 18555714Skris 18655714Skrisstatic int bio_read(BIO *bio, char *buf, int size_) 187280297Sjkim{ 188280297Sjkim size_t size = size_; 189280297Sjkim size_t rest; 190280297Sjkim struct bio_bio_st *b, *peer_b; 19155714Skris 192280297Sjkim BIO_clear_retry_flags(bio); 19355714Skris 194280297Sjkim if (!bio->init) 195280297Sjkim return 0; 19655714Skris 197280297Sjkim b = bio->ptr; 198280297Sjkim assert(b != NULL); 199280297Sjkim assert(b->peer != NULL); 200280297Sjkim peer_b = b->peer->ptr; 201280297Sjkim assert(peer_b != NULL); 202280297Sjkim assert(peer_b->buf != NULL); 20355714Skris 204280297Sjkim peer_b->request = 0; /* will be set in "retry_read" situation */ 20555714Skris 206280297Sjkim if (buf == NULL || size == 0) 207280297Sjkim return 0; 20855714Skris 209280297Sjkim if (peer_b->len == 0) { 210280297Sjkim if (peer_b->closed) 211280297Sjkim return 0; /* writer has closed, and no data is left */ 212280297Sjkim else { 213280297Sjkim BIO_set_retry_read(bio); /* buffer is empty */ 214280297Sjkim if (size <= peer_b->size) 215280297Sjkim peer_b->request = size; 216280297Sjkim else 217280297Sjkim /* 218280297Sjkim * don't ask for more than the peer can deliver in one write 219280297Sjkim */ 220280297Sjkim peer_b->request = peer_b->size; 221280297Sjkim return -1; 222280297Sjkim } 223280297Sjkim } 22455714Skris 225280297Sjkim /* we can read */ 226280297Sjkim if (peer_b->len < size) 227280297Sjkim size = peer_b->len; 22855714Skris 229280297Sjkim /* now read "size" bytes */ 23055714Skris 231280297Sjkim rest = size; 232280297Sjkim 233280297Sjkim assert(rest > 0); 234280297Sjkim do { /* one or two iterations */ 235280297Sjkim size_t chunk; 236280297Sjkim 237280297Sjkim assert(rest <= peer_b->len); 238280297Sjkim if (peer_b->offset + rest <= peer_b->size) 239280297Sjkim chunk = rest; 240280297Sjkim else 241280297Sjkim /* wrap around ring buffer */ 242280297Sjkim chunk = peer_b->size - peer_b->offset; 243280297Sjkim assert(peer_b->offset + chunk <= peer_b->size); 244280297Sjkim 245280297Sjkim memcpy(buf, peer_b->buf + peer_b->offset, chunk); 246280297Sjkim 247280297Sjkim peer_b->len -= chunk; 248280297Sjkim if (peer_b->len) { 249280297Sjkim peer_b->offset += chunk; 250280297Sjkim assert(peer_b->offset <= peer_b->size); 251280297Sjkim if (peer_b->offset == peer_b->size) 252280297Sjkim peer_b->offset = 0; 253280297Sjkim buf += chunk; 254280297Sjkim } else { 255280297Sjkim /* buffer now empty, no need to advance "buf" */ 256280297Sjkim assert(chunk == rest); 257280297Sjkim peer_b->offset = 0; 258280297Sjkim } 259280297Sjkim rest -= chunk; 260280297Sjkim } 261280297Sjkim while (rest); 262280297Sjkim 263280297Sjkim return size; 264280297Sjkim} 265280297Sjkim 266280297Sjkim/*- 267280297Sjkim * non-copying interface: provide pointer to available data in buffer 26859191Skris * bio_nread0: return number of available bytes 26959191Skris * bio_nread: also advance index 27059191Skris * (example usage: bio_nread0(), read from buffer, bio_nread() 27159191Skris * or just bio_nread(), read from buffer) 27259191Skris */ 273280297Sjkim/* 274280297Sjkim * WARNING: The non-copying interface is largely untested as of yet and may 275280297Sjkim * contain bugs. 276280297Sjkim */ 277238405Sjkimstatic ossl_ssize_t bio_nread0(BIO *bio, char **buf) 278280297Sjkim{ 279280297Sjkim struct bio_bio_st *b, *peer_b; 280280297Sjkim ossl_ssize_t num; 28159191Skris 282280297Sjkim BIO_clear_retry_flags(bio); 28359191Skris 284280297Sjkim if (!bio->init) 285280297Sjkim return 0; 28659191Skris 287280297Sjkim b = bio->ptr; 288280297Sjkim assert(b != NULL); 289280297Sjkim assert(b->peer != NULL); 290280297Sjkim peer_b = b->peer->ptr; 291280297Sjkim assert(peer_b != NULL); 292280297Sjkim assert(peer_b->buf != NULL); 29359191Skris 294280297Sjkim peer_b->request = 0; 295280297Sjkim 296280297Sjkim if (peer_b->len == 0) { 297280297Sjkim char dummy; 298280297Sjkim 299280297Sjkim /* avoid code duplication -- nothing available for reading */ 300280297Sjkim return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ 301280297Sjkim } 302280297Sjkim 303280297Sjkim num = peer_b->len; 304280297Sjkim if (peer_b->size < peer_b->offset + num) 305280297Sjkim /* no ring buffer wrap-around for non-copying interface */ 306280297Sjkim num = peer_b->size - peer_b->offset; 307280297Sjkim assert(num > 0); 308280297Sjkim 309280297Sjkim if (buf != NULL) 310280297Sjkim *buf = peer_b->buf + peer_b->offset; 311280297Sjkim return num; 312280297Sjkim} 313280297Sjkim 314238405Sjkimstatic ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_) 315280297Sjkim{ 316280297Sjkim struct bio_bio_st *b, *peer_b; 317280297Sjkim ossl_ssize_t num, available; 31859191Skris 319280297Sjkim if (num_ > SSIZE_MAX) 320280297Sjkim num = SSIZE_MAX; 321280297Sjkim else 322280297Sjkim num = (ossl_ssize_t) num_; 32359191Skris 324280297Sjkim available = bio_nread0(bio, buf); 325280297Sjkim if (num > available) 326280297Sjkim num = available; 327280297Sjkim if (num <= 0) 328280297Sjkim return num; 32959191Skris 330280297Sjkim b = bio->ptr; 331280297Sjkim peer_b = b->peer->ptr; 33259191Skris 333280297Sjkim peer_b->len -= num; 334280297Sjkim if (peer_b->len) { 335280297Sjkim peer_b->offset += num; 336280297Sjkim assert(peer_b->offset <= peer_b->size); 337280297Sjkim if (peer_b->offset == peer_b->size) 338280297Sjkim peer_b->offset = 0; 339280297Sjkim } else 340280297Sjkim peer_b->offset = 0; 34159191Skris 342280297Sjkim return num; 343280297Sjkim} 34459191Skris 34568651Skrisstatic int bio_write(BIO *bio, const char *buf, int num_) 346280297Sjkim{ 347280297Sjkim size_t num = num_; 348280297Sjkim size_t rest; 349280297Sjkim struct bio_bio_st *b; 35055714Skris 351280297Sjkim BIO_clear_retry_flags(bio); 35255714Skris 353280297Sjkim if (!bio->init || buf == NULL || num == 0) 354280297Sjkim return 0; 35555714Skris 356280297Sjkim b = bio->ptr; 357280297Sjkim assert(b != NULL); 358280297Sjkim assert(b->peer != NULL); 359280297Sjkim assert(b->buf != NULL); 36055714Skris 361280297Sjkim b->request = 0; 362280297Sjkim if (b->closed) { 363280297Sjkim /* we already closed */ 364280297Sjkim BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); 365280297Sjkim return -1; 366280297Sjkim } 36755714Skris 368280297Sjkim assert(b->len <= b->size); 36955714Skris 370280297Sjkim if (b->len == b->size) { 371280297Sjkim BIO_set_retry_write(bio); /* buffer is full */ 372280297Sjkim return -1; 373280297Sjkim } 37455714Skris 375280297Sjkim /* we can write */ 376280297Sjkim if (num > b->size - b->len) 377280297Sjkim num = b->size - b->len; 37855714Skris 379280297Sjkim /* now write "num" bytes */ 38055714Skris 381280297Sjkim rest = num; 38255714Skris 383280297Sjkim assert(rest > 0); 384280297Sjkim do { /* one or two iterations */ 385280297Sjkim size_t write_offset; 386280297Sjkim size_t chunk; 38755714Skris 388280297Sjkim assert(b->len + rest <= b->size); 38955714Skris 390280297Sjkim write_offset = b->offset + b->len; 391280297Sjkim if (write_offset >= b->size) 392280297Sjkim write_offset -= b->size; 393280297Sjkim /* b->buf[write_offset] is the first byte we can write to. */ 39455714Skris 395280297Sjkim if (write_offset + rest <= b->size) 396280297Sjkim chunk = rest; 397280297Sjkim else 398280297Sjkim /* wrap around ring buffer */ 399280297Sjkim chunk = b->size - write_offset; 40055714Skris 401280297Sjkim memcpy(b->buf + write_offset, buf, chunk); 402280297Sjkim 403280297Sjkim b->len += chunk; 404280297Sjkim 405280297Sjkim assert(b->len <= b->size); 406280297Sjkim 407280297Sjkim rest -= chunk; 408280297Sjkim buf += chunk; 409280297Sjkim } 410280297Sjkim while (rest); 411280297Sjkim 412280297Sjkim return num; 413280297Sjkim} 414280297Sjkim 415280297Sjkim/*- 416280297Sjkim * non-copying interface: provide pointer to region to write to 41759191Skris * bio_nwrite0: check how much space is available 41859191Skris * bio_nwrite: also increase length 41959191Skris * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() 42059191Skris * or just bio_nwrite(), write to buffer) 42159191Skris */ 422238405Sjkimstatic ossl_ssize_t bio_nwrite0(BIO *bio, char **buf) 423280297Sjkim{ 424280297Sjkim struct bio_bio_st *b; 425280297Sjkim size_t num; 426280297Sjkim size_t write_offset; 42755714Skris 428280297Sjkim BIO_clear_retry_flags(bio); 42959191Skris 430280297Sjkim if (!bio->init) 431280297Sjkim return 0; 43259191Skris 433280297Sjkim b = bio->ptr; 434280297Sjkim assert(b != NULL); 435280297Sjkim assert(b->peer != NULL); 436280297Sjkim assert(b->buf != NULL); 43759191Skris 438280297Sjkim b->request = 0; 439280297Sjkim if (b->closed) { 440280297Sjkim BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); 441280297Sjkim return -1; 442280297Sjkim } 44359191Skris 444280297Sjkim assert(b->len <= b->size); 44559191Skris 446280297Sjkim if (b->len == b->size) { 447280297Sjkim BIO_set_retry_write(bio); 448280297Sjkim return -1; 449280297Sjkim } 45059191Skris 451280297Sjkim num = b->size - b->len; 452280297Sjkim write_offset = b->offset + b->len; 453280297Sjkim if (write_offset >= b->size) 454280297Sjkim write_offset -= b->size; 455280297Sjkim if (write_offset + num > b->size) 456280297Sjkim /* 457280297Sjkim * no ring buffer wrap-around for non-copying interface (to fulfil 458280297Sjkim * the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have 459280297Sjkim * to be called twice) 460280297Sjkim */ 461280297Sjkim num = b->size - write_offset; 46259191Skris 463280297Sjkim if (buf != NULL) 464280297Sjkim *buf = b->buf + write_offset; 465280297Sjkim assert(write_offset + num <= b->size); 46659191Skris 467280297Sjkim return num; 468280297Sjkim} 46959191Skris 470238405Sjkimstatic ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) 471280297Sjkim{ 472280297Sjkim struct bio_bio_st *b; 473280297Sjkim ossl_ssize_t num, space; 47459191Skris 475280297Sjkim if (num_ > SSIZE_MAX) 476280297Sjkim num = SSIZE_MAX; 477280297Sjkim else 478280297Sjkim num = (ossl_ssize_t) num_; 47959191Skris 480280297Sjkim space = bio_nwrite0(bio, buf); 481280297Sjkim if (num > space) 482280297Sjkim num = space; 483280297Sjkim if (num <= 0) 484280297Sjkim return num; 485280297Sjkim b = bio->ptr; 486280297Sjkim assert(b != NULL); 487280297Sjkim b->len += num; 488280297Sjkim assert(b->len <= b->size); 48959191Skris 490280297Sjkim return num; 491280297Sjkim} 49259191Skris 49355714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 494280297Sjkim{ 495280297Sjkim long ret; 496280297Sjkim struct bio_bio_st *b = bio->ptr; 49755714Skris 498280297Sjkim assert(b != NULL); 49955714Skris 500280297Sjkim switch (cmd) { 501280297Sjkim /* specific CTRL codes */ 50255714Skris 503280297Sjkim case BIO_C_SET_WRITE_BUF_SIZE: 504280297Sjkim if (b->peer) { 505280297Sjkim BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); 506280297Sjkim ret = 0; 507280297Sjkim } else if (num == 0) { 508280297Sjkim BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); 509280297Sjkim ret = 0; 510280297Sjkim } else { 511280297Sjkim size_t new_size = num; 51255714Skris 513280297Sjkim if (b->size != new_size) { 514280297Sjkim if (b->buf) { 515280297Sjkim OPENSSL_free(b->buf); 516280297Sjkim b->buf = NULL; 517280297Sjkim } 518280297Sjkim b->size = new_size; 519280297Sjkim } 520280297Sjkim ret = 1; 521280297Sjkim } 522280297Sjkim break; 52355714Skris 524280297Sjkim case BIO_C_GET_WRITE_BUF_SIZE: 525280297Sjkim ret = (long)b->size; 526280297Sjkim break; 52755714Skris 528280297Sjkim case BIO_C_MAKE_BIO_PAIR: 529280297Sjkim { 530280297Sjkim BIO *other_bio = ptr; 53155714Skris 532280297Sjkim if (bio_make_pair(bio, other_bio)) 533280297Sjkim ret = 1; 534280297Sjkim else 535280297Sjkim ret = 0; 536280297Sjkim } 537280297Sjkim break; 53855714Skris 539280297Sjkim case BIO_C_DESTROY_BIO_PAIR: 540280297Sjkim /* 541280297Sjkim * Affects both BIOs in the pair -- call just once! Or let 542280297Sjkim * BIO_free(bio1); BIO_free(bio2); do the job. 543280297Sjkim */ 544280297Sjkim bio_destroy_pair(bio); 545280297Sjkim ret = 1; 546280297Sjkim break; 54759191Skris 548280297Sjkim case BIO_C_GET_WRITE_GUARANTEE: 549280297Sjkim /* 550280297Sjkim * How many bytes can the caller feed to the next write without 551280297Sjkim * having to keep any? 552280297Sjkim */ 553280297Sjkim if (b->peer == NULL || b->closed) 554280297Sjkim ret = 0; 555280297Sjkim else 556280297Sjkim ret = (long)b->size - b->len; 557280297Sjkim break; 55855714Skris 559280297Sjkim case BIO_C_GET_READ_REQUEST: 560280297Sjkim /* 561280297Sjkim * If the peer unsuccessfully tried to read, how many bytes were 562280297Sjkim * requested? (As with BIO_CTRL_PENDING, that number can usually be 563280297Sjkim * treated as boolean.) 564280297Sjkim */ 565280297Sjkim ret = (long)b->request; 566280297Sjkim break; 56755714Skris 568280297Sjkim case BIO_C_RESET_READ_REQUEST: 569280297Sjkim /* 570280297Sjkim * Reset request. (Can be useful after read attempts at the other 571280297Sjkim * side that are meant to be non-blocking, e.g. when probing SSL_read 572280297Sjkim * to see if any data is available.) 573280297Sjkim */ 574280297Sjkim b->request = 0; 575280297Sjkim ret = 1; 576280297Sjkim break; 57759191Skris 578280297Sjkim case BIO_C_SHUTDOWN_WR: 579280297Sjkim /* similar to shutdown(..., SHUT_WR) */ 580280297Sjkim b->closed = 1; 581280297Sjkim ret = 1; 582280297Sjkim break; 58355714Skris 584280297Sjkim case BIO_C_NREAD0: 585280297Sjkim /* prepare for non-copying read */ 586280297Sjkim ret = (long)bio_nread0(bio, ptr); 587280297Sjkim break; 58855714Skris 589280297Sjkim case BIO_C_NREAD: 590280297Sjkim /* non-copying read */ 591280297Sjkim ret = (long)bio_nread(bio, ptr, (size_t)num); 592280297Sjkim break; 59355714Skris 594280297Sjkim case BIO_C_NWRITE0: 595280297Sjkim /* prepare for non-copying write */ 596280297Sjkim ret = (long)bio_nwrite0(bio, ptr); 597280297Sjkim break; 59855714Skris 599280297Sjkim case BIO_C_NWRITE: 600280297Sjkim /* non-copying write */ 601280297Sjkim ret = (long)bio_nwrite(bio, ptr, (size_t)num); 602280297Sjkim break; 60355714Skris 604280297Sjkim /* standard CTRL codes follow */ 60555714Skris 606280297Sjkim case BIO_CTRL_RESET: 607280297Sjkim if (b->buf != NULL) { 608280297Sjkim b->len = 0; 609280297Sjkim b->offset = 0; 610280297Sjkim } 611280297Sjkim ret = 0; 612280297Sjkim break; 61355714Skris 614280297Sjkim case BIO_CTRL_GET_CLOSE: 615280297Sjkim ret = bio->shutdown; 616280297Sjkim break; 61755714Skris 618280297Sjkim case BIO_CTRL_SET_CLOSE: 619280297Sjkim bio->shutdown = (int)num; 620280297Sjkim ret = 1; 621280297Sjkim break; 62255714Skris 623280297Sjkim case BIO_CTRL_PENDING: 624280297Sjkim if (b->peer != NULL) { 625280297Sjkim struct bio_bio_st *peer_b = b->peer->ptr; 62655714Skris 627280297Sjkim ret = (long)peer_b->len; 628280297Sjkim } else 629280297Sjkim ret = 0; 630280297Sjkim break; 63155714Skris 632280297Sjkim case BIO_CTRL_WPENDING: 633280297Sjkim if (b->buf != NULL) 634280297Sjkim ret = (long)b->len; 635280297Sjkim else 636280297Sjkim ret = 0; 637280297Sjkim break; 63855714Skris 639280297Sjkim case BIO_CTRL_DUP: 640280297Sjkim /* See BIO_dup_chain for circumstances we have to expect. */ 641280297Sjkim { 642280297Sjkim BIO *other_bio = ptr; 643280297Sjkim struct bio_bio_st *other_b; 644280297Sjkim 645280297Sjkim assert(other_bio != NULL); 646280297Sjkim other_b = other_bio->ptr; 647280297Sjkim assert(other_b != NULL); 648280297Sjkim 649280297Sjkim assert(other_b->buf == NULL); /* other_bio is always fresh */ 650280297Sjkim 651280297Sjkim other_b->size = b->size; 652280297Sjkim } 653280297Sjkim 654280297Sjkim ret = 1; 655280297Sjkim break; 656280297Sjkim 657280297Sjkim case BIO_CTRL_FLUSH: 658280297Sjkim ret = 1; 659280297Sjkim break; 660280297Sjkim 661280297Sjkim case BIO_CTRL_EOF: 662306195Sjkim if (b->peer != NULL) { 663306195Sjkim struct bio_bio_st *peer_b = b->peer->ptr; 664280297Sjkim 665306195Sjkim if (peer_b->len == 0 && peer_b->closed) 666280297Sjkim ret = 1; 667306195Sjkim else 668306195Sjkim ret = 0; 669306195Sjkim } else { 670306195Sjkim ret = 1; 671280297Sjkim } 672280297Sjkim break; 673280297Sjkim 674280297Sjkim default: 675280297Sjkim ret = 0; 676280297Sjkim } 677280297Sjkim return ret; 678280297Sjkim} 679280297Sjkim 68068651Skrisstatic int bio_puts(BIO *bio, const char *str) 681280297Sjkim{ 682280297Sjkim return bio_write(bio, str, strlen(str)); 683280297Sjkim} 68455714Skris 68555714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2) 686280297Sjkim{ 687280297Sjkim struct bio_bio_st *b1, *b2; 68855714Skris 689280297Sjkim assert(bio1 != NULL); 690280297Sjkim assert(bio2 != NULL); 69155714Skris 692280297Sjkim b1 = bio1->ptr; 693280297Sjkim b2 = bio2->ptr; 69455714Skris 695280297Sjkim if (b1->peer != NULL || b2->peer != NULL) { 696280297Sjkim BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); 697280297Sjkim return 0; 698280297Sjkim } 69955714Skris 700280297Sjkim if (b1->buf == NULL) { 701280297Sjkim b1->buf = OPENSSL_malloc(b1->size); 702280297Sjkim if (b1->buf == NULL) { 703280297Sjkim BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 704280297Sjkim return 0; 705280297Sjkim } 706280297Sjkim b1->len = 0; 707280297Sjkim b1->offset = 0; 708280297Sjkim } 70955714Skris 710280297Sjkim if (b2->buf == NULL) { 711280297Sjkim b2->buf = OPENSSL_malloc(b2->size); 712280297Sjkim if (b2->buf == NULL) { 713280297Sjkim BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 714280297Sjkim return 0; 715280297Sjkim } 716280297Sjkim b2->len = 0; 717280297Sjkim b2->offset = 0; 718280297Sjkim } 719280297Sjkim 720280297Sjkim b1->peer = bio2; 721280297Sjkim b1->closed = 0; 722280297Sjkim b1->request = 0; 723280297Sjkim b2->peer = bio1; 724280297Sjkim b2->closed = 0; 725280297Sjkim b2->request = 0; 726280297Sjkim 727280297Sjkim bio1->init = 1; 728280297Sjkim bio2->init = 1; 729280297Sjkim 730280297Sjkim return 1; 731280297Sjkim} 732280297Sjkim 73355714Skrisstatic void bio_destroy_pair(BIO *bio) 734280297Sjkim{ 735280297Sjkim struct bio_bio_st *b = bio->ptr; 73655714Skris 737280297Sjkim if (b != NULL) { 738280297Sjkim BIO *peer_bio = b->peer; 73955714Skris 740280297Sjkim if (peer_bio != NULL) { 741280297Sjkim struct bio_bio_st *peer_b = peer_bio->ptr; 74255714Skris 743280297Sjkim assert(peer_b != NULL); 744280297Sjkim assert(peer_b->peer == bio); 74555714Skris 746280297Sjkim peer_b->peer = NULL; 747280297Sjkim peer_bio->init = 0; 748280297Sjkim assert(peer_b->buf != NULL); 749280297Sjkim peer_b->len = 0; 750280297Sjkim peer_b->offset = 0; 75155714Skris 752280297Sjkim b->peer = NULL; 753280297Sjkim bio->init = 0; 754280297Sjkim assert(b->buf != NULL); 755280297Sjkim b->len = 0; 756280297Sjkim b->offset = 0; 757280297Sjkim } 758280297Sjkim } 759280297Sjkim} 760280297Sjkim 76155714Skris/* Exported convenience functions */ 76255714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, 763280297Sjkim BIO **bio2_p, size_t writebuf2) 764280297Sjkim{ 765280297Sjkim BIO *bio1 = NULL, *bio2 = NULL; 766280297Sjkim long r; 767280297Sjkim int ret = 0; 76855714Skris 769280297Sjkim bio1 = BIO_new(BIO_s_bio()); 770280297Sjkim if (bio1 == NULL) 771280297Sjkim goto err; 772280297Sjkim bio2 = BIO_new(BIO_s_bio()); 773280297Sjkim if (bio2 == NULL) 774280297Sjkim goto err; 77555714Skris 776280297Sjkim if (writebuf1) { 777280297Sjkim r = BIO_set_write_buf_size(bio1, writebuf1); 778280297Sjkim if (!r) 779280297Sjkim goto err; 780280297Sjkim } 781280297Sjkim if (writebuf2) { 782280297Sjkim r = BIO_set_write_buf_size(bio2, writebuf2); 783280297Sjkim if (!r) 784280297Sjkim goto err; 785280297Sjkim } 78655714Skris 787280297Sjkim r = BIO_make_bio_pair(bio1, bio2); 788280297Sjkim if (!r) 789280297Sjkim goto err; 790280297Sjkim ret = 1; 79155714Skris 79255714Skris err: 793280297Sjkim if (ret == 0) { 794280297Sjkim if (bio1) { 795280297Sjkim BIO_free(bio1); 796280297Sjkim bio1 = NULL; 797280297Sjkim } 798280297Sjkim if (bio2) { 799280297Sjkim BIO_free(bio2); 800280297Sjkim bio2 = NULL; 801280297Sjkim } 802280297Sjkim } 80355714Skris 804280297Sjkim *bio1_p = bio1; 805280297Sjkim *bio2_p = bio2; 806280297Sjkim return ret; 807280297Sjkim} 80855714Skris 80955714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio) 810280297Sjkim{ 811280297Sjkim return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 812280297Sjkim} 81355714Skris 81455714Skrissize_t BIO_ctrl_get_read_request(BIO *bio) 815280297Sjkim{ 816280297Sjkim return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 817280297Sjkim} 81859191Skris 81959191Skrisint BIO_ctrl_reset_read_request(BIO *bio) 820280297Sjkim{ 821280297Sjkim return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); 822280297Sjkim} 82359191Skris 824280297Sjkim/* 825280297Sjkim * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now 826280297Sjkim * (conceivably some other BIOs could allow non-copying reads and writes 827280297Sjkim * too.) 82859191Skris */ 82959191Skrisint BIO_nread0(BIO *bio, char **buf) 830280297Sjkim{ 831280297Sjkim long ret; 83259191Skris 833280297Sjkim if (!bio->init) { 834280297Sjkim BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); 835280297Sjkim return -2; 836280297Sjkim } 83759191Skris 838280297Sjkim ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); 839280297Sjkim if (ret > INT_MAX) 840280297Sjkim return INT_MAX; 841280297Sjkim else 842280297Sjkim return (int)ret; 843280297Sjkim} 84459191Skris 84559191Skrisint BIO_nread(BIO *bio, char **buf, int num) 846280297Sjkim{ 847280297Sjkim int ret; 84859191Skris 849280297Sjkim if (!bio->init) { 850280297Sjkim BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); 851280297Sjkim return -2; 852280297Sjkim } 85359191Skris 854280297Sjkim ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf); 855280297Sjkim if (ret > 0) 856280297Sjkim bio->num_read += ret; 857280297Sjkim return ret; 858280297Sjkim} 85959191Skris 86059191Skrisint BIO_nwrite0(BIO *bio, char **buf) 861280297Sjkim{ 862280297Sjkim long ret; 86359191Skris 864280297Sjkim if (!bio->init) { 865280297Sjkim BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); 866280297Sjkim return -2; 867280297Sjkim } 86859191Skris 869280297Sjkim ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); 870280297Sjkim if (ret > INT_MAX) 871280297Sjkim return INT_MAX; 872280297Sjkim else 873280297Sjkim return (int)ret; 874280297Sjkim} 87559191Skris 87659191Skrisint BIO_nwrite(BIO *bio, char **buf, int num) 877280297Sjkim{ 878280297Sjkim int ret; 87959191Skris 880280297Sjkim if (!bio->init) { 881280297Sjkim BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); 882280297Sjkim return -2; 883280297Sjkim } 88459191Skris 885280297Sjkim ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); 886280297Sjkim if (ret > 0) 887280297Sjkim bio->num_write += ret; 888280297Sjkim return ret; 889280297Sjkim} 890