1 /* 2 * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "bio_local.h" 11 #include "internal/thread_once.h" 12 13 CRYPTO_RWLOCK *bio_type_lock = NULL; 14 static CRYPTO_ONCE bio_type_init = CRYPTO_ONCE_STATIC_INIT; 15 16 DEFINE_RUN_ONCE_STATIC(do_bio_type_init) 17 { 18 bio_type_lock = CRYPTO_THREAD_lock_new(); 19 return bio_type_lock != NULL; 20 } 21 22 int BIO_get_new_index(void) 23 { 24 static CRYPTO_REF_COUNT bio_count = BIO_TYPE_START; 25 int newval; 26 27 if (!RUN_ONCE(&bio_type_init, do_bio_type_init)) { 28 BIOerr(BIO_F_BIO_GET_NEW_INDEX, ERR_R_MALLOC_FAILURE); 29 return -1; 30 } 31 if (!CRYPTO_UP_REF(&bio_count, &newval, bio_type_lock)) 32 return -1; 33 return newval; 34 } 35 36 BIO_METHOD *BIO_meth_new(int type, const char *name) 37 { 38 BIO_METHOD *biom = OPENSSL_zalloc(sizeof(BIO_METHOD)); 39 40 if (biom == NULL 41 || (biom->name = OPENSSL_strdup(name)) == NULL) { 42 OPENSSL_free(biom); 43 BIOerr(BIO_F_BIO_METH_NEW, ERR_R_MALLOC_FAILURE); 44 return NULL; 45 } 46 biom->type = type; 47 return biom; 48 } 49 50 void BIO_meth_free(BIO_METHOD *biom) 51 { 52 if (biom != NULL) { 53 OPENSSL_free(biom->name); 54 OPENSSL_free(biom); 55 } 56 } 57 58 int (*BIO_meth_get_write(const BIO_METHOD *biom)) (BIO *, const char *, int) 59 { 60 return biom->bwrite_old; 61 } 62 63 int (*BIO_meth_get_write_ex(const BIO_METHOD *biom)) (BIO *, const char *, size_t, 64 size_t *) 65 { 66 return biom->bwrite; 67 } 68 69 /* Conversion for old style bwrite to new style */ 70 int bwrite_conv(BIO *bio, const char *data, size_t datal, size_t *written) 71 { 72 int ret; 73 74 if (datal > INT_MAX) 75 datal = INT_MAX; 76 77 ret = bio->method->bwrite_old(bio, data, (int)datal); 78 79 if (ret <= 0) { 80 *written = 0; 81 return ret; 82 } 83 84 *written = (size_t)ret; 85 86 return 1; 87 } 88 89 int BIO_meth_set_write(BIO_METHOD *biom, 90 int (*bwrite) (BIO *, const char *, int)) 91 { 92 biom->bwrite_old = bwrite; 93 biom->bwrite = bwrite_conv; 94 return 1; 95 } 96 97 int BIO_meth_set_write_ex(BIO_METHOD *biom, 98 int (*bwrite) (BIO *, const char *, size_t, size_t *)) 99 { 100 biom->bwrite_old = NULL; 101 biom->bwrite = bwrite; 102 return 1; 103 } 104 105 int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int) 106 { 107 return biom->bread_old; 108 } 109 110 int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *) 111 { 112 return biom->bread; 113 } 114 115 /* Conversion for old style bread to new style */ 116 int bread_conv(BIO *bio, char *data, size_t datal, size_t *readbytes) 117 { 118 int ret; 119 120 if (datal > INT_MAX) 121 datal = INT_MAX; 122 123 ret = bio->method->bread_old(bio, data, (int)datal); 124 125 if (ret <= 0) { 126 *readbytes = 0; 127 return ret; 128 } 129 130 *readbytes = (size_t)ret; 131 132 return 1; 133 } 134 135 int BIO_meth_set_read(BIO_METHOD *biom, 136 int (*bread) (BIO *, char *, int)) 137 { 138 biom->bread_old = bread; 139 biom->bread = bread_conv; 140 return 1; 141 } 142 143 int BIO_meth_set_read_ex(BIO_METHOD *biom, 144 int (*bread) (BIO *, char *, size_t, size_t *)) 145 { 146 biom->bread_old = NULL; 147 biom->bread = bread; 148 return 1; 149 } 150 151 int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *) 152 { 153 return biom->bputs; 154 } 155 156 int BIO_meth_set_puts(BIO_METHOD *biom, 157 int (*bputs) (BIO *, const char *)) 158 { 159 biom->bputs = bputs; 160 return 1; 161 } 162 163 int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int) 164 { 165 return biom->bgets; 166 } 167 168 int BIO_meth_set_gets(BIO_METHOD *biom, 169 int (*bgets) (BIO *, char *, int)) 170 { 171 biom->bgets = bgets; 172 return 1; 173 } 174 175 long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *) 176 { 177 return biom->ctrl; 178 } 179 180 int BIO_meth_set_ctrl(BIO_METHOD *biom, 181 long (*ctrl) (BIO *, int, long, void *)) 182 { 183 biom->ctrl = ctrl; 184 return 1; 185 } 186 187 int (*BIO_meth_get_create(const BIO_METHOD *biom)) (BIO *) 188 { 189 return biom->create; 190 } 191 192 int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *)) 193 { 194 biom->create = create; 195 return 1; 196 } 197 198 int (*BIO_meth_get_destroy(const BIO_METHOD *biom)) (BIO *) 199 { 200 return biom->destroy; 201 } 202 203 int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *)) 204 { 205 biom->destroy = destroy; 206 return 1; 207 } 208 209 long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom)) (BIO *, int, BIO_info_cb *) 210 { 211 return biom->callback_ctrl; 212 } 213 214 int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, 215 long (*callback_ctrl) (BIO *, int, 216 BIO_info_cb *)) 217 { 218 biom->callback_ctrl = callback_ctrl; 219 return 1; 220 } 221