1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * All rights reserved. 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This package is an SSL implementation written 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * by Eric Young (eay@cryptsoft.com). 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The implementation was written so as to conform with Netscapes SSL. 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This library is free for commercial and non-commercial use as long as 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the following conditions are aheared to. The following conditions 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * apply to all code found in this distribution, be it the RC4, RSA, 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * lhash, DES, etc., code; not just the SSL code. The SSL documentation 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * included with this distribution is covered by the same copyright terms 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com). 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright remains Eric Young's, and as such any Copyright notices in 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the code are not to be removed. 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * If this package is used in a product, Eric Young should be given attribution 18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * as the author of the parts of the library used. 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This can be in the form of a textual message at program startup or 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * in documentation (online or textual) provided with the package. 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met: 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the copyright 26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer. 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer in the 29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * documentation and/or other materials provided with the distribution. 30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this software 31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * must display the following acknowledgement: 32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes cryptographic software written by 33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Eric Young (eay@cryptsoft.com)" 34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The word 'cryptographic' can be left out if the rouines from the library 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * being used are not cryptographic related :-). 36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. If you include any Windows specific code (or a derivative thereof) from 37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the apps directory (application code) you must include an acknowledgement: 38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUCH DAMAGE. 51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The licence and distribution terms for any publically available version or 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * derivative of this code cannot be changed. i.e. this code cannot simply be 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copied and put under another distribution licence 55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * [including the GNU Public Licence.] */ 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bio.h> 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 594f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley#include <assert.h> 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <errno.h> 61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <limits.h> 62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h> 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h> 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/thread.h> 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 6853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley#include "../internal.h" 6953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* BIO_set initialises a BIO structure to have the given type and sets the 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * reference count to one. It returns one on success or zero on error. */ 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int bio_set(BIO *bio, const BIO_METHOD *method) { 74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* This function can be called with a stack allocated |BIO| so we have to 75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * assume that the contents of |BIO| are arbitary. This also means that it'll 76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * leak memory if you call |BIO_set| twice on the same BIO. */ 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley memset(bio, 0, sizeof(BIO)); 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->method = method; 80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->shutdown = 1; 81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->references = 1; 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 83e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (method->create != NULL && !method->create(bio)) { 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 90d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBIO *BIO_new(const BIO_METHOD *method) { 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO *ret = OPENSSL_malloc(sizeof(BIO)); 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ret == NULL) { 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(BIO, BIO_new, ERR_R_MALLOC_FAILURE); 94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!bio_set(ret, method)) { 98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(ret); 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = NULL; 100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_free(BIO *bio) { 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO *next_bio; 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (; bio != NULL; bio = next_bio) { 10953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley if (!CRYPTO_refcount_dec_and_test_zero(&bio->references)) { 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio->callback != NULL) { 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int i = (int)bio->callback(bio, BIO_CB_FREE, NULL, 0, 0, 1); 115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (i <= 0) { 116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return i; 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley next_bio = BIO_pop(bio); 121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio->method != NULL && bio->method->destroy != NULL) { 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->method->destroy(bio); 124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(bio); 127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 131e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam LangleyBIO *BIO_up_ref(BIO *bio) { 13253b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley CRYPTO_refcount_inc(&bio->references); 133e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return bio; 134e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 135e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_vfree(BIO *bio) { 137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_free(bio); 138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_free_all(BIO *bio) { 141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_free(bio); 142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 144d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int bio_io(BIO *bio, void *buf, int len, size_t method_offset, 145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int callback_flags, size_t *num) { 146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int i; 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley typedef int (*io_func_t)(BIO *, char *, int); 148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley io_func_t io_func = NULL; 149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio != NULL && bio->method != NULL) { 151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley io_func = 152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *((const io_func_t *)(((const uint8_t *)bio->method) + method_offset)); 153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (io_func == NULL) { 156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(BIO, bio_io, BIO_R_UNSUPPORTED_METHOD); 157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return -2; 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio->callback != NULL) { 161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i = (int) bio->callback(bio, callback_flags, buf, len, 0L, 1L); 162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (i <= 0) { 163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return i; 164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!bio->init) { 168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(BIO, bio_io, BIO_R_UNINITIALIZED); 169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return -2; 170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i = 0; 173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (buf != NULL && len > 0) { 174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i = io_func(bio, buf, len); 175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (i > 0) { 178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *num += i; 179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio->callback != NULL) { 182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i = (int)(bio->callback(bio, callback_flags | BIO_CB_RETURN, buf, len, 0L, 183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (long)i)); 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return i; 187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 189d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_read(BIO *bio, void *buf, int len) { 190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio_io(bio, buf, len, offsetof(BIO_METHOD, bread), BIO_CB_READ, 191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley &bio->num_read); 192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_gets(BIO *bio, char *buf, int len) { 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio_io(bio, buf, len, offsetof(BIO_METHOD, bgets), BIO_CB_GETS, 196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley &bio->num_read); 197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_write(BIO *bio, const void *in, int inl) { 200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio_io(bio, (char *)in, inl, offsetof(BIO_METHOD, bwrite), 201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_CB_WRITE, &bio->num_write); 202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 204d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_puts(BIO *bio, const char *in) { 205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_write(bio, in, strlen(in)); 206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 208d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_flush(BIO *bio) { 209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL); 210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 212d9e397b599b13d642138480a28c14db7a136bf0Adam Langleylong BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) { 213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley long ret; 214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio == NULL) { 216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio->method == NULL || bio->method->ctrl == NULL) { 220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(BIO, BIO_ctrl, BIO_R_UNSUPPORTED_METHOD); 221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return -2; 222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio->callback != NULL) { 225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = bio->callback(bio, BIO_CB_CTRL, parg, cmd, larg, 1); 226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ret <= 0) { 227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = bio->method->ctrl(bio, cmd, larg, parg); 232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio->callback != NULL) { 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = bio->callback(bio, BIO_CB_CTRL | BIO_CB_RETURN, parg, cmd, larg, ret); 235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 240d9e397b599b13d642138480a28c14db7a136bf0Adam Langleychar *BIO_ptr_ctrl(BIO *b, int cmd, long larg) { 241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley char *p = NULL; 242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BIO_ctrl(b, cmd, larg, (void *)&p) <= 0) { 244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return p; 248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 250d9e397b599b13d642138480a28c14db7a136bf0Adam Langleylong BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) { 251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int i = iarg; 252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_ctrl(b, cmd, larg, (void *)&i); 254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 256d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_reset(BIO *bio) { 257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL); 258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 260d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_set_flags(BIO *bio, int flags) { 261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->flags |= flags; 262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 264d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_test_flags(const BIO *bio, int flags) { 265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio->flags & flags; 266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 268d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_should_read(const BIO *bio) { 269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_test_flags(bio, BIO_FLAGS_READ); 270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 272d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_should_write(const BIO *bio) { 273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_test_flags(bio, BIO_FLAGS_WRITE); 274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 276d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_should_retry(const BIO *bio) { 277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_test_flags(bio, BIO_FLAGS_SHOULD_RETRY); 278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 280d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_should_io_special(const BIO *bio) { 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_test_flags(bio, BIO_FLAGS_IO_SPECIAL); 282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 284d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_get_retry_reason(const BIO *bio) { return bio->retry_reason; } 285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 286d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_clear_flags(BIO *bio, int flags) { 287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->flags &= ~flags; 288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 290d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_set_retry_read(BIO *bio) { 291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY; 292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 294d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_set_retry_write(BIO *bio) { 295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->flags |= BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY; 296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 298d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const int kRetryFlags = BIO_FLAGS_RWS | BIO_FLAGS_SHOULD_RETRY; 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 300d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_get_retry_flags(BIO *bio) { 301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio->flags & kRetryFlags; 302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 304d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_clear_retry_flags(BIO *bio) { 305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->flags &= ~kRetryFlags; 306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->retry_reason = 0; 307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 309d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_method_type(const BIO *bio) { return bio->method->type; } 310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 311d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_copy_next_retry(BIO *bio) { 312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_clear_retry_flags(bio); 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO_set_flags(bio, BIO_get_retry_flags(bio->next_bio)); 314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->retry_reason = bio->next_bio->retry_reason; 315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 317d9e397b599b13d642138480a28c14db7a136bf0Adam Langleylong BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) { 318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley long ret; 319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio_info_cb cb; 320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio == NULL) { 322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio->method == NULL || bio->method->callback_ctrl == NULL) { 326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_PUT_ERROR(BIO, BIO_callback_ctrl, BIO_R_UNSUPPORTED_METHOD); 327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley cb = bio->callback; 331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (cb != NULL) { 333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = cb(bio, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L); 334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ret <= 0) { 335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 338d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = bio->method->callback_ctrl(bio, cmd, fp); 340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (cb != NULL) { 342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = cb(bio, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, cmd, 0, ret); 343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 348d9e397b599b13d642138480a28c14db7a136bf0Adam Langleysize_t BIO_pending(const BIO *bio) { 349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL); 350d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 352d9e397b599b13d642138480a28c14db7a136bf0Adam Langleysize_t BIO_ctrl_pending(const BIO *bio) { 353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_pending(bio); 354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 356d9e397b599b13d642138480a28c14db7a136bf0Adam Langleysize_t BIO_wpending(const BIO *bio) { 357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL); 358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 360d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_set_close(BIO *bio, int close_flag) { 361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, close_flag, NULL); 362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 364d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_set_callback(BIO *bio, bio_info_cb callback_func) { 365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->callback = callback_func; 366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 368d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_set_callback_arg(BIO *bio, char *arg) { 369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->cb_arg = arg; 370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 372d9e397b599b13d642138480a28c14db7a136bf0Adam Langleychar *BIO_get_callback_arg(const BIO *bio) { 373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio->cb_arg; 374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 376d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyOPENSSL_EXPORT size_t BIO_number_read(const BIO *bio) { 377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio->num_read; 378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 380d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyOPENSSL_EXPORT size_t BIO_number_written(const BIO *bio) { 381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio->num_write; 382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 384d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBIO *BIO_push(BIO *bio, BIO *appended_bio) { 385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO *last_bio; 386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio == NULL) { 388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio; 389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley last_bio = bio; 392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (last_bio->next_bio != NULL) { 393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley last_bio = last_bio->next_bio; 394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 395d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley last_bio->next_bio = appended_bio; 397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio; 398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 400d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBIO *BIO_pop(BIO *bio) { 401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIO *ret; 402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio == NULL) { 404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = bio->next_bio; 407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio->next_bio = NULL; 408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 411d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBIO *BIO_next(BIO *bio) { 412d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!bio) { 413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio->next_bio; 416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 418d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyBIO *BIO_find_type(BIO *bio, int type) { 419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int method_type, mask; 420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!bio) { 422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley mask = type & 0xff; 425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley do { 427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (bio->method != NULL) { 428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley method_type = bio->method->type; 429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!mask) { 431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (method_type & type) { 432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio; 433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else if (method_type == type) { 435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return bio; 436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bio = bio->next_bio; 439d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } while (bio != NULL); 440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return NULL; 442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 444d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint BIO_indent(BIO *bio, unsigned indent, unsigned max_indent) { 445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (indent > max_indent) { 446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley indent = max_indent; 447d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 449d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while (indent--) { 450d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BIO_puts(bio, " ") != 1) { 451d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 452d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 453d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 454d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 457d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int print_bio(const char *str, size_t len, void *bio) { 458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return BIO_write((BIO *)bio, str, len); 459d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 460d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 461d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid BIO_print_errors(BIO *bio) { 462d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ERR_print_errors_cb(print_bio, bio); 463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 4644f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 4654f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley/* bio_read_all reads everything from |bio| and prepends |prefix| to it. On 4664f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley * success, |*out| is set to an allocated buffer (which should be freed with 4674f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley * |OPENSSL_free|), |*out_len| is set to its length and one is returned. The 4684f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley * buffer will contain |prefix| followed by the contents of |bio|. On failure, 4694f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley * zero is returned. 4704f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley * 4714f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley * The function will fail if the size of the output would equal or exceed 4724f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley * |max_len|. */ 4734f05b238eec1f3f026657a6da19058143d34ceaaAdam Langleystatic int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len, 4744f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley const uint8_t *prefix, size_t prefix_len, 4754f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley size_t max_len) { 4764f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley static const size_t kChunkSize = 4096; 4774f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 4784f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley size_t len = prefix_len + kChunkSize; 4794f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (len > max_len) { 4804f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley len = max_len; 4814f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 4824f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (len < prefix_len) { 4834f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 4844f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 4854f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley *out = OPENSSL_malloc(len); 4864f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (*out == NULL) { 4874f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 4884f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 4894f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley memcpy(*out, prefix, prefix_len); 4904f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley size_t done = prefix_len; 4914f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 4924f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley for (;;) { 4934f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (done == len) { 4944f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley OPENSSL_free(*out); 4954f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 4964f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 4974f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley const size_t todo = len - done; 4984f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley assert(todo < INT_MAX); 4994f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley const int n = BIO_read(bio, *out + done, todo); 5004f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (n == 0) { 5014f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley *out_len = done; 5024f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 1; 5034f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } else if (n == -1) { 5044f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley OPENSSL_free(*out); 5054f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5064f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5074f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5084f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley done += n; 5094f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (len < max_len && len - done < kChunkSize / 2) { 5104f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley len += kChunkSize; 51153b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley if (len < kChunkSize || len > max_len) { 5124f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley len = max_len; 5134f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5144f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley uint8_t *new_buf = OPENSSL_realloc(*out, len); 5154f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (new_buf == NULL) { 5164f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley OPENSSL_free(*out); 5174f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5184f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5194f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley *out = new_buf; 5204f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5214f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5224f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley} 5234f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5244f05b238eec1f3f026657a6da19058143d34ceaaAdam Langleyint BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) { 5254f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley uint8_t header[6]; 5264f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5274f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley static const size_t kInitialHeaderLen = 2; 5284f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (BIO_read(bio, header, kInitialHeaderLen) != kInitialHeaderLen) { 5294f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5304f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5314f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5324f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley const uint8_t tag = header[0]; 5334f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley const uint8_t length_byte = header[1]; 5344f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5354f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if ((tag & 0x1f) == 0x1f) { 5364f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley /* Long form tags are not supported. */ 5374f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5384f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5394f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5404f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley size_t len, header_len; 5414f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if ((length_byte & 0x80) == 0) { 5424f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley /* Short form length. */ 5434f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley len = length_byte; 5444f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley header_len = kInitialHeaderLen; 5454f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } else { 5464f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley const size_t num_bytes = length_byte & 0x7f; 5474f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5484f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if ((tag & 0x20 /* constructed */) != 0 && num_bytes == 0) { 5494f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley /* indefinite length. */ 5504f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return bio_read_all(bio, out, out_len, header, kInitialHeaderLen, 5514f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley max_len); 5524f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5534f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5544f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (num_bytes == 0 || num_bytes > 4) { 5554f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5564f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5574f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5584f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (BIO_read(bio, header + kInitialHeaderLen, num_bytes) != num_bytes) { 5594f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5604f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5614f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley header_len = kInitialHeaderLen + num_bytes; 5624f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5634f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley uint32_t len32 = 0; 5644f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley unsigned i; 5654f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley for (i = 0; i < num_bytes; i++) { 5664f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley len32 <<= 8; 5674f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley len32 |= header[kInitialHeaderLen + i]; 5684f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5694f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5704f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (len32 < 128) { 5714f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley /* Length should have used short-form encoding. */ 5724f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5734f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5744f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5754f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if ((len32 >> ((num_bytes-1)*8)) == 0) { 5764f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley /* Length should have been at least one byte shorter. */ 5774f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5784f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5794f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5804f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley len = len32; 5814f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5824f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5834f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (len + header_len < len || 5844f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley len + header_len > max_len) { 5854f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5864f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5874f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley len += header_len; 5884f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley *out_len = len; 5894f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 5904f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley *out = OPENSSL_malloc(len); 5914f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (*out == NULL) { 5924f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5934f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 5944f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley memcpy(*out, header, header_len); 5954f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley if (BIO_read(bio, (*out) + header_len, len - header_len) != 5964f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley len - header_len) { 5974f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley OPENSSL_free(*out); 5984f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 0; 5994f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley } 6004f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley 6014f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley return 1; 6024f05b238eec1f3f026657a6da19058143d34ceaaAdam Langley} 603