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