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