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