bss_bio.c revision 120631
155714Skris/* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ 2120631Snectar/* ==================================================================== 3120631Snectar * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 4120631Snectar * 5120631Snectar * Redistribution and use in source and binary forms, with or without 6120631Snectar * modification, are permitted provided that the following conditions 7120631Snectar * are met: 8120631Snectar * 9120631Snectar * 1. Redistributions of source code must retain the above copyright 10120631Snectar * notice, this list of conditions and the following disclaimer. 11120631Snectar * 12120631Snectar * 2. Redistributions in binary form must reproduce the above copyright 13120631Snectar * notice, this list of conditions and the following disclaimer in 14120631Snectar * the documentation and/or other materials provided with the 15120631Snectar * distribution. 16120631Snectar * 17120631Snectar * 3. All advertising materials mentioning features or use of this 18120631Snectar * software must display the following acknowledgment: 19120631Snectar * "This product includes software developed by the OpenSSL Project 20120631Snectar * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21120631Snectar * 22120631Snectar * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23120631Snectar * endorse or promote products derived from this software without 24120631Snectar * prior written permission. For written permission, please contact 25120631Snectar * openssl-core@openssl.org. 26120631Snectar * 27120631Snectar * 5. Products derived from this software may not be called "OpenSSL" 28120631Snectar * nor may "OpenSSL" appear in their names without prior written 29120631Snectar * permission of the OpenSSL Project. 30120631Snectar * 31120631Snectar * 6. Redistributions of any form whatsoever must retain the following 32120631Snectar * acknowledgment: 33120631Snectar * "This product includes software developed by the OpenSSL Project 34120631Snectar * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35120631Snectar * 36120631Snectar * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37120631Snectar * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38120631Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39120631Snectar * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40120631Snectar * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41120631Snectar * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42120631Snectar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43120631Snectar * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44120631Snectar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45120631Snectar * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46120631Snectar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47120631Snectar * OF THE POSSIBILITY OF SUCH DAMAGE. 48120631Snectar * ==================================================================== 49120631Snectar * 50120631Snectar * This product includes cryptographic software written by Eric Young 51120631Snectar * (eay@cryptsoft.com). This product includes software written by Tim 52120631Snectar * Hudson (tjh@cryptsoft.com). 53120631Snectar * 54120631Snectar */ 5555714Skris 5655714Skris/* Special method for a BIO where the other endpoint is also a BIO 5755714Skris * of this kind, handled by the same thread (i.e. the "peer" is actually 5855714Skris * ourselves, wearing a different hat). 5955714Skris * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces 6055714Skris * for which no specific BIO method is available. 6155714Skris * See ssl/ssltest.c for some hints on how this can be used. */ 6255714Skris 63100936Snectar/* BIO_DEBUG implies BIO_PAIR_DEBUG */ 64100936Snectar#ifdef BIO_DEBUG 65100936Snectar# ifndef BIO_PAIR_DEBUG 66100936Snectar# define BIO_PAIR_DEBUG 67100936Snectar# endif 68100936Snectar#endif 69100936Snectar 70100936Snectar/* disable assert() unless BIO_PAIR_DEBUG has been defined */ 7155714Skris#ifndef BIO_PAIR_DEBUG 72100936Snectar# ifndef NDEBUG 73100936Snectar# define NDEBUG 74100936Snectar# endif 7555714Skris#endif 7655714Skris 7755714Skris#include <assert.h> 7859191Skris#include <limits.h> 7955714Skris#include <stdlib.h> 8055714Skris#include <string.h> 8155714Skris 8255714Skris#include <openssl/bio.h> 8355714Skris#include <openssl/err.h> 8455714Skris#include <openssl/crypto.h> 8555714Skris 86109998Smarkm#include "e_os.h" 87100928Snectar 88109998Smarkm/* VxWorks defines SSIZE_MAX with an empty value causing compile errors */ 89109998Smarkm#if defined(OPENSSL_SYS_VXWORKS) 90100928Snectar# undef SSIZE_MAX 91109998Smarkm#endif 92109998Smarkm#ifndef SSIZE_MAX 9359191Skris# define SSIZE_MAX INT_MAX 9459191Skris#endif 9559191Skris 9655714Skrisstatic int bio_new(BIO *bio); 9755714Skrisstatic int bio_free(BIO *bio); 9855714Skrisstatic int bio_read(BIO *bio, char *buf, int size); 9968651Skrisstatic int bio_write(BIO *bio, const char *buf, int num); 10055714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); 10168651Skrisstatic int bio_puts(BIO *bio, const char *str); 10255714Skris 10355714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2); 10455714Skrisstatic void bio_destroy_pair(BIO *bio); 10555714Skris 10655714Skrisstatic BIO_METHOD methods_biop = 10755714Skris{ 10855714Skris BIO_TYPE_BIO, 10955714Skris "BIO pair", 11055714Skris bio_write, 11155714Skris bio_read, 11255714Skris bio_puts, 11355714Skris NULL /* no bio_gets */, 11455714Skris bio_ctrl, 11555714Skris bio_new, 11659191Skris bio_free, 11759191Skris NULL /* no bio_callback_ctrl */ 11855714Skris}; 11955714Skris 12055714SkrisBIO_METHOD *BIO_s_bio(void) 12155714Skris { 12255714Skris return &methods_biop; 12355714Skris } 12455714Skris 12555714Skrisstruct bio_bio_st 12655714Skris{ 12755714Skris BIO *peer; /* NULL if buf == NULL. 12855714Skris * If peer != NULL, then peer->ptr is also a bio_bio_st, 12955714Skris * and its "peer" member points back to us. 13055714Skris * peer != NULL iff init != 0 in the BIO. */ 13155714Skris 13255714Skris /* This is for what we write (i.e. reading uses peer's struct): */ 13355714Skris int closed; /* valid iff peer != NULL */ 13455714Skris size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ 13555714Skris size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ 13655714Skris size_t size; 13755714Skris char *buf; /* "size" elements (if != NULL) */ 13855714Skris 13955714Skris size_t request; /* valid iff peer != NULL; 0 if len != 0, 14055714Skris * otherwise set by peer to number of bytes 14159191Skris * it (unsuccessfully) tried to read, 14255714Skris * never more than buffer space (size-len) warrants. */ 14355714Skris}; 14455714Skris 14555714Skrisstatic int bio_new(BIO *bio) 14655714Skris { 14755714Skris struct bio_bio_st *b; 14855714Skris 14968651Skris b = OPENSSL_malloc(sizeof *b); 15055714Skris if (b == NULL) 15155714Skris return 0; 15255714Skris 15355714Skris b->peer = NULL; 15455714Skris b->size = 17*1024; /* enough for one TLS record (just a default) */ 15555714Skris b->buf = NULL; 15655714Skris 15755714Skris bio->ptr = b; 15855714Skris return 1; 15955714Skris } 16055714Skris 16155714Skris 16255714Skrisstatic int bio_free(BIO *bio) 16355714Skris { 16455714Skris struct bio_bio_st *b; 16555714Skris 16655714Skris if (bio == NULL) 16755714Skris return 0; 16855714Skris b = bio->ptr; 16955714Skris 17055714Skris assert(b != NULL); 17155714Skris 17255714Skris if (b->peer) 17355714Skris bio_destroy_pair(bio); 17455714Skris 17555714Skris if (b->buf != NULL) 17655714Skris { 17768651Skris OPENSSL_free(b->buf); 17855714Skris } 17955714Skris 18068651Skris OPENSSL_free(b); 18155714Skris 18255714Skris return 1; 18355714Skris } 18455714Skris 18555714Skris 18655714Skris 18755714Skrisstatic int bio_read(BIO *bio, char *buf, int size_) 18855714Skris { 18955714Skris size_t size = size_; 19055714Skris size_t rest; 19155714Skris struct bio_bio_st *b, *peer_b; 19255714Skris 19355714Skris BIO_clear_retry_flags(bio); 19455714Skris 19555714Skris if (!bio->init) 19655714Skris return 0; 19755714Skris 19855714Skris b = bio->ptr; 19955714Skris assert(b != NULL); 20055714Skris assert(b->peer != NULL); 20155714Skris peer_b = b->peer->ptr; 20255714Skris assert(peer_b != NULL); 20355714Skris assert(peer_b->buf != NULL); 20455714Skris 20555714Skris peer_b->request = 0; /* will be set in "retry_read" situation */ 20655714Skris 20755714Skris if (buf == NULL || size == 0) 20855714Skris return 0; 20955714Skris 21055714Skris if (peer_b->len == 0) 21155714Skris { 21255714Skris if (peer_b->closed) 21355714Skris return 0; /* writer has closed, and no data is left */ 21455714Skris else 21555714Skris { 21655714Skris BIO_set_retry_read(bio); /* buffer is empty */ 21755714Skris if (size <= peer_b->size) 21855714Skris peer_b->request = size; 21955714Skris else 22055714Skris /* don't ask for more than the peer can 22155714Skris * deliver in one write */ 22255714Skris peer_b->request = peer_b->size; 22355714Skris return -1; 22455714Skris } 22555714Skris } 22655714Skris 22755714Skris /* we can read */ 22855714Skris if (peer_b->len < size) 22955714Skris size = peer_b->len; 23055714Skris 23155714Skris /* now read "size" bytes */ 23255714Skris 23355714Skris rest = size; 23455714Skris 23555714Skris assert(rest > 0); 23655714Skris do /* one or two iterations */ 23755714Skris { 23855714Skris size_t chunk; 23955714Skris 24055714Skris assert(rest <= peer_b->len); 24155714Skris if (peer_b->offset + rest <= peer_b->size) 24255714Skris chunk = rest; 24355714Skris else 24455714Skris /* wrap around ring buffer */ 24555714Skris chunk = peer_b->size - peer_b->offset; 24655714Skris assert(peer_b->offset + chunk <= peer_b->size); 24755714Skris 24855714Skris memcpy(buf, peer_b->buf + peer_b->offset, chunk); 24955714Skris 25055714Skris peer_b->len -= chunk; 25155714Skris if (peer_b->len) 25255714Skris { 25355714Skris peer_b->offset += chunk; 25455714Skris assert(peer_b->offset <= peer_b->size); 25555714Skris if (peer_b->offset == peer_b->size) 25655714Skris peer_b->offset = 0; 25755714Skris buf += chunk; 25855714Skris } 25955714Skris else 26055714Skris { 26155714Skris /* buffer now empty, no need to advance "buf" */ 26255714Skris assert(chunk == rest); 26355714Skris peer_b->offset = 0; 26455714Skris } 26555714Skris rest -= chunk; 26655714Skris } 26755714Skris while (rest); 26855714Skris 26955714Skris return size; 27055714Skris } 27155714Skris 27259191Skris/* non-copying interface: provide pointer to available data in buffer 27359191Skris * bio_nread0: return number of available bytes 27459191Skris * bio_nread: also advance index 27559191Skris * (example usage: bio_nread0(), read from buffer, bio_nread() 27659191Skris * or just bio_nread(), read from buffer) 27759191Skris */ 27859191Skris/* WARNING: The non-copying interface is largely untested as of yet 27959191Skris * and may contain bugs. */ 28059191Skrisstatic ssize_t bio_nread0(BIO *bio, char **buf) 28159191Skris { 28259191Skris struct bio_bio_st *b, *peer_b; 28359191Skris ssize_t num; 28459191Skris 28559191Skris BIO_clear_retry_flags(bio); 28659191Skris 28759191Skris if (!bio->init) 28859191Skris return 0; 28959191Skris 29059191Skris b = bio->ptr; 29159191Skris assert(b != NULL); 29259191Skris assert(b->peer != NULL); 29359191Skris peer_b = b->peer->ptr; 29459191Skris assert(peer_b != NULL); 29559191Skris assert(peer_b->buf != NULL); 29659191Skris 29759191Skris peer_b->request = 0; 29859191Skris 29959191Skris if (peer_b->len == 0) 30059191Skris { 30159191Skris char dummy; 30259191Skris 30359191Skris /* avoid code duplication -- nothing available for reading */ 30459191Skris return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ 30559191Skris } 30659191Skris 30759191Skris num = peer_b->len; 30859191Skris if (peer_b->size < peer_b->offset + num) 30959191Skris /* no ring buffer wrap-around for non-copying interface */ 31059191Skris num = peer_b->size - peer_b->offset; 31159191Skris assert(num > 0); 31259191Skris 31359191Skris if (buf != NULL) 31459191Skris *buf = peer_b->buf + peer_b->offset; 31559191Skris return num; 31659191Skris } 31759191Skris 31859191Skrisstatic ssize_t bio_nread(BIO *bio, char **buf, size_t num_) 31959191Skris { 32059191Skris struct bio_bio_st *b, *peer_b; 32159191Skris ssize_t num, available; 32259191Skris 32359191Skris if (num_ > SSIZE_MAX) 32459191Skris num = SSIZE_MAX; 32559191Skris else 32659191Skris num = (ssize_t)num_; 32759191Skris 32859191Skris available = bio_nread0(bio, buf); 32959191Skris if (num > available) 33059191Skris num = available; 33159191Skris if (num <= 0) 33259191Skris return num; 33359191Skris 33459191Skris b = bio->ptr; 33559191Skris peer_b = b->peer->ptr; 33659191Skris 33759191Skris peer_b->len -= num; 33859191Skris if (peer_b->len) 33959191Skris { 34059191Skris peer_b->offset += num; 34159191Skris assert(peer_b->offset <= peer_b->size); 34259191Skris if (peer_b->offset == peer_b->size) 34359191Skris peer_b->offset = 0; 34459191Skris } 34559191Skris else 34659191Skris peer_b->offset = 0; 34759191Skris 34859191Skris return num; 34959191Skris } 35059191Skris 35159191Skris 35268651Skrisstatic int bio_write(BIO *bio, const char *buf, int num_) 35355714Skris { 35455714Skris size_t num = num_; 35555714Skris size_t rest; 35655714Skris struct bio_bio_st *b; 35755714Skris 35855714Skris BIO_clear_retry_flags(bio); 35955714Skris 36055714Skris if (!bio->init || buf == NULL || num == 0) 36155714Skris return 0; 36255714Skris 36355714Skris b = bio->ptr; 36455714Skris assert(b != NULL); 36555714Skris assert(b->peer != NULL); 36655714Skris assert(b->buf != NULL); 36755714Skris 36855714Skris b->request = 0; 36955714Skris if (b->closed) 37055714Skris { 37155714Skris /* we already closed */ 37255714Skris BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); 37355714Skris return -1; 37455714Skris } 37555714Skris 37655714Skris assert(b->len <= b->size); 37755714Skris 37855714Skris if (b->len == b->size) 37955714Skris { 38055714Skris BIO_set_retry_write(bio); /* buffer is full */ 38155714Skris return -1; 38255714Skris } 38355714Skris 38455714Skris /* we can write */ 38555714Skris if (num > b->size - b->len) 38655714Skris num = b->size - b->len; 38755714Skris 38855714Skris /* now write "num" bytes */ 38955714Skris 39055714Skris rest = num; 39155714Skris 39255714Skris assert(rest > 0); 39355714Skris do /* one or two iterations */ 39455714Skris { 39555714Skris size_t write_offset; 39655714Skris size_t chunk; 39755714Skris 39855714Skris assert(b->len + rest <= b->size); 39955714Skris 40055714Skris write_offset = b->offset + b->len; 40155714Skris if (write_offset >= b->size) 40255714Skris write_offset -= b->size; 40355714Skris /* b->buf[write_offset] is the first byte we can write to. */ 40455714Skris 40555714Skris if (write_offset + rest <= b->size) 40655714Skris chunk = rest; 40755714Skris else 40855714Skris /* wrap around ring buffer */ 40955714Skris chunk = b->size - write_offset; 41055714Skris 41155714Skris memcpy(b->buf + write_offset, buf, chunk); 41255714Skris 41355714Skris b->len += chunk; 41455714Skris 41555714Skris assert(b->len <= b->size); 41655714Skris 41755714Skris rest -= chunk; 41855714Skris buf += chunk; 41955714Skris } 42055714Skris while (rest); 42155714Skris 42255714Skris return num; 42355714Skris } 42455714Skris 42559191Skris/* non-copying interface: provide pointer to region to write to 42659191Skris * bio_nwrite0: check how much space is available 42759191Skris * bio_nwrite: also increase length 42859191Skris * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() 42959191Skris * or just bio_nwrite(), write to buffer) 43059191Skris */ 43159191Skrisstatic ssize_t bio_nwrite0(BIO *bio, char **buf) 43259191Skris { 43359191Skris struct bio_bio_st *b; 43459191Skris size_t num; 43559191Skris size_t write_offset; 43655714Skris 43759191Skris BIO_clear_retry_flags(bio); 43859191Skris 43959191Skris if (!bio->init) 44059191Skris return 0; 44159191Skris 44259191Skris b = bio->ptr; 44359191Skris assert(b != NULL); 44459191Skris assert(b->peer != NULL); 44559191Skris assert(b->buf != NULL); 44659191Skris 44759191Skris b->request = 0; 44859191Skris if (b->closed) 44959191Skris { 45059191Skris BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); 45159191Skris return -1; 45259191Skris } 45359191Skris 45459191Skris assert(b->len <= b->size); 45559191Skris 45659191Skris if (b->len == b->size) 45759191Skris { 45859191Skris BIO_set_retry_write(bio); 45959191Skris return -1; 46059191Skris } 46159191Skris 46259191Skris num = b->size - b->len; 46359191Skris write_offset = b->offset + b->len; 46459191Skris if (write_offset >= b->size) 46559191Skris write_offset -= b->size; 46659191Skris if (write_offset + num > b->size) 46759191Skris /* no ring buffer wrap-around for non-copying interface 46859191Skris * (to fulfil the promise by BIO_ctrl_get_write_guarantee, 46959191Skris * BIO_nwrite may have to be called twice) */ 47059191Skris num = b->size - write_offset; 47159191Skris 47259191Skris if (buf != NULL) 47359191Skris *buf = b->buf + write_offset; 47459191Skris assert(write_offset + num <= b->size); 47559191Skris 47659191Skris return num; 47759191Skris } 47859191Skris 47959191Skrisstatic ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) 48059191Skris { 48159191Skris struct bio_bio_st *b; 48259191Skris ssize_t num, space; 48359191Skris 48459191Skris if (num_ > SSIZE_MAX) 48559191Skris num = SSIZE_MAX; 48659191Skris else 48759191Skris num = (ssize_t)num_; 48859191Skris 48959191Skris space = bio_nwrite0(bio, buf); 49059191Skris if (num > space) 49159191Skris num = space; 49259191Skris if (num <= 0) 49359191Skris return num; 49459191Skris b = bio->ptr; 49559191Skris assert(b != NULL); 49659191Skris b->len += num; 49759191Skris assert(b->len <= b->size); 49859191Skris 49959191Skris return num; 50059191Skris } 50159191Skris 50259191Skris 50355714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 50455714Skris { 50555714Skris long ret; 50655714Skris struct bio_bio_st *b = bio->ptr; 50755714Skris 50855714Skris assert(b != NULL); 50955714Skris 51055714Skris switch (cmd) 51155714Skris { 51255714Skris /* specific CTRL codes */ 51355714Skris 51455714Skris case BIO_C_SET_WRITE_BUF_SIZE: 51555714Skris if (b->peer) 51655714Skris { 51755714Skris BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); 51855714Skris ret = 0; 51955714Skris } 52055714Skris else if (num == 0) 52155714Skris { 52255714Skris BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); 52355714Skris ret = 0; 52455714Skris } 52555714Skris else 52655714Skris { 52755714Skris size_t new_size = num; 52855714Skris 52955714Skris if (b->size != new_size) 53055714Skris { 53155714Skris if (b->buf) 53255714Skris { 53368651Skris OPENSSL_free(b->buf); 53455714Skris b->buf = NULL; 53555714Skris } 53655714Skris b->size = new_size; 53755714Skris } 53855714Skris ret = 1; 53955714Skris } 54055714Skris break; 54155714Skris 54255714Skris case BIO_C_GET_WRITE_BUF_SIZE: 54389837Skris ret = (long) b->size; 54489837Skris break; 54555714Skris 54655714Skris case BIO_C_MAKE_BIO_PAIR: 54755714Skris { 54855714Skris BIO *other_bio = ptr; 54955714Skris 55055714Skris if (bio_make_pair(bio, other_bio)) 55155714Skris ret = 1; 55255714Skris else 55355714Skris ret = 0; 55455714Skris } 55555714Skris break; 55655714Skris 55755714Skris case BIO_C_DESTROY_BIO_PAIR: 558120631Snectar /* Affects both BIOs in the pair -- call just once! 55955714Skris * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ 56055714Skris bio_destroy_pair(bio); 56155714Skris ret = 1; 56255714Skris break; 56355714Skris 56455714Skris case BIO_C_GET_WRITE_GUARANTEE: 56555714Skris /* How many bytes can the caller feed to the next write 56659191Skris * without having to keep any? */ 56755714Skris if (b->peer == NULL || b->closed) 56855714Skris ret = 0; 56955714Skris else 57055714Skris ret = (long) b->size - b->len; 57155714Skris break; 57255714Skris 57355714Skris case BIO_C_GET_READ_REQUEST: 57459191Skris /* If the peer unsuccessfully tried to read, how many bytes 57555714Skris * were requested? (As with BIO_CTRL_PENDING, that number 57655714Skris * can usually be treated as boolean.) */ 57755714Skris ret = (long) b->request; 57855714Skris break; 57955714Skris 58059191Skris case BIO_C_RESET_READ_REQUEST: 58159191Skris /* Reset request. (Can be useful after read attempts 58259191Skris * at the other side that are meant to be non-blocking, 58359191Skris * e.g. when probing SSL_read to see if any data is 58459191Skris * available.) */ 58559191Skris b->request = 0; 58659191Skris ret = 1; 58759191Skris break; 58859191Skris 58955714Skris case BIO_C_SHUTDOWN_WR: 59055714Skris /* similar to shutdown(..., SHUT_WR) */ 59155714Skris b->closed = 1; 59255714Skris ret = 1; 59355714Skris break; 59455714Skris 59559191Skris case BIO_C_NREAD0: 59659191Skris /* prepare for non-copying read */ 59759191Skris ret = (long) bio_nread0(bio, ptr); 59859191Skris break; 59959191Skris 60059191Skris case BIO_C_NREAD: 60159191Skris /* non-copying read */ 60259191Skris ret = (long) bio_nread(bio, ptr, (size_t) num); 60359191Skris break; 60459191Skris 60559191Skris case BIO_C_NWRITE0: 60659191Skris /* prepare for non-copying write */ 60759191Skris ret = (long) bio_nwrite0(bio, ptr); 60859191Skris break; 60955714Skris 61059191Skris case BIO_C_NWRITE: 61159191Skris /* non-copying write */ 61259191Skris ret = (long) bio_nwrite(bio, ptr, (size_t) num); 61359191Skris break; 61459191Skris 61559191Skris 61655714Skris /* standard CTRL codes follow */ 61755714Skris 61855714Skris case BIO_CTRL_RESET: 61955714Skris if (b->buf != NULL) 62055714Skris { 62155714Skris b->len = 0; 62255714Skris b->offset = 0; 62355714Skris } 62455714Skris ret = 0; 62555714Skris break; 62655714Skris 62755714Skris case BIO_CTRL_GET_CLOSE: 62855714Skris ret = bio->shutdown; 62955714Skris break; 63055714Skris 63155714Skris case BIO_CTRL_SET_CLOSE: 63255714Skris bio->shutdown = (int) num; 63355714Skris ret = 1; 63455714Skris break; 63555714Skris 63655714Skris case BIO_CTRL_PENDING: 63755714Skris if (b->peer != NULL) 63855714Skris { 63955714Skris struct bio_bio_st *peer_b = b->peer->ptr; 64055714Skris 64155714Skris ret = (long) peer_b->len; 64255714Skris } 64355714Skris else 64455714Skris ret = 0; 64555714Skris break; 64655714Skris 64755714Skris case BIO_CTRL_WPENDING: 64855714Skris if (b->buf != NULL) 64955714Skris ret = (long) b->len; 65055714Skris else 65155714Skris ret = 0; 65255714Skris break; 65355714Skris 65455714Skris case BIO_CTRL_DUP: 65555714Skris /* See BIO_dup_chain for circumstances we have to expect. */ 65655714Skris { 65755714Skris BIO *other_bio = ptr; 65855714Skris struct bio_bio_st *other_b; 65955714Skris 66055714Skris assert(other_bio != NULL); 66155714Skris other_b = other_bio->ptr; 66255714Skris assert(other_b != NULL); 66355714Skris 66455714Skris assert(other_b->buf == NULL); /* other_bio is always fresh */ 66555714Skris 66655714Skris other_b->size = b->size; 66755714Skris } 66855714Skris 66955714Skris ret = 1; 67055714Skris break; 67155714Skris 67255714Skris case BIO_CTRL_FLUSH: 67355714Skris ret = 1; 67455714Skris break; 67555714Skris 67655714Skris case BIO_CTRL_EOF: 67755714Skris { 67855714Skris BIO *other_bio = ptr; 67955714Skris 68055714Skris if (other_bio) 68155714Skris { 68255714Skris struct bio_bio_st *other_b = other_bio->ptr; 68355714Skris 68455714Skris assert(other_b != NULL); 68555714Skris ret = other_b->len == 0 && other_b->closed; 68655714Skris } 68755714Skris else 68855714Skris ret = 1; 68955714Skris } 69055714Skris break; 69155714Skris 69255714Skris default: 69355714Skris ret = 0; 69455714Skris } 69555714Skris return ret; 69655714Skris } 69755714Skris 69868651Skrisstatic int bio_puts(BIO *bio, const char *str) 69955714Skris { 70055714Skris return bio_write(bio, str, strlen(str)); 70155714Skris } 70255714Skris 70355714Skris 70455714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2) 70555714Skris { 70655714Skris struct bio_bio_st *b1, *b2; 70755714Skris 70855714Skris assert(bio1 != NULL); 70955714Skris assert(bio2 != NULL); 71055714Skris 71155714Skris b1 = bio1->ptr; 71255714Skris b2 = bio2->ptr; 71355714Skris 71455714Skris if (b1->peer != NULL || b2->peer != NULL) 71555714Skris { 71655714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); 71755714Skris return 0; 71855714Skris } 71955714Skris 72055714Skris if (b1->buf == NULL) 72155714Skris { 72268651Skris b1->buf = OPENSSL_malloc(b1->size); 72355714Skris if (b1->buf == NULL) 72455714Skris { 72555714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 72655714Skris return 0; 72755714Skris } 72855714Skris b1->len = 0; 72955714Skris b1->offset = 0; 73055714Skris } 73155714Skris 73255714Skris if (b2->buf == NULL) 73355714Skris { 73468651Skris b2->buf = OPENSSL_malloc(b2->size); 73555714Skris if (b2->buf == NULL) 73655714Skris { 73755714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 73855714Skris return 0; 73955714Skris } 74055714Skris b2->len = 0; 74155714Skris b2->offset = 0; 74255714Skris } 74355714Skris 74455714Skris b1->peer = bio2; 74555714Skris b1->closed = 0; 74655714Skris b1->request = 0; 74755714Skris b2->peer = bio1; 74855714Skris b2->closed = 0; 74955714Skris b2->request = 0; 75055714Skris 75155714Skris bio1->init = 1; 75255714Skris bio2->init = 1; 75355714Skris 75455714Skris return 1; 75555714Skris } 75655714Skris 75755714Skrisstatic void bio_destroy_pair(BIO *bio) 75855714Skris { 75955714Skris struct bio_bio_st *b = bio->ptr; 76055714Skris 76155714Skris if (b != NULL) 76255714Skris { 76355714Skris BIO *peer_bio = b->peer; 76455714Skris 76555714Skris if (peer_bio != NULL) 76655714Skris { 76755714Skris struct bio_bio_st *peer_b = peer_bio->ptr; 76855714Skris 76955714Skris assert(peer_b != NULL); 77055714Skris assert(peer_b->peer == bio); 77155714Skris 77255714Skris peer_b->peer = NULL; 77355714Skris peer_bio->init = 0; 77455714Skris assert(peer_b->buf != NULL); 77555714Skris peer_b->len = 0; 77655714Skris peer_b->offset = 0; 77755714Skris 77855714Skris b->peer = NULL; 77955714Skris bio->init = 0; 78055714Skris assert(b->buf != NULL); 78155714Skris b->len = 0; 78255714Skris b->offset = 0; 78355714Skris } 78455714Skris } 78555714Skris } 78655714Skris 78755714Skris 78855714Skris/* Exported convenience functions */ 78955714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, 79055714Skris BIO **bio2_p, size_t writebuf2) 79155714Skris { 79255714Skris BIO *bio1 = NULL, *bio2 = NULL; 79355714Skris long r; 79455714Skris int ret = 0; 79555714Skris 79655714Skris bio1 = BIO_new(BIO_s_bio()); 79755714Skris if (bio1 == NULL) 79855714Skris goto err; 79955714Skris bio2 = BIO_new(BIO_s_bio()); 80055714Skris if (bio2 == NULL) 80155714Skris goto err; 80255714Skris 80355714Skris if (writebuf1) 80455714Skris { 80555714Skris r = BIO_set_write_buf_size(bio1, writebuf1); 80655714Skris if (!r) 80755714Skris goto err; 80855714Skris } 80955714Skris if (writebuf2) 81055714Skris { 81155714Skris r = BIO_set_write_buf_size(bio2, writebuf2); 81255714Skris if (!r) 81355714Skris goto err; 81455714Skris } 81555714Skris 81655714Skris r = BIO_make_bio_pair(bio1, bio2); 81755714Skris if (!r) 81855714Skris goto err; 81955714Skris ret = 1; 82055714Skris 82155714Skris err: 82255714Skris if (ret == 0) 82355714Skris { 82455714Skris if (bio1) 82555714Skris { 82655714Skris BIO_free(bio1); 82755714Skris bio1 = NULL; 82855714Skris } 82955714Skris if (bio2) 83055714Skris { 83155714Skris BIO_free(bio2); 83255714Skris bio2 = NULL; 83355714Skris } 83455714Skris } 83555714Skris 83655714Skris *bio1_p = bio1; 83755714Skris *bio2_p = bio2; 83855714Skris return ret; 83955714Skris } 84055714Skris 84155714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio) 84255714Skris { 84355714Skris return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 84455714Skris } 84555714Skris 84655714Skrissize_t BIO_ctrl_get_read_request(BIO *bio) 84755714Skris { 84855714Skris return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 84955714Skris } 85059191Skris 85159191Skrisint BIO_ctrl_reset_read_request(BIO *bio) 85259191Skris { 85359191Skris return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); 85459191Skris } 85559191Skris 85659191Skris 85759191Skris/* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now 85859191Skris * (conceivably some other BIOs could allow non-copying reads and writes too.) 85959191Skris */ 86059191Skrisint BIO_nread0(BIO *bio, char **buf) 86159191Skris { 86259191Skris long ret; 86359191Skris 86459191Skris if (!bio->init) 86559191Skris { 86659191Skris BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); 86759191Skris return -2; 86859191Skris } 86959191Skris 87059191Skris ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); 87159191Skris if (ret > INT_MAX) 87259191Skris return INT_MAX; 87359191Skris else 87459191Skris return (int) ret; 87559191Skris } 87659191Skris 87759191Skrisint BIO_nread(BIO *bio, char **buf, int num) 87859191Skris { 87959191Skris int ret; 88059191Skris 88159191Skris if (!bio->init) 88259191Skris { 88359191Skris BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); 88459191Skris return -2; 88559191Skris } 88659191Skris 88759191Skris ret = (int) BIO_ctrl(bio, BIO_C_NREAD, num, buf); 88859191Skris if (ret > 0) 88959191Skris bio->num_read += ret; 89059191Skris return ret; 89159191Skris } 89259191Skris 89359191Skrisint BIO_nwrite0(BIO *bio, char **buf) 89459191Skris { 89559191Skris long ret; 89659191Skris 89759191Skris if (!bio->init) 89859191Skris { 89959191Skris BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); 90059191Skris return -2; 90159191Skris } 90259191Skris 90359191Skris ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); 90459191Skris if (ret > INT_MAX) 90559191Skris return INT_MAX; 90659191Skris else 90759191Skris return (int) ret; 90859191Skris } 90959191Skris 91059191Skrisint BIO_nwrite(BIO *bio, char **buf, int num) 91159191Skris { 91259191Skris int ret; 91359191Skris 91459191Skris if (!bio->init) 91559191Skris { 91659191Skris BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); 91759191Skris return -2; 91859191Skris } 91959191Skris 92059191Skris ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); 92159191Skris if (ret > 0) 92259191Skris bio->num_read += ret; 92359191Skris return ret; 92459191Skris } 925