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