1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci#include <stdio.h> 13e1051a39Sopenharmony_ci#include <errno.h> 14e1051a39Sopenharmony_ci#include <openssl/crypto.h> 15e1051a39Sopenharmony_ci#include "internal/numbers.h" 16e1051a39Sopenharmony_ci#include "bio_local.h" 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_ci/* 19e1051a39Sopenharmony_ci * Helper macro for the callback to determine whether an operator expects a 20e1051a39Sopenharmony_ci * len parameter or not 21e1051a39Sopenharmony_ci */ 22e1051a39Sopenharmony_ci#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE \ 23e1051a39Sopenharmony_ci || (o) == BIO_CB_GETS) 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 26e1051a39Sopenharmony_ci# define HAS_CALLBACK(b) ((b)->callback != NULL || (b)->callback_ex != NULL) 27e1051a39Sopenharmony_ci#else 28e1051a39Sopenharmony_ci# define HAS_CALLBACK(b) ((b)->callback_ex != NULL) 29e1051a39Sopenharmony_ci#endif 30e1051a39Sopenharmony_ci/* 31e1051a39Sopenharmony_ci * Helper function to work out whether to call the new style callback or the old 32e1051a39Sopenharmony_ci * one, and translate between the two. 33e1051a39Sopenharmony_ci * 34e1051a39Sopenharmony_ci * This has a long return type for consistency with the old callback. Similarly 35e1051a39Sopenharmony_ci * for the "long" used for "inret" 36e1051a39Sopenharmony_ci */ 37e1051a39Sopenharmony_cistatic long bio_call_callback(BIO *b, int oper, const char *argp, size_t len, 38e1051a39Sopenharmony_ci int argi, long argl, long inret, 39e1051a39Sopenharmony_ci size_t *processed) 40e1051a39Sopenharmony_ci{ 41e1051a39Sopenharmony_ci long ret = inret; 42e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 43e1051a39Sopenharmony_ci int bareoper; 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_ci if (b->callback_ex != NULL) 46e1051a39Sopenharmony_ci#endif 47e1051a39Sopenharmony_ci return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed); 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 50e1051a39Sopenharmony_ci /* Strip off any BIO_CB_RETURN flag */ 51e1051a39Sopenharmony_ci bareoper = oper & ~BIO_CB_RETURN; 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ci /* 54e1051a39Sopenharmony_ci * We have an old style callback, so we will have to do nasty casts and 55e1051a39Sopenharmony_ci * check for overflows. 56e1051a39Sopenharmony_ci */ 57e1051a39Sopenharmony_ci if (HAS_LEN_OPER(bareoper)) { 58e1051a39Sopenharmony_ci /* In this case |len| is set, and should be used instead of |argi| */ 59e1051a39Sopenharmony_ci if (len > INT_MAX) 60e1051a39Sopenharmony_ci return -1; 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci argi = (int)len; 63e1051a39Sopenharmony_ci } 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_ci if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { 66e1051a39Sopenharmony_ci if (*processed > INT_MAX) 67e1051a39Sopenharmony_ci return -1; 68e1051a39Sopenharmony_ci inret = *processed; 69e1051a39Sopenharmony_ci } 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ci ret = b->callback(b, oper, argp, argi, argl, inret); 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { 74e1051a39Sopenharmony_ci *processed = (size_t)ret; 75e1051a39Sopenharmony_ci ret = 1; 76e1051a39Sopenharmony_ci } 77e1051a39Sopenharmony_ci#endif 78e1051a39Sopenharmony_ci return ret; 79e1051a39Sopenharmony_ci} 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ciBIO *BIO_new_ex(OSSL_LIB_CTX *libctx, const BIO_METHOD *method) 82e1051a39Sopenharmony_ci{ 83e1051a39Sopenharmony_ci BIO *bio = OPENSSL_zalloc(sizeof(*bio)); 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_ci if (bio == NULL) { 86e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); 87e1051a39Sopenharmony_ci return NULL; 88e1051a39Sopenharmony_ci } 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci bio->libctx = libctx; 91e1051a39Sopenharmony_ci bio->method = method; 92e1051a39Sopenharmony_ci bio->shutdown = 1; 93e1051a39Sopenharmony_ci bio->references = 1; 94e1051a39Sopenharmony_ci 95e1051a39Sopenharmony_ci if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data)) 96e1051a39Sopenharmony_ci goto err; 97e1051a39Sopenharmony_ci 98e1051a39Sopenharmony_ci bio->lock = CRYPTO_THREAD_lock_new(); 99e1051a39Sopenharmony_ci if (bio->lock == NULL) { 100e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); 101e1051a39Sopenharmony_ci CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 102e1051a39Sopenharmony_ci goto err; 103e1051a39Sopenharmony_ci } 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_ci if (method->create != NULL && !method->create(bio)) { 106e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_INIT_FAIL); 107e1051a39Sopenharmony_ci CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 108e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(bio->lock); 109e1051a39Sopenharmony_ci goto err; 110e1051a39Sopenharmony_ci } 111e1051a39Sopenharmony_ci if (method->create == NULL) 112e1051a39Sopenharmony_ci bio->init = 1; 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci return bio; 115e1051a39Sopenharmony_ci 116e1051a39Sopenharmony_cierr: 117e1051a39Sopenharmony_ci OPENSSL_free(bio); 118e1051a39Sopenharmony_ci return NULL; 119e1051a39Sopenharmony_ci} 120e1051a39Sopenharmony_ci 121e1051a39Sopenharmony_ciBIO *BIO_new(const BIO_METHOD *method) 122e1051a39Sopenharmony_ci{ 123e1051a39Sopenharmony_ci return BIO_new_ex(NULL, method); 124e1051a39Sopenharmony_ci} 125e1051a39Sopenharmony_ci 126e1051a39Sopenharmony_ciint BIO_free(BIO *a) 127e1051a39Sopenharmony_ci{ 128e1051a39Sopenharmony_ci int ret; 129e1051a39Sopenharmony_ci 130e1051a39Sopenharmony_ci if (a == NULL) 131e1051a39Sopenharmony_ci return 0; 132e1051a39Sopenharmony_ci 133e1051a39Sopenharmony_ci if (CRYPTO_DOWN_REF(&a->references, &ret, a->lock) <= 0) 134e1051a39Sopenharmony_ci return 0; 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci REF_PRINT_COUNT("BIO", a); 137e1051a39Sopenharmony_ci if (ret > 0) 138e1051a39Sopenharmony_ci return 1; 139e1051a39Sopenharmony_ci REF_ASSERT_ISNT(ret < 0); 140e1051a39Sopenharmony_ci 141e1051a39Sopenharmony_ci if (HAS_CALLBACK(a)) { 142e1051a39Sopenharmony_ci ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL); 143e1051a39Sopenharmony_ci if (ret <= 0) 144e1051a39Sopenharmony_ci return 0; 145e1051a39Sopenharmony_ci } 146e1051a39Sopenharmony_ci 147e1051a39Sopenharmony_ci if ((a->method != NULL) && (a->method->destroy != NULL)) 148e1051a39Sopenharmony_ci a->method->destroy(a); 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_ci CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(a->lock); 153e1051a39Sopenharmony_ci 154e1051a39Sopenharmony_ci OPENSSL_free(a); 155e1051a39Sopenharmony_ci 156e1051a39Sopenharmony_ci return 1; 157e1051a39Sopenharmony_ci} 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_civoid BIO_set_data(BIO *a, void *ptr) 160e1051a39Sopenharmony_ci{ 161e1051a39Sopenharmony_ci a->ptr = ptr; 162e1051a39Sopenharmony_ci} 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_civoid *BIO_get_data(BIO *a) 165e1051a39Sopenharmony_ci{ 166e1051a39Sopenharmony_ci return a->ptr; 167e1051a39Sopenharmony_ci} 168e1051a39Sopenharmony_ci 169e1051a39Sopenharmony_civoid BIO_set_init(BIO *a, int init) 170e1051a39Sopenharmony_ci{ 171e1051a39Sopenharmony_ci a->init = init; 172e1051a39Sopenharmony_ci} 173e1051a39Sopenharmony_ci 174e1051a39Sopenharmony_ciint BIO_get_init(BIO *a) 175e1051a39Sopenharmony_ci{ 176e1051a39Sopenharmony_ci return a->init; 177e1051a39Sopenharmony_ci} 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_civoid BIO_set_shutdown(BIO *a, int shut) 180e1051a39Sopenharmony_ci{ 181e1051a39Sopenharmony_ci a->shutdown = shut; 182e1051a39Sopenharmony_ci} 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_ciint BIO_get_shutdown(BIO *a) 185e1051a39Sopenharmony_ci{ 186e1051a39Sopenharmony_ci return a->shutdown; 187e1051a39Sopenharmony_ci} 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_civoid BIO_vfree(BIO *a) 190e1051a39Sopenharmony_ci{ 191e1051a39Sopenharmony_ci BIO_free(a); 192e1051a39Sopenharmony_ci} 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ciint BIO_up_ref(BIO *a) 195e1051a39Sopenharmony_ci{ 196e1051a39Sopenharmony_ci int i; 197e1051a39Sopenharmony_ci 198e1051a39Sopenharmony_ci if (CRYPTO_UP_REF(&a->references, &i, a->lock) <= 0) 199e1051a39Sopenharmony_ci return 0; 200e1051a39Sopenharmony_ci 201e1051a39Sopenharmony_ci REF_PRINT_COUNT("BIO", a); 202e1051a39Sopenharmony_ci REF_ASSERT_ISNT(i < 2); 203e1051a39Sopenharmony_ci return i > 1; 204e1051a39Sopenharmony_ci} 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_civoid BIO_clear_flags(BIO *b, int flags) 207e1051a39Sopenharmony_ci{ 208e1051a39Sopenharmony_ci b->flags &= ~flags; 209e1051a39Sopenharmony_ci} 210e1051a39Sopenharmony_ci 211e1051a39Sopenharmony_ciint BIO_test_flags(const BIO *b, int flags) 212e1051a39Sopenharmony_ci{ 213e1051a39Sopenharmony_ci return (b->flags & flags); 214e1051a39Sopenharmony_ci} 215e1051a39Sopenharmony_ci 216e1051a39Sopenharmony_civoid BIO_set_flags(BIO *b, int flags) 217e1051a39Sopenharmony_ci{ 218e1051a39Sopenharmony_ci b->flags |= flags; 219e1051a39Sopenharmony_ci} 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 222e1051a39Sopenharmony_ciBIO_callback_fn BIO_get_callback(const BIO *b) 223e1051a39Sopenharmony_ci{ 224e1051a39Sopenharmony_ci return b->callback; 225e1051a39Sopenharmony_ci} 226e1051a39Sopenharmony_ci 227e1051a39Sopenharmony_civoid BIO_set_callback(BIO *b, BIO_callback_fn cb) 228e1051a39Sopenharmony_ci{ 229e1051a39Sopenharmony_ci b->callback = cb; 230e1051a39Sopenharmony_ci} 231e1051a39Sopenharmony_ci#endif 232e1051a39Sopenharmony_ci 233e1051a39Sopenharmony_ciBIO_callback_fn_ex BIO_get_callback_ex(const BIO *b) 234e1051a39Sopenharmony_ci{ 235e1051a39Sopenharmony_ci return b->callback_ex; 236e1051a39Sopenharmony_ci} 237e1051a39Sopenharmony_ci 238e1051a39Sopenharmony_civoid BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb) 239e1051a39Sopenharmony_ci{ 240e1051a39Sopenharmony_ci b->callback_ex = cb; 241e1051a39Sopenharmony_ci} 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_civoid BIO_set_callback_arg(BIO *b, char *arg) 244e1051a39Sopenharmony_ci{ 245e1051a39Sopenharmony_ci b->cb_arg = arg; 246e1051a39Sopenharmony_ci} 247e1051a39Sopenharmony_ci 248e1051a39Sopenharmony_cichar *BIO_get_callback_arg(const BIO *b) 249e1051a39Sopenharmony_ci{ 250e1051a39Sopenharmony_ci return b->cb_arg; 251e1051a39Sopenharmony_ci} 252e1051a39Sopenharmony_ci 253e1051a39Sopenharmony_ciconst char *BIO_method_name(const BIO *b) 254e1051a39Sopenharmony_ci{ 255e1051a39Sopenharmony_ci return b->method->name; 256e1051a39Sopenharmony_ci} 257e1051a39Sopenharmony_ci 258e1051a39Sopenharmony_ciint BIO_method_type(const BIO *b) 259e1051a39Sopenharmony_ci{ 260e1051a39Sopenharmony_ci return b->method->type; 261e1051a39Sopenharmony_ci} 262e1051a39Sopenharmony_ci 263e1051a39Sopenharmony_ci/* 264e1051a39Sopenharmony_ci * This is essentially the same as BIO_read_ex() except that it allows 265e1051a39Sopenharmony_ci * 0 or a negative value to indicate failure (retryable or not) in the return. 266e1051a39Sopenharmony_ci * This is for compatibility with the old style BIO_read(), where existing code 267e1051a39Sopenharmony_ci * may make assumptions about the return value that it might get. 268e1051a39Sopenharmony_ci */ 269e1051a39Sopenharmony_cistatic int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes) 270e1051a39Sopenharmony_ci{ 271e1051a39Sopenharmony_ci int ret; 272e1051a39Sopenharmony_ci 273e1051a39Sopenharmony_ci if (b == NULL) { 274e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 275e1051a39Sopenharmony_ci return -1; 276e1051a39Sopenharmony_ci } 277e1051a39Sopenharmony_ci if (b->method == NULL || b->method->bread == NULL) { 278e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); 279e1051a39Sopenharmony_ci return -2; 280e1051a39Sopenharmony_ci } 281e1051a39Sopenharmony_ci 282e1051a39Sopenharmony_ci if (HAS_CALLBACK(b) && 283e1051a39Sopenharmony_ci ((ret = (int)bio_call_callback(b, BIO_CB_READ, data, dlen, 0, 0L, 1L, 284e1051a39Sopenharmony_ci NULL)) <= 0)) 285e1051a39Sopenharmony_ci return ret; 286e1051a39Sopenharmony_ci 287e1051a39Sopenharmony_ci if (!b->init) { 288e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); 289e1051a39Sopenharmony_ci return -1; 290e1051a39Sopenharmony_ci } 291e1051a39Sopenharmony_ci 292e1051a39Sopenharmony_ci ret = b->method->bread(b, data, dlen, readbytes); 293e1051a39Sopenharmony_ci 294e1051a39Sopenharmony_ci if (ret > 0) 295e1051a39Sopenharmony_ci b->num_read += (uint64_t)*readbytes; 296e1051a39Sopenharmony_ci 297e1051a39Sopenharmony_ci if (HAS_CALLBACK(b)) 298e1051a39Sopenharmony_ci ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data, 299e1051a39Sopenharmony_ci dlen, 0, 0L, ret, readbytes); 300e1051a39Sopenharmony_ci 301e1051a39Sopenharmony_ci /* Shouldn't happen */ 302e1051a39Sopenharmony_ci if (ret > 0 && *readbytes > dlen) { 303e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR); 304e1051a39Sopenharmony_ci return -1; 305e1051a39Sopenharmony_ci } 306e1051a39Sopenharmony_ci 307e1051a39Sopenharmony_ci return ret; 308e1051a39Sopenharmony_ci} 309e1051a39Sopenharmony_ci 310e1051a39Sopenharmony_ciint BIO_read(BIO *b, void *data, int dlen) 311e1051a39Sopenharmony_ci{ 312e1051a39Sopenharmony_ci size_t readbytes; 313e1051a39Sopenharmony_ci int ret; 314e1051a39Sopenharmony_ci 315e1051a39Sopenharmony_ci if (dlen < 0) 316e1051a39Sopenharmony_ci return 0; 317e1051a39Sopenharmony_ci 318e1051a39Sopenharmony_ci ret = bio_read_intern(b, data, (size_t)dlen, &readbytes); 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_ci if (ret > 0) { 321e1051a39Sopenharmony_ci /* *readbytes should always be <= dlen */ 322e1051a39Sopenharmony_ci ret = (int)readbytes; 323e1051a39Sopenharmony_ci } 324e1051a39Sopenharmony_ci 325e1051a39Sopenharmony_ci return ret; 326e1051a39Sopenharmony_ci} 327e1051a39Sopenharmony_ci 328e1051a39Sopenharmony_ciint BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes) 329e1051a39Sopenharmony_ci{ 330e1051a39Sopenharmony_ci return bio_read_intern(b, data, dlen, readbytes) > 0; 331e1051a39Sopenharmony_ci} 332e1051a39Sopenharmony_ci 333e1051a39Sopenharmony_cistatic int bio_write_intern(BIO *b, const void *data, size_t dlen, 334e1051a39Sopenharmony_ci size_t *written) 335e1051a39Sopenharmony_ci{ 336e1051a39Sopenharmony_ci size_t local_written; 337e1051a39Sopenharmony_ci int ret; 338e1051a39Sopenharmony_ci 339e1051a39Sopenharmony_ci if (written != NULL) 340e1051a39Sopenharmony_ci *written = 0; 341e1051a39Sopenharmony_ci /* 342e1051a39Sopenharmony_ci * b == NULL is not an error but just means that zero bytes are written. 343e1051a39Sopenharmony_ci * Do not raise an error here. 344e1051a39Sopenharmony_ci */ 345e1051a39Sopenharmony_ci if (b == NULL) 346e1051a39Sopenharmony_ci return 0; 347e1051a39Sopenharmony_ci 348e1051a39Sopenharmony_ci if (b->method == NULL || b->method->bwrite == NULL) { 349e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); 350e1051a39Sopenharmony_ci return -2; 351e1051a39Sopenharmony_ci } 352e1051a39Sopenharmony_ci 353e1051a39Sopenharmony_ci if (HAS_CALLBACK(b) && 354e1051a39Sopenharmony_ci ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, data, dlen, 0, 0L, 1L, 355e1051a39Sopenharmony_ci NULL)) <= 0)) 356e1051a39Sopenharmony_ci return ret; 357e1051a39Sopenharmony_ci 358e1051a39Sopenharmony_ci if (!b->init) { 359e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); 360e1051a39Sopenharmony_ci return -1; 361e1051a39Sopenharmony_ci } 362e1051a39Sopenharmony_ci 363e1051a39Sopenharmony_ci ret = b->method->bwrite(b, data, dlen, &local_written); 364e1051a39Sopenharmony_ci 365e1051a39Sopenharmony_ci if (ret > 0) 366e1051a39Sopenharmony_ci b->num_write += (uint64_t)local_written; 367e1051a39Sopenharmony_ci 368e1051a39Sopenharmony_ci if (HAS_CALLBACK(b)) 369e1051a39Sopenharmony_ci ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, data, 370e1051a39Sopenharmony_ci dlen, 0, 0L, ret, &local_written); 371e1051a39Sopenharmony_ci 372e1051a39Sopenharmony_ci if (written != NULL) 373e1051a39Sopenharmony_ci *written = local_written; 374e1051a39Sopenharmony_ci return ret; 375e1051a39Sopenharmony_ci} 376e1051a39Sopenharmony_ci 377e1051a39Sopenharmony_ciint BIO_write(BIO *b, const void *data, int dlen) 378e1051a39Sopenharmony_ci{ 379e1051a39Sopenharmony_ci size_t written; 380e1051a39Sopenharmony_ci int ret; 381e1051a39Sopenharmony_ci 382e1051a39Sopenharmony_ci if (dlen <= 0) 383e1051a39Sopenharmony_ci return 0; 384e1051a39Sopenharmony_ci 385e1051a39Sopenharmony_ci ret = bio_write_intern(b, data, (size_t)dlen, &written); 386e1051a39Sopenharmony_ci 387e1051a39Sopenharmony_ci if (ret > 0) { 388e1051a39Sopenharmony_ci /* written should always be <= dlen */ 389e1051a39Sopenharmony_ci ret = (int)written; 390e1051a39Sopenharmony_ci } 391e1051a39Sopenharmony_ci 392e1051a39Sopenharmony_ci return ret; 393e1051a39Sopenharmony_ci} 394e1051a39Sopenharmony_ci 395e1051a39Sopenharmony_ciint BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written) 396e1051a39Sopenharmony_ci{ 397e1051a39Sopenharmony_ci return bio_write_intern(b, data, dlen, written) > 0 398e1051a39Sopenharmony_ci || (b != NULL && dlen == 0); /* order is important for *written */ 399e1051a39Sopenharmony_ci} 400e1051a39Sopenharmony_ci 401e1051a39Sopenharmony_ciint BIO_puts(BIO *b, const char *buf) 402e1051a39Sopenharmony_ci{ 403e1051a39Sopenharmony_ci int ret; 404e1051a39Sopenharmony_ci size_t written = 0; 405e1051a39Sopenharmony_ci 406e1051a39Sopenharmony_ci if (b == NULL) { 407e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 408e1051a39Sopenharmony_ci return -1; 409e1051a39Sopenharmony_ci } 410e1051a39Sopenharmony_ci if (b->method == NULL || b->method->bputs == NULL) { 411e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); 412e1051a39Sopenharmony_ci return -2; 413e1051a39Sopenharmony_ci } 414e1051a39Sopenharmony_ci 415e1051a39Sopenharmony_ci if (HAS_CALLBACK(b)) { 416e1051a39Sopenharmony_ci ret = (int)bio_call_callback(b, BIO_CB_PUTS, buf, 0, 0, 0L, 1L, NULL); 417e1051a39Sopenharmony_ci if (ret <= 0) 418e1051a39Sopenharmony_ci return ret; 419e1051a39Sopenharmony_ci } 420e1051a39Sopenharmony_ci 421e1051a39Sopenharmony_ci if (!b->init) { 422e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); 423e1051a39Sopenharmony_ci return -1; 424e1051a39Sopenharmony_ci } 425e1051a39Sopenharmony_ci 426e1051a39Sopenharmony_ci ret = b->method->bputs(b, buf); 427e1051a39Sopenharmony_ci 428e1051a39Sopenharmony_ci if (ret > 0) { 429e1051a39Sopenharmony_ci b->num_write += (uint64_t)ret; 430e1051a39Sopenharmony_ci written = ret; 431e1051a39Sopenharmony_ci ret = 1; 432e1051a39Sopenharmony_ci } 433e1051a39Sopenharmony_ci 434e1051a39Sopenharmony_ci if (HAS_CALLBACK(b)) 435e1051a39Sopenharmony_ci ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, buf, 0, 0, 436e1051a39Sopenharmony_ci 0L, ret, &written); 437e1051a39Sopenharmony_ci 438e1051a39Sopenharmony_ci if (ret > 0) { 439e1051a39Sopenharmony_ci if (written > INT_MAX) { 440e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_LENGTH_TOO_LONG); 441e1051a39Sopenharmony_ci ret = -1; 442e1051a39Sopenharmony_ci } else { 443e1051a39Sopenharmony_ci ret = (int)written; 444e1051a39Sopenharmony_ci } 445e1051a39Sopenharmony_ci } 446e1051a39Sopenharmony_ci 447e1051a39Sopenharmony_ci return ret; 448e1051a39Sopenharmony_ci} 449e1051a39Sopenharmony_ci 450e1051a39Sopenharmony_ciint BIO_gets(BIO *b, char *buf, int size) 451e1051a39Sopenharmony_ci{ 452e1051a39Sopenharmony_ci int ret; 453e1051a39Sopenharmony_ci size_t readbytes = 0; 454e1051a39Sopenharmony_ci 455e1051a39Sopenharmony_ci if (b == NULL) { 456e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 457e1051a39Sopenharmony_ci return -1; 458e1051a39Sopenharmony_ci } 459e1051a39Sopenharmony_ci if (b->method == NULL || b->method->bgets == NULL) { 460e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); 461e1051a39Sopenharmony_ci return -2; 462e1051a39Sopenharmony_ci } 463e1051a39Sopenharmony_ci 464e1051a39Sopenharmony_ci if (size < 0) { 465e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT); 466e1051a39Sopenharmony_ci return -1; 467e1051a39Sopenharmony_ci } 468e1051a39Sopenharmony_ci 469e1051a39Sopenharmony_ci if (HAS_CALLBACK(b)) { 470e1051a39Sopenharmony_ci ret = (int)bio_call_callback(b, BIO_CB_GETS, buf, size, 0, 0L, 1, NULL); 471e1051a39Sopenharmony_ci if (ret <= 0) 472e1051a39Sopenharmony_ci return ret; 473e1051a39Sopenharmony_ci } 474e1051a39Sopenharmony_ci 475e1051a39Sopenharmony_ci if (!b->init) { 476e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); 477e1051a39Sopenharmony_ci return -1; 478e1051a39Sopenharmony_ci } 479e1051a39Sopenharmony_ci 480e1051a39Sopenharmony_ci ret = b->method->bgets(b, buf, size); 481e1051a39Sopenharmony_ci 482e1051a39Sopenharmony_ci if (ret > 0) { 483e1051a39Sopenharmony_ci readbytes = ret; 484e1051a39Sopenharmony_ci ret = 1; 485e1051a39Sopenharmony_ci } 486e1051a39Sopenharmony_ci 487e1051a39Sopenharmony_ci if (HAS_CALLBACK(b)) 488e1051a39Sopenharmony_ci ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size, 489e1051a39Sopenharmony_ci 0, 0L, ret, &readbytes); 490e1051a39Sopenharmony_ci 491e1051a39Sopenharmony_ci if (ret > 0) { 492e1051a39Sopenharmony_ci /* Shouldn't happen */ 493e1051a39Sopenharmony_ci if (readbytes > (size_t)size) 494e1051a39Sopenharmony_ci ret = -1; 495e1051a39Sopenharmony_ci else 496e1051a39Sopenharmony_ci ret = (int)readbytes; 497e1051a39Sopenharmony_ci } 498e1051a39Sopenharmony_ci 499e1051a39Sopenharmony_ci return ret; 500e1051a39Sopenharmony_ci} 501e1051a39Sopenharmony_ci 502e1051a39Sopenharmony_ciint BIO_get_line(BIO *bio, char *buf, int size) 503e1051a39Sopenharmony_ci{ 504e1051a39Sopenharmony_ci int ret = 0; 505e1051a39Sopenharmony_ci char *ptr = buf; 506e1051a39Sopenharmony_ci 507e1051a39Sopenharmony_ci if (buf == NULL) { 508e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 509e1051a39Sopenharmony_ci return -1; 510e1051a39Sopenharmony_ci } 511e1051a39Sopenharmony_ci if (size <= 0) { 512e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT); 513e1051a39Sopenharmony_ci return -1; 514e1051a39Sopenharmony_ci } 515e1051a39Sopenharmony_ci *buf = '\0'; 516e1051a39Sopenharmony_ci 517e1051a39Sopenharmony_ci if (bio == NULL) { 518e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 519e1051a39Sopenharmony_ci return -1; 520e1051a39Sopenharmony_ci } 521e1051a39Sopenharmony_ci if (!bio->init) { 522e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); 523e1051a39Sopenharmony_ci return -1; 524e1051a39Sopenharmony_ci } 525e1051a39Sopenharmony_ci 526e1051a39Sopenharmony_ci while (size-- > 1 && (ret = BIO_read(bio, ptr, 1)) > 0) 527e1051a39Sopenharmony_ci if (*ptr++ == '\n') 528e1051a39Sopenharmony_ci break; 529e1051a39Sopenharmony_ci *ptr = '\0'; 530e1051a39Sopenharmony_ci return ret > 0 || BIO_eof(bio) ? ptr - buf : ret; 531e1051a39Sopenharmony_ci} 532e1051a39Sopenharmony_ci 533e1051a39Sopenharmony_ciint BIO_indent(BIO *b, int indent, int max) 534e1051a39Sopenharmony_ci{ 535e1051a39Sopenharmony_ci if (indent < 0) 536e1051a39Sopenharmony_ci indent = 0; 537e1051a39Sopenharmony_ci if (indent > max) 538e1051a39Sopenharmony_ci indent = max; 539e1051a39Sopenharmony_ci while (indent--) 540e1051a39Sopenharmony_ci if (BIO_puts(b, " ") != 1) 541e1051a39Sopenharmony_ci return 0; 542e1051a39Sopenharmony_ci return 1; 543e1051a39Sopenharmony_ci} 544e1051a39Sopenharmony_ci 545e1051a39Sopenharmony_cilong BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) 546e1051a39Sopenharmony_ci{ 547e1051a39Sopenharmony_ci int i; 548e1051a39Sopenharmony_ci 549e1051a39Sopenharmony_ci i = iarg; 550e1051a39Sopenharmony_ci return BIO_ctrl(b, cmd, larg, (char *)&i); 551e1051a39Sopenharmony_ci} 552e1051a39Sopenharmony_ci 553e1051a39Sopenharmony_civoid *BIO_ptr_ctrl(BIO *b, int cmd, long larg) 554e1051a39Sopenharmony_ci{ 555e1051a39Sopenharmony_ci void *p = NULL; 556e1051a39Sopenharmony_ci 557e1051a39Sopenharmony_ci if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0) 558e1051a39Sopenharmony_ci return NULL; 559e1051a39Sopenharmony_ci else 560e1051a39Sopenharmony_ci return p; 561e1051a39Sopenharmony_ci} 562e1051a39Sopenharmony_ci 563e1051a39Sopenharmony_cilong BIO_ctrl(BIO *b, int cmd, long larg, void *parg) 564e1051a39Sopenharmony_ci{ 565e1051a39Sopenharmony_ci long ret; 566e1051a39Sopenharmony_ci 567e1051a39Sopenharmony_ci if (b == NULL) 568e1051a39Sopenharmony_ci return -1; 569e1051a39Sopenharmony_ci if (b->method == NULL || b->method->ctrl == NULL) { 570e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); 571e1051a39Sopenharmony_ci return -2; 572e1051a39Sopenharmony_ci } 573e1051a39Sopenharmony_ci 574e1051a39Sopenharmony_ci if (HAS_CALLBACK(b)) { 575e1051a39Sopenharmony_ci ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL); 576e1051a39Sopenharmony_ci if (ret <= 0) 577e1051a39Sopenharmony_ci return ret; 578e1051a39Sopenharmony_ci } 579e1051a39Sopenharmony_ci 580e1051a39Sopenharmony_ci ret = b->method->ctrl(b, cmd, larg, parg); 581e1051a39Sopenharmony_ci 582e1051a39Sopenharmony_ci if (HAS_CALLBACK(b)) 583e1051a39Sopenharmony_ci ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd, 584e1051a39Sopenharmony_ci larg, ret, NULL); 585e1051a39Sopenharmony_ci 586e1051a39Sopenharmony_ci return ret; 587e1051a39Sopenharmony_ci} 588e1051a39Sopenharmony_ci 589e1051a39Sopenharmony_cilong BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 590e1051a39Sopenharmony_ci{ 591e1051a39Sopenharmony_ci long ret; 592e1051a39Sopenharmony_ci 593e1051a39Sopenharmony_ci if (b == NULL) 594e1051a39Sopenharmony_ci return -2; 595e1051a39Sopenharmony_ci if (b->method == NULL || b->method->callback_ctrl == NULL 596e1051a39Sopenharmony_ci || cmd != BIO_CTRL_SET_CALLBACK) { 597e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); 598e1051a39Sopenharmony_ci return -2; 599e1051a39Sopenharmony_ci } 600e1051a39Sopenharmony_ci 601e1051a39Sopenharmony_ci if (HAS_CALLBACK(b)) { 602e1051a39Sopenharmony_ci ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L, 603e1051a39Sopenharmony_ci NULL); 604e1051a39Sopenharmony_ci if (ret <= 0) 605e1051a39Sopenharmony_ci return ret; 606e1051a39Sopenharmony_ci } 607e1051a39Sopenharmony_ci 608e1051a39Sopenharmony_ci ret = b->method->callback_ctrl(b, cmd, fp); 609e1051a39Sopenharmony_ci 610e1051a39Sopenharmony_ci if (HAS_CALLBACK(b)) 611e1051a39Sopenharmony_ci ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0, 612e1051a39Sopenharmony_ci cmd, 0, ret, NULL); 613e1051a39Sopenharmony_ci 614e1051a39Sopenharmony_ci return ret; 615e1051a39Sopenharmony_ci} 616e1051a39Sopenharmony_ci 617e1051a39Sopenharmony_ci/* 618e1051a39Sopenharmony_ci * It is unfortunate to duplicate in functions what the BIO_(w)pending macros 619e1051a39Sopenharmony_ci * do; but those macros have inappropriate return type, and for interfacing 620e1051a39Sopenharmony_ci * from other programming languages, C macros aren't much of a help anyway. 621e1051a39Sopenharmony_ci */ 622e1051a39Sopenharmony_cisize_t BIO_ctrl_pending(BIO *bio) 623e1051a39Sopenharmony_ci{ 624e1051a39Sopenharmony_ci long ret = BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); 625e1051a39Sopenharmony_ci 626e1051a39Sopenharmony_ci if (ret < 0) 627e1051a39Sopenharmony_ci ret = 0; 628e1051a39Sopenharmony_ci#if LONG_MAX > SIZE_MAX 629e1051a39Sopenharmony_ci if (ret > SIZE_MAX) 630e1051a39Sopenharmony_ci ret = SIZE_MAX; 631e1051a39Sopenharmony_ci#endif 632e1051a39Sopenharmony_ci return (size_t)ret; 633e1051a39Sopenharmony_ci} 634e1051a39Sopenharmony_ci 635e1051a39Sopenharmony_cisize_t BIO_ctrl_wpending(BIO *bio) 636e1051a39Sopenharmony_ci{ 637e1051a39Sopenharmony_ci long ret = BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); 638e1051a39Sopenharmony_ci 639e1051a39Sopenharmony_ci if (ret < 0) 640e1051a39Sopenharmony_ci ret = 0; 641e1051a39Sopenharmony_ci#if LONG_MAX > SIZE_MAX 642e1051a39Sopenharmony_ci if (ret > SIZE_MAX) 643e1051a39Sopenharmony_ci ret = SIZE_MAX; 644e1051a39Sopenharmony_ci#endif 645e1051a39Sopenharmony_ci return (size_t)ret; 646e1051a39Sopenharmony_ci} 647e1051a39Sopenharmony_ci 648e1051a39Sopenharmony_ci/* put the 'bio' on the end of b's list of operators */ 649e1051a39Sopenharmony_ciBIO *BIO_push(BIO *b, BIO *bio) 650e1051a39Sopenharmony_ci{ 651e1051a39Sopenharmony_ci BIO *lb; 652e1051a39Sopenharmony_ci 653e1051a39Sopenharmony_ci if (b == NULL) 654e1051a39Sopenharmony_ci return bio; 655e1051a39Sopenharmony_ci lb = b; 656e1051a39Sopenharmony_ci while (lb->next_bio != NULL) 657e1051a39Sopenharmony_ci lb = lb->next_bio; 658e1051a39Sopenharmony_ci lb->next_bio = bio; 659e1051a39Sopenharmony_ci if (bio != NULL) 660e1051a39Sopenharmony_ci bio->prev_bio = lb; 661e1051a39Sopenharmony_ci /* called to do internal processing */ 662e1051a39Sopenharmony_ci BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb); 663e1051a39Sopenharmony_ci return b; 664e1051a39Sopenharmony_ci} 665e1051a39Sopenharmony_ci 666e1051a39Sopenharmony_ci/* Remove the first and return the rest */ 667e1051a39Sopenharmony_ciBIO *BIO_pop(BIO *b) 668e1051a39Sopenharmony_ci{ 669e1051a39Sopenharmony_ci BIO *ret; 670e1051a39Sopenharmony_ci 671e1051a39Sopenharmony_ci if (b == NULL) 672e1051a39Sopenharmony_ci return NULL; 673e1051a39Sopenharmony_ci ret = b->next_bio; 674e1051a39Sopenharmony_ci 675e1051a39Sopenharmony_ci BIO_ctrl(b, BIO_CTRL_POP, 0, b); 676e1051a39Sopenharmony_ci 677e1051a39Sopenharmony_ci if (b->prev_bio != NULL) 678e1051a39Sopenharmony_ci b->prev_bio->next_bio = b->next_bio; 679e1051a39Sopenharmony_ci if (b->next_bio != NULL) 680e1051a39Sopenharmony_ci b->next_bio->prev_bio = b->prev_bio; 681e1051a39Sopenharmony_ci 682e1051a39Sopenharmony_ci b->next_bio = NULL; 683e1051a39Sopenharmony_ci b->prev_bio = NULL; 684e1051a39Sopenharmony_ci return ret; 685e1051a39Sopenharmony_ci} 686e1051a39Sopenharmony_ci 687e1051a39Sopenharmony_ciBIO *BIO_get_retry_BIO(BIO *bio, int *reason) 688e1051a39Sopenharmony_ci{ 689e1051a39Sopenharmony_ci BIO *b, *last; 690e1051a39Sopenharmony_ci 691e1051a39Sopenharmony_ci b = last = bio; 692e1051a39Sopenharmony_ci for (;;) { 693e1051a39Sopenharmony_ci if (!BIO_should_retry(b)) 694e1051a39Sopenharmony_ci break; 695e1051a39Sopenharmony_ci last = b; 696e1051a39Sopenharmony_ci b = b->next_bio; 697e1051a39Sopenharmony_ci if (b == NULL) 698e1051a39Sopenharmony_ci break; 699e1051a39Sopenharmony_ci } 700e1051a39Sopenharmony_ci if (reason != NULL) 701e1051a39Sopenharmony_ci *reason = last->retry_reason; 702e1051a39Sopenharmony_ci return last; 703e1051a39Sopenharmony_ci} 704e1051a39Sopenharmony_ci 705e1051a39Sopenharmony_ciint BIO_get_retry_reason(BIO *bio) 706e1051a39Sopenharmony_ci{ 707e1051a39Sopenharmony_ci return bio->retry_reason; 708e1051a39Sopenharmony_ci} 709e1051a39Sopenharmony_ci 710e1051a39Sopenharmony_civoid BIO_set_retry_reason(BIO *bio, int reason) 711e1051a39Sopenharmony_ci{ 712e1051a39Sopenharmony_ci bio->retry_reason = reason; 713e1051a39Sopenharmony_ci} 714e1051a39Sopenharmony_ci 715e1051a39Sopenharmony_ciBIO *BIO_find_type(BIO *bio, int type) 716e1051a39Sopenharmony_ci{ 717e1051a39Sopenharmony_ci int mt, mask; 718e1051a39Sopenharmony_ci 719e1051a39Sopenharmony_ci if (bio == NULL) { 720e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 721e1051a39Sopenharmony_ci return NULL; 722e1051a39Sopenharmony_ci } 723e1051a39Sopenharmony_ci mask = type & 0xff; 724e1051a39Sopenharmony_ci do { 725e1051a39Sopenharmony_ci if (bio->method != NULL) { 726e1051a39Sopenharmony_ci mt = bio->method->type; 727e1051a39Sopenharmony_ci 728e1051a39Sopenharmony_ci if (!mask) { 729e1051a39Sopenharmony_ci if (mt & type) 730e1051a39Sopenharmony_ci return bio; 731e1051a39Sopenharmony_ci } else if (mt == type) { 732e1051a39Sopenharmony_ci return bio; 733e1051a39Sopenharmony_ci } 734e1051a39Sopenharmony_ci } 735e1051a39Sopenharmony_ci bio = bio->next_bio; 736e1051a39Sopenharmony_ci } while (bio != NULL); 737e1051a39Sopenharmony_ci return NULL; 738e1051a39Sopenharmony_ci} 739e1051a39Sopenharmony_ci 740e1051a39Sopenharmony_ciBIO *BIO_next(BIO *b) 741e1051a39Sopenharmony_ci{ 742e1051a39Sopenharmony_ci if (b == NULL) 743e1051a39Sopenharmony_ci return NULL; 744e1051a39Sopenharmony_ci return b->next_bio; 745e1051a39Sopenharmony_ci} 746e1051a39Sopenharmony_ci 747e1051a39Sopenharmony_civoid BIO_set_next(BIO *b, BIO *next) 748e1051a39Sopenharmony_ci{ 749e1051a39Sopenharmony_ci b->next_bio = next; 750e1051a39Sopenharmony_ci} 751e1051a39Sopenharmony_ci 752e1051a39Sopenharmony_civoid BIO_free_all(BIO *bio) 753e1051a39Sopenharmony_ci{ 754e1051a39Sopenharmony_ci BIO *b; 755e1051a39Sopenharmony_ci int ref; 756e1051a39Sopenharmony_ci 757e1051a39Sopenharmony_ci while (bio != NULL) { 758e1051a39Sopenharmony_ci b = bio; 759e1051a39Sopenharmony_ci ref = b->references; 760e1051a39Sopenharmony_ci bio = bio->next_bio; 761e1051a39Sopenharmony_ci BIO_free(b); 762e1051a39Sopenharmony_ci /* Since ref count > 1, don't free anyone else. */ 763e1051a39Sopenharmony_ci if (ref > 1) 764e1051a39Sopenharmony_ci break; 765e1051a39Sopenharmony_ci } 766e1051a39Sopenharmony_ci} 767e1051a39Sopenharmony_ci 768e1051a39Sopenharmony_ciBIO *BIO_dup_chain(BIO *in) 769e1051a39Sopenharmony_ci{ 770e1051a39Sopenharmony_ci BIO *ret = NULL, *eoc = NULL, *bio, *new_bio; 771e1051a39Sopenharmony_ci 772e1051a39Sopenharmony_ci for (bio = in; bio != NULL; bio = bio->next_bio) { 773e1051a39Sopenharmony_ci if ((new_bio = BIO_new(bio->method)) == NULL) 774e1051a39Sopenharmony_ci goto err; 775e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 776e1051a39Sopenharmony_ci new_bio->callback = bio->callback; 777e1051a39Sopenharmony_ci#endif 778e1051a39Sopenharmony_ci new_bio->callback_ex = bio->callback_ex; 779e1051a39Sopenharmony_ci new_bio->cb_arg = bio->cb_arg; 780e1051a39Sopenharmony_ci new_bio->init = bio->init; 781e1051a39Sopenharmony_ci new_bio->shutdown = bio->shutdown; 782e1051a39Sopenharmony_ci new_bio->flags = bio->flags; 783e1051a39Sopenharmony_ci 784e1051a39Sopenharmony_ci /* This will let SSL_s_sock() work with stdin/stdout */ 785e1051a39Sopenharmony_ci new_bio->num = bio->num; 786e1051a39Sopenharmony_ci 787e1051a39Sopenharmony_ci if (BIO_dup_state(bio, (char *)new_bio) <= 0) { 788e1051a39Sopenharmony_ci BIO_free(new_bio); 789e1051a39Sopenharmony_ci goto err; 790e1051a39Sopenharmony_ci } 791e1051a39Sopenharmony_ci 792e1051a39Sopenharmony_ci /* copy app data */ 793e1051a39Sopenharmony_ci if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data, 794e1051a39Sopenharmony_ci &bio->ex_data)) { 795e1051a39Sopenharmony_ci BIO_free(new_bio); 796e1051a39Sopenharmony_ci goto err; 797e1051a39Sopenharmony_ci } 798e1051a39Sopenharmony_ci 799e1051a39Sopenharmony_ci if (ret == NULL) { 800e1051a39Sopenharmony_ci eoc = new_bio; 801e1051a39Sopenharmony_ci ret = eoc; 802e1051a39Sopenharmony_ci } else { 803e1051a39Sopenharmony_ci BIO_push(eoc, new_bio); 804e1051a39Sopenharmony_ci eoc = new_bio; 805e1051a39Sopenharmony_ci } 806e1051a39Sopenharmony_ci } 807e1051a39Sopenharmony_ci return ret; 808e1051a39Sopenharmony_ci err: 809e1051a39Sopenharmony_ci BIO_free_all(ret); 810e1051a39Sopenharmony_ci 811e1051a39Sopenharmony_ci return NULL; 812e1051a39Sopenharmony_ci} 813e1051a39Sopenharmony_ci 814e1051a39Sopenharmony_civoid BIO_copy_next_retry(BIO *b) 815e1051a39Sopenharmony_ci{ 816e1051a39Sopenharmony_ci BIO_set_flags(b, BIO_get_retry_flags(b->next_bio)); 817e1051a39Sopenharmony_ci b->retry_reason = b->next_bio->retry_reason; 818e1051a39Sopenharmony_ci} 819e1051a39Sopenharmony_ci 820e1051a39Sopenharmony_ciint BIO_set_ex_data(BIO *bio, int idx, void *data) 821e1051a39Sopenharmony_ci{ 822e1051a39Sopenharmony_ci return CRYPTO_set_ex_data(&(bio->ex_data), idx, data); 823e1051a39Sopenharmony_ci} 824e1051a39Sopenharmony_ci 825e1051a39Sopenharmony_civoid *BIO_get_ex_data(const BIO *bio, int idx) 826e1051a39Sopenharmony_ci{ 827e1051a39Sopenharmony_ci return CRYPTO_get_ex_data(&(bio->ex_data), idx); 828e1051a39Sopenharmony_ci} 829e1051a39Sopenharmony_ci 830e1051a39Sopenharmony_ciuint64_t BIO_number_read(BIO *bio) 831e1051a39Sopenharmony_ci{ 832e1051a39Sopenharmony_ci if (bio) 833e1051a39Sopenharmony_ci return bio->num_read; 834e1051a39Sopenharmony_ci return 0; 835e1051a39Sopenharmony_ci} 836e1051a39Sopenharmony_ci 837e1051a39Sopenharmony_ciuint64_t BIO_number_written(BIO *bio) 838e1051a39Sopenharmony_ci{ 839e1051a39Sopenharmony_ci if (bio) 840e1051a39Sopenharmony_ci return bio->num_write; 841e1051a39Sopenharmony_ci return 0; 842e1051a39Sopenharmony_ci} 843e1051a39Sopenharmony_ci 844e1051a39Sopenharmony_civoid bio_free_ex_data(BIO *bio) 845e1051a39Sopenharmony_ci{ 846e1051a39Sopenharmony_ci CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 847e1051a39Sopenharmony_ci} 848e1051a39Sopenharmony_ci 849e1051a39Sopenharmony_civoid bio_cleanup(void) 850e1051a39Sopenharmony_ci{ 851e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_SOCK 852e1051a39Sopenharmony_ci bio_sock_cleanup_int(); 853e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(bio_lookup_lock); 854e1051a39Sopenharmony_ci bio_lookup_lock = NULL; 855e1051a39Sopenharmony_ci#endif 856e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(bio_type_lock); 857e1051a39Sopenharmony_ci bio_type_lock = NULL; 858e1051a39Sopenharmony_ci} 859e1051a39Sopenharmony_ci 860e1051a39Sopenharmony_ci/* Internal variant of the below BIO_wait() not calling BIOerr() */ 861e1051a39Sopenharmony_cistatic int bio_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds) 862e1051a39Sopenharmony_ci{ 863e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_SOCK 864e1051a39Sopenharmony_ci int fd; 865e1051a39Sopenharmony_ci#endif 866e1051a39Sopenharmony_ci long sec_diff; 867e1051a39Sopenharmony_ci 868e1051a39Sopenharmony_ci if (max_time == 0) /* no timeout */ 869e1051a39Sopenharmony_ci return 1; 870e1051a39Sopenharmony_ci 871e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_SOCK 872e1051a39Sopenharmony_ci if (BIO_get_fd(bio, &fd) > 0 && fd < FD_SETSIZE) 873e1051a39Sopenharmony_ci return BIO_socket_wait(fd, BIO_should_read(bio), max_time); 874e1051a39Sopenharmony_ci#endif 875e1051a39Sopenharmony_ci /* fall back to polling since no sockets are available */ 876e1051a39Sopenharmony_ci 877e1051a39Sopenharmony_ci sec_diff = (long)(max_time - time(NULL)); /* might overflow */ 878e1051a39Sopenharmony_ci if (sec_diff < 0) 879e1051a39Sopenharmony_ci return 0; /* clearly timeout */ 880e1051a39Sopenharmony_ci 881e1051a39Sopenharmony_ci /* now take a nap at most the given number of milliseconds */ 882e1051a39Sopenharmony_ci if (sec_diff == 0) { /* we are below the 1 seconds resolution of max_time */ 883e1051a39Sopenharmony_ci if (nap_milliseconds > 1000) 884e1051a39Sopenharmony_ci nap_milliseconds = 1000; 885e1051a39Sopenharmony_ci } else { /* for sec_diff > 0, take min(sec_diff * 1000, nap_milliseconds) */ 886e1051a39Sopenharmony_ci if ((unsigned long)sec_diff * 1000 < nap_milliseconds) 887e1051a39Sopenharmony_ci nap_milliseconds = (unsigned int)sec_diff * 1000; 888e1051a39Sopenharmony_ci } 889e1051a39Sopenharmony_ci ossl_sleep(nap_milliseconds); 890e1051a39Sopenharmony_ci return 1; 891e1051a39Sopenharmony_ci} 892e1051a39Sopenharmony_ci 893e1051a39Sopenharmony_ci/*- 894e1051a39Sopenharmony_ci * Wait on (typically socket-based) BIO at most until max_time. 895e1051a39Sopenharmony_ci * Succeed immediately if max_time == 0. 896e1051a39Sopenharmony_ci * If sockets are not available support polling: succeed after waiting at most 897e1051a39Sopenharmony_ci * the number of nap_milliseconds in order to avoid a tight busy loop. 898e1051a39Sopenharmony_ci * Call BIOerr(...) on timeout or error. 899e1051a39Sopenharmony_ci * Returns -1 on error, 0 on timeout, and 1 on success. 900e1051a39Sopenharmony_ci */ 901e1051a39Sopenharmony_ciint BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds) 902e1051a39Sopenharmony_ci{ 903e1051a39Sopenharmony_ci int rv = bio_wait(bio, max_time, nap_milliseconds); 904e1051a39Sopenharmony_ci 905e1051a39Sopenharmony_ci if (rv <= 0) 906e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, 907e1051a39Sopenharmony_ci rv == 0 ? BIO_R_TRANSFER_TIMEOUT : BIO_R_TRANSFER_ERROR); 908e1051a39Sopenharmony_ci return rv; 909e1051a39Sopenharmony_ci} 910e1051a39Sopenharmony_ci 911e1051a39Sopenharmony_ci/* 912e1051a39Sopenharmony_ci * Connect via given BIO using BIO_do_connect() until success/timeout/error. 913e1051a39Sopenharmony_ci * Parameter timeout == 0 means no timeout, < 0 means exactly one try. 914e1051a39Sopenharmony_ci * For non-blocking and potentially even non-socket BIOs perform polling with 915e1051a39Sopenharmony_ci * the given density: between polls sleep nap_milliseconds using BIO_wait() 916e1051a39Sopenharmony_ci * in order to avoid a tight busy loop. 917e1051a39Sopenharmony_ci * Returns -1 on error, 0 on timeout, and 1 on success. 918e1051a39Sopenharmony_ci */ 919e1051a39Sopenharmony_ciint BIO_do_connect_retry(BIO *bio, int timeout, int nap_milliseconds) 920e1051a39Sopenharmony_ci{ 921e1051a39Sopenharmony_ci int blocking = timeout <= 0; 922e1051a39Sopenharmony_ci time_t max_time = timeout > 0 ? time(NULL) + timeout : 0; 923e1051a39Sopenharmony_ci int rv; 924e1051a39Sopenharmony_ci 925e1051a39Sopenharmony_ci if (bio == NULL) { 926e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); 927e1051a39Sopenharmony_ci return -1; 928e1051a39Sopenharmony_ci } 929e1051a39Sopenharmony_ci 930e1051a39Sopenharmony_ci if (nap_milliseconds < 0) 931e1051a39Sopenharmony_ci nap_milliseconds = 100; 932e1051a39Sopenharmony_ci BIO_set_nbio(bio, !blocking); 933e1051a39Sopenharmony_ci 934e1051a39Sopenharmony_ci retry: 935e1051a39Sopenharmony_ci ERR_set_mark(); 936e1051a39Sopenharmony_ci rv = BIO_do_connect(bio); 937e1051a39Sopenharmony_ci 938e1051a39Sopenharmony_ci if (rv <= 0) { /* could be timeout or retryable error or fatal error */ 939e1051a39Sopenharmony_ci int err = ERR_peek_last_error(); 940e1051a39Sopenharmony_ci int reason = ERR_GET_REASON(err); 941e1051a39Sopenharmony_ci int do_retry = BIO_should_retry(bio); /* may be 1 only if !blocking */ 942e1051a39Sopenharmony_ci 943e1051a39Sopenharmony_ci if (ERR_GET_LIB(err) == ERR_LIB_BIO) { 944e1051a39Sopenharmony_ci switch (reason) { 945e1051a39Sopenharmony_ci case ERR_R_SYS_LIB: 946e1051a39Sopenharmony_ci /* 947e1051a39Sopenharmony_ci * likely retryable system error occurred, which may be 948e1051a39Sopenharmony_ci * EAGAIN (resource temporarily unavailable) some 40 secs after 949e1051a39Sopenharmony_ci * calling getaddrinfo(): Temporary failure in name resolution 950e1051a39Sopenharmony_ci * or a premature ETIMEDOUT, some 30 seconds after connect() 951e1051a39Sopenharmony_ci */ 952e1051a39Sopenharmony_ci case BIO_R_CONNECT_ERROR: 953e1051a39Sopenharmony_ci case BIO_R_NBIO_CONNECT_ERROR: 954e1051a39Sopenharmony_ci /* some likely retryable connection error occurred */ 955e1051a39Sopenharmony_ci (void)BIO_reset(bio); /* often needed to avoid retry failure */ 956e1051a39Sopenharmony_ci do_retry = 1; 957e1051a39Sopenharmony_ci break; 958e1051a39Sopenharmony_ci default: 959e1051a39Sopenharmony_ci break; 960e1051a39Sopenharmony_ci } 961e1051a39Sopenharmony_ci } 962e1051a39Sopenharmony_ci if (timeout >= 0 && do_retry) { 963e1051a39Sopenharmony_ci ERR_pop_to_mark(); 964e1051a39Sopenharmony_ci /* will not actually wait if timeout == 0 (i.e., blocking BIO): */ 965e1051a39Sopenharmony_ci rv = bio_wait(bio, max_time, nap_milliseconds); 966e1051a39Sopenharmony_ci if (rv > 0) 967e1051a39Sopenharmony_ci goto retry; 968e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, 969e1051a39Sopenharmony_ci rv == 0 ? BIO_R_CONNECT_TIMEOUT : BIO_R_CONNECT_ERROR); 970e1051a39Sopenharmony_ci } else { 971e1051a39Sopenharmony_ci ERR_clear_last_mark(); 972e1051a39Sopenharmony_ci rv = -1; 973e1051a39Sopenharmony_ci if (err == 0) /* missing error queue entry */ 974e1051a39Sopenharmony_ci /* workaround: general error */ 975e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR); 976e1051a39Sopenharmony_ci } 977e1051a39Sopenharmony_ci } else { 978e1051a39Sopenharmony_ci ERR_clear_last_mark(); 979e1051a39Sopenharmony_ci } 980e1051a39Sopenharmony_ci 981e1051a39Sopenharmony_ci return rv; 982e1051a39Sopenharmony_ci} 983