xref: /openbsd-src/lib/libcrypto/bio/bio_lib.c (revision b47f35fc0fdadbb7bcc45988f3e8c8ca81f55ff3)
1*b47f35fcStb /* $OpenBSD: bio_lib.c,v 1.24 2018/02/18 12:58:25 tb Exp $ */
25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
35b37fcf3Sryker  * All rights reserved.
45b37fcf3Sryker  *
55b37fcf3Sryker  * This package is an SSL implementation written
65b37fcf3Sryker  * by Eric Young (eay@cryptsoft.com).
75b37fcf3Sryker  * The implementation was written so as to conform with Netscapes SSL.
85b37fcf3Sryker  *
95b37fcf3Sryker  * This library is free for commercial and non-commercial use as long as
105b37fcf3Sryker  * the following conditions are aheared to.  The following conditions
115b37fcf3Sryker  * apply to all code found in this distribution, be it the RC4, RSA,
125b37fcf3Sryker  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
135b37fcf3Sryker  * included with this distribution is covered by the same copyright terms
145b37fcf3Sryker  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
155b37fcf3Sryker  *
165b37fcf3Sryker  * Copyright remains Eric Young's, and as such any Copyright notices in
175b37fcf3Sryker  * the code are not to be removed.
185b37fcf3Sryker  * If this package is used in a product, Eric Young should be given attribution
195b37fcf3Sryker  * as the author of the parts of the library used.
205b37fcf3Sryker  * This can be in the form of a textual message at program startup or
215b37fcf3Sryker  * in documentation (online or textual) provided with the package.
225b37fcf3Sryker  *
235b37fcf3Sryker  * Redistribution and use in source and binary forms, with or without
245b37fcf3Sryker  * modification, are permitted provided that the following conditions
255b37fcf3Sryker  * are met:
265b37fcf3Sryker  * 1. Redistributions of source code must retain the copyright
275b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer.
285b37fcf3Sryker  * 2. Redistributions in binary form must reproduce the above copyright
295b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer in the
305b37fcf3Sryker  *    documentation and/or other materials provided with the distribution.
315b37fcf3Sryker  * 3. All advertising materials mentioning features or use of this software
325b37fcf3Sryker  *    must display the following acknowledgement:
335b37fcf3Sryker  *    "This product includes cryptographic software written by
345b37fcf3Sryker  *     Eric Young (eay@cryptsoft.com)"
355b37fcf3Sryker  *    The word 'cryptographic' can be left out if the rouines from the library
365b37fcf3Sryker  *    being used are not cryptographic related :-).
375b37fcf3Sryker  * 4. If you include any Windows specific code (or a derivative thereof) from
385b37fcf3Sryker  *    the apps directory (application code) you must include an acknowledgement:
395b37fcf3Sryker  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
405b37fcf3Sryker  *
415b37fcf3Sryker  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
425b37fcf3Sryker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
435b37fcf3Sryker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
445b37fcf3Sryker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
455b37fcf3Sryker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
465b37fcf3Sryker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
475b37fcf3Sryker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485b37fcf3Sryker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
495b37fcf3Sryker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
505b37fcf3Sryker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
515b37fcf3Sryker  * SUCH DAMAGE.
525b37fcf3Sryker  *
535b37fcf3Sryker  * The licence and distribution terms for any publically available version or
545b37fcf3Sryker  * derivative of this code cannot be changed.  i.e. this code cannot simply be
555b37fcf3Sryker  * copied and put under another distribution licence
565b37fcf3Sryker  * [including the GNU Public Licence.]
575b37fcf3Sryker  */
585b37fcf3Sryker 
595b37fcf3Sryker #include <errno.h>
60b6ab114eSjsing #include <stdio.h>
61b6ab114eSjsing 
62913ec974Sbeck #include <openssl/bio.h>
63b6ab114eSjsing #include <openssl/crypto.h>
64b6ab114eSjsing #include <openssl/err.h>
65913ec974Sbeck #include <openssl/stack.h>
665b37fcf3Sryker 
67ae7f143bSderaadt BIO *
68ae7f143bSderaadt BIO_new(BIO_METHOD *method)
695b37fcf3Sryker {
705b37fcf3Sryker 	BIO *ret = NULL;
715b37fcf3Sryker 
723c6fe066Sderaadt 	ret = malloc(sizeof(BIO));
73c3d505beSjsing 	if (ret == NULL) {
745067ae9fSbeck 		BIOerror(ERR_R_MALLOC_FAILURE);
755b37fcf3Sryker 		return (NULL);
765b37fcf3Sryker 	}
77c3d505beSjsing 	if (!BIO_set(ret, method)) {
786f3a6cb1Sbeck 		free(ret);
795b37fcf3Sryker 		ret = NULL;
805b37fcf3Sryker 	}
815b37fcf3Sryker 	return (ret);
825b37fcf3Sryker }
835b37fcf3Sryker 
84c3d505beSjsing int
85c3d505beSjsing BIO_set(BIO *bio, BIO_METHOD *method)
865b37fcf3Sryker {
875b37fcf3Sryker 	bio->method = method;
885b37fcf3Sryker 	bio->callback = NULL;
895b37fcf3Sryker 	bio->cb_arg = NULL;
905b37fcf3Sryker 	bio->init = 0;
915b37fcf3Sryker 	bio->shutdown = 1;
925b37fcf3Sryker 	bio->flags = 0;
935b37fcf3Sryker 	bio->retry_reason = 0;
945b37fcf3Sryker 	bio->num = 0;
955b37fcf3Sryker 	bio->ptr = NULL;
965b37fcf3Sryker 	bio->prev_bio = NULL;
975b37fcf3Sryker 	bio->next_bio = NULL;
985b37fcf3Sryker 	bio->references = 1;
995b37fcf3Sryker 	bio->num_read = 0L;
1005b37fcf3Sryker 	bio->num_write = 0L;
101da347917Sbeck 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
1025b37fcf3Sryker 	if (method->create != NULL)
103c3d505beSjsing 		if (!method->create(bio)) {
104da347917Sbeck 			CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
105da347917Sbeck 			    &bio->ex_data);
1065b37fcf3Sryker 			return (0);
107da347917Sbeck 		}
1085b37fcf3Sryker 	return (1);
1095b37fcf3Sryker }
1105b37fcf3Sryker 
111c3d505beSjsing int
112c3d505beSjsing BIO_free(BIO *a)
1135b37fcf3Sryker {
114c32db552Sdjm 	int i;
1155b37fcf3Sryker 
116c3d505beSjsing 	if (a == NULL)
117c3d505beSjsing 		return (0);
1185b37fcf3Sryker 
1195b37fcf3Sryker 	i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO);
120c3d505beSjsing 	if (i > 0)
121c3d505beSjsing 		return (1);
1225b37fcf3Sryker 	if ((a->callback != NULL) &&
1235b37fcf3Sryker 	    ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0))
1245b37fcf3Sryker 		return (i);
1255b37fcf3Sryker 
126da347917Sbeck 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
1275b37fcf3Sryker 
1287803ca5eSmiod 	if (a->method != NULL && a->method->destroy != NULL)
129c32db552Sdjm 		a->method->destroy(a);
1306f3a6cb1Sbeck 	free(a);
1315b37fcf3Sryker 	return (1);
1325b37fcf3Sryker }
1335b37fcf3Sryker 
134c3d505beSjsing void
135c3d505beSjsing BIO_vfree(BIO *a)
136c3d505beSjsing {
137c3d505beSjsing 	BIO_free(a);
138c3d505beSjsing }
139c109e398Sbeck 
140*b47f35fcStb void *
141*b47f35fcStb BIO_get_data(BIO *a)
142*b47f35fcStb {
143*b47f35fcStb 	return (a->ptr);
144*b47f35fcStb }
145*b47f35fcStb 
146*b47f35fcStb void
147*b47f35fcStb BIO_set_data(BIO *a, void *ptr)
148*b47f35fcStb {
149*b47f35fcStb 	a->ptr = ptr;
150*b47f35fcStb }
151*b47f35fcStb 
152*b47f35fcStb void
153*b47f35fcStb BIO_set_init(BIO *a, int init)
154*b47f35fcStb {
155*b47f35fcStb 	a->init = init;
156*b47f35fcStb }
157*b47f35fcStb 
158c3d505beSjsing void
159c3d505beSjsing BIO_clear_flags(BIO *b, int flags)
1604fcf65c5Sdjm {
1614fcf65c5Sdjm 	b->flags &= ~flags;
1624fcf65c5Sdjm }
1634fcf65c5Sdjm 
164c3d505beSjsing int
165c3d505beSjsing BIO_test_flags(const BIO *b, int flags)
1664fcf65c5Sdjm {
1674fcf65c5Sdjm 	return (b->flags & flags);
1684fcf65c5Sdjm }
1694fcf65c5Sdjm 
170c3d505beSjsing void
171c3d505beSjsing BIO_set_flags(BIO *b, int flags)
1724fcf65c5Sdjm {
1734fcf65c5Sdjm 	b->flags |= flags;
1744fcf65c5Sdjm }
1754fcf65c5Sdjm 
176c3d505beSjsing long
177c3d505beSjsing (*BIO_get_callback(const BIO *b))(struct bio_st *, int, const char *, int,
178c3d505beSjsing     long, long)
1794fcf65c5Sdjm {
1804fcf65c5Sdjm 	return b->callback;
1814fcf65c5Sdjm }
1824fcf65c5Sdjm 
183c3d505beSjsing void
184c3d505beSjsing BIO_set_callback(BIO *b, long (*cb)(struct bio_st *, int, const char *, int,
185c3d505beSjsing     long, long))
1864fcf65c5Sdjm {
1874fcf65c5Sdjm 	b->callback = cb;
1884fcf65c5Sdjm }
1894fcf65c5Sdjm 
190c3d505beSjsing void
191c3d505beSjsing BIO_set_callback_arg(BIO *b, char *arg)
1924fcf65c5Sdjm {
1934fcf65c5Sdjm 	b->cb_arg = arg;
1944fcf65c5Sdjm }
1954fcf65c5Sdjm 
196c3d505beSjsing char *
197c3d505beSjsing BIO_get_callback_arg(const BIO *b)
1984fcf65c5Sdjm {
1994fcf65c5Sdjm 	return b->cb_arg;
2004fcf65c5Sdjm }
2014fcf65c5Sdjm 
202c3d505beSjsing const char *
203c3d505beSjsing BIO_method_name(const BIO *b)
2044fcf65c5Sdjm {
2054fcf65c5Sdjm 	return b->method->name;
2064fcf65c5Sdjm }
2074fcf65c5Sdjm 
208c3d505beSjsing int
209c3d505beSjsing BIO_method_type(const BIO *b)
2104fcf65c5Sdjm {
2114fcf65c5Sdjm 	return b->method->type;
2124fcf65c5Sdjm }
2134fcf65c5Sdjm 
214c3d505beSjsing int
215c3d505beSjsing BIO_read(BIO *b, void *out, int outl)
2165b37fcf3Sryker {
2175b37fcf3Sryker 	int i;
2184fcf65c5Sdjm 	long (*cb)(BIO *, int, const char *, int, long, long);
2195b37fcf3Sryker 
220c3d505beSjsing 	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
2215067ae9fSbeck 		BIOerror(BIO_R_UNSUPPORTED_METHOD);
2225b37fcf3Sryker 		return (-2);
2235b37fcf3Sryker 	}
2245b37fcf3Sryker 
2255b37fcf3Sryker 	cb = b->callback;
2265b37fcf3Sryker 	if ((cb != NULL) &&
2275b37fcf3Sryker 	    ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0))
2285b37fcf3Sryker 		return (i);
2295b37fcf3Sryker 
230c3d505beSjsing 	if (!b->init) {
2315067ae9fSbeck 		BIOerror(BIO_R_UNINITIALIZED);
2325b37fcf3Sryker 		return (-2);
2335b37fcf3Sryker 	}
2345b37fcf3Sryker 
2355b37fcf3Sryker 	i = b->method->bread(b, out, outl);
236913ec974Sbeck 
237c3d505beSjsing 	if (i > 0)
238c3d505beSjsing 		b->num_read += (unsigned long)i;
2395b37fcf3Sryker 
2405b37fcf3Sryker 	if (cb != NULL)
2415b37fcf3Sryker 		i = (int)cb(b, BIO_CB_READ|BIO_CB_RETURN, out, outl,
2425b37fcf3Sryker 		    0L, (long)i);
2435b37fcf3Sryker 	return (i);
2445b37fcf3Sryker }
2455b37fcf3Sryker 
246c3d505beSjsing int
247c3d505beSjsing BIO_write(BIO *b, const void *in, int inl)
2485b37fcf3Sryker {
2495b37fcf3Sryker 	int i;
2504fcf65c5Sdjm 	long (*cb)(BIO *, int, const char *, int, long, long);
2515b37fcf3Sryker 
2525b37fcf3Sryker 	if (b == NULL)
2535b37fcf3Sryker 		return (0);
2545b37fcf3Sryker 
2555b37fcf3Sryker 	cb = b->callback;
256c3d505beSjsing 	if ((b->method == NULL) || (b->method->bwrite == NULL)) {
2575067ae9fSbeck 		BIOerror(BIO_R_UNSUPPORTED_METHOD);
2585b37fcf3Sryker 		return (-2);
2595b37fcf3Sryker 	}
2605b37fcf3Sryker 
2615b37fcf3Sryker 	if ((cb != NULL) &&
2625b37fcf3Sryker 	    ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0))
2635b37fcf3Sryker 		return (i);
2645b37fcf3Sryker 
265c3d505beSjsing 	if (!b->init) {
2665067ae9fSbeck 		BIOerror(BIO_R_UNINITIALIZED);
2675b37fcf3Sryker 		return (-2);
2685b37fcf3Sryker 	}
2695b37fcf3Sryker 
2705b37fcf3Sryker 	i = b->method->bwrite(b, in, inl);
271913ec974Sbeck 
272c3d505beSjsing 	if (i > 0)
273c3d505beSjsing 		b->num_write += (unsigned long)i;
2745b37fcf3Sryker 
275c109e398Sbeck 	if (cb != NULL)
2765b37fcf3Sryker 		i = (int)cb(b, BIO_CB_WRITE|BIO_CB_RETURN, in, inl,
2775b37fcf3Sryker 		    0L, (long)i);
2785b37fcf3Sryker 	return (i);
2795b37fcf3Sryker }
2805b37fcf3Sryker 
281c3d505beSjsing int
282c3d505beSjsing BIO_puts(BIO *b, const char *in)
2835b37fcf3Sryker {
2845b37fcf3Sryker 	int i;
2854fcf65c5Sdjm 	long (*cb)(BIO *, int, const char *, int, long, long);
2865b37fcf3Sryker 
287c3d505beSjsing 	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
2885067ae9fSbeck 		BIOerror(BIO_R_UNSUPPORTED_METHOD);
2895b37fcf3Sryker 		return (-2);
2905b37fcf3Sryker 	}
2915b37fcf3Sryker 
2925b37fcf3Sryker 	cb = b->callback;
2935b37fcf3Sryker 
2945b37fcf3Sryker 	if ((cb != NULL) &&
2955b37fcf3Sryker 	    ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0))
2965b37fcf3Sryker 		return (i);
2975b37fcf3Sryker 
298c3d505beSjsing 	if (!b->init) {
2995067ae9fSbeck 		BIOerror(BIO_R_UNINITIALIZED);
3005b37fcf3Sryker 		return (-2);
3015b37fcf3Sryker 	}
3025b37fcf3Sryker 
3035b37fcf3Sryker 	i = b->method->bputs(b, in);
3045b37fcf3Sryker 
305c3d505beSjsing 	if (i > 0)
306c3d505beSjsing 		b->num_write += (unsigned long)i;
307c109e398Sbeck 
3085b37fcf3Sryker 	if (cb != NULL)
309c3d505beSjsing 		i = (int)cb(b, BIO_CB_PUTS|BIO_CB_RETURN, in, 0, 0L, (long)i);
3105b37fcf3Sryker 	return (i);
3115b37fcf3Sryker }
3125b37fcf3Sryker 
313c3d505beSjsing int
314c3d505beSjsing BIO_gets(BIO *b, char *in, int inl)
3155b37fcf3Sryker {
3165b37fcf3Sryker 	int i;
3174fcf65c5Sdjm 	long (*cb)(BIO *, int, const char *, int, long, long);
3185b37fcf3Sryker 
319c3d505beSjsing 	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
3205067ae9fSbeck 		BIOerror(BIO_R_UNSUPPORTED_METHOD);
3215b37fcf3Sryker 		return (-2);
3225b37fcf3Sryker 	}
3235b37fcf3Sryker 
3245b37fcf3Sryker 	cb = b->callback;
3255b37fcf3Sryker 
3265b37fcf3Sryker 	if ((cb != NULL) &&
3275b37fcf3Sryker 	    ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0))
3285b37fcf3Sryker 		return (i);
3295b37fcf3Sryker 
330c3d505beSjsing 	if (!b->init) {
3315067ae9fSbeck 		BIOerror(BIO_R_UNINITIALIZED);
3325b37fcf3Sryker 		return (-2);
3335b37fcf3Sryker 	}
3345b37fcf3Sryker 
3355b37fcf3Sryker 	i = b->method->bgets(b, in, inl);
3365b37fcf3Sryker 
3375b37fcf3Sryker 	if (cb != NULL)
338c3d505beSjsing 		i = (int)cb(b, BIO_CB_GETS|BIO_CB_RETURN, in, inl, 0L, (long)i);
3395b37fcf3Sryker 	return (i);
3405b37fcf3Sryker }
3415b37fcf3Sryker 
342c3d505beSjsing int
343c3d505beSjsing BIO_indent(BIO *b, int indent, int max)
344767fe2ffSmarkus {
345767fe2ffSmarkus 	if (indent < 0)
346767fe2ffSmarkus 		indent = 0;
347767fe2ffSmarkus 	if (indent > max)
348767fe2ffSmarkus 		indent = max;
349767fe2ffSmarkus 	while (indent--)
350767fe2ffSmarkus 		if (BIO_puts(b, " ") != 1)
351767fe2ffSmarkus 			return 0;
352767fe2ffSmarkus 	return 1;
353767fe2ffSmarkus }
354767fe2ffSmarkus 
355c3d505beSjsing long
356c3d505beSjsing BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
3575b37fcf3Sryker {
3585b37fcf3Sryker 	int i;
3595b37fcf3Sryker 
3605b37fcf3Sryker 	i = iarg;
3615b37fcf3Sryker 	return (BIO_ctrl(b, cmd, larg, (char *)&i));
3625b37fcf3Sryker }
3635b37fcf3Sryker 
364ae7f143bSderaadt char *
365ae7f143bSderaadt BIO_ptr_ctrl(BIO *b, int cmd, long larg)
3665b37fcf3Sryker {
3675b37fcf3Sryker 	char *p = NULL;
3685b37fcf3Sryker 
3695b37fcf3Sryker 	if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
3705b37fcf3Sryker 		return (NULL);
3715b37fcf3Sryker 	else
3725b37fcf3Sryker 		return (p);
3735b37fcf3Sryker }
3745b37fcf3Sryker 
375c3d505beSjsing long
376c3d505beSjsing BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
3775b37fcf3Sryker {
3785b37fcf3Sryker 	long ret;
3794fcf65c5Sdjm 	long (*cb)(BIO *, int, const char *, int, long, long);
3805b37fcf3Sryker 
381c3d505beSjsing 	if (b == NULL)
382c3d505beSjsing 		return (0);
3835b37fcf3Sryker 
384c3d505beSjsing 	if ((b->method == NULL) || (b->method->ctrl == NULL)) {
3855067ae9fSbeck 		BIOerror(BIO_R_UNSUPPORTED_METHOD);
3865b37fcf3Sryker 		return (-2);
3875b37fcf3Sryker 	}
3885b37fcf3Sryker 
3895b37fcf3Sryker 	cb = b->callback;
3905b37fcf3Sryker 
3915b37fcf3Sryker 	if ((cb != NULL) &&
3925b37fcf3Sryker 	    ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0))
3935b37fcf3Sryker 		return (ret);
3945b37fcf3Sryker 
3955b37fcf3Sryker 	ret = b->method->ctrl(b, cmd, larg, parg);
3965b37fcf3Sryker 
3975b37fcf3Sryker 	if (cb != NULL)
398c3d505beSjsing 		ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, parg, cmd, larg, ret);
3995b37fcf3Sryker 	return (ret);
4005b37fcf3Sryker }
4015b37fcf3Sryker 
402c3d505beSjsing long
403c3d505beSjsing BIO_callback_ctrl(BIO *b, int cmd,
404c3d505beSjsing     void (*fp)(struct bio_st *, int, const char *, int, long, long))
405ba5406e9Sbeck {
406ba5406e9Sbeck 	long ret;
4074fcf65c5Sdjm 	long (*cb)(BIO *, int, const char *, int, long, long);
408ba5406e9Sbeck 
409c3d505beSjsing 	if (b == NULL)
410c3d505beSjsing 		return (0);
411ba5406e9Sbeck 
412c3d505beSjsing 	if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) {
4135067ae9fSbeck 		BIOerror(BIO_R_UNSUPPORTED_METHOD);
414ba5406e9Sbeck 		return (-2);
415ba5406e9Sbeck 	}
416ba5406e9Sbeck 
417ba5406e9Sbeck 	cb = b->callback;
418ba5406e9Sbeck 
419ba5406e9Sbeck 	if ((cb != NULL) &&
420ba5406e9Sbeck 	    ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0))
421ba5406e9Sbeck 		return (ret);
422ba5406e9Sbeck 
423ba5406e9Sbeck 	ret = b->method->callback_ctrl(b, cmd, fp);
424ba5406e9Sbeck 
425ba5406e9Sbeck 	if (cb != NULL)
426c3d505beSjsing 		ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, (void *)&fp, cmd, 0, ret);
427ba5406e9Sbeck 	return (ret);
428ba5406e9Sbeck }
429ba5406e9Sbeck 
430913ec974Sbeck /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
431913ec974Sbeck  * do; but those macros have inappropriate return type, and for interfacing
432913ec974Sbeck  * from other programming languages, C macros aren't much of a help anyway. */
433c3d505beSjsing size_t
434c3d505beSjsing BIO_ctrl_pending(BIO *bio)
435913ec974Sbeck {
436913ec974Sbeck 	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
437913ec974Sbeck }
438913ec974Sbeck 
439c3d505beSjsing size_t
440c3d505beSjsing BIO_ctrl_wpending(BIO *bio)
441913ec974Sbeck {
442913ec974Sbeck 	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
443913ec974Sbeck }
444913ec974Sbeck 
445913ec974Sbeck 
4465b37fcf3Sryker /* put the 'bio' on the end of b's list of operators */
447ae7f143bSderaadt BIO *
448ae7f143bSderaadt BIO_push(BIO *b, BIO *bio)
4495b37fcf3Sryker {
4505b37fcf3Sryker 	BIO *lb;
4515b37fcf3Sryker 
452c3d505beSjsing 	if (b == NULL)
453c3d505beSjsing 		return (bio);
4545b37fcf3Sryker 	lb = b;
4555b37fcf3Sryker 	while (lb->next_bio != NULL)
4565b37fcf3Sryker 		lb = lb->next_bio;
4575b37fcf3Sryker 	lb->next_bio = bio;
4585b37fcf3Sryker 	if (bio != NULL)
4595b37fcf3Sryker 		bio->prev_bio = lb;
4605b37fcf3Sryker 	/* called to do internal processing */
4610a5d6edeSdjm 	BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
4625b37fcf3Sryker 	return (b);
4635b37fcf3Sryker }
4645b37fcf3Sryker 
4655b37fcf3Sryker /* Remove the first and return the rest */
466ae7f143bSderaadt BIO *
467ae7f143bSderaadt BIO_pop(BIO *b)
4685b37fcf3Sryker {
4695b37fcf3Sryker 	BIO *ret;
4705b37fcf3Sryker 
471c3d505beSjsing 	if (b == NULL)
472c3d505beSjsing 		return (NULL);
4735b37fcf3Sryker 	ret = b->next_bio;
4745b37fcf3Sryker 
4750a5d6edeSdjm 	BIO_ctrl(b, BIO_CTRL_POP, 0, b);
476767fe2ffSmarkus 
4775b37fcf3Sryker 	if (b->prev_bio != NULL)
4785b37fcf3Sryker 		b->prev_bio->next_bio = b->next_bio;
4795b37fcf3Sryker 	if (b->next_bio != NULL)
4805b37fcf3Sryker 		b->next_bio->prev_bio = b->prev_bio;
4815b37fcf3Sryker 
4825b37fcf3Sryker 	b->next_bio = NULL;
4835b37fcf3Sryker 	b->prev_bio = NULL;
4845b37fcf3Sryker 	return (ret);
4855b37fcf3Sryker }
4865b37fcf3Sryker 
487ae7f143bSderaadt BIO *
488ae7f143bSderaadt BIO_get_retry_BIO(BIO *bio, int *reason)
4895b37fcf3Sryker {
4905b37fcf3Sryker 	BIO *b, *last;
4915b37fcf3Sryker 
4925b37fcf3Sryker 	b = last = bio;
493c3d505beSjsing 	for (;;) {
494598842deSjsing 		if (!BIO_should_retry(b))
495598842deSjsing 			break;
4965b37fcf3Sryker 		last = b;
4975b37fcf3Sryker 		b = b->next_bio;
498c3d505beSjsing 		if (b == NULL)
499c3d505beSjsing 			break;
5005b37fcf3Sryker 	}
501c3d505beSjsing 	if (reason != NULL)
502c3d505beSjsing 		*reason = last->retry_reason;
5035b37fcf3Sryker 	return (last);
5045b37fcf3Sryker }
5055b37fcf3Sryker 
506c3d505beSjsing int
507c3d505beSjsing BIO_get_retry_reason(BIO *bio)
5085b37fcf3Sryker {
5095b37fcf3Sryker 	return (bio->retry_reason);
5105b37fcf3Sryker }
5115b37fcf3Sryker 
512ae7f143bSderaadt BIO *
513ae7f143bSderaadt BIO_find_type(BIO *bio, int type)
5145b37fcf3Sryker {
5155b37fcf3Sryker 	int mt, mask;
5165b37fcf3Sryker 
517c3d505beSjsing 	if (!bio)
518c3d505beSjsing 		return NULL;
5195b37fcf3Sryker 	mask = type & 0xff;
5205b37fcf3Sryker 	do {
521c3d505beSjsing 		if (bio->method != NULL) {
5225b37fcf3Sryker 			mt = bio->method->type;
523c3d505beSjsing 			if (!mask) {
524c3d505beSjsing 				if (mt & type)
525c3d505beSjsing 					return (bio);
526c3d505beSjsing 			} else if (mt == type)
5275b37fcf3Sryker 				return (bio);
5285b37fcf3Sryker 		}
5295b37fcf3Sryker 		bio = bio->next_bio;
5305b37fcf3Sryker 	} while (bio != NULL);
5315b37fcf3Sryker 	return (NULL);
5325b37fcf3Sryker }
5335b37fcf3Sryker 
534ae7f143bSderaadt BIO *
535ae7f143bSderaadt BIO_next(BIO *b)
536c109e398Sbeck {
537c3d505beSjsing 	if (!b)
538c3d505beSjsing 		return NULL;
539c109e398Sbeck 	return b->next_bio;
540c109e398Sbeck }
541c109e398Sbeck 
542c3d505beSjsing void
543c3d505beSjsing BIO_free_all(BIO *bio)
5445b37fcf3Sryker {
5455b37fcf3Sryker 	BIO *b;
5465b37fcf3Sryker 	int ref;
5475b37fcf3Sryker 
548c3d505beSjsing 	while (bio != NULL) {
5495b37fcf3Sryker 		b = bio;
5505b37fcf3Sryker 		ref = b->references;
5515b37fcf3Sryker 		bio = bio->next_bio;
5525b37fcf3Sryker 		BIO_free(b);
5535b37fcf3Sryker 		/* Since ref count > 1, don't free anyone else. */
554c3d505beSjsing 		if (ref > 1)
555c3d505beSjsing 			break;
5565b37fcf3Sryker 	}
5575b37fcf3Sryker }
5585b37fcf3Sryker 
559ae7f143bSderaadt BIO *
560ae7f143bSderaadt BIO_dup_chain(BIO *in)
5615b37fcf3Sryker {
5625cdd308eSdjm 	BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;
5635b37fcf3Sryker 
564c3d505beSjsing 	for (bio = in; bio != NULL; bio = bio->next_bio) {
565598842deSjsing 		if ((new_bio = BIO_new(bio->method)) == NULL)
566598842deSjsing 			goto err;
5675cdd308eSdjm 		new_bio->callback = bio->callback;
5685cdd308eSdjm 		new_bio->cb_arg = bio->cb_arg;
5695cdd308eSdjm 		new_bio->init = bio->init;
5705cdd308eSdjm 		new_bio->shutdown = bio->shutdown;
5715cdd308eSdjm 		new_bio->flags = bio->flags;
5725b37fcf3Sryker 
5735b37fcf3Sryker 		/* This will let SSL_s_sock() work with stdin/stdout */
5745cdd308eSdjm 		new_bio->num = bio->num;
5755b37fcf3Sryker 
576c3d505beSjsing 		if (!BIO_dup_state(bio, (char *)new_bio)) {
5775cdd308eSdjm 			BIO_free(new_bio);
5785b37fcf3Sryker 			goto err;
5795b37fcf3Sryker 		}
5805b37fcf3Sryker 
5815b37fcf3Sryker 		/* copy app data */
582c3d505beSjsing 		if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO,
583c3d505beSjsing 		    &new_bio->ex_data, &bio->ex_data))
5845b37fcf3Sryker 			goto err;
5855b37fcf3Sryker 
586c3d505beSjsing 		if (ret == NULL) {
5875cdd308eSdjm 			eoc = new_bio;
5885b37fcf3Sryker 			ret = eoc;
589c3d505beSjsing 		} else {
5905cdd308eSdjm 			BIO_push(eoc, new_bio);
5915cdd308eSdjm 			eoc = new_bio;
5925b37fcf3Sryker 		}
5935b37fcf3Sryker 	}
5945b37fcf3Sryker 	return (ret);
5955b37fcf3Sryker err:
5965b37fcf3Sryker 	BIO_free(ret);
5975b37fcf3Sryker 	return (NULL);
598c3d505beSjsing 
5995b37fcf3Sryker }
6005b37fcf3Sryker 
601c3d505beSjsing void
602c3d505beSjsing BIO_copy_next_retry(BIO *b)
6035b37fcf3Sryker {
6045b37fcf3Sryker 	BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
6055b37fcf3Sryker 	b->retry_reason = b->next_bio->retry_reason;
6065b37fcf3Sryker }
6075b37fcf3Sryker 
608c3d505beSjsing int
609c3d505beSjsing BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
610ba5406e9Sbeck     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
6115b37fcf3Sryker {
612da347917Sbeck 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
613da347917Sbeck 	    new_func, dup_func, free_func);
6145b37fcf3Sryker }
6155b37fcf3Sryker 
616c3d505beSjsing int
617c3d505beSjsing BIO_set_ex_data(BIO *bio, int idx, void *data)
6185b37fcf3Sryker {
6195b37fcf3Sryker 	return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data));
6205b37fcf3Sryker }
6215b37fcf3Sryker 
622ae7f143bSderaadt void *
623ae7f143bSderaadt BIO_get_ex_data(BIO *bio, int idx)
6245b37fcf3Sryker {
6255b37fcf3Sryker 	return (CRYPTO_get_ex_data(&(bio->ex_data), idx));
6265b37fcf3Sryker }
6275b37fcf3Sryker 
628c3d505beSjsing unsigned long
629c3d505beSjsing BIO_number_read(BIO *bio)
630ba5406e9Sbeck {
631c3d505beSjsing 	if (bio)
632c3d505beSjsing 		return bio->num_read;
633ba5406e9Sbeck 	return 0;
634ba5406e9Sbeck }
635ba5406e9Sbeck 
636c3d505beSjsing unsigned long
637c3d505beSjsing BIO_number_written(BIO *bio)
638ba5406e9Sbeck {
639c3d505beSjsing 	if (bio)
640c3d505beSjsing 		return bio->num_write;
641ba5406e9Sbeck 	return 0;
642ba5406e9Sbeck }
643