bss_bio.c revision 109998
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 10100936Snectar/* BIO_DEBUG implies BIO_PAIR_DEBUG */ 11100936Snectar#ifdef BIO_DEBUG 12100936Snectar# ifndef BIO_PAIR_DEBUG 13100936Snectar# define BIO_PAIR_DEBUG 14100936Snectar# endif 15100936Snectar#endif 16100936Snectar 17100936Snectar/* disable assert() unless BIO_PAIR_DEBUG has been defined */ 1855714Skris#ifndef BIO_PAIR_DEBUG 19100936Snectar# ifndef NDEBUG 20100936Snectar# define NDEBUG 21100936Snectar# endif 2255714Skris#endif 2355714Skris 2455714Skris#include <assert.h> 2559191Skris#include <limits.h> 2655714Skris#include <stdlib.h> 2755714Skris#include <string.h> 2855714Skris 2955714Skris#include <openssl/bio.h> 3055714Skris#include <openssl/err.h> 3155714Skris#include <openssl/crypto.h> 3255714Skris 33109998Smarkm#include "e_os.h" 34100928Snectar 35109998Smarkm/* VxWorks defines SSIZE_MAX with an empty value causing compile errors */ 36109998Smarkm#if defined(OPENSSL_SYS_VXWORKS) 37100928Snectar# undef SSIZE_MAX 38109998Smarkm#endif 39109998Smarkm#ifndef SSIZE_MAX 4059191Skris# define SSIZE_MAX INT_MAX 4159191Skris#endif 4259191Skris 4355714Skrisstatic int bio_new(BIO *bio); 4455714Skrisstatic int bio_free(BIO *bio); 4555714Skrisstatic int bio_read(BIO *bio, char *buf, int size); 4668651Skrisstatic int bio_write(BIO *bio, const char *buf, int num); 4755714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); 4868651Skrisstatic int bio_puts(BIO *bio, const char *str); 4955714Skris 5055714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2); 5155714Skrisstatic void bio_destroy_pair(BIO *bio); 5255714Skris 5355714Skrisstatic BIO_METHOD methods_biop = 5455714Skris{ 5555714Skris BIO_TYPE_BIO, 5655714Skris "BIO pair", 5755714Skris bio_write, 5855714Skris bio_read, 5955714Skris bio_puts, 6055714Skris NULL /* no bio_gets */, 6155714Skris bio_ctrl, 6255714Skris bio_new, 6359191Skris bio_free, 6459191Skris NULL /* no bio_callback_ctrl */ 6555714Skris}; 6655714Skris 6755714SkrisBIO_METHOD *BIO_s_bio(void) 6855714Skris { 6955714Skris return &methods_biop; 7055714Skris } 7155714Skris 7255714Skrisstruct bio_bio_st 7355714Skris{ 7455714Skris BIO *peer; /* NULL if buf == NULL. 7555714Skris * If peer != NULL, then peer->ptr is also a bio_bio_st, 7655714Skris * and its "peer" member points back to us. 7755714Skris * peer != NULL iff init != 0 in the BIO. */ 7855714Skris 7955714Skris /* This is for what we write (i.e. reading uses peer's struct): */ 8055714Skris int closed; /* valid iff peer != NULL */ 8155714Skris size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ 8255714Skris size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ 8355714Skris size_t size; 8455714Skris char *buf; /* "size" elements (if != NULL) */ 8555714Skris 8655714Skris size_t request; /* valid iff peer != NULL; 0 if len != 0, 8755714Skris * otherwise set by peer to number of bytes 8859191Skris * it (unsuccessfully) tried to read, 8955714Skris * never more than buffer space (size-len) warrants. */ 9055714Skris}; 9155714Skris 9255714Skrisstatic int bio_new(BIO *bio) 9355714Skris { 9455714Skris struct bio_bio_st *b; 9555714Skris 9668651Skris b = OPENSSL_malloc(sizeof *b); 9755714Skris if (b == NULL) 9855714Skris return 0; 9955714Skris 10055714Skris b->peer = NULL; 10155714Skris b->size = 17*1024; /* enough for one TLS record (just a default) */ 10255714Skris b->buf = NULL; 10355714Skris 10455714Skris bio->ptr = b; 10555714Skris return 1; 10655714Skris } 10755714Skris 10855714Skris 10955714Skrisstatic int bio_free(BIO *bio) 11055714Skris { 11155714Skris struct bio_bio_st *b; 11255714Skris 11355714Skris if (bio == NULL) 11455714Skris return 0; 11555714Skris b = bio->ptr; 11655714Skris 11755714Skris assert(b != NULL); 11855714Skris 11955714Skris if (b->peer) 12055714Skris bio_destroy_pair(bio); 12155714Skris 12255714Skris if (b->buf != NULL) 12355714Skris { 12468651Skris OPENSSL_free(b->buf); 12555714Skris } 12655714Skris 12768651Skris OPENSSL_free(b); 12855714Skris 12955714Skris return 1; 13055714Skris } 13155714Skris 13255714Skris 13355714Skris 13455714Skrisstatic int bio_read(BIO *bio, char *buf, int size_) 13555714Skris { 13655714Skris size_t size = size_; 13755714Skris size_t rest; 13855714Skris struct bio_bio_st *b, *peer_b; 13955714Skris 14055714Skris BIO_clear_retry_flags(bio); 14155714Skris 14255714Skris if (!bio->init) 14355714Skris return 0; 14455714Skris 14555714Skris b = bio->ptr; 14655714Skris assert(b != NULL); 14755714Skris assert(b->peer != NULL); 14855714Skris peer_b = b->peer->ptr; 14955714Skris assert(peer_b != NULL); 15055714Skris assert(peer_b->buf != NULL); 15155714Skris 15255714Skris peer_b->request = 0; /* will be set in "retry_read" situation */ 15355714Skris 15455714Skris if (buf == NULL || size == 0) 15555714Skris return 0; 15655714Skris 15755714Skris if (peer_b->len == 0) 15855714Skris { 15955714Skris if (peer_b->closed) 16055714Skris return 0; /* writer has closed, and no data is left */ 16155714Skris else 16255714Skris { 16355714Skris BIO_set_retry_read(bio); /* buffer is empty */ 16455714Skris if (size <= peer_b->size) 16555714Skris peer_b->request = size; 16655714Skris else 16755714Skris /* don't ask for more than the peer can 16855714Skris * deliver in one write */ 16955714Skris peer_b->request = peer_b->size; 17055714Skris return -1; 17155714Skris } 17255714Skris } 17355714Skris 17455714Skris /* we can read */ 17555714Skris if (peer_b->len < size) 17655714Skris size = peer_b->len; 17755714Skris 17855714Skris /* now read "size" bytes */ 17955714Skris 18055714Skris rest = size; 18155714Skris 18255714Skris assert(rest > 0); 18355714Skris do /* one or two iterations */ 18455714Skris { 18555714Skris size_t chunk; 18655714Skris 18755714Skris assert(rest <= peer_b->len); 18855714Skris if (peer_b->offset + rest <= peer_b->size) 18955714Skris chunk = rest; 19055714Skris else 19155714Skris /* wrap around ring buffer */ 19255714Skris chunk = peer_b->size - peer_b->offset; 19355714Skris assert(peer_b->offset + chunk <= peer_b->size); 19455714Skris 19555714Skris memcpy(buf, peer_b->buf + peer_b->offset, chunk); 19655714Skris 19755714Skris peer_b->len -= chunk; 19855714Skris if (peer_b->len) 19955714Skris { 20055714Skris peer_b->offset += chunk; 20155714Skris assert(peer_b->offset <= peer_b->size); 20255714Skris if (peer_b->offset == peer_b->size) 20355714Skris peer_b->offset = 0; 20455714Skris buf += chunk; 20555714Skris } 20655714Skris else 20755714Skris { 20855714Skris /* buffer now empty, no need to advance "buf" */ 20955714Skris assert(chunk == rest); 21055714Skris peer_b->offset = 0; 21155714Skris } 21255714Skris rest -= chunk; 21355714Skris } 21455714Skris while (rest); 21555714Skris 21655714Skris return size; 21755714Skris } 21855714Skris 21959191Skris/* non-copying interface: provide pointer to available data in buffer 22059191Skris * bio_nread0: return number of available bytes 22159191Skris * bio_nread: also advance index 22259191Skris * (example usage: bio_nread0(), read from buffer, bio_nread() 22359191Skris * or just bio_nread(), read from buffer) 22459191Skris */ 22559191Skris/* WARNING: The non-copying interface is largely untested as of yet 22659191Skris * and may contain bugs. */ 22759191Skrisstatic ssize_t bio_nread0(BIO *bio, char **buf) 22859191Skris { 22959191Skris struct bio_bio_st *b, *peer_b; 23059191Skris ssize_t num; 23159191Skris 23259191Skris BIO_clear_retry_flags(bio); 23359191Skris 23459191Skris if (!bio->init) 23559191Skris return 0; 23659191Skris 23759191Skris b = bio->ptr; 23859191Skris assert(b != NULL); 23959191Skris assert(b->peer != NULL); 24059191Skris peer_b = b->peer->ptr; 24159191Skris assert(peer_b != NULL); 24259191Skris assert(peer_b->buf != NULL); 24359191Skris 24459191Skris peer_b->request = 0; 24559191Skris 24659191Skris if (peer_b->len == 0) 24759191Skris { 24859191Skris char dummy; 24959191Skris 25059191Skris /* avoid code duplication -- nothing available for reading */ 25159191Skris return bio_read(bio, &dummy, 1); /* returns 0 or -1 */ 25259191Skris } 25359191Skris 25459191Skris num = peer_b->len; 25559191Skris if (peer_b->size < peer_b->offset + num) 25659191Skris /* no ring buffer wrap-around for non-copying interface */ 25759191Skris num = peer_b->size - peer_b->offset; 25859191Skris assert(num > 0); 25959191Skris 26059191Skris if (buf != NULL) 26159191Skris *buf = peer_b->buf + peer_b->offset; 26259191Skris return num; 26359191Skris } 26459191Skris 26559191Skrisstatic ssize_t bio_nread(BIO *bio, char **buf, size_t num_) 26659191Skris { 26759191Skris struct bio_bio_st *b, *peer_b; 26859191Skris ssize_t num, available; 26959191Skris 27059191Skris if (num_ > SSIZE_MAX) 27159191Skris num = SSIZE_MAX; 27259191Skris else 27359191Skris num = (ssize_t)num_; 27459191Skris 27559191Skris available = bio_nread0(bio, buf); 27659191Skris if (num > available) 27759191Skris num = available; 27859191Skris if (num <= 0) 27959191Skris return num; 28059191Skris 28159191Skris b = bio->ptr; 28259191Skris peer_b = b->peer->ptr; 28359191Skris 28459191Skris peer_b->len -= num; 28559191Skris if (peer_b->len) 28659191Skris { 28759191Skris peer_b->offset += num; 28859191Skris assert(peer_b->offset <= peer_b->size); 28959191Skris if (peer_b->offset == peer_b->size) 29059191Skris peer_b->offset = 0; 29159191Skris } 29259191Skris else 29359191Skris peer_b->offset = 0; 29459191Skris 29559191Skris return num; 29659191Skris } 29759191Skris 29859191Skris 29968651Skrisstatic int bio_write(BIO *bio, const char *buf, int num_) 30055714Skris { 30155714Skris size_t num = num_; 30255714Skris size_t rest; 30355714Skris struct bio_bio_st *b; 30455714Skris 30555714Skris BIO_clear_retry_flags(bio); 30655714Skris 30755714Skris if (!bio->init || buf == NULL || num == 0) 30855714Skris return 0; 30955714Skris 31055714Skris b = bio->ptr; 31155714Skris assert(b != NULL); 31255714Skris assert(b->peer != NULL); 31355714Skris assert(b->buf != NULL); 31455714Skris 31555714Skris b->request = 0; 31655714Skris if (b->closed) 31755714Skris { 31855714Skris /* we already closed */ 31955714Skris BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); 32055714Skris return -1; 32155714Skris } 32255714Skris 32355714Skris assert(b->len <= b->size); 32455714Skris 32555714Skris if (b->len == b->size) 32655714Skris { 32755714Skris BIO_set_retry_write(bio); /* buffer is full */ 32855714Skris return -1; 32955714Skris } 33055714Skris 33155714Skris /* we can write */ 33255714Skris if (num > b->size - b->len) 33355714Skris num = b->size - b->len; 33455714Skris 33555714Skris /* now write "num" bytes */ 33655714Skris 33755714Skris rest = num; 33855714Skris 33955714Skris assert(rest > 0); 34055714Skris do /* one or two iterations */ 34155714Skris { 34255714Skris size_t write_offset; 34355714Skris size_t chunk; 34455714Skris 34555714Skris assert(b->len + rest <= b->size); 34655714Skris 34755714Skris write_offset = b->offset + b->len; 34855714Skris if (write_offset >= b->size) 34955714Skris write_offset -= b->size; 35055714Skris /* b->buf[write_offset] is the first byte we can write to. */ 35155714Skris 35255714Skris if (write_offset + rest <= b->size) 35355714Skris chunk = rest; 35455714Skris else 35555714Skris /* wrap around ring buffer */ 35655714Skris chunk = b->size - write_offset; 35755714Skris 35855714Skris memcpy(b->buf + write_offset, buf, chunk); 35955714Skris 36055714Skris b->len += chunk; 36155714Skris 36255714Skris assert(b->len <= b->size); 36355714Skris 36455714Skris rest -= chunk; 36555714Skris buf += chunk; 36655714Skris } 36755714Skris while (rest); 36855714Skris 36955714Skris return num; 37055714Skris } 37155714Skris 37259191Skris/* non-copying interface: provide pointer to region to write to 37359191Skris * bio_nwrite0: check how much space is available 37459191Skris * bio_nwrite: also increase length 37559191Skris * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() 37659191Skris * or just bio_nwrite(), write to buffer) 37759191Skris */ 37859191Skrisstatic ssize_t bio_nwrite0(BIO *bio, char **buf) 37959191Skris { 38059191Skris struct bio_bio_st *b; 38159191Skris size_t num; 38259191Skris size_t write_offset; 38355714Skris 38459191Skris BIO_clear_retry_flags(bio); 38559191Skris 38659191Skris if (!bio->init) 38759191Skris return 0; 38859191Skris 38959191Skris b = bio->ptr; 39059191Skris assert(b != NULL); 39159191Skris assert(b->peer != NULL); 39259191Skris assert(b->buf != NULL); 39359191Skris 39459191Skris b->request = 0; 39559191Skris if (b->closed) 39659191Skris { 39759191Skris BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); 39859191Skris return -1; 39959191Skris } 40059191Skris 40159191Skris assert(b->len <= b->size); 40259191Skris 40359191Skris if (b->len == b->size) 40459191Skris { 40559191Skris BIO_set_retry_write(bio); 40659191Skris return -1; 40759191Skris } 40859191Skris 40959191Skris num = b->size - b->len; 41059191Skris write_offset = b->offset + b->len; 41159191Skris if (write_offset >= b->size) 41259191Skris write_offset -= b->size; 41359191Skris if (write_offset + num > b->size) 41459191Skris /* no ring buffer wrap-around for non-copying interface 41559191Skris * (to fulfil the promise by BIO_ctrl_get_write_guarantee, 41659191Skris * BIO_nwrite may have to be called twice) */ 41759191Skris num = b->size - write_offset; 41859191Skris 41959191Skris if (buf != NULL) 42059191Skris *buf = b->buf + write_offset; 42159191Skris assert(write_offset + num <= b->size); 42259191Skris 42359191Skris return num; 42459191Skris } 42559191Skris 42659191Skrisstatic ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) 42759191Skris { 42859191Skris struct bio_bio_st *b; 42959191Skris ssize_t num, space; 43059191Skris 43159191Skris if (num_ > SSIZE_MAX) 43259191Skris num = SSIZE_MAX; 43359191Skris else 43459191Skris num = (ssize_t)num_; 43559191Skris 43659191Skris space = bio_nwrite0(bio, buf); 43759191Skris if (num > space) 43859191Skris num = space; 43959191Skris if (num <= 0) 44059191Skris return num; 44159191Skris b = bio->ptr; 44259191Skris assert(b != NULL); 44359191Skris b->len += num; 44459191Skris assert(b->len <= b->size); 44559191Skris 44659191Skris return num; 44759191Skris } 44859191Skris 44959191Skris 45055714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 45155714Skris { 45255714Skris long ret; 45355714Skris struct bio_bio_st *b = bio->ptr; 45455714Skris 45555714Skris assert(b != NULL); 45655714Skris 45755714Skris switch (cmd) 45855714Skris { 45955714Skris /* specific CTRL codes */ 46055714Skris 46155714Skris case BIO_C_SET_WRITE_BUF_SIZE: 46255714Skris if (b->peer) 46355714Skris { 46455714Skris BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); 46555714Skris ret = 0; 46655714Skris } 46755714Skris else if (num == 0) 46855714Skris { 46955714Skris BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); 47055714Skris ret = 0; 47155714Skris } 47255714Skris else 47355714Skris { 47455714Skris size_t new_size = num; 47555714Skris 47655714Skris if (b->size != new_size) 47755714Skris { 47855714Skris if (b->buf) 47955714Skris { 48068651Skris OPENSSL_free(b->buf); 48155714Skris b->buf = NULL; 48255714Skris } 48355714Skris b->size = new_size; 48455714Skris } 48555714Skris ret = 1; 48655714Skris } 48755714Skris break; 48855714Skris 48955714Skris case BIO_C_GET_WRITE_BUF_SIZE: 49089837Skris ret = (long) b->size; 49189837Skris break; 49255714Skris 49355714Skris case BIO_C_MAKE_BIO_PAIR: 49455714Skris { 49555714Skris BIO *other_bio = ptr; 49655714Skris 49755714Skris if (bio_make_pair(bio, other_bio)) 49855714Skris ret = 1; 49955714Skris else 50055714Skris ret = 0; 50155714Skris } 50255714Skris break; 50355714Skris 50455714Skris case BIO_C_DESTROY_BIO_PAIR: 50555714Skris /* Effects both BIOs in the pair -- call just once! 50655714Skris * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ 50755714Skris bio_destroy_pair(bio); 50855714Skris ret = 1; 50955714Skris break; 51055714Skris 51155714Skris case BIO_C_GET_WRITE_GUARANTEE: 51255714Skris /* How many bytes can the caller feed to the next write 51359191Skris * without having to keep any? */ 51455714Skris if (b->peer == NULL || b->closed) 51555714Skris ret = 0; 51655714Skris else 51755714Skris ret = (long) b->size - b->len; 51855714Skris break; 51955714Skris 52055714Skris case BIO_C_GET_READ_REQUEST: 52159191Skris /* If the peer unsuccessfully tried to read, how many bytes 52255714Skris * were requested? (As with BIO_CTRL_PENDING, that number 52355714Skris * can usually be treated as boolean.) */ 52455714Skris ret = (long) b->request; 52555714Skris break; 52655714Skris 52759191Skris case BIO_C_RESET_READ_REQUEST: 52859191Skris /* Reset request. (Can be useful after read attempts 52959191Skris * at the other side that are meant to be non-blocking, 53059191Skris * e.g. when probing SSL_read to see if any data is 53159191Skris * available.) */ 53259191Skris b->request = 0; 53359191Skris ret = 1; 53459191Skris break; 53559191Skris 53655714Skris case BIO_C_SHUTDOWN_WR: 53755714Skris /* similar to shutdown(..., SHUT_WR) */ 53855714Skris b->closed = 1; 53955714Skris ret = 1; 54055714Skris break; 54155714Skris 54259191Skris case BIO_C_NREAD0: 54359191Skris /* prepare for non-copying read */ 54459191Skris ret = (long) bio_nread0(bio, ptr); 54559191Skris break; 54659191Skris 54759191Skris case BIO_C_NREAD: 54859191Skris /* non-copying read */ 54959191Skris ret = (long) bio_nread(bio, ptr, (size_t) num); 55059191Skris break; 55159191Skris 55259191Skris case BIO_C_NWRITE0: 55359191Skris /* prepare for non-copying write */ 55459191Skris ret = (long) bio_nwrite0(bio, ptr); 55559191Skris break; 55655714Skris 55759191Skris case BIO_C_NWRITE: 55859191Skris /* non-copying write */ 55959191Skris ret = (long) bio_nwrite(bio, ptr, (size_t) num); 56059191Skris break; 56159191Skris 56259191Skris 56355714Skris /* standard CTRL codes follow */ 56455714Skris 56555714Skris case BIO_CTRL_RESET: 56655714Skris if (b->buf != NULL) 56755714Skris { 56855714Skris b->len = 0; 56955714Skris b->offset = 0; 57055714Skris } 57155714Skris ret = 0; 57255714Skris break; 57355714Skris 57455714Skris case BIO_CTRL_GET_CLOSE: 57555714Skris ret = bio->shutdown; 57655714Skris break; 57755714Skris 57855714Skris case BIO_CTRL_SET_CLOSE: 57955714Skris bio->shutdown = (int) num; 58055714Skris ret = 1; 58155714Skris break; 58255714Skris 58355714Skris case BIO_CTRL_PENDING: 58455714Skris if (b->peer != NULL) 58555714Skris { 58655714Skris struct bio_bio_st *peer_b = b->peer->ptr; 58755714Skris 58855714Skris ret = (long) peer_b->len; 58955714Skris } 59055714Skris else 59155714Skris ret = 0; 59255714Skris break; 59355714Skris 59455714Skris case BIO_CTRL_WPENDING: 59555714Skris if (b->buf != NULL) 59655714Skris ret = (long) b->len; 59755714Skris else 59855714Skris ret = 0; 59955714Skris break; 60055714Skris 60155714Skris case BIO_CTRL_DUP: 60255714Skris /* See BIO_dup_chain for circumstances we have to expect. */ 60355714Skris { 60455714Skris BIO *other_bio = ptr; 60555714Skris struct bio_bio_st *other_b; 60655714Skris 60755714Skris assert(other_bio != NULL); 60855714Skris other_b = other_bio->ptr; 60955714Skris assert(other_b != NULL); 61055714Skris 61155714Skris assert(other_b->buf == NULL); /* other_bio is always fresh */ 61255714Skris 61355714Skris other_b->size = b->size; 61455714Skris } 61555714Skris 61655714Skris ret = 1; 61755714Skris break; 61855714Skris 61955714Skris case BIO_CTRL_FLUSH: 62055714Skris ret = 1; 62155714Skris break; 62255714Skris 62355714Skris case BIO_CTRL_EOF: 62455714Skris { 62555714Skris BIO *other_bio = ptr; 62655714Skris 62755714Skris if (other_bio) 62855714Skris { 62955714Skris struct bio_bio_st *other_b = other_bio->ptr; 63055714Skris 63155714Skris assert(other_b != NULL); 63255714Skris ret = other_b->len == 0 && other_b->closed; 63355714Skris } 63455714Skris else 63555714Skris ret = 1; 63655714Skris } 63755714Skris break; 63855714Skris 63955714Skris default: 64055714Skris ret = 0; 64155714Skris } 64255714Skris return ret; 64355714Skris } 64455714Skris 64568651Skrisstatic int bio_puts(BIO *bio, const char *str) 64655714Skris { 64755714Skris return bio_write(bio, str, strlen(str)); 64855714Skris } 64955714Skris 65055714Skris 65155714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2) 65255714Skris { 65355714Skris struct bio_bio_st *b1, *b2; 65455714Skris 65555714Skris assert(bio1 != NULL); 65655714Skris assert(bio2 != NULL); 65755714Skris 65855714Skris b1 = bio1->ptr; 65955714Skris b2 = bio2->ptr; 66055714Skris 66155714Skris if (b1->peer != NULL || b2->peer != NULL) 66255714Skris { 66355714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); 66455714Skris return 0; 66555714Skris } 66655714Skris 66755714Skris if (b1->buf == NULL) 66855714Skris { 66968651Skris b1->buf = OPENSSL_malloc(b1->size); 67055714Skris if (b1->buf == NULL) 67155714Skris { 67255714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 67355714Skris return 0; 67455714Skris } 67555714Skris b1->len = 0; 67655714Skris b1->offset = 0; 67755714Skris } 67855714Skris 67955714Skris if (b2->buf == NULL) 68055714Skris { 68168651Skris b2->buf = OPENSSL_malloc(b2->size); 68255714Skris if (b2->buf == NULL) 68355714Skris { 68455714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 68555714Skris return 0; 68655714Skris } 68755714Skris b2->len = 0; 68855714Skris b2->offset = 0; 68955714Skris } 69055714Skris 69155714Skris b1->peer = bio2; 69255714Skris b1->closed = 0; 69355714Skris b1->request = 0; 69455714Skris b2->peer = bio1; 69555714Skris b2->closed = 0; 69655714Skris b2->request = 0; 69755714Skris 69855714Skris bio1->init = 1; 69955714Skris bio2->init = 1; 70055714Skris 70155714Skris return 1; 70255714Skris } 70355714Skris 70455714Skrisstatic void bio_destroy_pair(BIO *bio) 70555714Skris { 70655714Skris struct bio_bio_st *b = bio->ptr; 70755714Skris 70855714Skris if (b != NULL) 70955714Skris { 71055714Skris BIO *peer_bio = b->peer; 71155714Skris 71255714Skris if (peer_bio != NULL) 71355714Skris { 71455714Skris struct bio_bio_st *peer_b = peer_bio->ptr; 71555714Skris 71655714Skris assert(peer_b != NULL); 71755714Skris assert(peer_b->peer == bio); 71855714Skris 71955714Skris peer_b->peer = NULL; 72055714Skris peer_bio->init = 0; 72155714Skris assert(peer_b->buf != NULL); 72255714Skris peer_b->len = 0; 72355714Skris peer_b->offset = 0; 72455714Skris 72555714Skris b->peer = NULL; 72655714Skris bio->init = 0; 72755714Skris assert(b->buf != NULL); 72855714Skris b->len = 0; 72955714Skris b->offset = 0; 73055714Skris } 73155714Skris } 73255714Skris } 73355714Skris 73455714Skris 73555714Skris/* Exported convenience functions */ 73655714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, 73755714Skris BIO **bio2_p, size_t writebuf2) 73855714Skris { 73955714Skris BIO *bio1 = NULL, *bio2 = NULL; 74055714Skris long r; 74155714Skris int ret = 0; 74255714Skris 74355714Skris bio1 = BIO_new(BIO_s_bio()); 74455714Skris if (bio1 == NULL) 74555714Skris goto err; 74655714Skris bio2 = BIO_new(BIO_s_bio()); 74755714Skris if (bio2 == NULL) 74855714Skris goto err; 74955714Skris 75055714Skris if (writebuf1) 75155714Skris { 75255714Skris r = BIO_set_write_buf_size(bio1, writebuf1); 75355714Skris if (!r) 75455714Skris goto err; 75555714Skris } 75655714Skris if (writebuf2) 75755714Skris { 75855714Skris r = BIO_set_write_buf_size(bio2, writebuf2); 75955714Skris if (!r) 76055714Skris goto err; 76155714Skris } 76255714Skris 76355714Skris r = BIO_make_bio_pair(bio1, bio2); 76455714Skris if (!r) 76555714Skris goto err; 76655714Skris ret = 1; 76755714Skris 76855714Skris err: 76955714Skris if (ret == 0) 77055714Skris { 77155714Skris if (bio1) 77255714Skris { 77355714Skris BIO_free(bio1); 77455714Skris bio1 = NULL; 77555714Skris } 77655714Skris if (bio2) 77755714Skris { 77855714Skris BIO_free(bio2); 77955714Skris bio2 = NULL; 78055714Skris } 78155714Skris } 78255714Skris 78355714Skris *bio1_p = bio1; 78455714Skris *bio2_p = bio2; 78555714Skris return ret; 78655714Skris } 78755714Skris 78855714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio) 78955714Skris { 79055714Skris return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 79155714Skris } 79255714Skris 79355714Skrissize_t BIO_ctrl_get_read_request(BIO *bio) 79455714Skris { 79555714Skris return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 79655714Skris } 79759191Skris 79859191Skrisint BIO_ctrl_reset_read_request(BIO *bio) 79959191Skris { 80059191Skris return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0); 80159191Skris } 80259191Skris 80359191Skris 80459191Skris/* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now 80559191Skris * (conceivably some other BIOs could allow non-copying reads and writes too.) 80659191Skris */ 80759191Skrisint BIO_nread0(BIO *bio, char **buf) 80859191Skris { 80959191Skris long ret; 81059191Skris 81159191Skris if (!bio->init) 81259191Skris { 81359191Skris BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); 81459191Skris return -2; 81559191Skris } 81659191Skris 81759191Skris ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf); 81859191Skris if (ret > INT_MAX) 81959191Skris return INT_MAX; 82059191Skris else 82159191Skris return (int) ret; 82259191Skris } 82359191Skris 82459191Skrisint BIO_nread(BIO *bio, char **buf, int num) 82559191Skris { 82659191Skris int ret; 82759191Skris 82859191Skris if (!bio->init) 82959191Skris { 83059191Skris BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); 83159191Skris return -2; 83259191Skris } 83359191Skris 83459191Skris ret = (int) BIO_ctrl(bio, BIO_C_NREAD, num, buf); 83559191Skris if (ret > 0) 83659191Skris bio->num_read += ret; 83759191Skris return ret; 83859191Skris } 83959191Skris 84059191Skrisint BIO_nwrite0(BIO *bio, char **buf) 84159191Skris { 84259191Skris long ret; 84359191Skris 84459191Skris if (!bio->init) 84559191Skris { 84659191Skris BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); 84759191Skris return -2; 84859191Skris } 84959191Skris 85059191Skris ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf); 85159191Skris if (ret > INT_MAX) 85259191Skris return INT_MAX; 85359191Skris else 85459191Skris return (int) ret; 85559191Skris } 85659191Skris 85759191Skrisint BIO_nwrite(BIO *bio, char **buf, int num) 85859191Skris { 85959191Skris int ret; 86059191Skris 86159191Skris if (!bio->init) 86259191Skris { 86359191Skris BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); 86459191Skris return -2; 86559191Skris } 86659191Skris 86759191Skris ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf); 86859191Skris if (ret > 0) 86959191Skris bio->num_read += ret; 87059191Skris return ret; 87159191Skris } 872