174664626SKris Kennaway /* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ 250ef0093SJacques Vidrine /* ==================================================================== 350ef0093SJacques Vidrine * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 450ef0093SJacques Vidrine * 550ef0093SJacques Vidrine * Redistribution and use in source and binary forms, with or without 650ef0093SJacques Vidrine * modification, are permitted provided that the following conditions 750ef0093SJacques Vidrine * are met: 850ef0093SJacques Vidrine * 950ef0093SJacques Vidrine * 1. Redistributions of source code must retain the above copyright 1050ef0093SJacques Vidrine * notice, this list of conditions and the following disclaimer. 1150ef0093SJacques Vidrine * 1250ef0093SJacques Vidrine * 2. Redistributions in binary form must reproduce the above copyright 1350ef0093SJacques Vidrine * notice, this list of conditions and the following disclaimer in 1450ef0093SJacques Vidrine * the documentation and/or other materials provided with the 1550ef0093SJacques Vidrine * distribution. 1650ef0093SJacques Vidrine * 1750ef0093SJacques Vidrine * 3. All advertising materials mentioning features or use of this 1850ef0093SJacques Vidrine * software must display the following acknowledgment: 1950ef0093SJacques Vidrine * "This product includes software developed by the OpenSSL Project 2050ef0093SJacques Vidrine * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 2150ef0093SJacques Vidrine * 2250ef0093SJacques Vidrine * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2350ef0093SJacques Vidrine * endorse or promote products derived from this software without 2450ef0093SJacques Vidrine * prior written permission. For written permission, please contact 2550ef0093SJacques Vidrine * openssl-core@openssl.org. 2650ef0093SJacques Vidrine * 2750ef0093SJacques Vidrine * 5. Products derived from this software may not be called "OpenSSL" 2850ef0093SJacques Vidrine * nor may "OpenSSL" appear in their names without prior written 2950ef0093SJacques Vidrine * permission of the OpenSSL Project. 3050ef0093SJacques Vidrine * 3150ef0093SJacques Vidrine * 6. Redistributions of any form whatsoever must retain the following 3250ef0093SJacques Vidrine * acknowledgment: 3350ef0093SJacques Vidrine * "This product includes software developed by the OpenSSL Project 3450ef0093SJacques Vidrine * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 3550ef0093SJacques Vidrine * 3650ef0093SJacques Vidrine * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 3750ef0093SJacques Vidrine * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3850ef0093SJacques Vidrine * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 3950ef0093SJacques Vidrine * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4050ef0093SJacques Vidrine * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4150ef0093SJacques Vidrine * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4250ef0093SJacques Vidrine * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4350ef0093SJacques Vidrine * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4450ef0093SJacques Vidrine * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4550ef0093SJacques Vidrine * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4650ef0093SJacques Vidrine * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 4750ef0093SJacques Vidrine * OF THE POSSIBILITY OF SUCH DAMAGE. 4850ef0093SJacques Vidrine * ==================================================================== 4950ef0093SJacques Vidrine * 5050ef0093SJacques Vidrine * This product includes cryptographic software written by Eric Young 5150ef0093SJacques Vidrine * (eay@cryptsoft.com). This product includes software written by Tim 5250ef0093SJacques Vidrine * Hudson (tjh@cryptsoft.com). 5350ef0093SJacques Vidrine * 5450ef0093SJacques Vidrine */ 5574664626SKris Kennaway 5674664626SKris Kennaway /* Special method for a BIO where the other endpoint is also a BIO 5774664626SKris Kennaway * of this kind, handled by the same thread (i.e. the "peer" is actually 5874664626SKris Kennaway * ourselves, wearing a different hat). 5974664626SKris Kennaway * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces 6074664626SKris Kennaway * for which no specific BIO method is available. 6174664626SKris Kennaway * See ssl/ssltest.c for some hints on how this can be used. */ 6274664626SKris Kennaway 634f20a5a2SJacques Vidrine /* BIO_DEBUG implies BIO_PAIR_DEBUG */ 644f20a5a2SJacques Vidrine #ifdef BIO_DEBUG 6574664626SKris Kennaway # ifndef BIO_PAIR_DEBUG 664f20a5a2SJacques Vidrine # define BIO_PAIR_DEBUG 674f20a5a2SJacques Vidrine # endif 684f20a5a2SJacques Vidrine #endif 694f20a5a2SJacques Vidrine 704f20a5a2SJacques Vidrine /* disable assert() unless BIO_PAIR_DEBUG has been defined */ 714f20a5a2SJacques Vidrine #ifndef BIO_PAIR_DEBUG 724f20a5a2SJacques Vidrine # ifndef NDEBUG 7374664626SKris Kennaway # define NDEBUG 7474664626SKris Kennaway # endif 754f20a5a2SJacques Vidrine #endif 7674664626SKris Kennaway 7774664626SKris Kennaway #include <assert.h> 78f579bf8eSKris Kennaway #include <limits.h> 7974664626SKris Kennaway #include <stdlib.h> 8074664626SKris Kennaway #include <string.h> 8174664626SKris Kennaway 8274664626SKris Kennaway #include <openssl/bio.h> 8374664626SKris Kennaway #include <openssl/err.h> 8474664626SKris Kennaway #include <openssl/crypto.h> 8574664626SKris Kennaway 865c87c606SMark Murray #include "e_os.h" 87c1803d78SJacques Vidrine 885c87c606SMark Murray /* VxWorks defines SSIZE_MAX with an empty value causing compile errors */ 895c87c606SMark Murray #if defined(OPENSSL_SYS_VXWORKS) 90c1803d78SJacques Vidrine # undef SSIZE_MAX 915c87c606SMark Murray #endif 925c87c606SMark Murray #ifndef SSIZE_MAX 93f579bf8eSKris Kennaway # define SSIZE_MAX INT_MAX 94f579bf8eSKris Kennaway #endif 95f579bf8eSKris Kennaway 9674664626SKris Kennaway static int bio_new(BIO *bio); 9774664626SKris Kennaway static int bio_free(BIO *bio); 9874664626SKris Kennaway static int bio_read(BIO *bio, char *buf, int size); 99ddd58736SKris Kennaway static int bio_write(BIO *bio, const char *buf, int num); 10074664626SKris Kennaway static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); 101ddd58736SKris Kennaway static int bio_puts(BIO *bio, const char *str); 10274664626SKris Kennaway 10374664626SKris Kennaway static int bio_make_pair(BIO *bio1, BIO *bio2); 10474664626SKris Kennaway static void bio_destroy_pair(BIO *bio); 10574664626SKris Kennaway 10674664626SKris Kennaway static BIO_METHOD methods_biop = 10774664626SKris Kennaway { 10874664626SKris Kennaway BIO_TYPE_BIO, 10974664626SKris Kennaway "BIO pair", 11074664626SKris Kennaway bio_write, 11174664626SKris Kennaway bio_read, 11274664626SKris Kennaway bio_puts, 11374664626SKris Kennaway NULL /* no bio_gets */, 11474664626SKris Kennaway bio_ctrl, 11574664626SKris Kennaway bio_new, 116f579bf8eSKris Kennaway bio_free, 117f579bf8eSKris Kennaway NULL /* no bio_callback_ctrl */ 11874664626SKris Kennaway }; 11974664626SKris Kennaway 12074664626SKris Kennaway BIO_METHOD *BIO_s_bio(void) 12174664626SKris Kennaway { 12274664626SKris Kennaway return &methods_biop; 12374664626SKris Kennaway } 12474664626SKris Kennaway 12574664626SKris Kennaway struct bio_bio_st 12674664626SKris Kennaway { 12774664626SKris Kennaway BIO *peer; /* NULL if buf == NULL. 12874664626SKris Kennaway * If peer != NULL, then peer->ptr is also a bio_bio_st, 12974664626SKris Kennaway * and its "peer" member points back to us. 13074664626SKris Kennaway * peer != NULL iff init != 0 in the BIO. */ 13174664626SKris Kennaway 13274664626SKris Kennaway /* This is for what we write (i.e. reading uses peer's struct): */ 13374664626SKris Kennaway int closed; /* valid iff peer != NULL */ 13474664626SKris Kennaway size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ 13574664626SKris Kennaway size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ 13674664626SKris Kennaway size_t size; 13774664626SKris Kennaway char *buf; /* "size" elements (if != NULL) */ 13874664626SKris Kennaway 13974664626SKris Kennaway size_t request; /* valid iff peer != NULL; 0 if len != 0, 14074664626SKris Kennaway * otherwise set by peer to number of bytes 141f579bf8eSKris Kennaway * it (unsuccessfully) tried to read, 14274664626SKris Kennaway * never more than buffer space (size-len) warrants. */ 14374664626SKris Kennaway }; 14474664626SKris Kennaway 14574664626SKris Kennaway static int bio_new(BIO *bio) 14674664626SKris Kennaway { 14774664626SKris Kennaway struct bio_bio_st *b; 14874664626SKris Kennaway 149ddd58736SKris Kennaway b = OPENSSL_malloc(sizeof *b); 15074664626SKris Kennaway if (b == NULL) 15174664626SKris Kennaway return 0; 15274664626SKris Kennaway 15374664626SKris Kennaway b->peer = NULL; 15474664626SKris Kennaway b->size = 17*1024; /* enough for one TLS record (just a default) */ 15574664626SKris Kennaway b->buf = NULL; 15674664626SKris Kennaway 15774664626SKris Kennaway bio->ptr = b; 15874664626SKris Kennaway return 1; 15974664626SKris Kennaway } 16074664626SKris Kennaway 16174664626SKris Kennaway 16274664626SKris Kennaway static int bio_free(BIO *bio) 16374664626SKris Kennaway { 16474664626SKris Kennaway struct bio_bio_st *b; 16574664626SKris Kennaway 16674664626SKris Kennaway if (bio == NULL) 16774664626SKris Kennaway return 0; 16874664626SKris Kennaway b = bio->ptr; 16974664626SKris Kennaway 17074664626SKris Kennaway assert(b != NULL); 17174664626SKris Kennaway 17274664626SKris Kennaway if (b->peer) 17374664626SKris Kennaway bio_destroy_pair(bio); 17474664626SKris Kennaway 17574664626SKris Kennaway if (b->buf != NULL) 17674664626SKris Kennaway { 177ddd58736SKris Kennaway OPENSSL_free(b->buf); 17874664626SKris Kennaway } 17974664626SKris Kennaway 180ddd58736SKris Kennaway OPENSSL_free(b); 18174664626SKris Kennaway 18274664626SKris Kennaway return 1; 18374664626SKris Kennaway } 18474664626SKris Kennaway 18574664626SKris Kennaway 18674664626SKris Kennaway 18774664626SKris Kennaway static int bio_read(BIO *bio, char *buf, int size_) 18874664626SKris Kennaway { 18974664626SKris Kennaway size_t size = size_; 19074664626SKris Kennaway size_t rest; 19174664626SKris Kennaway struct bio_bio_st *b, *peer_b; 19274664626SKris Kennaway 19374664626SKris Kennaway BIO_clear_retry_flags(bio); 19474664626SKris Kennaway 19574664626SKris Kennaway if (!bio->init) 19674664626SKris Kennaway return 0; 19774664626SKris Kennaway 19874664626SKris Kennaway b = bio->ptr; 19974664626SKris Kennaway assert(b != NULL); 20074664626SKris Kennaway assert(b->peer != NULL); 20174664626SKris Kennaway peer_b = b->peer->ptr; 20274664626SKris Kennaway assert(peer_b != NULL); 20374664626SKris Kennaway assert(peer_b->buf != NULL); 20474664626SKris Kennaway 20574664626SKris Kennaway peer_b->request = 0; /* will be set in "retry_read" situation */ 20674664626SKris Kennaway 20774664626SKris Kennaway if (buf == NULL || size == 0) 20874664626SKris Kennaway return 0; 20974664626SKris Kennaway 21074664626SKris Kennaway if (peer_b->len == 0) 21174664626SKris Kennaway { 21274664626SKris Kennaway if (peer_b->closed) 21374664626SKris Kennaway return 0; /* writer has closed, and no data is left */ 21474664626SKris Kennaway else 21574664626SKris Kennaway { 21674664626SKris Kennaway BIO_set_retry_read(bio); /* buffer is empty */ 21774664626SKris Kennaway if (size <= peer_b->size) 21874664626SKris Kennaway peer_b->request = size; 21974664626SKris Kennaway else 22074664626SKris Kennaway /* don't ask for more than the peer can 22174664626SKris Kennaway * deliver in one write */ 22274664626SKris Kennaway peer_b->request = peer_b->size; 22374664626SKris Kennaway return -1; 22474664626SKris Kennaway } 22574664626SKris Kennaway } 22674664626SKris Kennaway 22774664626SKris Kennaway /* we can read */ 22874664626SKris Kennaway if (peer_b->len < size) 22974664626SKris Kennaway size = peer_b->len; 23074664626SKris Kennaway 23174664626SKris Kennaway /* now read "size" bytes */ 23274664626SKris Kennaway 23374664626SKris Kennaway rest = size; 23474664626SKris Kennaway 23574664626SKris Kennaway assert(rest > 0); 23674664626SKris Kennaway do /* one or two iterations */ 23774664626SKris Kennaway { 23874664626SKris Kennaway size_t chunk; 23974664626SKris Kennaway 24074664626SKris Kennaway assert(rest <= peer_b->len); 24174664626SKris Kennaway if (peer_b->offset + rest <= peer_b->size) 24274664626SKris Kennaway chunk = rest; 24374664626SKris Kennaway else 24474664626SKris Kennaway /* wrap around ring buffer */ 24574664626SKris Kennaway chunk = peer_b->size - peer_b->offset; 24674664626SKris Kennaway assert(peer_b->offset + chunk <= peer_b->size); 24774664626SKris Kennaway 24874664626SKris Kennaway memcpy(buf, peer_b->buf + peer_b->offset, chunk); 24974664626SKris Kennaway 25074664626SKris Kennaway peer_b->len -= chunk; 25174664626SKris Kennaway if (peer_b->len) 25274664626SKris Kennaway { 25374664626SKris Kennaway peer_b->offset += chunk; 25474664626SKris Kennaway assert(peer_b->offset <= peer_b->size); 25574664626SKris Kennaway if (peer_b->offset == peer_b->size) 25674664626SKris Kennaway peer_b->offset = 0; 25774664626SKris Kennaway buf += chunk; 25874664626SKris Kennaway } 25974664626SKris Kennaway else 26074664626SKris Kennaway { 26174664626SKris Kennaway /* buffer now empty, no need to advance "buf" */ 26274664626SKris Kennaway assert(chunk == rest); 26374664626SKris Kennaway peer_b->offset = 0; 26474664626SKris Kennaway } 26574664626SKris Kennaway rest -= chunk; 26674664626SKris Kennaway } 26774664626SKris Kennaway while (rest); 26874664626SKris Kennaway 26974664626SKris Kennaway return size; 27074664626SKris Kennaway } 27174664626SKris Kennaway 272f579bf8eSKris Kennaway /* non-copying interface: provide pointer to available data in buffer 273f579bf8eSKris Kennaway * bio_nread0: return number of available bytes 274f579bf8eSKris Kennaway * bio_nread: also advance index 275f579bf8eSKris Kennaway * (example usage: bio_nread0(), read from buffer, bio_nread() 276f579bf8eSKris Kennaway * or just bio_nread(), read from buffer) 277f579bf8eSKris Kennaway */ 278f579bf8eSKris Kennaway /* WARNING: The non-copying interface is largely untested as of yet 279f579bf8eSKris Kennaway * and may contain bugs. */ 280f579bf8eSKris Kennaway static ssize_t bio_nread0(BIO *bio, char **buf) 281f579bf8eSKris Kennaway { 282f579bf8eSKris Kennaway struct bio_bio_st *b, *peer_b; 283f579bf8eSKris Kennaway ssize_t num; 284f579bf8eSKris Kennaway 285f579bf8eSKris Kennaway BIO_clear_retry_flags(bio); 286f579bf8eSKris Kennaway 287f579bf8eSKris Kennaway if (!bio->init) 288f579bf8eSKris Kennaway return 0; 289f579bf8eSKris Kennaway 290f579bf8eSKris Kennaway b = bio->ptr; 291f579bf8eSKris Kennaway assert(b != NULL); 292f579bf8eSKris Kennaway assert(b->peer != NULL); 293f579bf8eSKris Kennaway peer_b = b->peer->ptr; 294f579bf8eSKris Kennaway assert(peer_b != NULL); 295f579bf8eSKris Kennaway assert(peer_b->buf != NULL); 296f579bf8eSKris Kennaway 297f579bf8eSKris Kennaway peer_b->request = 0; 298f579bf8eSKris Kennaway 299f579bf8eSKris Kennaway if (peer_b->len == 0) 300f579bf8eSKris Kennaway { 301f579bf8eSKris Kennaway char dummy; 302f579bf8eSKris Kennaway 303f579bf8eSKris Kennaway /* avoid code duplication -- nothing available for reading */ 304f579bf8eSKris Kennaway return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ 305f579bf8eSKris Kennaway } 306f579bf8eSKris Kennaway 307f579bf8eSKris Kennaway num = peer_b->len; 308f579bf8eSKris Kennaway if (peer_b->size < peer_b->offset + num) 309f579bf8eSKris Kennaway /* no ring buffer wrap-around for non-copying interface */ 310f579bf8eSKris Kennaway num = peer_b->size - peer_b->offset; 311f579bf8eSKris Kennaway assert(num > 0); 312f579bf8eSKris Kennaway 313f579bf8eSKris Kennaway if (buf != NULL) 314f579bf8eSKris Kennaway *buf = peer_b->buf + peer_b->offset; 315f579bf8eSKris Kennaway return num; 316f579bf8eSKris Kennaway } 317f579bf8eSKris Kennaway 318f579bf8eSKris Kennaway static ssize_t bio_nread(BIO *bio, char **buf, size_t num_) 319f579bf8eSKris Kennaway { 320f579bf8eSKris Kennaway struct bio_bio_st *b, *peer_b; 321f579bf8eSKris Kennaway ssize_t num, available; 322f579bf8eSKris Kennaway 323f579bf8eSKris Kennaway if (num_ > SSIZE_MAX) 324f579bf8eSKris Kennaway num = SSIZE_MAX; 325f579bf8eSKris Kennaway else 326f579bf8eSKris Kennaway num = (ssize_t)num_; 327f579bf8eSKris Kennaway 328f579bf8eSKris Kennaway available = bio_nread0(bio, buf); 329f579bf8eSKris Kennaway if (num > available) 330f579bf8eSKris Kennaway num = available; 331f579bf8eSKris Kennaway if (num <= 0) 332f579bf8eSKris Kennaway return num; 333f579bf8eSKris Kennaway 334f579bf8eSKris Kennaway b = bio->ptr; 335f579bf8eSKris Kennaway peer_b = b->peer->ptr; 336f579bf8eSKris Kennaway 337f579bf8eSKris Kennaway peer_b->len -= num; 338f579bf8eSKris Kennaway if (peer_b->len) 339f579bf8eSKris Kennaway { 340f579bf8eSKris Kennaway peer_b->offset += num; 341f579bf8eSKris Kennaway assert(peer_b->offset <= peer_b->size); 342f579bf8eSKris Kennaway if (peer_b->offset == peer_b->size) 343f579bf8eSKris Kennaway peer_b->offset = 0; 344f579bf8eSKris Kennaway } 345f579bf8eSKris Kennaway else 346f579bf8eSKris Kennaway peer_b->offset = 0; 347f579bf8eSKris Kennaway 348f579bf8eSKris Kennaway return num; 349f579bf8eSKris Kennaway } 350f579bf8eSKris Kennaway 351f579bf8eSKris Kennaway 352ddd58736SKris Kennaway static int bio_write(BIO *bio, const char *buf, int num_) 35374664626SKris Kennaway { 35474664626SKris Kennaway size_t num = num_; 35574664626SKris Kennaway size_t rest; 35674664626SKris Kennaway struct bio_bio_st *b; 35774664626SKris Kennaway 35874664626SKris Kennaway BIO_clear_retry_flags(bio); 35974664626SKris Kennaway 36074664626SKris Kennaway if (!bio->init || buf == NULL || num == 0) 36174664626SKris Kennaway return 0; 36274664626SKris Kennaway 36374664626SKris Kennaway b = bio->ptr; 36474664626SKris Kennaway assert(b != NULL); 36574664626SKris Kennaway assert(b->peer != NULL); 36674664626SKris Kennaway assert(b->buf != NULL); 36774664626SKris Kennaway 36874664626SKris Kennaway b->request = 0; 36974664626SKris Kennaway if (b->closed) 37074664626SKris Kennaway { 37174664626SKris Kennaway /* we already closed */ 37274664626SKris Kennaway BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); 37374664626SKris Kennaway return -1; 37474664626SKris Kennaway } 37574664626SKris Kennaway 37674664626SKris Kennaway assert(b->len <= b->size); 37774664626SKris Kennaway 37874664626SKris Kennaway if (b->len == b->size) 37974664626SKris Kennaway { 38074664626SKris Kennaway BIO_set_retry_write(bio); /* buffer is full */ 38174664626SKris Kennaway return -1; 38274664626SKris Kennaway } 38374664626SKris Kennaway 38474664626SKris Kennaway /* we can write */ 38574664626SKris Kennaway if (num > b->size - b->len) 38674664626SKris Kennaway num = b->size - b->len; 38774664626SKris Kennaway 38874664626SKris Kennaway /* now write "num" bytes */ 38974664626SKris Kennaway 39074664626SKris Kennaway rest = num; 39174664626SKris Kennaway 39274664626SKris Kennaway assert(rest > 0); 39374664626SKris Kennaway do /* one or two iterations */ 39474664626SKris Kennaway { 39574664626SKris Kennaway size_t write_offset; 39674664626SKris Kennaway size_t chunk; 39774664626SKris Kennaway 39874664626SKris Kennaway assert(b->len + rest <= b->size); 39974664626SKris Kennaway 40074664626SKris Kennaway write_offset = b->offset + b->len; 40174664626SKris Kennaway if (write_offset >= b->size) 40274664626SKris Kennaway write_offset -= b->size; 40374664626SKris Kennaway /* b->buf[write_offset] is the first byte we can write to. */ 40474664626SKris Kennaway 40574664626SKris Kennaway if (write_offset + rest <= b->size) 40674664626SKris Kennaway chunk = rest; 40774664626SKris Kennaway else 40874664626SKris Kennaway /* wrap around ring buffer */ 40974664626SKris Kennaway chunk = b->size - write_offset; 41074664626SKris Kennaway 41174664626SKris Kennaway memcpy(b->buf + write_offset, buf, chunk); 41274664626SKris Kennaway 41374664626SKris Kennaway b->len += chunk; 41474664626SKris Kennaway 41574664626SKris Kennaway assert(b->len <= b->size); 41674664626SKris Kennaway 41774664626SKris Kennaway rest -= chunk; 41874664626SKris Kennaway buf += chunk; 41974664626SKris Kennaway } 42074664626SKris Kennaway while (rest); 42174664626SKris Kennaway 42274664626SKris Kennaway return num; 42374664626SKris Kennaway } 42474664626SKris Kennaway 425f579bf8eSKris Kennaway /* non-copying interface: provide pointer to region to write to 426f579bf8eSKris Kennaway * bio_nwrite0: check how much space is available 427f579bf8eSKris Kennaway * bio_nwrite: also increase length 428f579bf8eSKris Kennaway * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() 429f579bf8eSKris Kennaway * or just bio_nwrite(), write to buffer) 430f579bf8eSKris Kennaway */ 431f579bf8eSKris Kennaway static ssize_t bio_nwrite0(BIO *bio, char **buf) 432f579bf8eSKris Kennaway { 433f579bf8eSKris Kennaway struct bio_bio_st *b; 434f579bf8eSKris Kennaway size_t num; 435f579bf8eSKris Kennaway size_t write_offset; 436f579bf8eSKris Kennaway 437f579bf8eSKris Kennaway BIO_clear_retry_flags(bio); 438f579bf8eSKris Kennaway 439f579bf8eSKris Kennaway if (!bio->init) 440f579bf8eSKris Kennaway return 0; 441f579bf8eSKris Kennaway 442f579bf8eSKris Kennaway b = bio->ptr; 443f579bf8eSKris Kennaway assert(b != NULL); 444f579bf8eSKris Kennaway assert(b->peer != NULL); 445f579bf8eSKris Kennaway assert(b->buf != NULL); 446f579bf8eSKris Kennaway 447f579bf8eSKris Kennaway b->request = 0; 448f579bf8eSKris Kennaway if (b->closed) 449f579bf8eSKris Kennaway { 450f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); 451f579bf8eSKris Kennaway return -1; 452f579bf8eSKris Kennaway } 453f579bf8eSKris Kennaway 454f579bf8eSKris Kennaway assert(b->len <= b->size); 455f579bf8eSKris Kennaway 456f579bf8eSKris Kennaway if (b->len == b->size) 457f579bf8eSKris Kennaway { 458f579bf8eSKris Kennaway BIO_set_retry_write(bio); 459f579bf8eSKris Kennaway return -1; 460f579bf8eSKris Kennaway } 461f579bf8eSKris Kennaway 462f579bf8eSKris Kennaway num = b->size - b->len; 463f579bf8eSKris Kennaway write_offset = b->offset + b->len; 464f579bf8eSKris Kennaway if (write_offset >= b->size) 465f579bf8eSKris Kennaway write_offset -= b->size; 466f579bf8eSKris Kennaway if (write_offset + num > b->size) 467f579bf8eSKris Kennaway /* no ring buffer wrap-around for non-copying interface 468f579bf8eSKris Kennaway * (to fulfil the promise by BIO_ctrl_get_write_guarantee, 469f579bf8eSKris Kennaway * BIO_nwrite may have to be called twice) */ 470f579bf8eSKris Kennaway num = b->size - write_offset; 471f579bf8eSKris Kennaway 472f579bf8eSKris Kennaway if (buf != NULL) 473f579bf8eSKris Kennaway *buf = b->buf + write_offset; 474f579bf8eSKris Kennaway assert(write_offset + num <= b->size); 475f579bf8eSKris Kennaway 476f579bf8eSKris Kennaway return num; 477f579bf8eSKris Kennaway } 478f579bf8eSKris Kennaway 479f579bf8eSKris Kennaway static ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) 480f579bf8eSKris Kennaway { 481f579bf8eSKris Kennaway struct bio_bio_st *b; 482f579bf8eSKris Kennaway ssize_t num, space; 483f579bf8eSKris Kennaway 484f579bf8eSKris Kennaway if (num_ > SSIZE_MAX) 485f579bf8eSKris Kennaway num = SSIZE_MAX; 486f579bf8eSKris Kennaway else 487f579bf8eSKris Kennaway num = (ssize_t)num_; 488f579bf8eSKris Kennaway 489f579bf8eSKris Kennaway space = bio_nwrite0(bio, buf); 490f579bf8eSKris Kennaway if (num > space) 491f579bf8eSKris Kennaway num = space; 492f579bf8eSKris Kennaway if (num <= 0) 493f579bf8eSKris Kennaway return num; 494f579bf8eSKris Kennaway b = bio->ptr; 495f579bf8eSKris Kennaway assert(b != NULL); 496f579bf8eSKris Kennaway b->len += num; 497f579bf8eSKris Kennaway assert(b->len <= b->size); 498f579bf8eSKris Kennaway 499f579bf8eSKris Kennaway return num; 500f579bf8eSKris Kennaway } 501f579bf8eSKris Kennaway 50274664626SKris Kennaway 50374664626SKris Kennaway static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 50474664626SKris Kennaway { 50574664626SKris Kennaway long ret; 50674664626SKris Kennaway struct bio_bio_st *b = bio->ptr; 50774664626SKris Kennaway 50874664626SKris Kennaway assert(b != NULL); 50974664626SKris Kennaway 51074664626SKris Kennaway switch (cmd) 51174664626SKris Kennaway { 51274664626SKris Kennaway /* specific CTRL codes */ 51374664626SKris Kennaway 51474664626SKris Kennaway case BIO_C_SET_WRITE_BUF_SIZE: 51574664626SKris Kennaway if (b->peer) 51674664626SKris Kennaway { 51774664626SKris Kennaway BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); 51874664626SKris Kennaway ret = 0; 51974664626SKris Kennaway } 52074664626SKris Kennaway else if (num == 0) 52174664626SKris Kennaway { 52274664626SKris Kennaway BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); 52374664626SKris Kennaway ret = 0; 52474664626SKris Kennaway } 52574664626SKris Kennaway else 52674664626SKris Kennaway { 52774664626SKris Kennaway size_t new_size = num; 52874664626SKris Kennaway 52974664626SKris Kennaway if (b->size != new_size) 53074664626SKris Kennaway { 53174664626SKris Kennaway if (b->buf) 53274664626SKris Kennaway { 533ddd58736SKris Kennaway OPENSSL_free(b->buf); 53474664626SKris Kennaway b->buf = NULL; 53574664626SKris Kennaway } 53674664626SKris Kennaway b->size = new_size; 53774664626SKris Kennaway } 53874664626SKris Kennaway ret = 1; 53974664626SKris Kennaway } 54074664626SKris Kennaway break; 54174664626SKris Kennaway 54274664626SKris Kennaway case BIO_C_GET_WRITE_BUF_SIZE: 543a21b1b38SKris Kennaway ret = (long) b->size; 544a21b1b38SKris Kennaway break; 54574664626SKris Kennaway 54674664626SKris Kennaway case BIO_C_MAKE_BIO_PAIR: 54774664626SKris Kennaway { 54874664626SKris Kennaway BIO *other_bio = ptr; 54974664626SKris Kennaway 55074664626SKris Kennaway if (bio_make_pair(bio, other_bio)) 55174664626SKris Kennaway ret = 1; 55274664626SKris Kennaway else 55374664626SKris Kennaway ret = 0; 55474664626SKris Kennaway } 55574664626SKris Kennaway break; 55674664626SKris Kennaway 55774664626SKris Kennaway case BIO_C_DESTROY_BIO_PAIR: 55850ef0093SJacques Vidrine /* Affects both BIOs in the pair -- call just once! 55974664626SKris Kennaway * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ 56074664626SKris Kennaway bio_destroy_pair(bio); 56174664626SKris Kennaway ret = 1; 56274664626SKris Kennaway break; 56374664626SKris Kennaway 56474664626SKris Kennaway case BIO_C_GET_WRITE_GUARANTEE: 56574664626SKris Kennaway /* How many bytes can the caller feed to the next write 566f579bf8eSKris Kennaway * without having to keep any? */ 56774664626SKris Kennaway if (b->peer == NULL || b->closed) 56874664626SKris Kennaway ret = 0; 56974664626SKris Kennaway else 57074664626SKris Kennaway ret = (long) b->size - b->len; 57174664626SKris Kennaway break; 57274664626SKris Kennaway 57374664626SKris Kennaway case BIO_C_GET_READ_REQUEST: 574f579bf8eSKris Kennaway /* If the peer unsuccessfully tried to read, how many bytes 57574664626SKris Kennaway * were requested? (As with BIO_CTRL_PENDING, that number 57674664626SKris Kennaway * can usually be treated as boolean.) */ 57774664626SKris Kennaway ret = (long) b->request; 57874664626SKris Kennaway break; 57974664626SKris Kennaway 580f579bf8eSKris Kennaway case BIO_C_RESET_READ_REQUEST: 581f579bf8eSKris Kennaway /* Reset request. (Can be useful after read attempts 582f579bf8eSKris Kennaway * at the other side that are meant to be non-blocking, 583f579bf8eSKris Kennaway * e.g. when probing SSL_read to see if any data is 584f579bf8eSKris Kennaway * available.) */ 585f579bf8eSKris Kennaway b->request = 0; 586f579bf8eSKris Kennaway ret = 1; 587f579bf8eSKris Kennaway break; 588f579bf8eSKris Kennaway 58974664626SKris Kennaway case BIO_C_SHUTDOWN_WR: 59074664626SKris Kennaway /* similar to shutdown(..., SHUT_WR) */ 59174664626SKris Kennaway b->closed = 1; 59274664626SKris Kennaway ret = 1; 59374664626SKris Kennaway break; 59474664626SKris Kennaway 595f579bf8eSKris Kennaway case BIO_C_NREAD0: 596f579bf8eSKris Kennaway /* prepare for non-copying read */ 597f579bf8eSKris Kennaway ret = (long) bio_nread0(bio, ptr); 598f579bf8eSKris Kennaway break; 599f579bf8eSKris Kennaway 600f579bf8eSKris Kennaway case BIO_C_NREAD: 601f579bf8eSKris Kennaway /* non-copying read */ 602f579bf8eSKris Kennaway ret = (long) bio_nread(bio, ptr, (size_t) num); 603f579bf8eSKris Kennaway break; 604f579bf8eSKris Kennaway 605f579bf8eSKris Kennaway case BIO_C_NWRITE0: 606f579bf8eSKris Kennaway /* prepare for non-copying write */ 607f579bf8eSKris Kennaway ret = (long) bio_nwrite0(bio, ptr); 608f579bf8eSKris Kennaway break; 609f579bf8eSKris Kennaway 610f579bf8eSKris Kennaway case BIO_C_NWRITE: 611f579bf8eSKris Kennaway /* non-copying write */ 612f579bf8eSKris Kennaway ret = (long) bio_nwrite(bio, ptr, (size_t) num); 613f579bf8eSKris Kennaway break; 614f579bf8eSKris Kennaway 61574664626SKris Kennaway 61674664626SKris Kennaway /* standard CTRL codes follow */ 61774664626SKris Kennaway 61874664626SKris Kennaway case BIO_CTRL_RESET: 61974664626SKris Kennaway if (b->buf != NULL) 62074664626SKris Kennaway { 62174664626SKris Kennaway b->len = 0; 62274664626SKris Kennaway b->offset = 0; 62374664626SKris Kennaway } 62474664626SKris Kennaway ret = 0; 62574664626SKris Kennaway break; 62674664626SKris Kennaway 62774664626SKris Kennaway case BIO_CTRL_GET_CLOSE: 62874664626SKris Kennaway ret = bio->shutdown; 62974664626SKris Kennaway break; 63074664626SKris Kennaway 63174664626SKris Kennaway case BIO_CTRL_SET_CLOSE: 63274664626SKris Kennaway bio->shutdown = (int) num; 63374664626SKris Kennaway ret = 1; 63474664626SKris Kennaway break; 63574664626SKris Kennaway 63674664626SKris Kennaway case BIO_CTRL_PENDING: 63774664626SKris Kennaway if (b->peer != NULL) 63874664626SKris Kennaway { 63974664626SKris Kennaway struct bio_bio_st *peer_b = b->peer->ptr; 64074664626SKris Kennaway 64174664626SKris Kennaway ret = (long) peer_b->len; 64274664626SKris Kennaway } 64374664626SKris Kennaway else 64474664626SKris Kennaway ret = 0; 64574664626SKris Kennaway break; 64674664626SKris Kennaway 64774664626SKris Kennaway case BIO_CTRL_WPENDING: 64874664626SKris Kennaway if (b->buf != NULL) 64974664626SKris Kennaway ret = (long) b->len; 65074664626SKris Kennaway else 65174664626SKris Kennaway ret = 0; 65274664626SKris Kennaway break; 65374664626SKris Kennaway 65474664626SKris Kennaway case BIO_CTRL_DUP: 65574664626SKris Kennaway /* See BIO_dup_chain for circumstances we have to expect. */ 65674664626SKris Kennaway { 65774664626SKris Kennaway BIO *other_bio = ptr; 65874664626SKris Kennaway struct bio_bio_st *other_b; 65974664626SKris Kennaway 66074664626SKris Kennaway assert(other_bio != NULL); 66174664626SKris Kennaway other_b = other_bio->ptr; 66274664626SKris Kennaway assert(other_b != NULL); 66374664626SKris Kennaway 66474664626SKris Kennaway assert(other_b->buf == NULL); /* other_bio is always fresh */ 66574664626SKris Kennaway 66674664626SKris Kennaway other_b->size = b->size; 66774664626SKris Kennaway } 66874664626SKris Kennaway 66974664626SKris Kennaway ret = 1; 67074664626SKris Kennaway break; 67174664626SKris Kennaway 67274664626SKris Kennaway case BIO_CTRL_FLUSH: 67374664626SKris Kennaway ret = 1; 67474664626SKris Kennaway break; 67574664626SKris Kennaway 67674664626SKris Kennaway case BIO_CTRL_EOF: 67774664626SKris Kennaway { 67874664626SKris Kennaway BIO *other_bio = ptr; 67974664626SKris Kennaway 68074664626SKris Kennaway if (other_bio) 68174664626SKris Kennaway { 68274664626SKris Kennaway struct bio_bio_st *other_b = other_bio->ptr; 68374664626SKris Kennaway 68474664626SKris Kennaway assert(other_b != NULL); 68574664626SKris Kennaway ret = other_b->len == 0 && other_b->closed; 68674664626SKris Kennaway } 68774664626SKris Kennaway else 68874664626SKris Kennaway ret = 1; 68974664626SKris Kennaway } 69074664626SKris Kennaway break; 69174664626SKris Kennaway 69274664626SKris Kennaway default: 69374664626SKris Kennaway ret = 0; 69474664626SKris Kennaway } 69574664626SKris Kennaway return ret; 69674664626SKris Kennaway } 69774664626SKris Kennaway 698ddd58736SKris Kennaway static int bio_puts(BIO *bio, const char *str) 69974664626SKris Kennaway { 70074664626SKris Kennaway return bio_write(bio, str, strlen(str)); 70174664626SKris Kennaway } 70274664626SKris Kennaway 70374664626SKris Kennaway 70474664626SKris Kennaway static int bio_make_pair(BIO *bio1, BIO *bio2) 70574664626SKris Kennaway { 70674664626SKris Kennaway struct bio_bio_st *b1, *b2; 70774664626SKris Kennaway 70874664626SKris Kennaway assert(bio1 != NULL); 70974664626SKris Kennaway assert(bio2 != NULL); 71074664626SKris Kennaway 71174664626SKris Kennaway b1 = bio1->ptr; 71274664626SKris Kennaway b2 = bio2->ptr; 71374664626SKris Kennaway 71474664626SKris Kennaway if (b1->peer != NULL || b2->peer != NULL) 71574664626SKris Kennaway { 71674664626SKris Kennaway BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); 71774664626SKris Kennaway return 0; 71874664626SKris Kennaway } 71974664626SKris Kennaway 72074664626SKris Kennaway if (b1->buf == NULL) 72174664626SKris Kennaway { 722ddd58736SKris Kennaway b1->buf = OPENSSL_malloc(b1->size); 72374664626SKris Kennaway if (b1->buf == NULL) 72474664626SKris Kennaway { 72574664626SKris Kennaway BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 72674664626SKris Kennaway return 0; 72774664626SKris Kennaway } 72874664626SKris Kennaway b1->len = 0; 72974664626SKris Kennaway b1->offset = 0; 73074664626SKris Kennaway } 73174664626SKris Kennaway 73274664626SKris Kennaway if (b2->buf == NULL) 73374664626SKris Kennaway { 734ddd58736SKris Kennaway b2->buf = OPENSSL_malloc(b2->size); 73574664626SKris Kennaway if (b2->buf == NULL) 73674664626SKris Kennaway { 73774664626SKris Kennaway BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 73874664626SKris Kennaway return 0; 73974664626SKris Kennaway } 74074664626SKris Kennaway b2->len = 0; 74174664626SKris Kennaway b2->offset = 0; 74274664626SKris Kennaway } 74374664626SKris Kennaway 74474664626SKris Kennaway b1->peer = bio2; 74574664626SKris Kennaway b1->closed = 0; 74674664626SKris Kennaway b1->request = 0; 74774664626SKris Kennaway b2->peer = bio1; 74874664626SKris Kennaway b2->closed = 0; 74974664626SKris Kennaway b2->request = 0; 75074664626SKris Kennaway 75174664626SKris Kennaway bio1->init = 1; 75274664626SKris Kennaway bio2->init = 1; 75374664626SKris Kennaway 75474664626SKris Kennaway return 1; 75574664626SKris Kennaway } 75674664626SKris Kennaway 75774664626SKris Kennaway static void bio_destroy_pair(BIO *bio) 75874664626SKris Kennaway { 75974664626SKris Kennaway struct bio_bio_st *b = bio->ptr; 76074664626SKris Kennaway 76174664626SKris Kennaway if (b != NULL) 76274664626SKris Kennaway { 76374664626SKris Kennaway BIO *peer_bio = b->peer; 76474664626SKris Kennaway 76574664626SKris Kennaway if (peer_bio != NULL) 76674664626SKris Kennaway { 76774664626SKris Kennaway struct bio_bio_st *peer_b = peer_bio->ptr; 76874664626SKris Kennaway 76974664626SKris Kennaway assert(peer_b != NULL); 77074664626SKris Kennaway assert(peer_b->peer == bio); 77174664626SKris Kennaway 77274664626SKris Kennaway peer_b->peer = NULL; 77374664626SKris Kennaway peer_bio->init = 0; 77474664626SKris Kennaway assert(peer_b->buf != NULL); 77574664626SKris Kennaway peer_b->len = 0; 77674664626SKris Kennaway peer_b->offset = 0; 77774664626SKris Kennaway 77874664626SKris Kennaway b->peer = NULL; 77974664626SKris Kennaway bio->init = 0; 78074664626SKris Kennaway assert(b->buf != NULL); 78174664626SKris Kennaway b->len = 0; 78274664626SKris Kennaway b->offset = 0; 78374664626SKris Kennaway } 78474664626SKris Kennaway } 78574664626SKris Kennaway } 78674664626SKris Kennaway 78774664626SKris Kennaway 78874664626SKris Kennaway /* Exported convenience functions */ 78974664626SKris Kennaway int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, 79074664626SKris Kennaway BIO **bio2_p, size_t writebuf2) 79174664626SKris Kennaway { 79274664626SKris Kennaway BIO *bio1 = NULL, *bio2 = NULL; 79374664626SKris Kennaway long r; 79474664626SKris Kennaway int ret = 0; 79574664626SKris Kennaway 79674664626SKris Kennaway bio1 = BIO_new(BIO_s_bio()); 79774664626SKris Kennaway if (bio1 == NULL) 79874664626SKris Kennaway goto err; 79974664626SKris Kennaway bio2 = BIO_new(BIO_s_bio()); 80074664626SKris Kennaway if (bio2 == NULL) 80174664626SKris Kennaway goto err; 80274664626SKris Kennaway 80374664626SKris Kennaway if (writebuf1) 80474664626SKris Kennaway { 80574664626SKris Kennaway r = BIO_set_write_buf_size(bio1, writebuf1); 80674664626SKris Kennaway if (!r) 80774664626SKris Kennaway goto err; 80874664626SKris Kennaway } 80974664626SKris Kennaway if (writebuf2) 81074664626SKris Kennaway { 81174664626SKris Kennaway r = BIO_set_write_buf_size(bio2, writebuf2); 81274664626SKris Kennaway if (!r) 81374664626SKris Kennaway goto err; 81474664626SKris Kennaway } 81574664626SKris Kennaway 81674664626SKris Kennaway r = BIO_make_bio_pair(bio1, bio2); 81774664626SKris Kennaway if (!r) 81874664626SKris Kennaway goto err; 81974664626SKris Kennaway ret = 1; 82074664626SKris Kennaway 82174664626SKris Kennaway err: 82274664626SKris Kennaway if (ret == 0) 82374664626SKris Kennaway { 82474664626SKris Kennaway if (bio1) 82574664626SKris Kennaway { 82674664626SKris Kennaway BIO_free(bio1); 82774664626SKris Kennaway bio1 = NULL; 82874664626SKris Kennaway } 82974664626SKris Kennaway if (bio2) 83074664626SKris Kennaway { 83174664626SKris Kennaway BIO_free(bio2); 83274664626SKris Kennaway bio2 = NULL; 83374664626SKris Kennaway } 83474664626SKris Kennaway } 83574664626SKris Kennaway 83674664626SKris Kennaway *bio1_p = bio1; 83774664626SKris Kennaway *bio2_p = bio2; 83874664626SKris Kennaway return ret; 83974664626SKris Kennaway } 84074664626SKris Kennaway 84174664626SKris Kennaway size_t BIO_ctrl_get_write_guarantee(BIO *bio) 84274664626SKris Kennaway { 84374664626SKris Kennaway return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 84474664626SKris Kennaway } 84574664626SKris Kennaway 84674664626SKris Kennaway size_t BIO_ctrl_get_read_request(BIO *bio) 84774664626SKris Kennaway { 84874664626SKris Kennaway return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 84974664626SKris Kennaway } 850f579bf8eSKris Kennaway 851f579bf8eSKris Kennaway int BIO_ctrl_reset_read_request(BIO *bio) 852f579bf8eSKris Kennaway { 853f579bf8eSKris Kennaway return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); 854f579bf8eSKris Kennaway } 855f579bf8eSKris Kennaway 856f579bf8eSKris Kennaway 857f579bf8eSKris Kennaway /* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now 858f579bf8eSKris Kennaway * (conceivably some other BIOs could allow non-copying reads and writes too.) 859f579bf8eSKris Kennaway */ 860f579bf8eSKris Kennaway int BIO_nread0(BIO *bio, char **buf) 861f579bf8eSKris Kennaway { 862f579bf8eSKris Kennaway long ret; 863f579bf8eSKris Kennaway 864f579bf8eSKris Kennaway if (!bio->init) 865f579bf8eSKris Kennaway { 866f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); 867f579bf8eSKris Kennaway return -2; 868f579bf8eSKris Kennaway } 869f579bf8eSKris Kennaway 870f579bf8eSKris Kennaway ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); 871f579bf8eSKris Kennaway if (ret > INT_MAX) 872f579bf8eSKris Kennaway return INT_MAX; 873f579bf8eSKris Kennaway else 874f579bf8eSKris Kennaway return (int) ret; 875f579bf8eSKris Kennaway } 876f579bf8eSKris Kennaway 877f579bf8eSKris Kennaway int BIO_nread(BIO *bio, char **buf, int num) 878f579bf8eSKris Kennaway { 879f579bf8eSKris Kennaway int ret; 880f579bf8eSKris Kennaway 881f579bf8eSKris Kennaway if (!bio->init) 882f579bf8eSKris Kennaway { 883f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); 884f579bf8eSKris Kennaway return -2; 885f579bf8eSKris Kennaway } 886f579bf8eSKris Kennaway 887f579bf8eSKris Kennaway ret = (int) BIO_ctrl(bio, BIO_C_NREAD, num, buf); 888f579bf8eSKris Kennaway if (ret > 0) 889f579bf8eSKris Kennaway bio->num_read += ret; 890f579bf8eSKris Kennaway return ret; 891f579bf8eSKris Kennaway } 892f579bf8eSKris Kennaway 893f579bf8eSKris Kennaway int BIO_nwrite0(BIO *bio, char **buf) 894f579bf8eSKris Kennaway { 895f579bf8eSKris Kennaway long ret; 896f579bf8eSKris Kennaway 897f579bf8eSKris Kennaway if (!bio->init) 898f579bf8eSKris Kennaway { 899f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); 900f579bf8eSKris Kennaway return -2; 901f579bf8eSKris Kennaway } 902f579bf8eSKris Kennaway 903f579bf8eSKris Kennaway ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); 904f579bf8eSKris Kennaway if (ret > INT_MAX) 905f579bf8eSKris Kennaway return INT_MAX; 906f579bf8eSKris Kennaway else 907f579bf8eSKris Kennaway return (int) ret; 908f579bf8eSKris Kennaway } 909f579bf8eSKris Kennaway 910f579bf8eSKris Kennaway int BIO_nwrite(BIO *bio, char **buf, int num) 911f579bf8eSKris Kennaway { 912f579bf8eSKris Kennaway int ret; 913f579bf8eSKris Kennaway 914f579bf8eSKris Kennaway if (!bio->init) 915f579bf8eSKris Kennaway { 916f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); 917f579bf8eSKris Kennaway return -2; 918f579bf8eSKris Kennaway } 919f579bf8eSKris Kennaway 920f579bf8eSKris Kennaway ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); 921f579bf8eSKris Kennaway if (ret > 0) 922db522d3aSSimon L. B. Nielsen bio->num_write += ret; 923f579bf8eSKris Kennaway return ret; 924f579bf8eSKris Kennaway } 925