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