1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2021 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#include <stdio.h> 11e1051a39Sopenharmony_ci#include <errno.h> 12e1051a39Sopenharmony_ci#include "bio_local.h" 13e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 14e1051a39Sopenharmony_ci#include <openssl/rand.h> 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci/* 17e1051a39Sopenharmony_ci * BIO_put and BIO_get both add to the digest, BIO_gets returns the digest 18e1051a39Sopenharmony_ci */ 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_cistatic int nbiof_write(BIO *h, const char *buf, int num); 21e1051a39Sopenharmony_cistatic int nbiof_read(BIO *h, char *buf, int size); 22e1051a39Sopenharmony_cistatic int nbiof_puts(BIO *h, const char *str); 23e1051a39Sopenharmony_cistatic int nbiof_gets(BIO *h, char *str, int size); 24e1051a39Sopenharmony_cistatic long nbiof_ctrl(BIO *h, int cmd, long arg1, void *arg2); 25e1051a39Sopenharmony_cistatic int nbiof_new(BIO *h); 26e1051a39Sopenharmony_cistatic int nbiof_free(BIO *data); 27e1051a39Sopenharmony_cistatic long nbiof_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); 28e1051a39Sopenharmony_citypedef struct nbio_test_st { 29e1051a39Sopenharmony_ci /* only set if we sent a 'should retry' error */ 30e1051a39Sopenharmony_ci int lrn; 31e1051a39Sopenharmony_ci int lwn; 32e1051a39Sopenharmony_ci} NBIO_TEST; 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_cistatic const BIO_METHOD methods_nbiof = { 35e1051a39Sopenharmony_ci BIO_TYPE_NBIO_TEST, 36e1051a39Sopenharmony_ci "non-blocking IO test filter", 37e1051a39Sopenharmony_ci bwrite_conv, 38e1051a39Sopenharmony_ci nbiof_write, 39e1051a39Sopenharmony_ci bread_conv, 40e1051a39Sopenharmony_ci nbiof_read, 41e1051a39Sopenharmony_ci nbiof_puts, 42e1051a39Sopenharmony_ci nbiof_gets, 43e1051a39Sopenharmony_ci nbiof_ctrl, 44e1051a39Sopenharmony_ci nbiof_new, 45e1051a39Sopenharmony_ci nbiof_free, 46e1051a39Sopenharmony_ci nbiof_callback_ctrl, 47e1051a39Sopenharmony_ci}; 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_ciconst BIO_METHOD *BIO_f_nbio_test(void) 50e1051a39Sopenharmony_ci{ 51e1051a39Sopenharmony_ci return &methods_nbiof; 52e1051a39Sopenharmony_ci} 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_cistatic int nbiof_new(BIO *bi) 55e1051a39Sopenharmony_ci{ 56e1051a39Sopenharmony_ci NBIO_TEST *nt; 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci if ((nt = OPENSSL_zalloc(sizeof(*nt))) == NULL) { 59e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); 60e1051a39Sopenharmony_ci return 0; 61e1051a39Sopenharmony_ci } 62e1051a39Sopenharmony_ci nt->lrn = -1; 63e1051a39Sopenharmony_ci nt->lwn = -1; 64e1051a39Sopenharmony_ci bi->ptr = (char *)nt; 65e1051a39Sopenharmony_ci bi->init = 1; 66e1051a39Sopenharmony_ci return 1; 67e1051a39Sopenharmony_ci} 68e1051a39Sopenharmony_ci 69e1051a39Sopenharmony_cistatic int nbiof_free(BIO *a) 70e1051a39Sopenharmony_ci{ 71e1051a39Sopenharmony_ci if (a == NULL) 72e1051a39Sopenharmony_ci return 0; 73e1051a39Sopenharmony_ci OPENSSL_free(a->ptr); 74e1051a39Sopenharmony_ci a->ptr = NULL; 75e1051a39Sopenharmony_ci a->init = 0; 76e1051a39Sopenharmony_ci a->flags = 0; 77e1051a39Sopenharmony_ci return 1; 78e1051a39Sopenharmony_ci} 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_cistatic int nbiof_read(BIO *b, char *out, int outl) 81e1051a39Sopenharmony_ci{ 82e1051a39Sopenharmony_ci int ret = 0; 83e1051a39Sopenharmony_ci int num; 84e1051a39Sopenharmony_ci unsigned char n; 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci if (out == NULL) 87e1051a39Sopenharmony_ci return 0; 88e1051a39Sopenharmony_ci if (b->next_bio == NULL) 89e1051a39Sopenharmony_ci return 0; 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 92e1051a39Sopenharmony_ci if (RAND_priv_bytes(&n, 1) <= 0) 93e1051a39Sopenharmony_ci return -1; 94e1051a39Sopenharmony_ci num = (n & 0x07); 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci if (outl > num) 97e1051a39Sopenharmony_ci outl = num; 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci if (num == 0) { 100e1051a39Sopenharmony_ci ret = -1; 101e1051a39Sopenharmony_ci BIO_set_retry_read(b); 102e1051a39Sopenharmony_ci } else { 103e1051a39Sopenharmony_ci ret = BIO_read(b->next_bio, out, outl); 104e1051a39Sopenharmony_ci if (ret < 0) 105e1051a39Sopenharmony_ci BIO_copy_next_retry(b); 106e1051a39Sopenharmony_ci } 107e1051a39Sopenharmony_ci return ret; 108e1051a39Sopenharmony_ci} 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_cistatic int nbiof_write(BIO *b, const char *in, int inl) 111e1051a39Sopenharmony_ci{ 112e1051a39Sopenharmony_ci NBIO_TEST *nt; 113e1051a39Sopenharmony_ci int ret = 0; 114e1051a39Sopenharmony_ci int num; 115e1051a39Sopenharmony_ci unsigned char n; 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci if ((in == NULL) || (inl <= 0)) 118e1051a39Sopenharmony_ci return 0; 119e1051a39Sopenharmony_ci if (b->next_bio == NULL) 120e1051a39Sopenharmony_ci return 0; 121e1051a39Sopenharmony_ci nt = (NBIO_TEST *)b->ptr; 122e1051a39Sopenharmony_ci 123e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 124e1051a39Sopenharmony_ci 125e1051a39Sopenharmony_ci if (nt->lwn > 0) { 126e1051a39Sopenharmony_ci num = nt->lwn; 127e1051a39Sopenharmony_ci nt->lwn = 0; 128e1051a39Sopenharmony_ci } else { 129e1051a39Sopenharmony_ci if (RAND_priv_bytes(&n, 1) <= 0) 130e1051a39Sopenharmony_ci return -1; 131e1051a39Sopenharmony_ci num = (n & 7); 132e1051a39Sopenharmony_ci } 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ci if (inl > num) 135e1051a39Sopenharmony_ci inl = num; 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_ci if (num == 0) { 138e1051a39Sopenharmony_ci ret = -1; 139e1051a39Sopenharmony_ci BIO_set_retry_write(b); 140e1051a39Sopenharmony_ci } else { 141e1051a39Sopenharmony_ci ret = BIO_write(b->next_bio, in, inl); 142e1051a39Sopenharmony_ci if (ret < 0) { 143e1051a39Sopenharmony_ci BIO_copy_next_retry(b); 144e1051a39Sopenharmony_ci nt->lwn = inl; 145e1051a39Sopenharmony_ci } 146e1051a39Sopenharmony_ci } 147e1051a39Sopenharmony_ci return ret; 148e1051a39Sopenharmony_ci} 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_cistatic long nbiof_ctrl(BIO *b, int cmd, long num, void *ptr) 151e1051a39Sopenharmony_ci{ 152e1051a39Sopenharmony_ci long ret; 153e1051a39Sopenharmony_ci 154e1051a39Sopenharmony_ci if (b->next_bio == NULL) 155e1051a39Sopenharmony_ci return 0; 156e1051a39Sopenharmony_ci switch (cmd) { 157e1051a39Sopenharmony_ci case BIO_C_DO_STATE_MACHINE: 158e1051a39Sopenharmony_ci BIO_clear_retry_flags(b); 159e1051a39Sopenharmony_ci ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 160e1051a39Sopenharmony_ci BIO_copy_next_retry(b); 161e1051a39Sopenharmony_ci break; 162e1051a39Sopenharmony_ci case BIO_CTRL_DUP: 163e1051a39Sopenharmony_ci ret = 0L; 164e1051a39Sopenharmony_ci break; 165e1051a39Sopenharmony_ci default: 166e1051a39Sopenharmony_ci ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 167e1051a39Sopenharmony_ci break; 168e1051a39Sopenharmony_ci } 169e1051a39Sopenharmony_ci return ret; 170e1051a39Sopenharmony_ci} 171e1051a39Sopenharmony_ci 172e1051a39Sopenharmony_cistatic long nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 173e1051a39Sopenharmony_ci{ 174e1051a39Sopenharmony_ci if (b->next_bio == NULL) 175e1051a39Sopenharmony_ci return 0; 176e1051a39Sopenharmony_ci return BIO_callback_ctrl(b->next_bio, cmd, fp); 177e1051a39Sopenharmony_ci} 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_cistatic int nbiof_gets(BIO *bp, char *buf, int size) 180e1051a39Sopenharmony_ci{ 181e1051a39Sopenharmony_ci if (bp->next_bio == NULL) 182e1051a39Sopenharmony_ci return 0; 183e1051a39Sopenharmony_ci return BIO_gets(bp->next_bio, buf, size); 184e1051a39Sopenharmony_ci} 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_cistatic int nbiof_puts(BIO *bp, const char *str) 187e1051a39Sopenharmony_ci{ 188e1051a39Sopenharmony_ci if (bp->next_bio == NULL) 189e1051a39Sopenharmony_ci return 0; 190e1051a39Sopenharmony_ci return BIO_puts(bp->next_bio, str); 191e1051a39Sopenharmony_ci} 192