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 10296465Sdelphij * 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 56296465Sdelphij/* 57296465Sdelphij * Special method for a BIO where the other endpoint is also a BIO of this 58296465Sdelphij * kind, handled by the same thread (i.e. the "peer" is actually ourselves, 59296465Sdelphij * wearing a different hat). Such "BIO pairs" are mainly for using the SSL 60296465Sdelphij * library with I/O interfaces for which no specific BIO method is available. 61296465Sdelphij * See ssl/ssltest.c for some hints on how this can be used. 62296465Sdelphij */ 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 107296465Sdelphijstatic BIO_METHOD methods_biop = { 108296465Sdelphij BIO_TYPE_BIO, 109296465Sdelphij "BIO pair", 110296465Sdelphij bio_write, 111296465Sdelphij bio_read, 112296465Sdelphij bio_puts, 113296465Sdelphij NULL /* no bio_gets */ , 114296465Sdelphij bio_ctrl, 115296465Sdelphij bio_new, 116296465Sdelphij bio_free, 117296465Sdelphij NULL /* no bio_callback_ctrl */ 11855714Skris}; 11955714Skris 12055714SkrisBIO_METHOD *BIO_s_bio(void) 12155714Skris{ 122296465Sdelphij return &methods_biop; 123296465Sdelphij} 12455714Skris 125296465Sdelphijstruct bio_bio_st { 126296465Sdelphij BIO *peer; /* NULL if buf == NULL. If peer != NULL, then 127296465Sdelphij * peer->ptr is also a bio_bio_st, and its 128296465Sdelphij * "peer" member points back to us. peer != 129296465Sdelphij * NULL iff init != 0 in the BIO. */ 130296465Sdelphij /* This is for what we write (i.e. reading uses peer's struct): */ 131296465Sdelphij int closed; /* valid iff peer != NULL */ 132296465Sdelphij size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ 133296465Sdelphij size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ 134296465Sdelphij size_t size; 135296465Sdelphij char *buf; /* "size" elements (if != NULL) */ 136296465Sdelphij size_t request; /* valid iff peer != NULL; 0 if len != 0, 137296465Sdelphij * otherwise set by peer to number of bytes 138296465Sdelphij * it (unsuccessfully) tried to read, never 139296465Sdelphij * more than buffer space (size-len) 140296465Sdelphij * warrants. */ 14155714Skris}; 14255714Skris 14355714Skrisstatic int bio_new(BIO *bio) 144296465Sdelphij{ 145296465Sdelphij struct bio_bio_st *b; 14655714Skris 147296465Sdelphij b = OPENSSL_malloc(sizeof *b); 148296465Sdelphij if (b == NULL) 149296465Sdelphij return 0; 15055714Skris 151296465Sdelphij b->peer = NULL; 152296465Sdelphij /* enough for one TLS record (just a default) */ 153296465Sdelphij b->size = 17 * 1024; 154296465Sdelphij b->buf = NULL; 15555714Skris 156296465Sdelphij bio->ptr = b; 157296465Sdelphij return 1; 158296465Sdelphij} 15955714Skris 16055714Skrisstatic int bio_free(BIO *bio) 161296465Sdelphij{ 162296465Sdelphij struct bio_bio_st *b; 16355714Skris 164296465Sdelphij if (bio == NULL) 165296465Sdelphij return 0; 166296465Sdelphij b = bio->ptr; 16755714Skris 168296465Sdelphij assert(b != NULL); 16955714Skris 170296465Sdelphij if (b->peer) 171296465Sdelphij bio_destroy_pair(bio); 17255714Skris 173296465Sdelphij if (b->buf != NULL) { 174296465Sdelphij OPENSSL_free(b->buf); 175296465Sdelphij } 17655714Skris 177296465Sdelphij OPENSSL_free(b); 17855714Skris 179296465Sdelphij return 1; 180296465Sdelphij} 18155714Skris 18255714Skrisstatic int bio_read(BIO *bio, char *buf, int size_) 183296465Sdelphij{ 184296465Sdelphij size_t size = size_; 185296465Sdelphij size_t rest; 186296465Sdelphij struct bio_bio_st *b, *peer_b; 18755714Skris 188296465Sdelphij BIO_clear_retry_flags(bio); 18955714Skris 190296465Sdelphij if (!bio->init) 191296465Sdelphij return 0; 19255714Skris 193296465Sdelphij b = bio->ptr; 194296465Sdelphij assert(b != NULL); 195296465Sdelphij assert(b->peer != NULL); 196296465Sdelphij peer_b = b->peer->ptr; 197296465Sdelphij assert(peer_b != NULL); 198296465Sdelphij assert(peer_b->buf != NULL); 19955714Skris 200296465Sdelphij peer_b->request = 0; /* will be set in "retry_read" situation */ 20155714Skris 202296465Sdelphij if (buf == NULL || size == 0) 203296465Sdelphij return 0; 20455714Skris 205296465Sdelphij if (peer_b->len == 0) { 206296465Sdelphij if (peer_b->closed) 207296465Sdelphij return 0; /* writer has closed, and no data is left */ 208296465Sdelphij else { 209296465Sdelphij BIO_set_retry_read(bio); /* buffer is empty */ 210296465Sdelphij if (size <= peer_b->size) 211296465Sdelphij peer_b->request = size; 212296465Sdelphij else 213296465Sdelphij /* 214296465Sdelphij * don't ask for more than the peer can deliver in one write 215296465Sdelphij */ 216296465Sdelphij peer_b->request = peer_b->size; 217296465Sdelphij return -1; 218296465Sdelphij } 219296465Sdelphij } 22055714Skris 221296465Sdelphij /* we can read */ 222296465Sdelphij if (peer_b->len < size) 223296465Sdelphij size = peer_b->len; 22455714Skris 225296465Sdelphij /* now read "size" bytes */ 22655714Skris 227296465Sdelphij rest = size; 228296465Sdelphij 229296465Sdelphij assert(rest > 0); 230296465Sdelphij do { /* one or two iterations */ 231296465Sdelphij size_t chunk; 232296465Sdelphij 233296465Sdelphij assert(rest <= peer_b->len); 234296465Sdelphij if (peer_b->offset + rest <= peer_b->size) 235296465Sdelphij chunk = rest; 236296465Sdelphij else 237296465Sdelphij /* wrap around ring buffer */ 238296465Sdelphij chunk = peer_b->size - peer_b->offset; 239296465Sdelphij assert(peer_b->offset + chunk <= peer_b->size); 240296465Sdelphij 241296465Sdelphij memcpy(buf, peer_b->buf + peer_b->offset, chunk); 242296465Sdelphij 243296465Sdelphij peer_b->len -= chunk; 244296465Sdelphij if (peer_b->len) { 245296465Sdelphij peer_b->offset += chunk; 246296465Sdelphij assert(peer_b->offset <= peer_b->size); 247296465Sdelphij if (peer_b->offset == peer_b->size) 248296465Sdelphij peer_b->offset = 0; 249296465Sdelphij buf += chunk; 250296465Sdelphij } else { 251296465Sdelphij /* buffer now empty, no need to advance "buf" */ 252296465Sdelphij assert(chunk == rest); 253296465Sdelphij peer_b->offset = 0; 254296465Sdelphij } 255296465Sdelphij rest -= chunk; 256296465Sdelphij } 257296465Sdelphij while (rest); 258296465Sdelphij 259296465Sdelphij return size; 260296465Sdelphij} 261296465Sdelphij 262296465Sdelphij/*- 263296465Sdelphij * 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 */ 269296465Sdelphij/* 270296465Sdelphij * WARNING: The non-copying interface is largely untested as of yet and may 271296465Sdelphij * contain bugs. 272296465Sdelphij */ 27359191Skrisstatic ssize_t bio_nread0(BIO *bio, char **buf) 274296465Sdelphij{ 275296465Sdelphij struct bio_bio_st *b, *peer_b; 276296465Sdelphij ssize_t num; 27759191Skris 278296465Sdelphij BIO_clear_retry_flags(bio); 27959191Skris 280296465Sdelphij if (!bio->init) 281296465Sdelphij return 0; 28259191Skris 283296465Sdelphij b = bio->ptr; 284296465Sdelphij assert(b != NULL); 285296465Sdelphij assert(b->peer != NULL); 286296465Sdelphij peer_b = b->peer->ptr; 287296465Sdelphij assert(peer_b != NULL); 288296465Sdelphij assert(peer_b->buf != NULL); 28959191Skris 290296465Sdelphij peer_b->request = 0; 291296465Sdelphij 292296465Sdelphij if (peer_b->len == 0) { 293296465Sdelphij char dummy; 294296465Sdelphij 295296465Sdelphij /* avoid code duplication -- nothing available for reading */ 296296465Sdelphij return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ 297296465Sdelphij } 298296465Sdelphij 299296465Sdelphij num = peer_b->len; 300296465Sdelphij if (peer_b->size < peer_b->offset + num) 301296465Sdelphij /* no ring buffer wrap-around for non-copying interface */ 302296465Sdelphij num = peer_b->size - peer_b->offset; 303296465Sdelphij assert(num > 0); 304296465Sdelphij 305296465Sdelphij if (buf != NULL) 306296465Sdelphij *buf = peer_b->buf + peer_b->offset; 307296465Sdelphij return num; 308296465Sdelphij} 309296465Sdelphij 31059191Skrisstatic ssize_t bio_nread(BIO *bio, char **buf, size_t num_) 311296465Sdelphij{ 312296465Sdelphij struct bio_bio_st *b, *peer_b; 313296465Sdelphij ssize_t num, available; 31459191Skris 315296465Sdelphij if (num_ > SSIZE_MAX) 316296465Sdelphij num = SSIZE_MAX; 317296465Sdelphij else 318296465Sdelphij num = (ssize_t) num_; 31959191Skris 320296465Sdelphij available = bio_nread0(bio, buf); 321296465Sdelphij if (num > available) 322296465Sdelphij num = available; 323296465Sdelphij if (num <= 0) 324296465Sdelphij return num; 32559191Skris 326296465Sdelphij b = bio->ptr; 327296465Sdelphij peer_b = b->peer->ptr; 32859191Skris 329296465Sdelphij peer_b->len -= num; 330296465Sdelphij if (peer_b->len) { 331296465Sdelphij peer_b->offset += num; 332296465Sdelphij assert(peer_b->offset <= peer_b->size); 333296465Sdelphij if (peer_b->offset == peer_b->size) 334296465Sdelphij peer_b->offset = 0; 335296465Sdelphij } else 336296465Sdelphij peer_b->offset = 0; 33759191Skris 338296465Sdelphij return num; 339296465Sdelphij} 34059191Skris 34168651Skrisstatic int bio_write(BIO *bio, const char *buf, int num_) 342296465Sdelphij{ 343296465Sdelphij size_t num = num_; 344296465Sdelphij size_t rest; 345296465Sdelphij struct bio_bio_st *b; 34655714Skris 347296465Sdelphij BIO_clear_retry_flags(bio); 34855714Skris 349296465Sdelphij if (!bio->init || buf == NULL || num == 0) 350296465Sdelphij return 0; 35155714Skris 352296465Sdelphij b = bio->ptr; 353296465Sdelphij assert(b != NULL); 354296465Sdelphij assert(b->peer != NULL); 355296465Sdelphij assert(b->buf != NULL); 35655714Skris 357296465Sdelphij b->request = 0; 358296465Sdelphij if (b->closed) { 359296465Sdelphij /* we already closed */ 360296465Sdelphij BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); 361296465Sdelphij return -1; 362296465Sdelphij } 36355714Skris 364296465Sdelphij assert(b->len <= b->size); 36555714Skris 366296465Sdelphij if (b->len == b->size) { 367296465Sdelphij BIO_set_retry_write(bio); /* buffer is full */ 368296465Sdelphij return -1; 369296465Sdelphij } 37055714Skris 371296465Sdelphij /* we can write */ 372296465Sdelphij if (num > b->size - b->len) 373296465Sdelphij num = b->size - b->len; 37455714Skris 375296465Sdelphij /* now write "num" bytes */ 37655714Skris 377296465Sdelphij rest = num; 37855714Skris 379296465Sdelphij assert(rest > 0); 380296465Sdelphij do { /* one or two iterations */ 381296465Sdelphij size_t write_offset; 382296465Sdelphij size_t chunk; 38355714Skris 384296465Sdelphij assert(b->len + rest <= b->size); 38555714Skris 386296465Sdelphij write_offset = b->offset + b->len; 387296465Sdelphij if (write_offset >= b->size) 388296465Sdelphij write_offset -= b->size; 389296465Sdelphij /* b->buf[write_offset] is the first byte we can write to. */ 39055714Skris 391296465Sdelphij if (write_offset + rest <= b->size) 392296465Sdelphij chunk = rest; 393296465Sdelphij else 394296465Sdelphij /* wrap around ring buffer */ 395296465Sdelphij chunk = b->size - write_offset; 39655714Skris 397296465Sdelphij memcpy(b->buf + write_offset, buf, chunk); 398296465Sdelphij 399296465Sdelphij b->len += chunk; 400296465Sdelphij 401296465Sdelphij assert(b->len <= b->size); 402296465Sdelphij 403296465Sdelphij rest -= chunk; 404296465Sdelphij buf += chunk; 405296465Sdelphij } 406296465Sdelphij while (rest); 407296465Sdelphij 408296465Sdelphij return num; 409296465Sdelphij} 410296465Sdelphij 411296465Sdelphij/*- 412296465Sdelphij * 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 */ 41859191Skrisstatic ssize_t bio_nwrite0(BIO *bio, char **buf) 419296465Sdelphij{ 420296465Sdelphij struct bio_bio_st *b; 421296465Sdelphij size_t num; 422296465Sdelphij size_t write_offset; 42355714Skris 424296465Sdelphij BIO_clear_retry_flags(bio); 42559191Skris 426296465Sdelphij if (!bio->init) 427296465Sdelphij return 0; 42859191Skris 429296465Sdelphij b = bio->ptr; 430296465Sdelphij assert(b != NULL); 431296465Sdelphij assert(b->peer != NULL); 432296465Sdelphij assert(b->buf != NULL); 43359191Skris 434296465Sdelphij b->request = 0; 435296465Sdelphij if (b->closed) { 436296465Sdelphij BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); 437296465Sdelphij return -1; 438296465Sdelphij } 43959191Skris 440296465Sdelphij assert(b->len <= b->size); 44159191Skris 442296465Sdelphij if (b->len == b->size) { 443296465Sdelphij BIO_set_retry_write(bio); 444296465Sdelphij return -1; 445296465Sdelphij } 44659191Skris 447296465Sdelphij num = b->size - b->len; 448296465Sdelphij write_offset = b->offset + b->len; 449296465Sdelphij if (write_offset >= b->size) 450296465Sdelphij write_offset -= b->size; 451296465Sdelphij if (write_offset + num > b->size) 452296465Sdelphij /* 453296465Sdelphij * no ring buffer wrap-around for non-copying interface (to fulfil 454296465Sdelphij * the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have 455296465Sdelphij * to be called twice) 456296465Sdelphij */ 457296465Sdelphij num = b->size - write_offset; 45859191Skris 459296465Sdelphij if (buf != NULL) 460296465Sdelphij *buf = b->buf + write_offset; 461296465Sdelphij assert(write_offset + num <= b->size); 46259191Skris 463296465Sdelphij return num; 464296465Sdelphij} 46559191Skris 46659191Skrisstatic ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) 467296465Sdelphij{ 468296465Sdelphij struct bio_bio_st *b; 469296465Sdelphij ssize_t num, space; 47059191Skris 471296465Sdelphij if (num_ > SSIZE_MAX) 472296465Sdelphij num = SSIZE_MAX; 473296465Sdelphij else 474296465Sdelphij num = (ssize_t) num_; 47559191Skris 476296465Sdelphij space = bio_nwrite0(bio, buf); 477296465Sdelphij if (num > space) 478296465Sdelphij num = space; 479296465Sdelphij if (num <= 0) 480296465Sdelphij return num; 481296465Sdelphij b = bio->ptr; 482296465Sdelphij assert(b != NULL); 483296465Sdelphij b->len += num; 484296465Sdelphij assert(b->len <= b->size); 48559191Skris 486296465Sdelphij return num; 487296465Sdelphij} 48859191Skris 48955714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 490296465Sdelphij{ 491296465Sdelphij long ret; 492296465Sdelphij struct bio_bio_st *b = bio->ptr; 49355714Skris 494296465Sdelphij assert(b != NULL); 49555714Skris 496296465Sdelphij switch (cmd) { 497296465Sdelphij /* specific CTRL codes */ 49855714Skris 499296465Sdelphij case BIO_C_SET_WRITE_BUF_SIZE: 500296465Sdelphij if (b->peer) { 501296465Sdelphij BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); 502296465Sdelphij ret = 0; 503296465Sdelphij } else if (num == 0) { 504296465Sdelphij BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); 505296465Sdelphij ret = 0; 506296465Sdelphij } else { 507296465Sdelphij size_t new_size = num; 50855714Skris 509296465Sdelphij if (b->size != new_size) { 510296465Sdelphij if (b->buf) { 511296465Sdelphij OPENSSL_free(b->buf); 512296465Sdelphij b->buf = NULL; 513296465Sdelphij } 514296465Sdelphij b->size = new_size; 515296465Sdelphij } 516296465Sdelphij ret = 1; 517296465Sdelphij } 518296465Sdelphij break; 51955714Skris 520296465Sdelphij case BIO_C_GET_WRITE_BUF_SIZE: 521296465Sdelphij ret = (long)b->size; 522296465Sdelphij break; 52355714Skris 524296465Sdelphij case BIO_C_MAKE_BIO_PAIR: 525296465Sdelphij { 526296465Sdelphij BIO *other_bio = ptr; 52755714Skris 528296465Sdelphij if (bio_make_pair(bio, other_bio)) 529296465Sdelphij ret = 1; 530296465Sdelphij else 531296465Sdelphij ret = 0; 532296465Sdelphij } 533296465Sdelphij break; 53455714Skris 535296465Sdelphij case BIO_C_DESTROY_BIO_PAIR: 536296465Sdelphij /* 537296465Sdelphij * Affects both BIOs in the pair -- call just once! Or let 538296465Sdelphij * BIO_free(bio1); BIO_free(bio2); do the job. 539296465Sdelphij */ 540296465Sdelphij bio_destroy_pair(bio); 541296465Sdelphij ret = 1; 542296465Sdelphij break; 54359191Skris 544296465Sdelphij case BIO_C_GET_WRITE_GUARANTEE: 545296465Sdelphij /* 546296465Sdelphij * How many bytes can the caller feed to the next write without 547296465Sdelphij * having to keep any? 548296465Sdelphij */ 549296465Sdelphij if (b->peer == NULL || b->closed) 550296465Sdelphij ret = 0; 551296465Sdelphij else 552296465Sdelphij ret = (long)b->size - b->len; 553296465Sdelphij break; 55455714Skris 555296465Sdelphij case BIO_C_GET_READ_REQUEST: 556296465Sdelphij /* 557296465Sdelphij * If the peer unsuccessfully tried to read, how many bytes were 558296465Sdelphij * requested? (As with BIO_CTRL_PENDING, that number can usually be 559296465Sdelphij * treated as boolean.) 560296465Sdelphij */ 561296465Sdelphij ret = (long)b->request; 562296465Sdelphij break; 56355714Skris 564296465Sdelphij case BIO_C_RESET_READ_REQUEST: 565296465Sdelphij /* 566296465Sdelphij * Reset request. (Can be useful after read attempts at the other 567296465Sdelphij * side that are meant to be non-blocking, e.g. when probing SSL_read 568296465Sdelphij * to see if any data is available.) 569296465Sdelphij */ 570296465Sdelphij b->request = 0; 571296465Sdelphij ret = 1; 572296465Sdelphij break; 57359191Skris 574296465Sdelphij case BIO_C_SHUTDOWN_WR: 575296465Sdelphij /* similar to shutdown(..., SHUT_WR) */ 576296465Sdelphij b->closed = 1; 577296465Sdelphij ret = 1; 578296465Sdelphij break; 57955714Skris 580296465Sdelphij case BIO_C_NREAD0: 581296465Sdelphij /* prepare for non-copying read */ 582296465Sdelphij ret = (long)bio_nread0(bio, ptr); 583296465Sdelphij break; 58455714Skris 585296465Sdelphij case BIO_C_NREAD: 586296465Sdelphij /* non-copying read */ 587296465Sdelphij ret = (long)bio_nread(bio, ptr, (size_t)num); 588296465Sdelphij break; 58955714Skris 590296465Sdelphij case BIO_C_NWRITE0: 591296465Sdelphij /* prepare for non-copying write */ 592296465Sdelphij ret = (long)bio_nwrite0(bio, ptr); 593296465Sdelphij break; 59455714Skris 595296465Sdelphij case BIO_C_NWRITE: 596296465Sdelphij /* non-copying write */ 597296465Sdelphij ret = (long)bio_nwrite(bio, ptr, (size_t)num); 598296465Sdelphij break; 59955714Skris 600296465Sdelphij /* standard CTRL codes follow */ 60155714Skris 602296465Sdelphij case BIO_CTRL_RESET: 603296465Sdelphij if (b->buf != NULL) { 604296465Sdelphij b->len = 0; 605296465Sdelphij b->offset = 0; 606296465Sdelphij } 607296465Sdelphij ret = 0; 608296465Sdelphij break; 60955714Skris 610296465Sdelphij case BIO_CTRL_GET_CLOSE: 611296465Sdelphij ret = bio->shutdown; 612296465Sdelphij break; 61355714Skris 614296465Sdelphij case BIO_CTRL_SET_CLOSE: 615296465Sdelphij bio->shutdown = (int)num; 616296465Sdelphij ret = 1; 617296465Sdelphij break; 61855714Skris 619296465Sdelphij case BIO_CTRL_PENDING: 620296465Sdelphij if (b->peer != NULL) { 621296465Sdelphij struct bio_bio_st *peer_b = b->peer->ptr; 62255714Skris 623296465Sdelphij ret = (long)peer_b->len; 624296465Sdelphij } else 625296465Sdelphij ret = 0; 626296465Sdelphij break; 62755714Skris 628296465Sdelphij case BIO_CTRL_WPENDING: 629296465Sdelphij if (b->buf != NULL) 630296465Sdelphij ret = (long)b->len; 631296465Sdelphij else 632296465Sdelphij ret = 0; 633296465Sdelphij break; 63455714Skris 635296465Sdelphij case BIO_CTRL_DUP: 636296465Sdelphij /* See BIO_dup_chain for circumstances we have to expect. */ 637296465Sdelphij { 638296465Sdelphij BIO *other_bio = ptr; 639296465Sdelphij struct bio_bio_st *other_b; 640296465Sdelphij 641296465Sdelphij assert(other_bio != NULL); 642296465Sdelphij other_b = other_bio->ptr; 643296465Sdelphij assert(other_b != NULL); 644296465Sdelphij 645296465Sdelphij assert(other_b->buf == NULL); /* other_bio is always fresh */ 646296465Sdelphij 647296465Sdelphij other_b->size = b->size; 648296465Sdelphij } 649296465Sdelphij 650296465Sdelphij ret = 1; 651296465Sdelphij break; 652296465Sdelphij 653296465Sdelphij case BIO_CTRL_FLUSH: 654296465Sdelphij ret = 1; 655296465Sdelphij break; 656296465Sdelphij 657296465Sdelphij case BIO_CTRL_EOF: 658296465Sdelphij { 659296465Sdelphij BIO *other_bio = ptr; 660296465Sdelphij 661296465Sdelphij if (other_bio) { 662296465Sdelphij struct bio_bio_st *other_b = other_bio->ptr; 663296465Sdelphij 664296465Sdelphij assert(other_b != NULL); 665296465Sdelphij ret = other_b->len == 0 && other_b->closed; 666296465Sdelphij } else 667296465Sdelphij ret = 1; 668296465Sdelphij } 669296465Sdelphij break; 670296465Sdelphij 671296465Sdelphij default: 672296465Sdelphij ret = 0; 673296465Sdelphij } 674296465Sdelphij return ret; 675296465Sdelphij} 676296465Sdelphij 67768651Skrisstatic int bio_puts(BIO *bio, const char *str) 678296465Sdelphij{ 679296465Sdelphij return bio_write(bio, str, strlen(str)); 680296465Sdelphij} 68155714Skris 68255714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2) 683296465Sdelphij{ 684296465Sdelphij struct bio_bio_st *b1, *b2; 68555714Skris 686296465Sdelphij assert(bio1 != NULL); 687296465Sdelphij assert(bio2 != NULL); 68855714Skris 689296465Sdelphij b1 = bio1->ptr; 690296465Sdelphij b2 = bio2->ptr; 69155714Skris 692296465Sdelphij if (b1->peer != NULL || b2->peer != NULL) { 693296465Sdelphij BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); 694296465Sdelphij return 0; 695296465Sdelphij } 69655714Skris 697296465Sdelphij if (b1->buf == NULL) { 698296465Sdelphij b1->buf = OPENSSL_malloc(b1->size); 699296465Sdelphij if (b1->buf == NULL) { 700296465Sdelphij BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 701296465Sdelphij return 0; 702296465Sdelphij } 703296465Sdelphij b1->len = 0; 704296465Sdelphij b1->offset = 0; 705296465Sdelphij } 70655714Skris 707296465Sdelphij if (b2->buf == NULL) { 708296465Sdelphij b2->buf = OPENSSL_malloc(b2->size); 709296465Sdelphij if (b2->buf == NULL) { 710296465Sdelphij BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 711296465Sdelphij return 0; 712296465Sdelphij } 713296465Sdelphij b2->len = 0; 714296465Sdelphij b2->offset = 0; 715296465Sdelphij } 716296465Sdelphij 717296465Sdelphij b1->peer = bio2; 718296465Sdelphij b1->closed = 0; 719296465Sdelphij b1->request = 0; 720296465Sdelphij b2->peer = bio1; 721296465Sdelphij b2->closed = 0; 722296465Sdelphij b2->request = 0; 723296465Sdelphij 724296465Sdelphij bio1->init = 1; 725296465Sdelphij bio2->init = 1; 726296465Sdelphij 727296465Sdelphij return 1; 728296465Sdelphij} 729296465Sdelphij 73055714Skrisstatic void bio_destroy_pair(BIO *bio) 731296465Sdelphij{ 732296465Sdelphij struct bio_bio_st *b = bio->ptr; 73355714Skris 734296465Sdelphij if (b != NULL) { 735296465Sdelphij BIO *peer_bio = b->peer; 73655714Skris 737296465Sdelphij if (peer_bio != NULL) { 738296465Sdelphij struct bio_bio_st *peer_b = peer_bio->ptr; 73955714Skris 740296465Sdelphij assert(peer_b != NULL); 741296465Sdelphij assert(peer_b->peer == bio); 74255714Skris 743296465Sdelphij peer_b->peer = NULL; 744296465Sdelphij peer_bio->init = 0; 745296465Sdelphij assert(peer_b->buf != NULL); 746296465Sdelphij peer_b->len = 0; 747296465Sdelphij peer_b->offset = 0; 74855714Skris 749296465Sdelphij b->peer = NULL; 750296465Sdelphij bio->init = 0; 751296465Sdelphij assert(b->buf != NULL); 752296465Sdelphij b->len = 0; 753296465Sdelphij b->offset = 0; 754296465Sdelphij } 755296465Sdelphij } 756296465Sdelphij} 757296465Sdelphij 75855714Skris/* Exported convenience functions */ 75955714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, 760296465Sdelphij BIO **bio2_p, size_t writebuf2) 761296465Sdelphij{ 762296465Sdelphij BIO *bio1 = NULL, *bio2 = NULL; 763296465Sdelphij long r; 764296465Sdelphij int ret = 0; 76555714Skris 766296465Sdelphij bio1 = BIO_new(BIO_s_bio()); 767296465Sdelphij if (bio1 == NULL) 768296465Sdelphij goto err; 769296465Sdelphij bio2 = BIO_new(BIO_s_bio()); 770296465Sdelphij if (bio2 == NULL) 771296465Sdelphij goto err; 77255714Skris 773296465Sdelphij if (writebuf1) { 774296465Sdelphij r = BIO_set_write_buf_size(bio1, writebuf1); 775296465Sdelphij if (!r) 776296465Sdelphij goto err; 777296465Sdelphij } 778296465Sdelphij if (writebuf2) { 779296465Sdelphij r = BIO_set_write_buf_size(bio2, writebuf2); 780296465Sdelphij if (!r) 781296465Sdelphij goto err; 782296465Sdelphij } 78355714Skris 784296465Sdelphij r = BIO_make_bio_pair(bio1, bio2); 785296465Sdelphij if (!r) 786296465Sdelphij goto err; 787296465Sdelphij ret = 1; 78855714Skris 78955714Skris err: 790296465Sdelphij if (ret == 0) { 791296465Sdelphij if (bio1) { 792296465Sdelphij BIO_free(bio1); 793296465Sdelphij bio1 = NULL; 794296465Sdelphij } 795296465Sdelphij if (bio2) { 796296465Sdelphij BIO_free(bio2); 797296465Sdelphij bio2 = NULL; 798296465Sdelphij } 799296465Sdelphij } 80055714Skris 801296465Sdelphij *bio1_p = bio1; 802296465Sdelphij *bio2_p = bio2; 803296465Sdelphij return ret; 804296465Sdelphij} 80555714Skris 80655714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio) 807296465Sdelphij{ 808296465Sdelphij return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 809296465Sdelphij} 81055714Skris 81155714Skrissize_t BIO_ctrl_get_read_request(BIO *bio) 812296465Sdelphij{ 813296465Sdelphij return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 814296465Sdelphij} 81559191Skris 81659191Skrisint BIO_ctrl_reset_read_request(BIO *bio) 817296465Sdelphij{ 818296465Sdelphij return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); 819296465Sdelphij} 82059191Skris 821296465Sdelphij/* 822296465Sdelphij * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now 823296465Sdelphij * (conceivably some other BIOs could allow non-copying reads and writes 824296465Sdelphij * too.) 82559191Skris */ 82659191Skrisint BIO_nread0(BIO *bio, char **buf) 827296465Sdelphij{ 828296465Sdelphij long ret; 82959191Skris 830296465Sdelphij if (!bio->init) { 831296465Sdelphij BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); 832296465Sdelphij return -2; 833296465Sdelphij } 83459191Skris 835296465Sdelphij ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); 836296465Sdelphij if (ret > INT_MAX) 837296465Sdelphij return INT_MAX; 838296465Sdelphij else 839296465Sdelphij return (int)ret; 840296465Sdelphij} 84159191Skris 84259191Skrisint BIO_nread(BIO *bio, char **buf, int num) 843296465Sdelphij{ 844296465Sdelphij int ret; 84559191Skris 846296465Sdelphij if (!bio->init) { 847296465Sdelphij BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); 848296465Sdelphij return -2; 849296465Sdelphij } 85059191Skris 851296465Sdelphij ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf); 852296465Sdelphij if (ret > 0) 853296465Sdelphij bio->num_read += ret; 854296465Sdelphij return ret; 855296465Sdelphij} 85659191Skris 85759191Skrisint BIO_nwrite0(BIO *bio, char **buf) 858296465Sdelphij{ 859296465Sdelphij long ret; 86059191Skris 861296465Sdelphij if (!bio->init) { 862296465Sdelphij BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); 863296465Sdelphij return -2; 864296465Sdelphij } 86559191Skris 866296465Sdelphij ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); 867296465Sdelphij if (ret > INT_MAX) 868296465Sdelphij return INT_MAX; 869296465Sdelphij else 870296465Sdelphij return (int)ret; 871296465Sdelphij} 87259191Skris 87359191Skrisint BIO_nwrite(BIO *bio, char **buf, int num) 874296465Sdelphij{ 875296465Sdelphij int ret; 87659191Skris 877296465Sdelphij if (!bio->init) { 878296465Sdelphij BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); 879296465Sdelphij return -2; 880296465Sdelphij } 88159191Skris 882296465Sdelphij ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); 883296465Sdelphij if (ret > 0) 884296465Sdelphij bio->num_write += ret; 885296465Sdelphij return ret; 886296465Sdelphij} 887