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 56*6f9291ceSJung-uk Kim /* 57*6f9291ceSJung-uk Kim * Special method for a BIO where the other endpoint is also a BIO of this 58*6f9291ceSJung-uk Kim * kind, handled by the same thread (i.e. the "peer" is actually ourselves, 59*6f9291ceSJung-uk Kim * wearing a different hat). Such "BIO pairs" are mainly for using the SSL 60*6f9291ceSJung-uk Kim * library with I/O interfaces for which no specific BIO method is available. 61*6f9291ceSJung-uk Kim * See ssl/ssltest.c for some hints on how this can be used. 62*6f9291ceSJung-uk Kim */ 6374664626SKris Kennaway 644f20a5a2SJacques Vidrine /* BIO_DEBUG implies BIO_PAIR_DEBUG */ 654f20a5a2SJacques Vidrine #ifdef BIO_DEBUG 6674664626SKris Kennaway # ifndef BIO_PAIR_DEBUG 674f20a5a2SJacques Vidrine # define BIO_PAIR_DEBUG 684f20a5a2SJacques Vidrine # endif 694f20a5a2SJacques Vidrine #endif 704f20a5a2SJacques Vidrine 714f20a5a2SJacques Vidrine /* disable assert() unless BIO_PAIR_DEBUG has been defined */ 724f20a5a2SJacques Vidrine #ifndef BIO_PAIR_DEBUG 734f20a5a2SJacques Vidrine # ifndef NDEBUG 7474664626SKris Kennaway # define NDEBUG 7574664626SKris Kennaway # endif 764f20a5a2SJacques Vidrine #endif 7774664626SKris Kennaway 7874664626SKris Kennaway #include <assert.h> 79f579bf8eSKris Kennaway #include <limits.h> 8074664626SKris Kennaway #include <stdlib.h> 8174664626SKris Kennaway #include <string.h> 8274664626SKris Kennaway 8374664626SKris Kennaway #include <openssl/bio.h> 8474664626SKris Kennaway #include <openssl/err.h> 8574664626SKris Kennaway #include <openssl/crypto.h> 8674664626SKris Kennaway 875c87c606SMark Murray #include "e_os.h" 88c1803d78SJacques Vidrine 895c87c606SMark Murray /* VxWorks defines SSIZE_MAX with an empty value causing compile errors */ 905c87c606SMark Murray #if defined(OPENSSL_SYS_VXWORKS) 91c1803d78SJacques Vidrine # undef SSIZE_MAX 925c87c606SMark Murray #endif 935c87c606SMark Murray #ifndef SSIZE_MAX 94f579bf8eSKris Kennaway # define SSIZE_MAX INT_MAX 95f579bf8eSKris Kennaway #endif 96f579bf8eSKris Kennaway 9774664626SKris Kennaway static int bio_new(BIO *bio); 9874664626SKris Kennaway static int bio_free(BIO *bio); 9974664626SKris Kennaway static int bio_read(BIO *bio, char *buf, int size); 100ddd58736SKris Kennaway static int bio_write(BIO *bio, const char *buf, int num); 10174664626SKris Kennaway static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); 102ddd58736SKris Kennaway static int bio_puts(BIO *bio, const char *str); 10374664626SKris Kennaway 10474664626SKris Kennaway static int bio_make_pair(BIO *bio1, BIO *bio2); 10574664626SKris Kennaway static void bio_destroy_pair(BIO *bio); 10674664626SKris Kennaway 107*6f9291ceSJung-uk Kim static BIO_METHOD methods_biop = { 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 125*6f9291ceSJung-uk Kim struct bio_bio_st { 126*6f9291ceSJung-uk Kim BIO *peer; /* NULL if buf == NULL. If peer != NULL, then 127*6f9291ceSJung-uk Kim * peer->ptr is also a bio_bio_st, and its 128*6f9291ceSJung-uk Kim * "peer" member points back to us. peer != 129*6f9291ceSJung-uk Kim * NULL iff init != 0 in the BIO. */ 13074664626SKris Kennaway /* This is for what we write (i.e. reading uses peer's struct): */ 13174664626SKris Kennaway int closed; /* valid iff peer != NULL */ 13274664626SKris Kennaway size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ 13374664626SKris Kennaway size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ 13474664626SKris Kennaway size_t size; 13574664626SKris Kennaway char *buf; /* "size" elements (if != NULL) */ 13674664626SKris Kennaway size_t request; /* valid iff peer != NULL; 0 if len != 0, 13774664626SKris Kennaway * otherwise set by peer to number of bytes 138*6f9291ceSJung-uk Kim * it (unsuccessfully) tried to read, never 139*6f9291ceSJung-uk Kim * more than buffer space (size-len) 140*6f9291ceSJung-uk Kim * warrants. */ 14174664626SKris Kennaway }; 14274664626SKris Kennaway 14374664626SKris Kennaway static int bio_new(BIO *bio) 14474664626SKris Kennaway { 14574664626SKris Kennaway struct bio_bio_st *b; 14674664626SKris Kennaway 147ddd58736SKris Kennaway b = OPENSSL_malloc(sizeof *b); 14874664626SKris Kennaway if (b == NULL) 14974664626SKris Kennaway return 0; 15074664626SKris Kennaway 15174664626SKris Kennaway b->peer = NULL; 152*6f9291ceSJung-uk Kim /* enough for one TLS record (just a default) */ 153*6f9291ceSJung-uk Kim b->size = 17 * 1024; 15474664626SKris Kennaway b->buf = NULL; 15574664626SKris Kennaway 15674664626SKris Kennaway bio->ptr = b; 15774664626SKris Kennaway return 1; 15874664626SKris Kennaway } 15974664626SKris Kennaway 16074664626SKris Kennaway static int bio_free(BIO *bio) 16174664626SKris Kennaway { 16274664626SKris Kennaway struct bio_bio_st *b; 16374664626SKris Kennaway 16474664626SKris Kennaway if (bio == NULL) 16574664626SKris Kennaway return 0; 16674664626SKris Kennaway b = bio->ptr; 16774664626SKris Kennaway 16874664626SKris Kennaway assert(b != NULL); 16974664626SKris Kennaway 17074664626SKris Kennaway if (b->peer) 17174664626SKris Kennaway bio_destroy_pair(bio); 17274664626SKris Kennaway 173*6f9291ceSJung-uk Kim if (b->buf != NULL) { 174ddd58736SKris Kennaway OPENSSL_free(b->buf); 17574664626SKris Kennaway } 17674664626SKris Kennaway 177ddd58736SKris Kennaway OPENSSL_free(b); 17874664626SKris Kennaway 17974664626SKris Kennaway return 1; 18074664626SKris Kennaway } 18174664626SKris Kennaway 18274664626SKris Kennaway static int bio_read(BIO *bio, char *buf, int size_) 18374664626SKris Kennaway { 18474664626SKris Kennaway size_t size = size_; 18574664626SKris Kennaway size_t rest; 18674664626SKris Kennaway struct bio_bio_st *b, *peer_b; 18774664626SKris Kennaway 18874664626SKris Kennaway BIO_clear_retry_flags(bio); 18974664626SKris Kennaway 19074664626SKris Kennaway if (!bio->init) 19174664626SKris Kennaway return 0; 19274664626SKris Kennaway 19374664626SKris Kennaway b = bio->ptr; 19474664626SKris Kennaway assert(b != NULL); 19574664626SKris Kennaway assert(b->peer != NULL); 19674664626SKris Kennaway peer_b = b->peer->ptr; 19774664626SKris Kennaway assert(peer_b != NULL); 19874664626SKris Kennaway assert(peer_b->buf != NULL); 19974664626SKris Kennaway 20074664626SKris Kennaway peer_b->request = 0; /* will be set in "retry_read" situation */ 20174664626SKris Kennaway 20274664626SKris Kennaway if (buf == NULL || size == 0) 20374664626SKris Kennaway return 0; 20474664626SKris Kennaway 205*6f9291ceSJung-uk Kim if (peer_b->len == 0) { 20674664626SKris Kennaway if (peer_b->closed) 20774664626SKris Kennaway return 0; /* writer has closed, and no data is left */ 208*6f9291ceSJung-uk Kim else { 20974664626SKris Kennaway BIO_set_retry_read(bio); /* buffer is empty */ 21074664626SKris Kennaway if (size <= peer_b->size) 21174664626SKris Kennaway peer_b->request = size; 21274664626SKris Kennaway else 213*6f9291ceSJung-uk Kim /* 214*6f9291ceSJung-uk Kim * don't ask for more than the peer can deliver in one write 215*6f9291ceSJung-uk Kim */ 21674664626SKris Kennaway peer_b->request = peer_b->size; 21774664626SKris Kennaway return -1; 21874664626SKris Kennaway } 21974664626SKris Kennaway } 22074664626SKris Kennaway 22174664626SKris Kennaway /* we can read */ 22274664626SKris Kennaway if (peer_b->len < size) 22374664626SKris Kennaway size = peer_b->len; 22474664626SKris Kennaway 22574664626SKris Kennaway /* now read "size" bytes */ 22674664626SKris Kennaway 22774664626SKris Kennaway rest = size; 22874664626SKris Kennaway 22974664626SKris Kennaway assert(rest > 0); 230*6f9291ceSJung-uk Kim do { /* one or two iterations */ 23174664626SKris Kennaway size_t chunk; 23274664626SKris Kennaway 23374664626SKris Kennaway assert(rest <= peer_b->len); 23474664626SKris Kennaway if (peer_b->offset + rest <= peer_b->size) 23574664626SKris Kennaway chunk = rest; 23674664626SKris Kennaway else 23774664626SKris Kennaway /* wrap around ring buffer */ 23874664626SKris Kennaway chunk = peer_b->size - peer_b->offset; 23974664626SKris Kennaway assert(peer_b->offset + chunk <= peer_b->size); 24074664626SKris Kennaway 24174664626SKris Kennaway memcpy(buf, peer_b->buf + peer_b->offset, chunk); 24274664626SKris Kennaway 24374664626SKris Kennaway peer_b->len -= chunk; 244*6f9291ceSJung-uk Kim if (peer_b->len) { 24574664626SKris Kennaway peer_b->offset += chunk; 24674664626SKris Kennaway assert(peer_b->offset <= peer_b->size); 24774664626SKris Kennaway if (peer_b->offset == peer_b->size) 24874664626SKris Kennaway peer_b->offset = 0; 24974664626SKris Kennaway buf += chunk; 250*6f9291ceSJung-uk Kim } else { 25174664626SKris Kennaway /* buffer now empty, no need to advance "buf" */ 25274664626SKris Kennaway assert(chunk == rest); 25374664626SKris Kennaway peer_b->offset = 0; 25474664626SKris Kennaway } 25574664626SKris Kennaway rest -= chunk; 25674664626SKris Kennaway } 25774664626SKris Kennaway while (rest); 25874664626SKris Kennaway 25974664626SKris Kennaway return size; 26074664626SKris Kennaway } 26174664626SKris Kennaway 262*6f9291ceSJung-uk Kim /*- 263*6f9291ceSJung-uk Kim * non-copying interface: provide pointer to available data in buffer 264f579bf8eSKris Kennaway * bio_nread0: return number of available bytes 265f579bf8eSKris Kennaway * bio_nread: also advance index 266f579bf8eSKris Kennaway * (example usage: bio_nread0(), read from buffer, bio_nread() 267f579bf8eSKris Kennaway * or just bio_nread(), read from buffer) 268f579bf8eSKris Kennaway */ 269*6f9291ceSJung-uk Kim /* 270*6f9291ceSJung-uk Kim * WARNING: The non-copying interface is largely untested as of yet and may 271*6f9291ceSJung-uk Kim * contain bugs. 272*6f9291ceSJung-uk Kim */ 2731f13597dSJung-uk Kim static ossl_ssize_t bio_nread0(BIO *bio, char **buf) 274f579bf8eSKris Kennaway { 275f579bf8eSKris Kennaway struct bio_bio_st *b, *peer_b; 2761f13597dSJung-uk Kim ossl_ssize_t num; 277f579bf8eSKris Kennaway 278f579bf8eSKris Kennaway BIO_clear_retry_flags(bio); 279f579bf8eSKris Kennaway 280f579bf8eSKris Kennaway if (!bio->init) 281f579bf8eSKris Kennaway return 0; 282f579bf8eSKris Kennaway 283f579bf8eSKris Kennaway b = bio->ptr; 284f579bf8eSKris Kennaway assert(b != NULL); 285f579bf8eSKris Kennaway assert(b->peer != NULL); 286f579bf8eSKris Kennaway peer_b = b->peer->ptr; 287f579bf8eSKris Kennaway assert(peer_b != NULL); 288f579bf8eSKris Kennaway assert(peer_b->buf != NULL); 289f579bf8eSKris Kennaway 290f579bf8eSKris Kennaway peer_b->request = 0; 291f579bf8eSKris Kennaway 292*6f9291ceSJung-uk Kim if (peer_b->len == 0) { 293f579bf8eSKris Kennaway char dummy; 294f579bf8eSKris Kennaway 295f579bf8eSKris Kennaway /* avoid code duplication -- nothing available for reading */ 296f579bf8eSKris Kennaway return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ 297f579bf8eSKris Kennaway } 298f579bf8eSKris Kennaway 299f579bf8eSKris Kennaway num = peer_b->len; 300f579bf8eSKris Kennaway if (peer_b->size < peer_b->offset + num) 301f579bf8eSKris Kennaway /* no ring buffer wrap-around for non-copying interface */ 302f579bf8eSKris Kennaway num = peer_b->size - peer_b->offset; 303f579bf8eSKris Kennaway assert(num > 0); 304f579bf8eSKris Kennaway 305f579bf8eSKris Kennaway if (buf != NULL) 306f579bf8eSKris Kennaway *buf = peer_b->buf + peer_b->offset; 307f579bf8eSKris Kennaway return num; 308f579bf8eSKris Kennaway } 309f579bf8eSKris Kennaway 3101f13597dSJung-uk Kim static ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_) 311f579bf8eSKris Kennaway { 312f579bf8eSKris Kennaway struct bio_bio_st *b, *peer_b; 3131f13597dSJung-uk Kim ossl_ssize_t num, available; 314f579bf8eSKris Kennaway 315f579bf8eSKris Kennaway if (num_ > SSIZE_MAX) 316f579bf8eSKris Kennaway num = SSIZE_MAX; 317f579bf8eSKris Kennaway else 3181f13597dSJung-uk Kim num = (ossl_ssize_t) num_; 319f579bf8eSKris Kennaway 320f579bf8eSKris Kennaway available = bio_nread0(bio, buf); 321f579bf8eSKris Kennaway if (num > available) 322f579bf8eSKris Kennaway num = available; 323f579bf8eSKris Kennaway if (num <= 0) 324f579bf8eSKris Kennaway return num; 325f579bf8eSKris Kennaway 326f579bf8eSKris Kennaway b = bio->ptr; 327f579bf8eSKris Kennaway peer_b = b->peer->ptr; 328f579bf8eSKris Kennaway 329f579bf8eSKris Kennaway peer_b->len -= num; 330*6f9291ceSJung-uk Kim if (peer_b->len) { 331f579bf8eSKris Kennaway peer_b->offset += num; 332f579bf8eSKris Kennaway assert(peer_b->offset <= peer_b->size); 333f579bf8eSKris Kennaway if (peer_b->offset == peer_b->size) 334f579bf8eSKris Kennaway peer_b->offset = 0; 335*6f9291ceSJung-uk Kim } else 336f579bf8eSKris Kennaway peer_b->offset = 0; 337f579bf8eSKris Kennaway 338f579bf8eSKris Kennaway return num; 339f579bf8eSKris Kennaway } 340f579bf8eSKris Kennaway 341ddd58736SKris Kennaway static int bio_write(BIO *bio, const char *buf, int num_) 34274664626SKris Kennaway { 34374664626SKris Kennaway size_t num = num_; 34474664626SKris Kennaway size_t rest; 34574664626SKris Kennaway struct bio_bio_st *b; 34674664626SKris Kennaway 34774664626SKris Kennaway BIO_clear_retry_flags(bio); 34874664626SKris Kennaway 34974664626SKris Kennaway if (!bio->init || buf == NULL || num == 0) 35074664626SKris Kennaway return 0; 35174664626SKris Kennaway 35274664626SKris Kennaway b = bio->ptr; 35374664626SKris Kennaway assert(b != NULL); 35474664626SKris Kennaway assert(b->peer != NULL); 35574664626SKris Kennaway assert(b->buf != NULL); 35674664626SKris Kennaway 35774664626SKris Kennaway b->request = 0; 358*6f9291ceSJung-uk Kim if (b->closed) { 35974664626SKris Kennaway /* we already closed */ 36074664626SKris Kennaway BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); 36174664626SKris Kennaway return -1; 36274664626SKris Kennaway } 36374664626SKris Kennaway 36474664626SKris Kennaway assert(b->len <= b->size); 36574664626SKris Kennaway 366*6f9291ceSJung-uk Kim if (b->len == b->size) { 36774664626SKris Kennaway BIO_set_retry_write(bio); /* buffer is full */ 36874664626SKris Kennaway return -1; 36974664626SKris Kennaway } 37074664626SKris Kennaway 37174664626SKris Kennaway /* we can write */ 37274664626SKris Kennaway if (num > b->size - b->len) 37374664626SKris Kennaway num = b->size - b->len; 37474664626SKris Kennaway 37574664626SKris Kennaway /* now write "num" bytes */ 37674664626SKris Kennaway 37774664626SKris Kennaway rest = num; 37874664626SKris Kennaway 37974664626SKris Kennaway assert(rest > 0); 380*6f9291ceSJung-uk Kim do { /* one or two iterations */ 38174664626SKris Kennaway size_t write_offset; 38274664626SKris Kennaway size_t chunk; 38374664626SKris Kennaway 38474664626SKris Kennaway assert(b->len + rest <= b->size); 38574664626SKris Kennaway 38674664626SKris Kennaway write_offset = b->offset + b->len; 38774664626SKris Kennaway if (write_offset >= b->size) 38874664626SKris Kennaway write_offset -= b->size; 38974664626SKris Kennaway /* b->buf[write_offset] is the first byte we can write to. */ 39074664626SKris Kennaway 39174664626SKris Kennaway if (write_offset + rest <= b->size) 39274664626SKris Kennaway chunk = rest; 39374664626SKris Kennaway else 39474664626SKris Kennaway /* wrap around ring buffer */ 39574664626SKris Kennaway chunk = b->size - write_offset; 39674664626SKris Kennaway 39774664626SKris Kennaway memcpy(b->buf + write_offset, buf, chunk); 39874664626SKris Kennaway 39974664626SKris Kennaway b->len += chunk; 40074664626SKris Kennaway 40174664626SKris Kennaway assert(b->len <= b->size); 40274664626SKris Kennaway 40374664626SKris Kennaway rest -= chunk; 40474664626SKris Kennaway buf += chunk; 40574664626SKris Kennaway } 40674664626SKris Kennaway while (rest); 40774664626SKris Kennaway 40874664626SKris Kennaway return num; 40974664626SKris Kennaway } 41074664626SKris Kennaway 411*6f9291ceSJung-uk Kim /*- 412*6f9291ceSJung-uk Kim * non-copying interface: provide pointer to region to write to 413f579bf8eSKris Kennaway * bio_nwrite0: check how much space is available 414f579bf8eSKris Kennaway * bio_nwrite: also increase length 415f579bf8eSKris Kennaway * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() 416f579bf8eSKris Kennaway * or just bio_nwrite(), write to buffer) 417f579bf8eSKris Kennaway */ 4181f13597dSJung-uk Kim static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf) 419f579bf8eSKris Kennaway { 420f579bf8eSKris Kennaway struct bio_bio_st *b; 421f579bf8eSKris Kennaway size_t num; 422f579bf8eSKris Kennaway size_t write_offset; 423f579bf8eSKris Kennaway 424f579bf8eSKris Kennaway BIO_clear_retry_flags(bio); 425f579bf8eSKris Kennaway 426f579bf8eSKris Kennaway if (!bio->init) 427f579bf8eSKris Kennaway return 0; 428f579bf8eSKris Kennaway 429f579bf8eSKris Kennaway b = bio->ptr; 430f579bf8eSKris Kennaway assert(b != NULL); 431f579bf8eSKris Kennaway assert(b->peer != NULL); 432f579bf8eSKris Kennaway assert(b->buf != NULL); 433f579bf8eSKris Kennaway 434f579bf8eSKris Kennaway b->request = 0; 435*6f9291ceSJung-uk Kim if (b->closed) { 436f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); 437f579bf8eSKris Kennaway return -1; 438f579bf8eSKris Kennaway } 439f579bf8eSKris Kennaway 440f579bf8eSKris Kennaway assert(b->len <= b->size); 441f579bf8eSKris Kennaway 442*6f9291ceSJung-uk Kim if (b->len == b->size) { 443f579bf8eSKris Kennaway BIO_set_retry_write(bio); 444f579bf8eSKris Kennaway return -1; 445f579bf8eSKris Kennaway } 446f579bf8eSKris Kennaway 447f579bf8eSKris Kennaway num = b->size - b->len; 448f579bf8eSKris Kennaway write_offset = b->offset + b->len; 449f579bf8eSKris Kennaway if (write_offset >= b->size) 450f579bf8eSKris Kennaway write_offset -= b->size; 451f579bf8eSKris Kennaway if (write_offset + num > b->size) 452*6f9291ceSJung-uk Kim /* 453*6f9291ceSJung-uk Kim * no ring buffer wrap-around for non-copying interface (to fulfil 454*6f9291ceSJung-uk Kim * the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have 455*6f9291ceSJung-uk Kim * to be called twice) 456*6f9291ceSJung-uk Kim */ 457f579bf8eSKris Kennaway num = b->size - write_offset; 458f579bf8eSKris Kennaway 459f579bf8eSKris Kennaway if (buf != NULL) 460f579bf8eSKris Kennaway *buf = b->buf + write_offset; 461f579bf8eSKris Kennaway assert(write_offset + num <= b->size); 462f579bf8eSKris Kennaway 463f579bf8eSKris Kennaway return num; 464f579bf8eSKris Kennaway } 465f579bf8eSKris Kennaway 4661f13597dSJung-uk Kim static ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) 467f579bf8eSKris Kennaway { 468f579bf8eSKris Kennaway struct bio_bio_st *b; 4691f13597dSJung-uk Kim ossl_ssize_t num, space; 470f579bf8eSKris Kennaway 471f579bf8eSKris Kennaway if (num_ > SSIZE_MAX) 472f579bf8eSKris Kennaway num = SSIZE_MAX; 473f579bf8eSKris Kennaway else 4741f13597dSJung-uk Kim num = (ossl_ssize_t) num_; 475f579bf8eSKris Kennaway 476f579bf8eSKris Kennaway space = bio_nwrite0(bio, buf); 477f579bf8eSKris Kennaway if (num > space) 478f579bf8eSKris Kennaway num = space; 479f579bf8eSKris Kennaway if (num <= 0) 480f579bf8eSKris Kennaway return num; 481f579bf8eSKris Kennaway b = bio->ptr; 482f579bf8eSKris Kennaway assert(b != NULL); 483f579bf8eSKris Kennaway b->len += num; 484f579bf8eSKris Kennaway assert(b->len <= b->size); 485f579bf8eSKris Kennaway 486f579bf8eSKris Kennaway return num; 487f579bf8eSKris Kennaway } 488f579bf8eSKris Kennaway 48974664626SKris Kennaway static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 49074664626SKris Kennaway { 49174664626SKris Kennaway long ret; 49274664626SKris Kennaway struct bio_bio_st *b = bio->ptr; 49374664626SKris Kennaway 49474664626SKris Kennaway assert(b != NULL); 49574664626SKris Kennaway 496*6f9291ceSJung-uk Kim switch (cmd) { 49774664626SKris Kennaway /* specific CTRL codes */ 49874664626SKris Kennaway 49974664626SKris Kennaway case BIO_C_SET_WRITE_BUF_SIZE: 500*6f9291ceSJung-uk Kim if (b->peer) { 50174664626SKris Kennaway BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); 50274664626SKris Kennaway ret = 0; 503*6f9291ceSJung-uk Kim } else if (num == 0) { 50474664626SKris Kennaway BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); 50574664626SKris Kennaway ret = 0; 506*6f9291ceSJung-uk Kim } else { 50774664626SKris Kennaway size_t new_size = num; 50874664626SKris Kennaway 509*6f9291ceSJung-uk Kim if (b->size != new_size) { 510*6f9291ceSJung-uk Kim if (b->buf) { 511ddd58736SKris Kennaway OPENSSL_free(b->buf); 51274664626SKris Kennaway b->buf = NULL; 51374664626SKris Kennaway } 51474664626SKris Kennaway b->size = new_size; 51574664626SKris Kennaway } 51674664626SKris Kennaway ret = 1; 51774664626SKris Kennaway } 51874664626SKris Kennaway break; 51974664626SKris Kennaway 52074664626SKris Kennaway case BIO_C_GET_WRITE_BUF_SIZE: 521a21b1b38SKris Kennaway ret = (long)b->size; 522a21b1b38SKris Kennaway break; 52374664626SKris Kennaway 52474664626SKris Kennaway case BIO_C_MAKE_BIO_PAIR: 52574664626SKris Kennaway { 52674664626SKris Kennaway BIO *other_bio = ptr; 52774664626SKris Kennaway 52874664626SKris Kennaway if (bio_make_pair(bio, other_bio)) 52974664626SKris Kennaway ret = 1; 53074664626SKris Kennaway else 53174664626SKris Kennaway ret = 0; 53274664626SKris Kennaway } 53374664626SKris Kennaway break; 53474664626SKris Kennaway 53574664626SKris Kennaway case BIO_C_DESTROY_BIO_PAIR: 536*6f9291ceSJung-uk Kim /* 537*6f9291ceSJung-uk Kim * Affects both BIOs in the pair -- call just once! Or let 538*6f9291ceSJung-uk Kim * BIO_free(bio1); BIO_free(bio2); do the job. 539*6f9291ceSJung-uk Kim */ 54074664626SKris Kennaway bio_destroy_pair(bio); 54174664626SKris Kennaway ret = 1; 54274664626SKris Kennaway break; 54374664626SKris Kennaway 54474664626SKris Kennaway case BIO_C_GET_WRITE_GUARANTEE: 545*6f9291ceSJung-uk Kim /* 546*6f9291ceSJung-uk Kim * How many bytes can the caller feed to the next write without 547*6f9291ceSJung-uk Kim * having to keep any? 548*6f9291ceSJung-uk Kim */ 54974664626SKris Kennaway if (b->peer == NULL || b->closed) 55074664626SKris Kennaway ret = 0; 55174664626SKris Kennaway else 55274664626SKris Kennaway ret = (long)b->size - b->len; 55374664626SKris Kennaway break; 55474664626SKris Kennaway 55574664626SKris Kennaway case BIO_C_GET_READ_REQUEST: 556*6f9291ceSJung-uk Kim /* 557*6f9291ceSJung-uk Kim * If the peer unsuccessfully tried to read, how many bytes were 558*6f9291ceSJung-uk Kim * requested? (As with BIO_CTRL_PENDING, that number can usually be 559*6f9291ceSJung-uk Kim * treated as boolean.) 560*6f9291ceSJung-uk Kim */ 56174664626SKris Kennaway ret = (long)b->request; 56274664626SKris Kennaway break; 56374664626SKris Kennaway 564f579bf8eSKris Kennaway case BIO_C_RESET_READ_REQUEST: 565*6f9291ceSJung-uk Kim /* 566*6f9291ceSJung-uk Kim * Reset request. (Can be useful after read attempts at the other 567*6f9291ceSJung-uk Kim * side that are meant to be non-blocking, e.g. when probing SSL_read 568*6f9291ceSJung-uk Kim * to see if any data is available.) 569*6f9291ceSJung-uk Kim */ 570f579bf8eSKris Kennaway b->request = 0; 571f579bf8eSKris Kennaway ret = 1; 572f579bf8eSKris Kennaway break; 573f579bf8eSKris Kennaway 57474664626SKris Kennaway case BIO_C_SHUTDOWN_WR: 57574664626SKris Kennaway /* similar to shutdown(..., SHUT_WR) */ 57674664626SKris Kennaway b->closed = 1; 57774664626SKris Kennaway ret = 1; 57874664626SKris Kennaway break; 57974664626SKris Kennaway 580f579bf8eSKris Kennaway case BIO_C_NREAD0: 581f579bf8eSKris Kennaway /* prepare for non-copying read */ 582f579bf8eSKris Kennaway ret = (long)bio_nread0(bio, ptr); 583f579bf8eSKris Kennaway break; 584f579bf8eSKris Kennaway 585f579bf8eSKris Kennaway case BIO_C_NREAD: 586f579bf8eSKris Kennaway /* non-copying read */ 587f579bf8eSKris Kennaway ret = (long)bio_nread(bio, ptr, (size_t)num); 588f579bf8eSKris Kennaway break; 589f579bf8eSKris Kennaway 590f579bf8eSKris Kennaway case BIO_C_NWRITE0: 591f579bf8eSKris Kennaway /* prepare for non-copying write */ 592f579bf8eSKris Kennaway ret = (long)bio_nwrite0(bio, ptr); 593f579bf8eSKris Kennaway break; 594f579bf8eSKris Kennaway 595f579bf8eSKris Kennaway case BIO_C_NWRITE: 596f579bf8eSKris Kennaway /* non-copying write */ 597f579bf8eSKris Kennaway ret = (long)bio_nwrite(bio, ptr, (size_t)num); 598f579bf8eSKris Kennaway break; 599f579bf8eSKris Kennaway 60074664626SKris Kennaway /* standard CTRL codes follow */ 60174664626SKris Kennaway 60274664626SKris Kennaway case BIO_CTRL_RESET: 603*6f9291ceSJung-uk Kim if (b->buf != NULL) { 60474664626SKris Kennaway b->len = 0; 60574664626SKris Kennaway b->offset = 0; 60674664626SKris Kennaway } 60774664626SKris Kennaway ret = 0; 60874664626SKris Kennaway break; 60974664626SKris Kennaway 61074664626SKris Kennaway case BIO_CTRL_GET_CLOSE: 61174664626SKris Kennaway ret = bio->shutdown; 61274664626SKris Kennaway break; 61374664626SKris Kennaway 61474664626SKris Kennaway case BIO_CTRL_SET_CLOSE: 61574664626SKris Kennaway bio->shutdown = (int)num; 61674664626SKris Kennaway ret = 1; 61774664626SKris Kennaway break; 61874664626SKris Kennaway 61974664626SKris Kennaway case BIO_CTRL_PENDING: 620*6f9291ceSJung-uk Kim if (b->peer != NULL) { 62174664626SKris Kennaway struct bio_bio_st *peer_b = b->peer->ptr; 62274664626SKris Kennaway 62374664626SKris Kennaway ret = (long)peer_b->len; 624*6f9291ceSJung-uk Kim } else 62574664626SKris Kennaway ret = 0; 62674664626SKris Kennaway break; 62774664626SKris Kennaway 62874664626SKris Kennaway case BIO_CTRL_WPENDING: 62974664626SKris Kennaway if (b->buf != NULL) 63074664626SKris Kennaway ret = (long)b->len; 63174664626SKris Kennaway else 63274664626SKris Kennaway ret = 0; 63374664626SKris Kennaway break; 63474664626SKris Kennaway 63574664626SKris Kennaway case BIO_CTRL_DUP: 63674664626SKris Kennaway /* See BIO_dup_chain for circumstances we have to expect. */ 63774664626SKris Kennaway { 63874664626SKris Kennaway BIO *other_bio = ptr; 63974664626SKris Kennaway struct bio_bio_st *other_b; 64074664626SKris Kennaway 64174664626SKris Kennaway assert(other_bio != NULL); 64274664626SKris Kennaway other_b = other_bio->ptr; 64374664626SKris Kennaway assert(other_b != NULL); 64474664626SKris Kennaway 64574664626SKris Kennaway assert(other_b->buf == NULL); /* other_bio is always fresh */ 64674664626SKris Kennaway 64774664626SKris Kennaway other_b->size = b->size; 64874664626SKris Kennaway } 64974664626SKris Kennaway 65074664626SKris Kennaway ret = 1; 65174664626SKris Kennaway break; 65274664626SKris Kennaway 65374664626SKris Kennaway case BIO_CTRL_FLUSH: 65474664626SKris Kennaway ret = 1; 65574664626SKris Kennaway break; 65674664626SKris Kennaway 65774664626SKris Kennaway case BIO_CTRL_EOF: 65874664626SKris Kennaway { 65974664626SKris Kennaway BIO *other_bio = ptr; 66074664626SKris Kennaway 661*6f9291ceSJung-uk Kim if (other_bio) { 66274664626SKris Kennaway struct bio_bio_st *other_b = other_bio->ptr; 66374664626SKris Kennaway 66474664626SKris Kennaway assert(other_b != NULL); 66574664626SKris Kennaway ret = other_b->len == 0 && other_b->closed; 666*6f9291ceSJung-uk Kim } else 66774664626SKris Kennaway ret = 1; 66874664626SKris Kennaway } 66974664626SKris Kennaway break; 67074664626SKris Kennaway 67174664626SKris Kennaway default: 67274664626SKris Kennaway ret = 0; 67374664626SKris Kennaway } 67474664626SKris Kennaway return ret; 67574664626SKris Kennaway } 67674664626SKris Kennaway 677ddd58736SKris Kennaway static int bio_puts(BIO *bio, const char *str) 67874664626SKris Kennaway { 67974664626SKris Kennaway return bio_write(bio, str, strlen(str)); 68074664626SKris Kennaway } 68174664626SKris Kennaway 68274664626SKris Kennaway static int bio_make_pair(BIO *bio1, BIO *bio2) 68374664626SKris Kennaway { 68474664626SKris Kennaway struct bio_bio_st *b1, *b2; 68574664626SKris Kennaway 68674664626SKris Kennaway assert(bio1 != NULL); 68774664626SKris Kennaway assert(bio2 != NULL); 68874664626SKris Kennaway 68974664626SKris Kennaway b1 = bio1->ptr; 69074664626SKris Kennaway b2 = bio2->ptr; 69174664626SKris Kennaway 692*6f9291ceSJung-uk Kim if (b1->peer != NULL || b2->peer != NULL) { 69374664626SKris Kennaway BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); 69474664626SKris Kennaway return 0; 69574664626SKris Kennaway } 69674664626SKris Kennaway 697*6f9291ceSJung-uk Kim if (b1->buf == NULL) { 698ddd58736SKris Kennaway b1->buf = OPENSSL_malloc(b1->size); 699*6f9291ceSJung-uk Kim if (b1->buf == NULL) { 70074664626SKris Kennaway BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 70174664626SKris Kennaway return 0; 70274664626SKris Kennaway } 70374664626SKris Kennaway b1->len = 0; 70474664626SKris Kennaway b1->offset = 0; 70574664626SKris Kennaway } 70674664626SKris Kennaway 707*6f9291ceSJung-uk Kim if (b2->buf == NULL) { 708ddd58736SKris Kennaway b2->buf = OPENSSL_malloc(b2->size); 709*6f9291ceSJung-uk Kim if (b2->buf == NULL) { 71074664626SKris Kennaway BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 71174664626SKris Kennaway return 0; 71274664626SKris Kennaway } 71374664626SKris Kennaway b2->len = 0; 71474664626SKris Kennaway b2->offset = 0; 71574664626SKris Kennaway } 71674664626SKris Kennaway 71774664626SKris Kennaway b1->peer = bio2; 71874664626SKris Kennaway b1->closed = 0; 71974664626SKris Kennaway b1->request = 0; 72074664626SKris Kennaway b2->peer = bio1; 72174664626SKris Kennaway b2->closed = 0; 72274664626SKris Kennaway b2->request = 0; 72374664626SKris Kennaway 72474664626SKris Kennaway bio1->init = 1; 72574664626SKris Kennaway bio2->init = 1; 72674664626SKris Kennaway 72774664626SKris Kennaway return 1; 72874664626SKris Kennaway } 72974664626SKris Kennaway 73074664626SKris Kennaway static void bio_destroy_pair(BIO *bio) 73174664626SKris Kennaway { 73274664626SKris Kennaway struct bio_bio_st *b = bio->ptr; 73374664626SKris Kennaway 734*6f9291ceSJung-uk Kim if (b != NULL) { 73574664626SKris Kennaway BIO *peer_bio = b->peer; 73674664626SKris Kennaway 737*6f9291ceSJung-uk Kim if (peer_bio != NULL) { 73874664626SKris Kennaway struct bio_bio_st *peer_b = peer_bio->ptr; 73974664626SKris Kennaway 74074664626SKris Kennaway assert(peer_b != NULL); 74174664626SKris Kennaway assert(peer_b->peer == bio); 74274664626SKris Kennaway 74374664626SKris Kennaway peer_b->peer = NULL; 74474664626SKris Kennaway peer_bio->init = 0; 74574664626SKris Kennaway assert(peer_b->buf != NULL); 74674664626SKris Kennaway peer_b->len = 0; 74774664626SKris Kennaway peer_b->offset = 0; 74874664626SKris Kennaway 74974664626SKris Kennaway b->peer = NULL; 75074664626SKris Kennaway bio->init = 0; 75174664626SKris Kennaway assert(b->buf != NULL); 75274664626SKris Kennaway b->len = 0; 75374664626SKris Kennaway b->offset = 0; 75474664626SKris Kennaway } 75574664626SKris Kennaway } 75674664626SKris Kennaway } 75774664626SKris Kennaway 75874664626SKris Kennaway /* Exported convenience functions */ 75974664626SKris Kennaway int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, 76074664626SKris Kennaway BIO **bio2_p, size_t writebuf2) 76174664626SKris Kennaway { 76274664626SKris Kennaway BIO *bio1 = NULL, *bio2 = NULL; 76374664626SKris Kennaway long r; 76474664626SKris Kennaway int ret = 0; 76574664626SKris Kennaway 76674664626SKris Kennaway bio1 = BIO_new(BIO_s_bio()); 76774664626SKris Kennaway if (bio1 == NULL) 76874664626SKris Kennaway goto err; 76974664626SKris Kennaway bio2 = BIO_new(BIO_s_bio()); 77074664626SKris Kennaway if (bio2 == NULL) 77174664626SKris Kennaway goto err; 77274664626SKris Kennaway 773*6f9291ceSJung-uk Kim if (writebuf1) { 77474664626SKris Kennaway r = BIO_set_write_buf_size(bio1, writebuf1); 77574664626SKris Kennaway if (!r) 77674664626SKris Kennaway goto err; 77774664626SKris Kennaway } 778*6f9291ceSJung-uk Kim if (writebuf2) { 77974664626SKris Kennaway r = BIO_set_write_buf_size(bio2, writebuf2); 78074664626SKris Kennaway if (!r) 78174664626SKris Kennaway goto err; 78274664626SKris Kennaway } 78374664626SKris Kennaway 78474664626SKris Kennaway r = BIO_make_bio_pair(bio1, bio2); 78574664626SKris Kennaway if (!r) 78674664626SKris Kennaway goto err; 78774664626SKris Kennaway ret = 1; 78874664626SKris Kennaway 78974664626SKris Kennaway err: 790*6f9291ceSJung-uk Kim if (ret == 0) { 791*6f9291ceSJung-uk Kim if (bio1) { 79274664626SKris Kennaway BIO_free(bio1); 79374664626SKris Kennaway bio1 = NULL; 79474664626SKris Kennaway } 795*6f9291ceSJung-uk Kim if (bio2) { 79674664626SKris Kennaway BIO_free(bio2); 79774664626SKris Kennaway bio2 = NULL; 79874664626SKris Kennaway } 79974664626SKris Kennaway } 80074664626SKris Kennaway 80174664626SKris Kennaway *bio1_p = bio1; 80274664626SKris Kennaway *bio2_p = bio2; 80374664626SKris Kennaway return ret; 80474664626SKris Kennaway } 80574664626SKris Kennaway 80674664626SKris Kennaway size_t BIO_ctrl_get_write_guarantee(BIO *bio) 80774664626SKris Kennaway { 80874664626SKris Kennaway return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 80974664626SKris Kennaway } 81074664626SKris Kennaway 81174664626SKris Kennaway size_t BIO_ctrl_get_read_request(BIO *bio) 81274664626SKris Kennaway { 81374664626SKris Kennaway return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 81474664626SKris Kennaway } 815f579bf8eSKris Kennaway 816f579bf8eSKris Kennaway int BIO_ctrl_reset_read_request(BIO *bio) 817f579bf8eSKris Kennaway { 818f579bf8eSKris Kennaway return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); 819f579bf8eSKris Kennaway } 820f579bf8eSKris Kennaway 821*6f9291ceSJung-uk Kim /* 822*6f9291ceSJung-uk Kim * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now 823*6f9291ceSJung-uk Kim * (conceivably some other BIOs could allow non-copying reads and writes 824*6f9291ceSJung-uk Kim * too.) 825f579bf8eSKris Kennaway */ 826f579bf8eSKris Kennaway int BIO_nread0(BIO *bio, char **buf) 827f579bf8eSKris Kennaway { 828f579bf8eSKris Kennaway long ret; 829f579bf8eSKris Kennaway 830*6f9291ceSJung-uk Kim if (!bio->init) { 831f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); 832f579bf8eSKris Kennaway return -2; 833f579bf8eSKris Kennaway } 834f579bf8eSKris Kennaway 835f579bf8eSKris Kennaway ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); 836f579bf8eSKris Kennaway if (ret > INT_MAX) 837f579bf8eSKris Kennaway return INT_MAX; 838f579bf8eSKris Kennaway else 839f579bf8eSKris Kennaway return (int)ret; 840f579bf8eSKris Kennaway } 841f579bf8eSKris Kennaway 842f579bf8eSKris Kennaway int BIO_nread(BIO *bio, char **buf, int num) 843f579bf8eSKris Kennaway { 844f579bf8eSKris Kennaway int ret; 845f579bf8eSKris Kennaway 846*6f9291ceSJung-uk Kim if (!bio->init) { 847f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); 848f579bf8eSKris Kennaway return -2; 849f579bf8eSKris Kennaway } 850f579bf8eSKris Kennaway 851f579bf8eSKris Kennaway ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf); 852f579bf8eSKris Kennaway if (ret > 0) 853f579bf8eSKris Kennaway bio->num_read += ret; 854f579bf8eSKris Kennaway return ret; 855f579bf8eSKris Kennaway } 856f579bf8eSKris Kennaway 857f579bf8eSKris Kennaway int BIO_nwrite0(BIO *bio, char **buf) 858f579bf8eSKris Kennaway { 859f579bf8eSKris Kennaway long ret; 860f579bf8eSKris Kennaway 861*6f9291ceSJung-uk Kim if (!bio->init) { 862f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); 863f579bf8eSKris Kennaway return -2; 864f579bf8eSKris Kennaway } 865f579bf8eSKris Kennaway 866f579bf8eSKris Kennaway ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); 867f579bf8eSKris Kennaway if (ret > INT_MAX) 868f579bf8eSKris Kennaway return INT_MAX; 869f579bf8eSKris Kennaway else 870f579bf8eSKris Kennaway return (int)ret; 871f579bf8eSKris Kennaway } 872f579bf8eSKris Kennaway 873f579bf8eSKris Kennaway int BIO_nwrite(BIO *bio, char **buf, int num) 874f579bf8eSKris Kennaway { 875f579bf8eSKris Kennaway int ret; 876f579bf8eSKris Kennaway 877*6f9291ceSJung-uk Kim if (!bio->init) { 878f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); 879f579bf8eSKris Kennaway return -2; 880f579bf8eSKris Kennaway } 881f579bf8eSKris Kennaway 882f579bf8eSKris Kennaway ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); 883f579bf8eSKris Kennaway if (ret > 0) 884db522d3aSSimon L. B. Nielsen bio->num_write += ret; 885f579bf8eSKris Kennaway return ret; 886f579bf8eSKris Kennaway } 887