18180e704SJung-uk Kim /* crypto/bio/bss_bio.c */ 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 566f9291ceSJung-uk Kim /* 576f9291ceSJung-uk Kim * Special method for a BIO where the other endpoint is also a BIO of this 586f9291ceSJung-uk Kim * kind, handled by the same thread (i.e. the "peer" is actually ourselves, 596f9291ceSJung-uk Kim * wearing a different hat). Such "BIO pairs" are mainly for using the SSL 606f9291ceSJung-uk Kim * library with I/O interfaces for which no specific BIO method is available. 616f9291ceSJung-uk Kim * See ssl/ssltest.c for some hints on how this can be used. 626f9291ceSJung-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 1076f9291ceSJung-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 1256f9291ceSJung-uk Kim struct bio_bio_st { 1266f9291ceSJung-uk Kim BIO *peer; /* NULL if buf == NULL. If peer != NULL, then 1276f9291ceSJung-uk Kim * peer->ptr is also a bio_bio_st, and its 1286f9291ceSJung-uk Kim * "peer" member points back to us. peer != 1296f9291ceSJung-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 1386f9291ceSJung-uk Kim * it (unsuccessfully) tried to read, never 1396f9291ceSJung-uk Kim * more than buffer space (size-len) 1406f9291ceSJung-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*aeb5019cSJung-uk Kim b->closed = 0; 153*aeb5019cSJung-uk Kim b->len = 0; 154*aeb5019cSJung-uk Kim b->offset = 0; 1556f9291ceSJung-uk Kim /* enough for one TLS record (just a default) */ 1566f9291ceSJung-uk Kim b->size = 17 * 1024; 15774664626SKris Kennaway b->buf = NULL; 158*aeb5019cSJung-uk Kim b->request = 0; 15974664626SKris Kennaway 16074664626SKris Kennaway bio->ptr = b; 16174664626SKris Kennaway return 1; 16274664626SKris Kennaway } 16374664626SKris Kennaway 16474664626SKris Kennaway static int bio_free(BIO *bio) 16574664626SKris Kennaway { 16674664626SKris Kennaway struct bio_bio_st *b; 16774664626SKris Kennaway 16874664626SKris Kennaway if (bio == NULL) 16974664626SKris Kennaway return 0; 17074664626SKris Kennaway b = bio->ptr; 17174664626SKris Kennaway 17274664626SKris Kennaway assert(b != NULL); 17374664626SKris Kennaway 17474664626SKris Kennaway if (b->peer) 17574664626SKris Kennaway bio_destroy_pair(bio); 17674664626SKris Kennaway 1776f9291ceSJung-uk Kim if (b->buf != NULL) { 178ddd58736SKris Kennaway OPENSSL_free(b->buf); 17974664626SKris Kennaway } 18074664626SKris Kennaway 181ddd58736SKris Kennaway OPENSSL_free(b); 18274664626SKris Kennaway 18374664626SKris Kennaway return 1; 18474664626SKris Kennaway } 18574664626SKris Kennaway 18674664626SKris Kennaway static int bio_read(BIO *bio, char *buf, int size_) 18774664626SKris Kennaway { 18874664626SKris Kennaway size_t size = size_; 18974664626SKris Kennaway size_t rest; 19074664626SKris Kennaway struct bio_bio_st *b, *peer_b; 19174664626SKris Kennaway 19274664626SKris Kennaway BIO_clear_retry_flags(bio); 19374664626SKris Kennaway 19474664626SKris Kennaway if (!bio->init) 19574664626SKris Kennaway return 0; 19674664626SKris Kennaway 19774664626SKris Kennaway b = bio->ptr; 19874664626SKris Kennaway assert(b != NULL); 19974664626SKris Kennaway assert(b->peer != NULL); 20074664626SKris Kennaway peer_b = b->peer->ptr; 20174664626SKris Kennaway assert(peer_b != NULL); 20274664626SKris Kennaway assert(peer_b->buf != NULL); 20374664626SKris Kennaway 20474664626SKris Kennaway peer_b->request = 0; /* will be set in "retry_read" situation */ 20574664626SKris Kennaway 20674664626SKris Kennaway if (buf == NULL || size == 0) 20774664626SKris Kennaway return 0; 20874664626SKris Kennaway 2096f9291ceSJung-uk Kim if (peer_b->len == 0) { 21074664626SKris Kennaway if (peer_b->closed) 21174664626SKris Kennaway return 0; /* writer has closed, and no data is left */ 2126f9291ceSJung-uk Kim else { 21374664626SKris Kennaway BIO_set_retry_read(bio); /* buffer is empty */ 21474664626SKris Kennaway if (size <= peer_b->size) 21574664626SKris Kennaway peer_b->request = size; 21674664626SKris Kennaway else 2176f9291ceSJung-uk Kim /* 2186f9291ceSJung-uk Kim * don't ask for more than the peer can deliver in one write 2196f9291ceSJung-uk Kim */ 22074664626SKris Kennaway peer_b->request = peer_b->size; 22174664626SKris Kennaway return -1; 22274664626SKris Kennaway } 22374664626SKris Kennaway } 22474664626SKris Kennaway 22574664626SKris Kennaway /* we can read */ 22674664626SKris Kennaway if (peer_b->len < size) 22774664626SKris Kennaway size = peer_b->len; 22874664626SKris Kennaway 22974664626SKris Kennaway /* now read "size" bytes */ 23074664626SKris Kennaway 23174664626SKris Kennaway rest = size; 23274664626SKris Kennaway 23374664626SKris Kennaway assert(rest > 0); 2346f9291ceSJung-uk Kim do { /* one or two iterations */ 23574664626SKris Kennaway size_t chunk; 23674664626SKris Kennaway 23774664626SKris Kennaway assert(rest <= peer_b->len); 23874664626SKris Kennaway if (peer_b->offset + rest <= peer_b->size) 23974664626SKris Kennaway chunk = rest; 24074664626SKris Kennaway else 24174664626SKris Kennaway /* wrap around ring buffer */ 24274664626SKris Kennaway chunk = peer_b->size - peer_b->offset; 24374664626SKris Kennaway assert(peer_b->offset + chunk <= peer_b->size); 24474664626SKris Kennaway 24574664626SKris Kennaway memcpy(buf, peer_b->buf + peer_b->offset, chunk); 24674664626SKris Kennaway 24774664626SKris Kennaway peer_b->len -= chunk; 2486f9291ceSJung-uk Kim if (peer_b->len) { 24974664626SKris Kennaway peer_b->offset += chunk; 25074664626SKris Kennaway assert(peer_b->offset <= peer_b->size); 25174664626SKris Kennaway if (peer_b->offset == peer_b->size) 25274664626SKris Kennaway peer_b->offset = 0; 25374664626SKris Kennaway buf += chunk; 2546f9291ceSJung-uk Kim } else { 25574664626SKris Kennaway /* buffer now empty, no need to advance "buf" */ 25674664626SKris Kennaway assert(chunk == rest); 25774664626SKris Kennaway peer_b->offset = 0; 25874664626SKris Kennaway } 25974664626SKris Kennaway rest -= chunk; 26074664626SKris Kennaway } 26174664626SKris Kennaway while (rest); 26274664626SKris Kennaway 26374664626SKris Kennaway return size; 26474664626SKris Kennaway } 26574664626SKris Kennaway 2666f9291ceSJung-uk Kim /*- 2676f9291ceSJung-uk Kim * non-copying interface: provide pointer to available data in buffer 268f579bf8eSKris Kennaway * bio_nread0: return number of available bytes 269f579bf8eSKris Kennaway * bio_nread: also advance index 270f579bf8eSKris Kennaway * (example usage: bio_nread0(), read from buffer, bio_nread() 271f579bf8eSKris Kennaway * or just bio_nread(), read from buffer) 272f579bf8eSKris Kennaway */ 2736f9291ceSJung-uk Kim /* 2746f9291ceSJung-uk Kim * WARNING: The non-copying interface is largely untested as of yet and may 2756f9291ceSJung-uk Kim * contain bugs. 2766f9291ceSJung-uk Kim */ 2771f13597dSJung-uk Kim static ossl_ssize_t bio_nread0(BIO *bio, char **buf) 278f579bf8eSKris Kennaway { 279f579bf8eSKris Kennaway struct bio_bio_st *b, *peer_b; 2801f13597dSJung-uk Kim ossl_ssize_t num; 281f579bf8eSKris Kennaway 282f579bf8eSKris Kennaway BIO_clear_retry_flags(bio); 283f579bf8eSKris Kennaway 284f579bf8eSKris Kennaway if (!bio->init) 285f579bf8eSKris Kennaway return 0; 286f579bf8eSKris Kennaway 287f579bf8eSKris Kennaway b = bio->ptr; 288f579bf8eSKris Kennaway assert(b != NULL); 289f579bf8eSKris Kennaway assert(b->peer != NULL); 290f579bf8eSKris Kennaway peer_b = b->peer->ptr; 291f579bf8eSKris Kennaway assert(peer_b != NULL); 292f579bf8eSKris Kennaway assert(peer_b->buf != NULL); 293f579bf8eSKris Kennaway 294f579bf8eSKris Kennaway peer_b->request = 0; 295f579bf8eSKris Kennaway 2966f9291ceSJung-uk Kim if (peer_b->len == 0) { 297f579bf8eSKris Kennaway char dummy; 298f579bf8eSKris Kennaway 299f579bf8eSKris Kennaway /* avoid code duplication -- nothing available for reading */ 300f579bf8eSKris Kennaway return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ 301f579bf8eSKris Kennaway } 302f579bf8eSKris Kennaway 303f579bf8eSKris Kennaway num = peer_b->len; 304f579bf8eSKris Kennaway if (peer_b->size < peer_b->offset + num) 305f579bf8eSKris Kennaway /* no ring buffer wrap-around for non-copying interface */ 306f579bf8eSKris Kennaway num = peer_b->size - peer_b->offset; 307f579bf8eSKris Kennaway assert(num > 0); 308f579bf8eSKris Kennaway 309f579bf8eSKris Kennaway if (buf != NULL) 310f579bf8eSKris Kennaway *buf = peer_b->buf + peer_b->offset; 311f579bf8eSKris Kennaway return num; 312f579bf8eSKris Kennaway } 313f579bf8eSKris Kennaway 3141f13597dSJung-uk Kim static ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_) 315f579bf8eSKris Kennaway { 316f579bf8eSKris Kennaway struct bio_bio_st *b, *peer_b; 3171f13597dSJung-uk Kim ossl_ssize_t num, available; 318f579bf8eSKris Kennaway 319f579bf8eSKris Kennaway if (num_ > SSIZE_MAX) 320f579bf8eSKris Kennaway num = SSIZE_MAX; 321f579bf8eSKris Kennaway else 3221f13597dSJung-uk Kim num = (ossl_ssize_t) num_; 323f579bf8eSKris Kennaway 324f579bf8eSKris Kennaway available = bio_nread0(bio, buf); 325f579bf8eSKris Kennaway if (num > available) 326f579bf8eSKris Kennaway num = available; 327f579bf8eSKris Kennaway if (num <= 0) 328f579bf8eSKris Kennaway return num; 329f579bf8eSKris Kennaway 330f579bf8eSKris Kennaway b = bio->ptr; 331f579bf8eSKris Kennaway peer_b = b->peer->ptr; 332f579bf8eSKris Kennaway 333f579bf8eSKris Kennaway peer_b->len -= num; 3346f9291ceSJung-uk Kim if (peer_b->len) { 335f579bf8eSKris Kennaway peer_b->offset += num; 336f579bf8eSKris Kennaway assert(peer_b->offset <= peer_b->size); 337f579bf8eSKris Kennaway if (peer_b->offset == peer_b->size) 338f579bf8eSKris Kennaway peer_b->offset = 0; 3396f9291ceSJung-uk Kim } else 340f579bf8eSKris Kennaway peer_b->offset = 0; 341f579bf8eSKris Kennaway 342f579bf8eSKris Kennaway return num; 343f579bf8eSKris Kennaway } 344f579bf8eSKris Kennaway 345ddd58736SKris Kennaway static int bio_write(BIO *bio, const char *buf, int num_) 34674664626SKris Kennaway { 34774664626SKris Kennaway size_t num = num_; 34874664626SKris Kennaway size_t rest; 34974664626SKris Kennaway struct bio_bio_st *b; 35074664626SKris Kennaway 35174664626SKris Kennaway BIO_clear_retry_flags(bio); 35274664626SKris Kennaway 35374664626SKris Kennaway if (!bio->init || buf == NULL || num == 0) 35474664626SKris Kennaway return 0; 35574664626SKris Kennaway 35674664626SKris Kennaway b = bio->ptr; 35774664626SKris Kennaway assert(b != NULL); 35874664626SKris Kennaway assert(b->peer != NULL); 35974664626SKris Kennaway assert(b->buf != NULL); 36074664626SKris Kennaway 36174664626SKris Kennaway b->request = 0; 3626f9291ceSJung-uk Kim if (b->closed) { 36374664626SKris Kennaway /* we already closed */ 36474664626SKris Kennaway BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); 36574664626SKris Kennaway return -1; 36674664626SKris Kennaway } 36774664626SKris Kennaway 36874664626SKris Kennaway assert(b->len <= b->size); 36974664626SKris Kennaway 3706f9291ceSJung-uk Kim if (b->len == b->size) { 37174664626SKris Kennaway BIO_set_retry_write(bio); /* buffer is full */ 37274664626SKris Kennaway return -1; 37374664626SKris Kennaway } 37474664626SKris Kennaway 37574664626SKris Kennaway /* we can write */ 37674664626SKris Kennaway if (num > b->size - b->len) 37774664626SKris Kennaway num = b->size - b->len; 37874664626SKris Kennaway 37974664626SKris Kennaway /* now write "num" bytes */ 38074664626SKris Kennaway 38174664626SKris Kennaway rest = num; 38274664626SKris Kennaway 38374664626SKris Kennaway assert(rest > 0); 3846f9291ceSJung-uk Kim do { /* one or two iterations */ 38574664626SKris Kennaway size_t write_offset; 38674664626SKris Kennaway size_t chunk; 38774664626SKris Kennaway 38874664626SKris Kennaway assert(b->len + rest <= b->size); 38974664626SKris Kennaway 39074664626SKris Kennaway write_offset = b->offset + b->len; 39174664626SKris Kennaway if (write_offset >= b->size) 39274664626SKris Kennaway write_offset -= b->size; 39374664626SKris Kennaway /* b->buf[write_offset] is the first byte we can write to. */ 39474664626SKris Kennaway 39574664626SKris Kennaway if (write_offset + rest <= b->size) 39674664626SKris Kennaway chunk = rest; 39774664626SKris Kennaway else 39874664626SKris Kennaway /* wrap around ring buffer */ 39974664626SKris Kennaway chunk = b->size - write_offset; 40074664626SKris Kennaway 40174664626SKris Kennaway memcpy(b->buf + write_offset, buf, chunk); 40274664626SKris Kennaway 40374664626SKris Kennaway b->len += chunk; 40474664626SKris Kennaway 40574664626SKris Kennaway assert(b->len <= b->size); 40674664626SKris Kennaway 40774664626SKris Kennaway rest -= chunk; 40874664626SKris Kennaway buf += chunk; 40974664626SKris Kennaway } 41074664626SKris Kennaway while (rest); 41174664626SKris Kennaway 41274664626SKris Kennaway return num; 41374664626SKris Kennaway } 41474664626SKris Kennaway 4156f9291ceSJung-uk Kim /*- 4166f9291ceSJung-uk Kim * non-copying interface: provide pointer to region to write to 417f579bf8eSKris Kennaway * bio_nwrite0: check how much space is available 418f579bf8eSKris Kennaway * bio_nwrite: also increase length 419f579bf8eSKris Kennaway * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() 420f579bf8eSKris Kennaway * or just bio_nwrite(), write to buffer) 421f579bf8eSKris Kennaway */ 4221f13597dSJung-uk Kim static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf) 423f579bf8eSKris Kennaway { 424f579bf8eSKris Kennaway struct bio_bio_st *b; 425f579bf8eSKris Kennaway size_t num; 426f579bf8eSKris Kennaway size_t write_offset; 427f579bf8eSKris Kennaway 428f579bf8eSKris Kennaway BIO_clear_retry_flags(bio); 429f579bf8eSKris Kennaway 430f579bf8eSKris Kennaway if (!bio->init) 431f579bf8eSKris Kennaway return 0; 432f579bf8eSKris Kennaway 433f579bf8eSKris Kennaway b = bio->ptr; 434f579bf8eSKris Kennaway assert(b != NULL); 435f579bf8eSKris Kennaway assert(b->peer != NULL); 436f579bf8eSKris Kennaway assert(b->buf != NULL); 437f579bf8eSKris Kennaway 438f579bf8eSKris Kennaway b->request = 0; 4396f9291ceSJung-uk Kim if (b->closed) { 440f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); 441f579bf8eSKris Kennaway return -1; 442f579bf8eSKris Kennaway } 443f579bf8eSKris Kennaway 444f579bf8eSKris Kennaway assert(b->len <= b->size); 445f579bf8eSKris Kennaway 4466f9291ceSJung-uk Kim if (b->len == b->size) { 447f579bf8eSKris Kennaway BIO_set_retry_write(bio); 448f579bf8eSKris Kennaway return -1; 449f579bf8eSKris Kennaway } 450f579bf8eSKris Kennaway 451f579bf8eSKris Kennaway num = b->size - b->len; 452f579bf8eSKris Kennaway write_offset = b->offset + b->len; 453f579bf8eSKris Kennaway if (write_offset >= b->size) 454f579bf8eSKris Kennaway write_offset -= b->size; 455f579bf8eSKris Kennaway if (write_offset + num > b->size) 4566f9291ceSJung-uk Kim /* 4576f9291ceSJung-uk Kim * no ring buffer wrap-around for non-copying interface (to fulfil 4586f9291ceSJung-uk Kim * the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have 4596f9291ceSJung-uk Kim * to be called twice) 4606f9291ceSJung-uk Kim */ 461f579bf8eSKris Kennaway num = b->size - write_offset; 462f579bf8eSKris Kennaway 463f579bf8eSKris Kennaway if (buf != NULL) 464f579bf8eSKris Kennaway *buf = b->buf + write_offset; 465f579bf8eSKris Kennaway assert(write_offset + num <= b->size); 466f579bf8eSKris Kennaway 467f579bf8eSKris Kennaway return num; 468f579bf8eSKris Kennaway } 469f579bf8eSKris Kennaway 4701f13597dSJung-uk Kim static ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) 471f579bf8eSKris Kennaway { 472f579bf8eSKris Kennaway struct bio_bio_st *b; 4731f13597dSJung-uk Kim ossl_ssize_t num, space; 474f579bf8eSKris Kennaway 475f579bf8eSKris Kennaway if (num_ > SSIZE_MAX) 476f579bf8eSKris Kennaway num = SSIZE_MAX; 477f579bf8eSKris Kennaway else 4781f13597dSJung-uk Kim num = (ossl_ssize_t) num_; 479f579bf8eSKris Kennaway 480f579bf8eSKris Kennaway space = bio_nwrite0(bio, buf); 481f579bf8eSKris Kennaway if (num > space) 482f579bf8eSKris Kennaway num = space; 483f579bf8eSKris Kennaway if (num <= 0) 484f579bf8eSKris Kennaway return num; 485f579bf8eSKris Kennaway b = bio->ptr; 486f579bf8eSKris Kennaway assert(b != NULL); 487f579bf8eSKris Kennaway b->len += num; 488f579bf8eSKris Kennaway assert(b->len <= b->size); 489f579bf8eSKris Kennaway 490f579bf8eSKris Kennaway return num; 491f579bf8eSKris Kennaway } 492f579bf8eSKris Kennaway 49374664626SKris Kennaway static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 49474664626SKris Kennaway { 49574664626SKris Kennaway long ret; 49674664626SKris Kennaway struct bio_bio_st *b = bio->ptr; 49774664626SKris Kennaway 49874664626SKris Kennaway assert(b != NULL); 49974664626SKris Kennaway 5006f9291ceSJung-uk Kim switch (cmd) { 50174664626SKris Kennaway /* specific CTRL codes */ 50274664626SKris Kennaway 50374664626SKris Kennaway case BIO_C_SET_WRITE_BUF_SIZE: 5046f9291ceSJung-uk Kim if (b->peer) { 50574664626SKris Kennaway BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); 50674664626SKris Kennaway ret = 0; 5076f9291ceSJung-uk Kim } else if (num == 0) { 50874664626SKris Kennaway BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); 50974664626SKris Kennaway ret = 0; 5106f9291ceSJung-uk Kim } else { 51174664626SKris Kennaway size_t new_size = num; 51274664626SKris Kennaway 5136f9291ceSJung-uk Kim if (b->size != new_size) { 5146f9291ceSJung-uk Kim if (b->buf) { 515ddd58736SKris Kennaway OPENSSL_free(b->buf); 51674664626SKris Kennaway b->buf = NULL; 51774664626SKris Kennaway } 51874664626SKris Kennaway b->size = new_size; 51974664626SKris Kennaway } 52074664626SKris Kennaway ret = 1; 52174664626SKris Kennaway } 52274664626SKris Kennaway break; 52374664626SKris Kennaway 52474664626SKris Kennaway case BIO_C_GET_WRITE_BUF_SIZE: 525a21b1b38SKris Kennaway ret = (long)b->size; 526a21b1b38SKris Kennaway break; 52774664626SKris Kennaway 52874664626SKris Kennaway case BIO_C_MAKE_BIO_PAIR: 52974664626SKris Kennaway { 53074664626SKris Kennaway BIO *other_bio = ptr; 53174664626SKris Kennaway 53274664626SKris Kennaway if (bio_make_pair(bio, other_bio)) 53374664626SKris Kennaway ret = 1; 53474664626SKris Kennaway else 53574664626SKris Kennaway ret = 0; 53674664626SKris Kennaway } 53774664626SKris Kennaway break; 53874664626SKris Kennaway 53974664626SKris Kennaway case BIO_C_DESTROY_BIO_PAIR: 5406f9291ceSJung-uk Kim /* 5416f9291ceSJung-uk Kim * Affects both BIOs in the pair -- call just once! Or let 5426f9291ceSJung-uk Kim * BIO_free(bio1); BIO_free(bio2); do the job. 5436f9291ceSJung-uk Kim */ 54474664626SKris Kennaway bio_destroy_pair(bio); 54574664626SKris Kennaway ret = 1; 54674664626SKris Kennaway break; 54774664626SKris Kennaway 54874664626SKris Kennaway case BIO_C_GET_WRITE_GUARANTEE: 5496f9291ceSJung-uk Kim /* 5506f9291ceSJung-uk Kim * How many bytes can the caller feed to the next write without 5516f9291ceSJung-uk Kim * having to keep any? 5526f9291ceSJung-uk Kim */ 55374664626SKris Kennaway if (b->peer == NULL || b->closed) 55474664626SKris Kennaway ret = 0; 55574664626SKris Kennaway else 55674664626SKris Kennaway ret = (long)b->size - b->len; 55774664626SKris Kennaway break; 55874664626SKris Kennaway 55974664626SKris Kennaway case BIO_C_GET_READ_REQUEST: 5606f9291ceSJung-uk Kim /* 5616f9291ceSJung-uk Kim * If the peer unsuccessfully tried to read, how many bytes were 5626f9291ceSJung-uk Kim * requested? (As with BIO_CTRL_PENDING, that number can usually be 5636f9291ceSJung-uk Kim * treated as boolean.) 5646f9291ceSJung-uk Kim */ 56574664626SKris Kennaway ret = (long)b->request; 56674664626SKris Kennaway break; 56774664626SKris Kennaway 568f579bf8eSKris Kennaway case BIO_C_RESET_READ_REQUEST: 5696f9291ceSJung-uk Kim /* 5706f9291ceSJung-uk Kim * Reset request. (Can be useful after read attempts at the other 5716f9291ceSJung-uk Kim * side that are meant to be non-blocking, e.g. when probing SSL_read 5726f9291ceSJung-uk Kim * to see if any data is available.) 5736f9291ceSJung-uk Kim */ 574f579bf8eSKris Kennaway b->request = 0; 575f579bf8eSKris Kennaway ret = 1; 576f579bf8eSKris Kennaway break; 577f579bf8eSKris Kennaway 57874664626SKris Kennaway case BIO_C_SHUTDOWN_WR: 57974664626SKris Kennaway /* similar to shutdown(..., SHUT_WR) */ 58074664626SKris Kennaway b->closed = 1; 58174664626SKris Kennaway ret = 1; 58274664626SKris Kennaway break; 58374664626SKris Kennaway 584f579bf8eSKris Kennaway case BIO_C_NREAD0: 585f579bf8eSKris Kennaway /* prepare for non-copying read */ 586f579bf8eSKris Kennaway ret = (long)bio_nread0(bio, ptr); 587f579bf8eSKris Kennaway break; 588f579bf8eSKris Kennaway 589f579bf8eSKris Kennaway case BIO_C_NREAD: 590f579bf8eSKris Kennaway /* non-copying read */ 591f579bf8eSKris Kennaway ret = (long)bio_nread(bio, ptr, (size_t)num); 592f579bf8eSKris Kennaway break; 593f579bf8eSKris Kennaway 594f579bf8eSKris Kennaway case BIO_C_NWRITE0: 595f579bf8eSKris Kennaway /* prepare for non-copying write */ 596f579bf8eSKris Kennaway ret = (long)bio_nwrite0(bio, ptr); 597f579bf8eSKris Kennaway break; 598f579bf8eSKris Kennaway 599f579bf8eSKris Kennaway case BIO_C_NWRITE: 600f579bf8eSKris Kennaway /* non-copying write */ 601f579bf8eSKris Kennaway ret = (long)bio_nwrite(bio, ptr, (size_t)num); 602f579bf8eSKris Kennaway break; 603f579bf8eSKris Kennaway 60474664626SKris Kennaway /* standard CTRL codes follow */ 60574664626SKris Kennaway 60674664626SKris Kennaway case BIO_CTRL_RESET: 6076f9291ceSJung-uk Kim if (b->buf != NULL) { 60874664626SKris Kennaway b->len = 0; 60974664626SKris Kennaway b->offset = 0; 61074664626SKris Kennaway } 61174664626SKris Kennaway ret = 0; 61274664626SKris Kennaway break; 61374664626SKris Kennaway 61474664626SKris Kennaway case BIO_CTRL_GET_CLOSE: 61574664626SKris Kennaway ret = bio->shutdown; 61674664626SKris Kennaway break; 61774664626SKris Kennaway 61874664626SKris Kennaway case BIO_CTRL_SET_CLOSE: 61974664626SKris Kennaway bio->shutdown = (int)num; 62074664626SKris Kennaway ret = 1; 62174664626SKris Kennaway break; 62274664626SKris Kennaway 62374664626SKris Kennaway case BIO_CTRL_PENDING: 6246f9291ceSJung-uk Kim if (b->peer != NULL) { 62574664626SKris Kennaway struct bio_bio_st *peer_b = b->peer->ptr; 62674664626SKris Kennaway 62774664626SKris Kennaway ret = (long)peer_b->len; 6286f9291ceSJung-uk Kim } else 62974664626SKris Kennaway ret = 0; 63074664626SKris Kennaway break; 63174664626SKris Kennaway 63274664626SKris Kennaway case BIO_CTRL_WPENDING: 63374664626SKris Kennaway if (b->buf != NULL) 63474664626SKris Kennaway ret = (long)b->len; 63574664626SKris Kennaway else 63674664626SKris Kennaway ret = 0; 63774664626SKris Kennaway break; 63874664626SKris Kennaway 63974664626SKris Kennaway case BIO_CTRL_DUP: 64074664626SKris Kennaway /* See BIO_dup_chain for circumstances we have to expect. */ 64174664626SKris Kennaway { 64274664626SKris Kennaway BIO *other_bio = ptr; 64374664626SKris Kennaway struct bio_bio_st *other_b; 64474664626SKris Kennaway 64574664626SKris Kennaway assert(other_bio != NULL); 64674664626SKris Kennaway other_b = other_bio->ptr; 64774664626SKris Kennaway assert(other_b != NULL); 64874664626SKris Kennaway 64974664626SKris Kennaway assert(other_b->buf == NULL); /* other_bio is always fresh */ 65074664626SKris Kennaway 65174664626SKris Kennaway other_b->size = b->size; 65274664626SKris Kennaway } 65374664626SKris Kennaway 65474664626SKris Kennaway ret = 1; 65574664626SKris Kennaway break; 65674664626SKris Kennaway 65774664626SKris Kennaway case BIO_CTRL_FLUSH: 65874664626SKris Kennaway ret = 1; 65974664626SKris Kennaway break; 66074664626SKris Kennaway 66174664626SKris Kennaway case BIO_CTRL_EOF: 662*aeb5019cSJung-uk Kim if (b->peer != NULL) { 663*aeb5019cSJung-uk Kim struct bio_bio_st *peer_b = b->peer->ptr; 66474664626SKris Kennaway 665*aeb5019cSJung-uk Kim if (peer_b->len == 0 && peer_b->closed) 666*aeb5019cSJung-uk Kim ret = 1; 667*aeb5019cSJung-uk Kim else 668*aeb5019cSJung-uk Kim ret = 0; 669*aeb5019cSJung-uk Kim } else { 67074664626SKris Kennaway ret = 1; 67174664626SKris Kennaway } 67274664626SKris Kennaway break; 67374664626SKris Kennaway 67474664626SKris Kennaway default: 67574664626SKris Kennaway ret = 0; 67674664626SKris Kennaway } 67774664626SKris Kennaway return ret; 67874664626SKris Kennaway } 67974664626SKris Kennaway 680ddd58736SKris Kennaway static int bio_puts(BIO *bio, const char *str) 68174664626SKris Kennaway { 68274664626SKris Kennaway return bio_write(bio, str, strlen(str)); 68374664626SKris Kennaway } 68474664626SKris Kennaway 68574664626SKris Kennaway static int bio_make_pair(BIO *bio1, BIO *bio2) 68674664626SKris Kennaway { 68774664626SKris Kennaway struct bio_bio_st *b1, *b2; 68874664626SKris Kennaway 68974664626SKris Kennaway assert(bio1 != NULL); 69074664626SKris Kennaway assert(bio2 != NULL); 69174664626SKris Kennaway 69274664626SKris Kennaway b1 = bio1->ptr; 69374664626SKris Kennaway b2 = bio2->ptr; 69474664626SKris Kennaway 6956f9291ceSJung-uk Kim if (b1->peer != NULL || b2->peer != NULL) { 69674664626SKris Kennaway BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); 69774664626SKris Kennaway return 0; 69874664626SKris Kennaway } 69974664626SKris Kennaway 7006f9291ceSJung-uk Kim if (b1->buf == NULL) { 701ddd58736SKris Kennaway b1->buf = OPENSSL_malloc(b1->size); 7026f9291ceSJung-uk Kim if (b1->buf == NULL) { 70374664626SKris Kennaway BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 70474664626SKris Kennaway return 0; 70574664626SKris Kennaway } 70674664626SKris Kennaway b1->len = 0; 70774664626SKris Kennaway b1->offset = 0; 70874664626SKris Kennaway } 70974664626SKris Kennaway 7106f9291ceSJung-uk Kim if (b2->buf == NULL) { 711ddd58736SKris Kennaway b2->buf = OPENSSL_malloc(b2->size); 7126f9291ceSJung-uk Kim if (b2->buf == NULL) { 71374664626SKris Kennaway BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 71474664626SKris Kennaway return 0; 71574664626SKris Kennaway } 71674664626SKris Kennaway b2->len = 0; 71774664626SKris Kennaway b2->offset = 0; 71874664626SKris Kennaway } 71974664626SKris Kennaway 72074664626SKris Kennaway b1->peer = bio2; 72174664626SKris Kennaway b1->closed = 0; 72274664626SKris Kennaway b1->request = 0; 72374664626SKris Kennaway b2->peer = bio1; 72474664626SKris Kennaway b2->closed = 0; 72574664626SKris Kennaway b2->request = 0; 72674664626SKris Kennaway 72774664626SKris Kennaway bio1->init = 1; 72874664626SKris Kennaway bio2->init = 1; 72974664626SKris Kennaway 73074664626SKris Kennaway return 1; 73174664626SKris Kennaway } 73274664626SKris Kennaway 73374664626SKris Kennaway static void bio_destroy_pair(BIO *bio) 73474664626SKris Kennaway { 73574664626SKris Kennaway struct bio_bio_st *b = bio->ptr; 73674664626SKris Kennaway 7376f9291ceSJung-uk Kim if (b != NULL) { 73874664626SKris Kennaway BIO *peer_bio = b->peer; 73974664626SKris Kennaway 7406f9291ceSJung-uk Kim if (peer_bio != NULL) { 74174664626SKris Kennaway struct bio_bio_st *peer_b = peer_bio->ptr; 74274664626SKris Kennaway 74374664626SKris Kennaway assert(peer_b != NULL); 74474664626SKris Kennaway assert(peer_b->peer == bio); 74574664626SKris Kennaway 74674664626SKris Kennaway peer_b->peer = NULL; 74774664626SKris Kennaway peer_bio->init = 0; 74874664626SKris Kennaway assert(peer_b->buf != NULL); 74974664626SKris Kennaway peer_b->len = 0; 75074664626SKris Kennaway peer_b->offset = 0; 75174664626SKris Kennaway 75274664626SKris Kennaway b->peer = NULL; 75374664626SKris Kennaway bio->init = 0; 75474664626SKris Kennaway assert(b->buf != NULL); 75574664626SKris Kennaway b->len = 0; 75674664626SKris Kennaway b->offset = 0; 75774664626SKris Kennaway } 75874664626SKris Kennaway } 75974664626SKris Kennaway } 76074664626SKris Kennaway 76174664626SKris Kennaway /* Exported convenience functions */ 76274664626SKris Kennaway int BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, 76374664626SKris Kennaway BIO **bio2_p, size_t writebuf2) 76474664626SKris Kennaway { 76574664626SKris Kennaway BIO *bio1 = NULL, *bio2 = NULL; 76674664626SKris Kennaway long r; 76774664626SKris Kennaway int ret = 0; 76874664626SKris Kennaway 76974664626SKris Kennaway bio1 = BIO_new(BIO_s_bio()); 77074664626SKris Kennaway if (bio1 == NULL) 77174664626SKris Kennaway goto err; 77274664626SKris Kennaway bio2 = BIO_new(BIO_s_bio()); 77374664626SKris Kennaway if (bio2 == NULL) 77474664626SKris Kennaway goto err; 77574664626SKris Kennaway 7766f9291ceSJung-uk Kim if (writebuf1) { 77774664626SKris Kennaway r = BIO_set_write_buf_size(bio1, writebuf1); 77874664626SKris Kennaway if (!r) 77974664626SKris Kennaway goto err; 78074664626SKris Kennaway } 7816f9291ceSJung-uk Kim if (writebuf2) { 78274664626SKris Kennaway r = BIO_set_write_buf_size(bio2, writebuf2); 78374664626SKris Kennaway if (!r) 78474664626SKris Kennaway goto err; 78574664626SKris Kennaway } 78674664626SKris Kennaway 78774664626SKris Kennaway r = BIO_make_bio_pair(bio1, bio2); 78874664626SKris Kennaway if (!r) 78974664626SKris Kennaway goto err; 79074664626SKris Kennaway ret = 1; 79174664626SKris Kennaway 79274664626SKris Kennaway err: 7936f9291ceSJung-uk Kim if (ret == 0) { 7946f9291ceSJung-uk Kim if (bio1) { 79574664626SKris Kennaway BIO_free(bio1); 79674664626SKris Kennaway bio1 = NULL; 79774664626SKris Kennaway } 7986f9291ceSJung-uk Kim if (bio2) { 79974664626SKris Kennaway BIO_free(bio2); 80074664626SKris Kennaway bio2 = NULL; 80174664626SKris Kennaway } 80274664626SKris Kennaway } 80374664626SKris Kennaway 80474664626SKris Kennaway *bio1_p = bio1; 80574664626SKris Kennaway *bio2_p = bio2; 80674664626SKris Kennaway return ret; 80774664626SKris Kennaway } 80874664626SKris Kennaway 80974664626SKris Kennaway size_t BIO_ctrl_get_write_guarantee(BIO *bio) 81074664626SKris Kennaway { 81174664626SKris Kennaway return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 81274664626SKris Kennaway } 81374664626SKris Kennaway 81474664626SKris Kennaway size_t BIO_ctrl_get_read_request(BIO *bio) 81574664626SKris Kennaway { 81674664626SKris Kennaway return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 81774664626SKris Kennaway } 818f579bf8eSKris Kennaway 819f579bf8eSKris Kennaway int BIO_ctrl_reset_read_request(BIO *bio) 820f579bf8eSKris Kennaway { 821f579bf8eSKris Kennaway return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); 822f579bf8eSKris Kennaway } 823f579bf8eSKris Kennaway 8246f9291ceSJung-uk Kim /* 8256f9291ceSJung-uk Kim * BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now 8266f9291ceSJung-uk Kim * (conceivably some other BIOs could allow non-copying reads and writes 8276f9291ceSJung-uk Kim * too.) 828f579bf8eSKris Kennaway */ 829f579bf8eSKris Kennaway int BIO_nread0(BIO *bio, char **buf) 830f579bf8eSKris Kennaway { 831f579bf8eSKris Kennaway long ret; 832f579bf8eSKris Kennaway 8336f9291ceSJung-uk Kim if (!bio->init) { 834f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); 835f579bf8eSKris Kennaway return -2; 836f579bf8eSKris Kennaway } 837f579bf8eSKris Kennaway 838f579bf8eSKris Kennaway ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); 839f579bf8eSKris Kennaway if (ret > INT_MAX) 840f579bf8eSKris Kennaway return INT_MAX; 841f579bf8eSKris Kennaway else 842f579bf8eSKris Kennaway return (int)ret; 843f579bf8eSKris Kennaway } 844f579bf8eSKris Kennaway 845f579bf8eSKris Kennaway int BIO_nread(BIO *bio, char **buf, int num) 846f579bf8eSKris Kennaway { 847f579bf8eSKris Kennaway int ret; 848f579bf8eSKris Kennaway 8496f9291ceSJung-uk Kim if (!bio->init) { 850f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); 851f579bf8eSKris Kennaway return -2; 852f579bf8eSKris Kennaway } 853f579bf8eSKris Kennaway 854f579bf8eSKris Kennaway ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf); 855f579bf8eSKris Kennaway if (ret > 0) 856f579bf8eSKris Kennaway bio->num_read += ret; 857f579bf8eSKris Kennaway return ret; 858f579bf8eSKris Kennaway } 859f579bf8eSKris Kennaway 860f579bf8eSKris Kennaway int BIO_nwrite0(BIO *bio, char **buf) 861f579bf8eSKris Kennaway { 862f579bf8eSKris Kennaway long ret; 863f579bf8eSKris Kennaway 8646f9291ceSJung-uk Kim if (!bio->init) { 865f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); 866f579bf8eSKris Kennaway return -2; 867f579bf8eSKris Kennaway } 868f579bf8eSKris Kennaway 869f579bf8eSKris Kennaway ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); 870f579bf8eSKris Kennaway if (ret > INT_MAX) 871f579bf8eSKris Kennaway return INT_MAX; 872f579bf8eSKris Kennaway else 873f579bf8eSKris Kennaway return (int)ret; 874f579bf8eSKris Kennaway } 875f579bf8eSKris Kennaway 876f579bf8eSKris Kennaway int BIO_nwrite(BIO *bio, char **buf, int num) 877f579bf8eSKris Kennaway { 878f579bf8eSKris Kennaway int ret; 879f579bf8eSKris Kennaway 8806f9291ceSJung-uk Kim if (!bio->init) { 881f579bf8eSKris Kennaway BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); 882f579bf8eSKris Kennaway return -2; 883f579bf8eSKris Kennaway } 884f579bf8eSKris Kennaway 885f579bf8eSKris Kennaway ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); 886f579bf8eSKris Kennaway if (ret > 0) 887db522d3aSSimon L. B. Nielsen bio->num_write += ret; 888f579bf8eSKris Kennaway return ret; 889f579bf8eSKris Kennaway } 890