bss_bio.c revision 100928
155714Skris/* crypto/bio/bss_bio.c -*- Mode: C; c-file-style: "eay" -*- */ 255714Skris 355714Skris/* Special method for a BIO where the other endpoint is also a BIO 455714Skris * of this kind, handled by the same thread (i.e. the "peer" is actually 555714Skris * ourselves, wearing a different hat). 655714Skris * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces 755714Skris * for which no specific BIO method is available. 855714Skris * See ssl/ssltest.c for some hints on how this can be used. */ 955714Skris 1055714Skris#ifndef BIO_PAIR_DEBUG 1155714Skris# undef NDEBUG /* avoid conflicting definitions */ 1255714Skris# define NDEBUG 1355714Skris#endif 1455714Skris 1555714Skris#include <assert.h> 1659191Skris#include <limits.h> 1755714Skris#include <stdlib.h> 1855714Skris#include <string.h> 1955714Skris 2055714Skris#include <openssl/bio.h> 2155714Skris#include <openssl/err.h> 2259191Skris#include <openssl/err.h> 2355714Skris#include <openssl/crypto.h> 2455714Skris 2559191Skris#include "openssl/e_os.h" 26100928Snectar 27100928Snectar/* VxWorks defines SSiZE_MAX with an empty value causing compile errors */ 28100928Snectar#if defined(VXWORKS) 29100928Snectar# undef SSIZE_MAX 3059191Skris# define SSIZE_MAX INT_MAX 31100928Snectar#elif !defined(SSIZE_MAX) 32100928Snectar# define SSIZE_MAX INT_MAX 3359191Skris#endif 3459191Skris 3555714Skrisstatic int bio_new(BIO *bio); 3655714Skrisstatic int bio_free(BIO *bio); 3755714Skrisstatic int bio_read(BIO *bio, char *buf, int size); 3868651Skrisstatic int bio_write(BIO *bio, const char *buf, int num); 3955714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); 4068651Skrisstatic int bio_puts(BIO *bio, const char *str); 4155714Skris 4255714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2); 4355714Skrisstatic void bio_destroy_pair(BIO *bio); 4455714Skris 4555714Skrisstatic BIO_METHOD methods_biop = 4655714Skris{ 4755714Skris BIO_TYPE_BIO, 4855714Skris "BIO pair", 4955714Skris bio_write, 5055714Skris bio_read, 5155714Skris bio_puts, 5255714Skris NULL /* no bio_gets */, 5355714Skris bio_ctrl, 5455714Skris bio_new, 5559191Skris bio_free, 5659191Skris NULL /* no bio_callback_ctrl */ 5755714Skris}; 5855714Skris 5955714SkrisBIO_METHOD *BIO_s_bio(void) 6055714Skris { 6155714Skris return &methods_biop; 6255714Skris } 6355714Skris 6455714Skrisstruct bio_bio_st 6555714Skris{ 6655714Skris BIO *peer; /* NULL if buf == NULL. 6755714Skris * If peer != NULL, then peer->ptr is also a bio_bio_st, 6855714Skris * and its "peer" member points back to us. 6955714Skris * peer != NULL iff init != 0 in the BIO. */ 7055714Skris 7155714Skris /* This is for what we write (i.e. reading uses peer's struct): */ 7255714Skris int closed; /* valid iff peer != NULL */ 7355714Skris size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ 7455714Skris size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ 7555714Skris size_t size; 7655714Skris char *buf; /* "size" elements (if != NULL) */ 7755714Skris 7855714Skris size_t request; /* valid iff peer != NULL; 0 if len != 0, 7955714Skris * otherwise set by peer to number of bytes 8059191Skris * it (unsuccessfully) tried to read, 8155714Skris * never more than buffer space (size-len) warrants. */ 8255714Skris}; 8355714Skris 8455714Skrisstatic int bio_new(BIO *bio) 8555714Skris { 8655714Skris struct bio_bio_st *b; 8755714Skris 8868651Skris b = OPENSSL_malloc(sizeof *b); 8955714Skris if (b == NULL) 9055714Skris return 0; 9155714Skris 9255714Skris b->peer = NULL; 9355714Skris b->size = 17*1024; /* enough for one TLS record (just a default) */ 9455714Skris b->buf = NULL; 9555714Skris 9655714Skris bio->ptr = b; 9755714Skris return 1; 9855714Skris } 9955714Skris 10055714Skris 10155714Skrisstatic int bio_free(BIO *bio) 10255714Skris { 10355714Skris struct bio_bio_st *b; 10455714Skris 10555714Skris if (bio == NULL) 10655714Skris return 0; 10755714Skris b = bio->ptr; 10855714Skris 10955714Skris assert(b != NULL); 11055714Skris 11155714Skris if (b->peer) 11255714Skris bio_destroy_pair(bio); 11355714Skris 11455714Skris if (b->buf != NULL) 11555714Skris { 11668651Skris OPENSSL_free(b->buf); 11755714Skris } 11855714Skris 11968651Skris OPENSSL_free(b); 12055714Skris 12155714Skris return 1; 12255714Skris } 12355714Skris 12455714Skris 12555714Skris 12655714Skrisstatic int bio_read(BIO *bio, char *buf, int size_) 12755714Skris { 12855714Skris size_t size = size_; 12955714Skris size_t rest; 13055714Skris struct bio_bio_st *b, *peer_b; 13155714Skris 13255714Skris BIO_clear_retry_flags(bio); 13355714Skris 13455714Skris if (!bio->init) 13555714Skris return 0; 13655714Skris 13755714Skris b = bio->ptr; 13855714Skris assert(b != NULL); 13955714Skris assert(b->peer != NULL); 14055714Skris peer_b = b->peer->ptr; 14155714Skris assert(peer_b != NULL); 14255714Skris assert(peer_b->buf != NULL); 14355714Skris 14455714Skris peer_b->request = 0; /* will be set in "retry_read" situation */ 14555714Skris 14655714Skris if (buf == NULL || size == 0) 14755714Skris return 0; 14855714Skris 14955714Skris if (peer_b->len == 0) 15055714Skris { 15155714Skris if (peer_b->closed) 15255714Skris return 0; /* writer has closed, and no data is left */ 15355714Skris else 15455714Skris { 15555714Skris BIO_set_retry_read(bio); /* buffer is empty */ 15655714Skris if (size <= peer_b->size) 15755714Skris peer_b->request = size; 15855714Skris else 15955714Skris /* don't ask for more than the peer can 16055714Skris * deliver in one write */ 16155714Skris peer_b->request = peer_b->size; 16255714Skris return -1; 16355714Skris } 16455714Skris } 16555714Skris 16655714Skris /* we can read */ 16755714Skris if (peer_b->len < size) 16855714Skris size = peer_b->len; 16955714Skris 17055714Skris /* now read "size" bytes */ 17155714Skris 17255714Skris rest = size; 17355714Skris 17455714Skris assert(rest > 0); 17555714Skris do /* one or two iterations */ 17655714Skris { 17755714Skris size_t chunk; 17855714Skris 17955714Skris assert(rest <= peer_b->len); 18055714Skris if (peer_b->offset + rest <= peer_b->size) 18155714Skris chunk = rest; 18255714Skris else 18355714Skris /* wrap around ring buffer */ 18455714Skris chunk = peer_b->size - peer_b->offset; 18555714Skris assert(peer_b->offset + chunk <= peer_b->size); 18655714Skris 18755714Skris memcpy(buf, peer_b->buf + peer_b->offset, chunk); 18855714Skris 18955714Skris peer_b->len -= chunk; 19055714Skris if (peer_b->len) 19155714Skris { 19255714Skris peer_b->offset += chunk; 19355714Skris assert(peer_b->offset <= peer_b->size); 19455714Skris if (peer_b->offset == peer_b->size) 19555714Skris peer_b->offset = 0; 19655714Skris buf += chunk; 19755714Skris } 19855714Skris else 19955714Skris { 20055714Skris /* buffer now empty, no need to advance "buf" */ 20155714Skris assert(chunk == rest); 20255714Skris peer_b->offset = 0; 20355714Skris } 20455714Skris rest -= chunk; 20555714Skris } 20655714Skris while (rest); 20755714Skris 20855714Skris return size; 20955714Skris } 21055714Skris 21159191Skris/* non-copying interface: provide pointer to available data in buffer 21259191Skris * bio_nread0: return number of available bytes 21359191Skris * bio_nread: also advance index 21459191Skris * (example usage: bio_nread0(), read from buffer, bio_nread() 21559191Skris * or just bio_nread(), read from buffer) 21659191Skris */ 21759191Skris/* WARNING: The non-copying interface is largely untested as of yet 21859191Skris * and may contain bugs. */ 21959191Skrisstatic ssize_t bio_nread0(BIO *bio, char **buf) 22059191Skris { 22159191Skris struct bio_bio_st *b, *peer_b; 22259191Skris ssize_t num; 22359191Skris 22459191Skris BIO_clear_retry_flags(bio); 22559191Skris 22659191Skris if (!bio->init) 22759191Skris return 0; 22859191Skris 22959191Skris b = bio->ptr; 23059191Skris assert(b != NULL); 23159191Skris assert(b->peer != NULL); 23259191Skris peer_b = b->peer->ptr; 23359191Skris assert(peer_b != NULL); 23459191Skris assert(peer_b->buf != NULL); 23559191Skris 23659191Skris peer_b->request = 0; 23759191Skris 23859191Skris if (peer_b->len == 0) 23959191Skris { 24059191Skris char dummy; 24159191Skris 24259191Skris /* avoid code duplication -- nothing available for reading */ 24359191Skris return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ 24459191Skris } 24559191Skris 24659191Skris num = peer_b->len; 24759191Skris if (peer_b->size < peer_b->offset + num) 24859191Skris /* no ring buffer wrap-around for non-copying interface */ 24959191Skris num = peer_b->size - peer_b->offset; 25059191Skris assert(num > 0); 25159191Skris 25259191Skris if (buf != NULL) 25359191Skris *buf = peer_b->buf + peer_b->offset; 25459191Skris return num; 25559191Skris } 25659191Skris 25759191Skrisstatic ssize_t bio_nread(BIO *bio, char **buf, size_t num_) 25859191Skris { 25959191Skris struct bio_bio_st *b, *peer_b; 26059191Skris ssize_t num, available; 26159191Skris 26259191Skris if (num_ > SSIZE_MAX) 26359191Skris num = SSIZE_MAX; 26459191Skris else 26559191Skris num = (ssize_t)num_; 26659191Skris 26759191Skris available = bio_nread0(bio, buf); 26859191Skris if (num > available) 26959191Skris num = available; 27059191Skris if (num <= 0) 27159191Skris return num; 27259191Skris 27359191Skris b = bio->ptr; 27459191Skris peer_b = b->peer->ptr; 27559191Skris 27659191Skris peer_b->len -= num; 27759191Skris if (peer_b->len) 27859191Skris { 27959191Skris peer_b->offset += num; 28059191Skris assert(peer_b->offset <= peer_b->size); 28159191Skris if (peer_b->offset == peer_b->size) 28259191Skris peer_b->offset = 0; 28359191Skris } 28459191Skris else 28559191Skris peer_b->offset = 0; 28659191Skris 28759191Skris return num; 28859191Skris } 28959191Skris 29059191Skris 29168651Skrisstatic int bio_write(BIO *bio, const char *buf, int num_) 29255714Skris { 29355714Skris size_t num = num_; 29455714Skris size_t rest; 29555714Skris struct bio_bio_st *b; 29655714Skris 29755714Skris BIO_clear_retry_flags(bio); 29855714Skris 29955714Skris if (!bio->init || buf == NULL || num == 0) 30055714Skris return 0; 30155714Skris 30255714Skris b = bio->ptr; 30355714Skris assert(b != NULL); 30455714Skris assert(b->peer != NULL); 30555714Skris assert(b->buf != NULL); 30655714Skris 30755714Skris b->request = 0; 30855714Skris if (b->closed) 30955714Skris { 31055714Skris /* we already closed */ 31155714Skris BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); 31255714Skris return -1; 31355714Skris } 31455714Skris 31555714Skris assert(b->len <= b->size); 31655714Skris 31755714Skris if (b->len == b->size) 31855714Skris { 31955714Skris BIO_set_retry_write(bio); /* buffer is full */ 32055714Skris return -1; 32155714Skris } 32255714Skris 32355714Skris /* we can write */ 32455714Skris if (num > b->size - b->len) 32555714Skris num = b->size - b->len; 32655714Skris 32755714Skris /* now write "num" bytes */ 32855714Skris 32955714Skris rest = num; 33055714Skris 33155714Skris assert(rest > 0); 33255714Skris do /* one or two iterations */ 33355714Skris { 33455714Skris size_t write_offset; 33555714Skris size_t chunk; 33655714Skris 33755714Skris assert(b->len + rest <= b->size); 33855714Skris 33955714Skris write_offset = b->offset + b->len; 34055714Skris if (write_offset >= b->size) 34155714Skris write_offset -= b->size; 34255714Skris /* b->buf[write_offset] is the first byte we can write to. */ 34355714Skris 34455714Skris if (write_offset + rest <= b->size) 34555714Skris chunk = rest; 34655714Skris else 34755714Skris /* wrap around ring buffer */ 34855714Skris chunk = b->size - write_offset; 34955714Skris 35055714Skris memcpy(b->buf + write_offset, buf, chunk); 35155714Skris 35255714Skris b->len += chunk; 35355714Skris 35455714Skris assert(b->len <= b->size); 35555714Skris 35655714Skris rest -= chunk; 35755714Skris buf += chunk; 35855714Skris } 35955714Skris while (rest); 36055714Skris 36155714Skris return num; 36255714Skris } 36355714Skris 36459191Skris/* non-copying interface: provide pointer to region to write to 36559191Skris * bio_nwrite0: check how much space is available 36659191Skris * bio_nwrite: also increase length 36759191Skris * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() 36859191Skris * or just bio_nwrite(), write to buffer) 36959191Skris */ 37059191Skrisstatic ssize_t bio_nwrite0(BIO *bio, char **buf) 37159191Skris { 37259191Skris struct bio_bio_st *b; 37359191Skris size_t num; 37459191Skris size_t write_offset; 37555714Skris 37659191Skris BIO_clear_retry_flags(bio); 37759191Skris 37859191Skris if (!bio->init) 37959191Skris return 0; 38059191Skris 38159191Skris b = bio->ptr; 38259191Skris assert(b != NULL); 38359191Skris assert(b->peer != NULL); 38459191Skris assert(b->buf != NULL); 38559191Skris 38659191Skris b->request = 0; 38759191Skris if (b->closed) 38859191Skris { 38959191Skris BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); 39059191Skris return -1; 39159191Skris } 39259191Skris 39359191Skris assert(b->len <= b->size); 39459191Skris 39559191Skris if (b->len == b->size) 39659191Skris { 39759191Skris BIO_set_retry_write(bio); 39859191Skris return -1; 39959191Skris } 40059191Skris 40159191Skris num = b->size - b->len; 40259191Skris write_offset = b->offset + b->len; 40359191Skris if (write_offset >= b->size) 40459191Skris write_offset -= b->size; 40559191Skris if (write_offset + num > b->size) 40659191Skris /* no ring buffer wrap-around for non-copying interface 40759191Skris * (to fulfil the promise by BIO_ctrl_get_write_guarantee, 40859191Skris * BIO_nwrite may have to be called twice) */ 40959191Skris num = b->size - write_offset; 41059191Skris 41159191Skris if (buf != NULL) 41259191Skris *buf = b->buf + write_offset; 41359191Skris assert(write_offset + num <= b->size); 41459191Skris 41559191Skris return num; 41659191Skris } 41759191Skris 41859191Skrisstatic ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) 41959191Skris { 42059191Skris struct bio_bio_st *b; 42159191Skris ssize_t num, space; 42259191Skris 42359191Skris if (num_ > SSIZE_MAX) 42459191Skris num = SSIZE_MAX; 42559191Skris else 42659191Skris num = (ssize_t)num_; 42759191Skris 42859191Skris space = bio_nwrite0(bio, buf); 42959191Skris if (num > space) 43059191Skris num = space; 43159191Skris if (num <= 0) 43259191Skris return num; 43359191Skris b = bio->ptr; 43459191Skris assert(b != NULL); 43559191Skris b->len += num; 43659191Skris assert(b->len <= b->size); 43759191Skris 43859191Skris return num; 43959191Skris } 44059191Skris 44159191Skris 44255714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 44355714Skris { 44455714Skris long ret; 44555714Skris struct bio_bio_st *b = bio->ptr; 44655714Skris 44755714Skris assert(b != NULL); 44855714Skris 44955714Skris switch (cmd) 45055714Skris { 45155714Skris /* specific CTRL codes */ 45255714Skris 45355714Skris case BIO_C_SET_WRITE_BUF_SIZE: 45455714Skris if (b->peer) 45555714Skris { 45655714Skris BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); 45755714Skris ret = 0; 45855714Skris } 45955714Skris else if (num == 0) 46055714Skris { 46155714Skris BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); 46255714Skris ret = 0; 46355714Skris } 46455714Skris else 46555714Skris { 46655714Skris size_t new_size = num; 46755714Skris 46855714Skris if (b->size != new_size) 46955714Skris { 47055714Skris if (b->buf) 47155714Skris { 47268651Skris OPENSSL_free(b->buf); 47355714Skris b->buf = NULL; 47455714Skris } 47555714Skris b->size = new_size; 47655714Skris } 47755714Skris ret = 1; 47855714Skris } 47955714Skris break; 48055714Skris 48155714Skris case BIO_C_GET_WRITE_BUF_SIZE: 48289837Skris ret = (long) b->size; 48389837Skris break; 48455714Skris 48555714Skris case BIO_C_MAKE_BIO_PAIR: 48655714Skris { 48755714Skris BIO *other_bio = ptr; 48855714Skris 48955714Skris if (bio_make_pair(bio, other_bio)) 49055714Skris ret = 1; 49155714Skris else 49255714Skris ret = 0; 49355714Skris } 49455714Skris break; 49555714Skris 49655714Skris case BIO_C_DESTROY_BIO_PAIR: 49755714Skris /* Effects both BIOs in the pair -- call just once! 49855714Skris * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ 49955714Skris bio_destroy_pair(bio); 50055714Skris ret = 1; 50155714Skris break; 50255714Skris 50355714Skris case BIO_C_GET_WRITE_GUARANTEE: 50455714Skris /* How many bytes can the caller feed to the next write 50559191Skris * without having to keep any? */ 50655714Skris if (b->peer == NULL || b->closed) 50755714Skris ret = 0; 50855714Skris else 50955714Skris ret = (long) b->size - b->len; 51055714Skris break; 51155714Skris 51255714Skris case BIO_C_GET_READ_REQUEST: 51359191Skris /* If the peer unsuccessfully tried to read, how many bytes 51455714Skris * were requested? (As with BIO_CTRL_PENDING, that number 51555714Skris * can usually be treated as boolean.) */ 51655714Skris ret = (long) b->request; 51755714Skris break; 51855714Skris 51959191Skris case BIO_C_RESET_READ_REQUEST: 52059191Skris /* Reset request. (Can be useful after read attempts 52159191Skris * at the other side that are meant to be non-blocking, 52259191Skris * e.g. when probing SSL_read to see if any data is 52359191Skris * available.) */ 52459191Skris b->request = 0; 52559191Skris ret = 1; 52659191Skris break; 52759191Skris 52855714Skris case BIO_C_SHUTDOWN_WR: 52955714Skris /* similar to shutdown(..., SHUT_WR) */ 53055714Skris b->closed = 1; 53155714Skris ret = 1; 53255714Skris break; 53355714Skris 53459191Skris case BIO_C_NREAD0: 53559191Skris /* prepare for non-copying read */ 53659191Skris ret = (long) bio_nread0(bio, ptr); 53759191Skris break; 53859191Skris 53959191Skris case BIO_C_NREAD: 54059191Skris /* non-copying read */ 54159191Skris ret = (long) bio_nread(bio, ptr, (size_t) num); 54259191Skris break; 54359191Skris 54459191Skris case BIO_C_NWRITE0: 54559191Skris /* prepare for non-copying write */ 54659191Skris ret = (long) bio_nwrite0(bio, ptr); 54759191Skris break; 54855714Skris 54959191Skris case BIO_C_NWRITE: 55059191Skris /* non-copying write */ 55159191Skris ret = (long) bio_nwrite(bio, ptr, (size_t) num); 55259191Skris break; 55359191Skris 55459191Skris 55555714Skris /* standard CTRL codes follow */ 55655714Skris 55755714Skris case BIO_CTRL_RESET: 55855714Skris if (b->buf != NULL) 55955714Skris { 56055714Skris b->len = 0; 56155714Skris b->offset = 0; 56255714Skris } 56355714Skris ret = 0; 56455714Skris break; 56555714Skris 56655714Skris case BIO_CTRL_GET_CLOSE: 56755714Skris ret = bio->shutdown; 56855714Skris break; 56955714Skris 57055714Skris case BIO_CTRL_SET_CLOSE: 57155714Skris bio->shutdown = (int) num; 57255714Skris ret = 1; 57355714Skris break; 57455714Skris 57555714Skris case BIO_CTRL_PENDING: 57655714Skris if (b->peer != NULL) 57755714Skris { 57855714Skris struct bio_bio_st *peer_b = b->peer->ptr; 57955714Skris 58055714Skris ret = (long) peer_b->len; 58155714Skris } 58255714Skris else 58355714Skris ret = 0; 58455714Skris break; 58555714Skris 58655714Skris case BIO_CTRL_WPENDING: 58755714Skris if (b->buf != NULL) 58855714Skris ret = (long) b->len; 58955714Skris else 59055714Skris ret = 0; 59155714Skris break; 59255714Skris 59355714Skris case BIO_CTRL_DUP: 59455714Skris /* See BIO_dup_chain for circumstances we have to expect. */ 59555714Skris { 59655714Skris BIO *other_bio = ptr; 59755714Skris struct bio_bio_st *other_b; 59855714Skris 59955714Skris assert(other_bio != NULL); 60055714Skris other_b = other_bio->ptr; 60155714Skris assert(other_b != NULL); 60255714Skris 60355714Skris assert(other_b->buf == NULL); /* other_bio is always fresh */ 60455714Skris 60555714Skris other_b->size = b->size; 60655714Skris } 60755714Skris 60855714Skris ret = 1; 60955714Skris break; 61055714Skris 61155714Skris case BIO_CTRL_FLUSH: 61255714Skris ret = 1; 61355714Skris break; 61455714Skris 61555714Skris case BIO_CTRL_EOF: 61655714Skris { 61755714Skris BIO *other_bio = ptr; 61855714Skris 61955714Skris if (other_bio) 62055714Skris { 62155714Skris struct bio_bio_st *other_b = other_bio->ptr; 62255714Skris 62355714Skris assert(other_b != NULL); 62455714Skris ret = other_b->len == 0 && other_b->closed; 62555714Skris } 62655714Skris else 62755714Skris ret = 1; 62855714Skris } 62955714Skris break; 63055714Skris 63155714Skris default: 63255714Skris ret = 0; 63355714Skris } 63455714Skris return ret; 63555714Skris } 63655714Skris 63768651Skrisstatic int bio_puts(BIO *bio, const char *str) 63855714Skris { 63955714Skris return bio_write(bio, str, strlen(str)); 64055714Skris } 64155714Skris 64255714Skris 64355714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2) 64455714Skris { 64555714Skris struct bio_bio_st *b1, *b2; 64655714Skris 64755714Skris assert(bio1 != NULL); 64855714Skris assert(bio2 != NULL); 64955714Skris 65055714Skris b1 = bio1->ptr; 65155714Skris b2 = bio2->ptr; 65255714Skris 65355714Skris if (b1->peer != NULL || b2->peer != NULL) 65455714Skris { 65555714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); 65655714Skris return 0; 65755714Skris } 65855714Skris 65955714Skris if (b1->buf == NULL) 66055714Skris { 66168651Skris b1->buf = OPENSSL_malloc(b1->size); 66255714Skris if (b1->buf == NULL) 66355714Skris { 66455714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 66555714Skris return 0; 66655714Skris } 66755714Skris b1->len = 0; 66855714Skris b1->offset = 0; 66955714Skris } 67055714Skris 67155714Skris if (b2->buf == NULL) 67255714Skris { 67368651Skris b2->buf = OPENSSL_malloc(b2->size); 67455714Skris if (b2->buf == NULL) 67555714Skris { 67655714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 67755714Skris return 0; 67855714Skris } 67955714Skris b2->len = 0; 68055714Skris b2->offset = 0; 68155714Skris } 68255714Skris 68355714Skris b1->peer = bio2; 68455714Skris b1->closed = 0; 68555714Skris b1->request = 0; 68655714Skris b2->peer = bio1; 68755714Skris b2->closed = 0; 68855714Skris b2->request = 0; 68955714Skris 69055714Skris bio1->init = 1; 69155714Skris bio2->init = 1; 69255714Skris 69355714Skris return 1; 69455714Skris } 69555714Skris 69655714Skrisstatic void bio_destroy_pair(BIO *bio) 69755714Skris { 69855714Skris struct bio_bio_st *b = bio->ptr; 69955714Skris 70055714Skris if (b != NULL) 70155714Skris { 70255714Skris BIO *peer_bio = b->peer; 70355714Skris 70455714Skris if (peer_bio != NULL) 70555714Skris { 70655714Skris struct bio_bio_st *peer_b = peer_bio->ptr; 70755714Skris 70855714Skris assert(peer_b != NULL); 70955714Skris assert(peer_b->peer == bio); 71055714Skris 71155714Skris peer_b->peer = NULL; 71255714Skris peer_bio->init = 0; 71355714Skris assert(peer_b->buf != NULL); 71455714Skris peer_b->len = 0; 71555714Skris peer_b->offset = 0; 71655714Skris 71755714Skris b->peer = NULL; 71855714Skris bio->init = 0; 71955714Skris assert(b->buf != NULL); 72055714Skris b->len = 0; 72155714Skris b->offset = 0; 72255714Skris } 72355714Skris } 72455714Skris } 72555714Skris 72655714Skris 72755714Skris/* Exported convenience functions */ 72855714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, 72955714Skris BIO **bio2_p, size_t writebuf2) 73055714Skris { 73155714Skris BIO *bio1 = NULL, *bio2 = NULL; 73255714Skris long r; 73355714Skris int ret = 0; 73455714Skris 73555714Skris bio1 = BIO_new(BIO_s_bio()); 73655714Skris if (bio1 == NULL) 73755714Skris goto err; 73855714Skris bio2 = BIO_new(BIO_s_bio()); 73955714Skris if (bio2 == NULL) 74055714Skris goto err; 74155714Skris 74255714Skris if (writebuf1) 74355714Skris { 74455714Skris r = BIO_set_write_buf_size(bio1, writebuf1); 74555714Skris if (!r) 74655714Skris goto err; 74755714Skris } 74855714Skris if (writebuf2) 74955714Skris { 75055714Skris r = BIO_set_write_buf_size(bio2, writebuf2); 75155714Skris if (!r) 75255714Skris goto err; 75355714Skris } 75455714Skris 75555714Skris r = BIO_make_bio_pair(bio1, bio2); 75655714Skris if (!r) 75755714Skris goto err; 75855714Skris ret = 1; 75955714Skris 76055714Skris err: 76155714Skris if (ret == 0) 76255714Skris { 76355714Skris if (bio1) 76455714Skris { 76555714Skris BIO_free(bio1); 76655714Skris bio1 = NULL; 76755714Skris } 76855714Skris if (bio2) 76955714Skris { 77055714Skris BIO_free(bio2); 77155714Skris bio2 = NULL; 77255714Skris } 77355714Skris } 77455714Skris 77555714Skris *bio1_p = bio1; 77655714Skris *bio2_p = bio2; 77755714Skris return ret; 77855714Skris } 77955714Skris 78055714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio) 78155714Skris { 78255714Skris return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 78355714Skris } 78455714Skris 78555714Skrissize_t BIO_ctrl_get_read_request(BIO *bio) 78655714Skris { 78755714Skris return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 78855714Skris } 78959191Skris 79059191Skrisint BIO_ctrl_reset_read_request(BIO *bio) 79159191Skris { 79259191Skris return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); 79359191Skris } 79459191Skris 79559191Skris 79659191Skris/* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now 79759191Skris * (conceivably some other BIOs could allow non-copying reads and writes too.) 79859191Skris */ 79959191Skrisint BIO_nread0(BIO *bio, char **buf) 80059191Skris { 80159191Skris long ret; 80259191Skris 80359191Skris if (!bio->init) 80459191Skris { 80559191Skris BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); 80659191Skris return -2; 80759191Skris } 80859191Skris 80959191Skris ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); 81059191Skris if (ret > INT_MAX) 81159191Skris return INT_MAX; 81259191Skris else 81359191Skris return (int) ret; 81459191Skris } 81559191Skris 81659191Skrisint BIO_nread(BIO *bio, char **buf, int num) 81759191Skris { 81859191Skris int ret; 81959191Skris 82059191Skris if (!bio->init) 82159191Skris { 82259191Skris BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); 82359191Skris return -2; 82459191Skris } 82559191Skris 82659191Skris ret = (int) BIO_ctrl(bio, BIO_C_NREAD, num, buf); 82759191Skris if (ret > 0) 82859191Skris bio->num_read += ret; 82959191Skris return ret; 83059191Skris } 83159191Skris 83259191Skrisint BIO_nwrite0(BIO *bio, char **buf) 83359191Skris { 83459191Skris long ret; 83559191Skris 83659191Skris if (!bio->init) 83759191Skris { 83859191Skris BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); 83959191Skris return -2; 84059191Skris } 84159191Skris 84259191Skris ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); 84359191Skris if (ret > INT_MAX) 84459191Skris return INT_MAX; 84559191Skris else 84659191Skris return (int) ret; 84759191Skris } 84859191Skris 84959191Skrisint BIO_nwrite(BIO *bio, char **buf, int num) 85059191Skris { 85159191Skris int ret; 85259191Skris 85359191Skris if (!bio->init) 85459191Skris { 85559191Skris BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); 85659191Skris return -2; 85759191Skris } 85859191Skris 85959191Skris ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); 86059191Skris if (ret > 0) 86159191Skris bio->num_read += ret; 86259191Skris return ret; 86359191Skris } 864