bss_bio.c revision 55714
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> 1655714Skris#include <stdlib.h> 1755714Skris#include <string.h> 1855714Skris 1955714Skris#include <openssl/bio.h> 2055714Skris#include <openssl/err.h> 2155714Skris#include <openssl/crypto.h> 2255714Skris 2355714Skrisstatic int bio_new(BIO *bio); 2455714Skrisstatic int bio_free(BIO *bio); 2555714Skrisstatic int bio_read(BIO *bio, char *buf, int size); 2655714Skrisstatic int bio_write(BIO *bio, char *buf, int num); 2755714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr); 2855714Skrisstatic int bio_puts(BIO *bio, char *str); 2955714Skris 3055714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2); 3155714Skrisstatic void bio_destroy_pair(BIO *bio); 3255714Skris 3355714Skrisstatic BIO_METHOD methods_biop = 3455714Skris{ 3555714Skris BIO_TYPE_BIO, 3655714Skris "BIO pair", 3755714Skris bio_write, 3855714Skris bio_read, 3955714Skris bio_puts, 4055714Skris NULL /* no bio_gets */, 4155714Skris bio_ctrl, 4255714Skris bio_new, 4355714Skris bio_free 4455714Skris}; 4555714Skris 4655714SkrisBIO_METHOD *BIO_s_bio(void) 4755714Skris { 4855714Skris return &methods_biop; 4955714Skris } 5055714Skris 5155714Skrisstruct bio_bio_st 5255714Skris{ 5355714Skris BIO *peer; /* NULL if buf == NULL. 5455714Skris * If peer != NULL, then peer->ptr is also a bio_bio_st, 5555714Skris * and its "peer" member points back to us. 5655714Skris * peer != NULL iff init != 0 in the BIO. */ 5755714Skris 5855714Skris /* This is for what we write (i.e. reading uses peer's struct): */ 5955714Skris int closed; /* valid iff peer != NULL */ 6055714Skris size_t len; /* valid iff buf != NULL; 0 if peer == NULL */ 6155714Skris size_t offset; /* valid iff buf != NULL; 0 if len == 0 */ 6255714Skris size_t size; 6355714Skris char *buf; /* "size" elements (if != NULL) */ 6455714Skris 6555714Skris size_t request; /* valid iff peer != NULL; 0 if len != 0, 6655714Skris * otherwise set by peer to number of bytes 6755714Skris * it (unsuccesfully) tried to read, 6855714Skris * never more than buffer space (size-len) warrants. */ 6955714Skris}; 7055714Skris 7155714Skrisstatic int bio_new(BIO *bio) 7255714Skris { 7355714Skris struct bio_bio_st *b; 7455714Skris 7555714Skris b = Malloc(sizeof *b); 7655714Skris if (b == NULL) 7755714Skris return 0; 7855714Skris 7955714Skris b->peer = NULL; 8055714Skris b->size = 17*1024; /* enough for one TLS record (just a default) */ 8155714Skris b->buf = NULL; 8255714Skris 8355714Skris bio->ptr = b; 8455714Skris return 1; 8555714Skris } 8655714Skris 8755714Skris 8855714Skrisstatic int bio_free(BIO *bio) 8955714Skris { 9055714Skris struct bio_bio_st *b; 9155714Skris 9255714Skris if (bio == NULL) 9355714Skris return 0; 9455714Skris b = bio->ptr; 9555714Skris 9655714Skris assert(b != NULL); 9755714Skris 9855714Skris if (b->peer) 9955714Skris bio_destroy_pair(bio); 10055714Skris 10155714Skris if (b->buf != NULL) 10255714Skris { 10355714Skris Free(b->buf); 10455714Skris } 10555714Skris 10655714Skris Free(b); 10755714Skris 10855714Skris return 1; 10955714Skris } 11055714Skris 11155714Skris 11255714Skris 11355714Skrisstatic int bio_read(BIO *bio, char *buf, int size_) 11455714Skris { 11555714Skris size_t size = size_; 11655714Skris size_t rest; 11755714Skris struct bio_bio_st *b, *peer_b; 11855714Skris 11955714Skris BIO_clear_retry_flags(bio); 12055714Skris 12155714Skris if (!bio->init) 12255714Skris return 0; 12355714Skris 12455714Skris b = bio->ptr; 12555714Skris assert(b != NULL); 12655714Skris assert(b->peer != NULL); 12755714Skris peer_b = b->peer->ptr; 12855714Skris assert(peer_b != NULL); 12955714Skris assert(peer_b->buf != NULL); 13055714Skris 13155714Skris peer_b->request = 0; /* will be set in "retry_read" situation */ 13255714Skris 13355714Skris if (buf == NULL || size == 0) 13455714Skris return 0; 13555714Skris 13655714Skris if (peer_b->len == 0) 13755714Skris { 13855714Skris if (peer_b->closed) 13955714Skris return 0; /* writer has closed, and no data is left */ 14055714Skris else 14155714Skris { 14255714Skris BIO_set_retry_read(bio); /* buffer is empty */ 14355714Skris if (size <= peer_b->size) 14455714Skris peer_b->request = size; 14555714Skris else 14655714Skris /* don't ask for more than the peer can 14755714Skris * deliver in one write */ 14855714Skris peer_b->request = peer_b->size; 14955714Skris return -1; 15055714Skris } 15155714Skris } 15255714Skris 15355714Skris /* we can read */ 15455714Skris if (peer_b->len < size) 15555714Skris size = peer_b->len; 15655714Skris 15755714Skris /* now read "size" bytes */ 15855714Skris 15955714Skris rest = size; 16055714Skris 16155714Skris assert(rest > 0); 16255714Skris do /* one or two iterations */ 16355714Skris { 16455714Skris size_t chunk; 16555714Skris 16655714Skris assert(rest <= peer_b->len); 16755714Skris if (peer_b->offset + rest <= peer_b->size) 16855714Skris chunk = rest; 16955714Skris else 17055714Skris /* wrap around ring buffer */ 17155714Skris chunk = peer_b->size - peer_b->offset; 17255714Skris assert(peer_b->offset + chunk <= peer_b->size); 17355714Skris 17455714Skris memcpy(buf, peer_b->buf + peer_b->offset, chunk); 17555714Skris 17655714Skris peer_b->len -= chunk; 17755714Skris if (peer_b->len) 17855714Skris { 17955714Skris peer_b->offset += chunk; 18055714Skris assert(peer_b->offset <= peer_b->size); 18155714Skris if (peer_b->offset == peer_b->size) 18255714Skris peer_b->offset = 0; 18355714Skris buf += chunk; 18455714Skris } 18555714Skris else 18655714Skris { 18755714Skris /* buffer now empty, no need to advance "buf" */ 18855714Skris assert(chunk == rest); 18955714Skris peer_b->offset = 0; 19055714Skris } 19155714Skris rest -= chunk; 19255714Skris } 19355714Skris while (rest); 19455714Skris 19555714Skris return size; 19655714Skris } 19755714Skris 19855714Skrisstatic int bio_write(BIO *bio, char *buf, int num_) 19955714Skris { 20055714Skris size_t num = num_; 20155714Skris size_t rest; 20255714Skris struct bio_bio_st *b; 20355714Skris 20455714Skris BIO_clear_retry_flags(bio); 20555714Skris 20655714Skris if (!bio->init || buf == NULL || num == 0) 20755714Skris return 0; 20855714Skris 20955714Skris b = bio->ptr; 21055714Skris assert(b != NULL); 21155714Skris assert(b->peer != NULL); 21255714Skris assert(b->buf != NULL); 21355714Skris 21455714Skris b->request = 0; 21555714Skris if (b->closed) 21655714Skris { 21755714Skris /* we already closed */ 21855714Skris BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); 21955714Skris return -1; 22055714Skris } 22155714Skris 22255714Skris assert(b->len <= b->size); 22355714Skris 22455714Skris if (b->len == b->size) 22555714Skris { 22655714Skris BIO_set_retry_write(bio); /* buffer is full */ 22755714Skris return -1; 22855714Skris } 22955714Skris 23055714Skris /* we can write */ 23155714Skris if (num > b->size - b->len) 23255714Skris num = b->size - b->len; 23355714Skris 23455714Skris /* now write "num" bytes */ 23555714Skris 23655714Skris rest = num; 23755714Skris 23855714Skris assert(rest > 0); 23955714Skris do /* one or two iterations */ 24055714Skris { 24155714Skris size_t write_offset; 24255714Skris size_t chunk; 24355714Skris 24455714Skris assert(b->len + rest <= b->size); 24555714Skris 24655714Skris write_offset = b->offset + b->len; 24755714Skris if (write_offset >= b->size) 24855714Skris write_offset -= b->size; 24955714Skris /* b->buf[write_offset] is the first byte we can write to. */ 25055714Skris 25155714Skris if (write_offset + rest <= b->size) 25255714Skris chunk = rest; 25355714Skris else 25455714Skris /* wrap around ring buffer */ 25555714Skris chunk = b->size - write_offset; 25655714Skris 25755714Skris memcpy(b->buf + write_offset, buf, chunk); 25855714Skris 25955714Skris b->len += chunk; 26055714Skris 26155714Skris assert(b->len <= b->size); 26255714Skris 26355714Skris rest -= chunk; 26455714Skris buf += chunk; 26555714Skris } 26655714Skris while (rest); 26755714Skris 26855714Skris return num; 26955714Skris } 27055714Skris 27155714Skris 27255714Skrisstatic long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) 27355714Skris { 27455714Skris long ret; 27555714Skris struct bio_bio_st *b = bio->ptr; 27655714Skris 27755714Skris assert(b != NULL); 27855714Skris 27955714Skris switch (cmd) 28055714Skris { 28155714Skris /* specific CTRL codes */ 28255714Skris 28355714Skris case BIO_C_SET_WRITE_BUF_SIZE: 28455714Skris if (b->peer) 28555714Skris { 28655714Skris BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); 28755714Skris ret = 0; 28855714Skris } 28955714Skris else if (num == 0) 29055714Skris { 29155714Skris BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); 29255714Skris ret = 0; 29355714Skris } 29455714Skris else 29555714Skris { 29655714Skris size_t new_size = num; 29755714Skris 29855714Skris if (b->size != new_size) 29955714Skris { 30055714Skris if (b->buf) 30155714Skris { 30255714Skris Free(b->buf); 30355714Skris b->buf = NULL; 30455714Skris } 30555714Skris b->size = new_size; 30655714Skris } 30755714Skris ret = 1; 30855714Skris } 30955714Skris break; 31055714Skris 31155714Skris case BIO_C_GET_WRITE_BUF_SIZE: 31255714Skris num = (long) b->size; 31355714Skris 31455714Skris case BIO_C_MAKE_BIO_PAIR: 31555714Skris { 31655714Skris BIO *other_bio = ptr; 31755714Skris 31855714Skris if (bio_make_pair(bio, other_bio)) 31955714Skris ret = 1; 32055714Skris else 32155714Skris ret = 0; 32255714Skris } 32355714Skris break; 32455714Skris 32555714Skris case BIO_C_DESTROY_BIO_PAIR: 32655714Skris /* Effects both BIOs in the pair -- call just once! 32755714Skris * Or let BIO_free(bio1); BIO_free(bio2); do the job. */ 32855714Skris bio_destroy_pair(bio); 32955714Skris ret = 1; 33055714Skris break; 33155714Skris 33255714Skris case BIO_C_GET_WRITE_GUARANTEE: 33355714Skris /* How many bytes can the caller feed to the next write 33455714Skris * withouth having to keep any? */ 33555714Skris if (b->peer == NULL || b->closed) 33655714Skris ret = 0; 33755714Skris else 33855714Skris ret = (long) b->size - b->len; 33955714Skris break; 34055714Skris 34155714Skris case BIO_C_GET_READ_REQUEST: 34255714Skris /* If the peer unsuccesfully tried to read, how many bytes 34355714Skris * were requested? (As with BIO_CTRL_PENDING, that number 34455714Skris * can usually be treated as boolean.) */ 34555714Skris ret = (long) b->request; 34655714Skris break; 34755714Skris 34855714Skris case BIO_C_SHUTDOWN_WR: 34955714Skris /* similar to shutdown(..., SHUT_WR) */ 35055714Skris b->closed = 1; 35155714Skris ret = 1; 35255714Skris break; 35355714Skris 35455714Skris 35555714Skris /* standard CTRL codes follow */ 35655714Skris 35755714Skris case BIO_CTRL_RESET: 35855714Skris if (b->buf != NULL) 35955714Skris { 36055714Skris b->len = 0; 36155714Skris b->offset = 0; 36255714Skris } 36355714Skris ret = 0; 36455714Skris break; 36555714Skris 36655714Skris case BIO_CTRL_GET_CLOSE: 36755714Skris ret = bio->shutdown; 36855714Skris break; 36955714Skris 37055714Skris case BIO_CTRL_SET_CLOSE: 37155714Skris bio->shutdown = (int) num; 37255714Skris ret = 1; 37355714Skris break; 37455714Skris 37555714Skris case BIO_CTRL_PENDING: 37655714Skris if (b->peer != NULL) 37755714Skris { 37855714Skris struct bio_bio_st *peer_b = b->peer->ptr; 37955714Skris 38055714Skris ret = (long) peer_b->len; 38155714Skris } 38255714Skris else 38355714Skris ret = 0; 38455714Skris break; 38555714Skris 38655714Skris case BIO_CTRL_WPENDING: 38755714Skris if (b->buf != NULL) 38855714Skris ret = (long) b->len; 38955714Skris else 39055714Skris ret = 0; 39155714Skris break; 39255714Skris 39355714Skris case BIO_CTRL_DUP: 39455714Skris /* See BIO_dup_chain for circumstances we have to expect. */ 39555714Skris { 39655714Skris BIO *other_bio = ptr; 39755714Skris struct bio_bio_st *other_b; 39855714Skris 39955714Skris assert(other_bio != NULL); 40055714Skris other_b = other_bio->ptr; 40155714Skris assert(other_b != NULL); 40255714Skris 40355714Skris assert(other_b->buf == NULL); /* other_bio is always fresh */ 40455714Skris 40555714Skris other_b->size = b->size; 40655714Skris } 40755714Skris 40855714Skris ret = 1; 40955714Skris break; 41055714Skris 41155714Skris case BIO_CTRL_FLUSH: 41255714Skris ret = 1; 41355714Skris break; 41455714Skris 41555714Skris case BIO_CTRL_EOF: 41655714Skris { 41755714Skris BIO *other_bio = ptr; 41855714Skris 41955714Skris if (other_bio) 42055714Skris { 42155714Skris struct bio_bio_st *other_b = other_bio->ptr; 42255714Skris 42355714Skris assert(other_b != NULL); 42455714Skris ret = other_b->len == 0 && other_b->closed; 42555714Skris } 42655714Skris else 42755714Skris ret = 1; 42855714Skris } 42955714Skris break; 43055714Skris 43155714Skris default: 43255714Skris ret = 0; 43355714Skris } 43455714Skris return ret; 43555714Skris } 43655714Skris 43755714Skrisstatic int bio_puts(BIO *bio, char *str) 43855714Skris { 43955714Skris return bio_write(bio, str, strlen(str)); 44055714Skris } 44155714Skris 44255714Skris 44355714Skrisstatic int bio_make_pair(BIO *bio1, BIO *bio2) 44455714Skris { 44555714Skris struct bio_bio_st *b1, *b2; 44655714Skris 44755714Skris assert(bio1 != NULL); 44855714Skris assert(bio2 != NULL); 44955714Skris 45055714Skris b1 = bio1->ptr; 45155714Skris b2 = bio2->ptr; 45255714Skris 45355714Skris if (b1->peer != NULL || b2->peer != NULL) 45455714Skris { 45555714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); 45655714Skris return 0; 45755714Skris } 45855714Skris 45955714Skris if (b1->buf == NULL) 46055714Skris { 46155714Skris b1->buf = Malloc(b1->size); 46255714Skris if (b1->buf == NULL) 46355714Skris { 46455714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 46555714Skris return 0; 46655714Skris } 46755714Skris b1->len = 0; 46855714Skris b1->offset = 0; 46955714Skris } 47055714Skris 47155714Skris if (b2->buf == NULL) 47255714Skris { 47355714Skris b2->buf = Malloc(b2->size); 47455714Skris if (b2->buf == NULL) 47555714Skris { 47655714Skris BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); 47755714Skris return 0; 47855714Skris } 47955714Skris b2->len = 0; 48055714Skris b2->offset = 0; 48155714Skris } 48255714Skris 48355714Skris b1->peer = bio2; 48455714Skris b1->closed = 0; 48555714Skris b1->request = 0; 48655714Skris b2->peer = bio1; 48755714Skris b2->closed = 0; 48855714Skris b2->request = 0; 48955714Skris 49055714Skris bio1->init = 1; 49155714Skris bio2->init = 1; 49255714Skris 49355714Skris return 1; 49455714Skris } 49555714Skris 49655714Skrisstatic void bio_destroy_pair(BIO *bio) 49755714Skris { 49855714Skris struct bio_bio_st *b = bio->ptr; 49955714Skris 50055714Skris if (b != NULL) 50155714Skris { 50255714Skris BIO *peer_bio = b->peer; 50355714Skris 50455714Skris if (peer_bio != NULL) 50555714Skris { 50655714Skris struct bio_bio_st *peer_b = peer_bio->ptr; 50755714Skris 50855714Skris assert(peer_b != NULL); 50955714Skris assert(peer_b->peer == bio); 51055714Skris 51155714Skris peer_b->peer = NULL; 51255714Skris peer_bio->init = 0; 51355714Skris assert(peer_b->buf != NULL); 51455714Skris peer_b->len = 0; 51555714Skris peer_b->offset = 0; 51655714Skris 51755714Skris b->peer = NULL; 51855714Skris bio->init = 0; 51955714Skris assert(b->buf != NULL); 52055714Skris b->len = 0; 52155714Skris b->offset = 0; 52255714Skris } 52355714Skris } 52455714Skris } 52555714Skris 52655714Skris 52755714Skris/* Exported convenience functions */ 52855714Skrisint BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, 52955714Skris BIO **bio2_p, size_t writebuf2) 53055714Skris { 53155714Skris BIO *bio1 = NULL, *bio2 = NULL; 53255714Skris long r; 53355714Skris int ret = 0; 53455714Skris 53555714Skris bio1 = BIO_new(BIO_s_bio()); 53655714Skris if (bio1 == NULL) 53755714Skris goto err; 53855714Skris bio2 = BIO_new(BIO_s_bio()); 53955714Skris if (bio2 == NULL) 54055714Skris goto err; 54155714Skris 54255714Skris if (writebuf1) 54355714Skris { 54455714Skris r = BIO_set_write_buf_size(bio1, writebuf1); 54555714Skris if (!r) 54655714Skris goto err; 54755714Skris } 54855714Skris if (writebuf2) 54955714Skris { 55055714Skris r = BIO_set_write_buf_size(bio2, writebuf2); 55155714Skris if (!r) 55255714Skris goto err; 55355714Skris } 55455714Skris 55555714Skris r = BIO_make_bio_pair(bio1, bio2); 55655714Skris if (!r) 55755714Skris goto err; 55855714Skris ret = 1; 55955714Skris 56055714Skris err: 56155714Skris if (ret == 0) 56255714Skris { 56355714Skris if (bio1) 56455714Skris { 56555714Skris BIO_free(bio1); 56655714Skris bio1 = NULL; 56755714Skris } 56855714Skris if (bio2) 56955714Skris { 57055714Skris BIO_free(bio2); 57155714Skris bio2 = NULL; 57255714Skris } 57355714Skris } 57455714Skris 57555714Skris *bio1_p = bio1; 57655714Skris *bio2_p = bio2; 57755714Skris return ret; 57855714Skris } 57955714Skris 58055714Skrissize_t BIO_ctrl_get_write_guarantee(BIO *bio) 58155714Skris { 58255714Skris return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL); 58355714Skris } 58455714Skris 58555714Skrissize_t BIO_ctrl_get_read_request(BIO *bio) 58655714Skris { 58755714Skris return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL); 58855714Skris } 589