1 /* 2 * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (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 <openssl/core_dispatch.h> 11 #include "bio_local.h" 12 #include "internal/cryptlib.h" 13 #include "crypto/context.h" 14 15 typedef struct { 16 OSSL_FUNC_BIO_read_ex_fn *c_bio_read_ex; 17 OSSL_FUNC_BIO_write_ex_fn *c_bio_write_ex; 18 OSSL_FUNC_BIO_gets_fn *c_bio_gets; 19 OSSL_FUNC_BIO_puts_fn *c_bio_puts; 20 OSSL_FUNC_BIO_ctrl_fn *c_bio_ctrl; 21 OSSL_FUNC_BIO_up_ref_fn *c_bio_up_ref; 22 OSSL_FUNC_BIO_free_fn *c_bio_free; 23 } BIO_CORE_GLOBALS; 24 25 void ossl_bio_core_globals_free(void *vbcg) 26 { 27 OPENSSL_free(vbcg); 28 } 29 30 void *ossl_bio_core_globals_new(OSSL_LIB_CTX *ctx) 31 { 32 return OPENSSL_zalloc(sizeof(BIO_CORE_GLOBALS)); 33 } 34 35 static ossl_inline BIO_CORE_GLOBALS *get_globals(OSSL_LIB_CTX *libctx) 36 { 37 return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_BIO_CORE_INDEX); 38 } 39 40 static int bio_core_read_ex(BIO *bio, char *data, size_t data_len, 41 size_t *bytes_read) 42 { 43 BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); 44 45 if (bcgbl == NULL || bcgbl->c_bio_read_ex == NULL) 46 return 0; 47 return bcgbl->c_bio_read_ex(BIO_get_data(bio), data, data_len, bytes_read); 48 } 49 50 static int bio_core_write_ex(BIO *bio, const char *data, size_t data_len, 51 size_t *written) 52 { 53 BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); 54 55 if (bcgbl == NULL || bcgbl->c_bio_write_ex == NULL) 56 return 0; 57 return bcgbl->c_bio_write_ex(BIO_get_data(bio), data, data_len, written); 58 } 59 60 static long bio_core_ctrl(BIO *bio, int cmd, long num, void *ptr) 61 { 62 BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); 63 64 if (bcgbl == NULL || bcgbl->c_bio_ctrl == NULL) 65 return -1; 66 return bcgbl->c_bio_ctrl(BIO_get_data(bio), cmd, num, ptr); 67 } 68 69 static int bio_core_gets(BIO *bio, char *buf, int size) 70 { 71 BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); 72 73 if (bcgbl == NULL || bcgbl->c_bio_gets == NULL) 74 return -1; 75 return bcgbl->c_bio_gets(BIO_get_data(bio), buf, size); 76 } 77 78 static int bio_core_puts(BIO *bio, const char *str) 79 { 80 BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); 81 82 if (bcgbl == NULL || bcgbl->c_bio_puts == NULL) 83 return -1; 84 return bcgbl->c_bio_puts(BIO_get_data(bio), str); 85 } 86 87 static int bio_core_new(BIO *bio) 88 { 89 BIO_set_init(bio, 1); 90 91 return 1; 92 } 93 94 static int bio_core_free(BIO *bio) 95 { 96 BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); 97 98 if (bcgbl == NULL) 99 return 0; 100 101 BIO_set_init(bio, 0); 102 bcgbl->c_bio_free(BIO_get_data(bio)); 103 104 return 1; 105 } 106 107 static const BIO_METHOD corebiometh = { 108 BIO_TYPE_CORE_TO_PROV, 109 "BIO to Core filter", 110 bio_core_write_ex, 111 NULL, 112 bio_core_read_ex, 113 NULL, 114 bio_core_puts, 115 bio_core_gets, 116 bio_core_ctrl, 117 bio_core_new, 118 bio_core_free, 119 NULL, 120 }; 121 122 const BIO_METHOD *BIO_s_core(void) 123 { 124 return &corebiometh; 125 } 126 127 BIO *BIO_new_from_core_bio(OSSL_LIB_CTX *libctx, OSSL_CORE_BIO *corebio) 128 { 129 BIO *outbio; 130 BIO_CORE_GLOBALS *bcgbl = get_globals(libctx); 131 132 /* Check the library context has been initialised with the callbacks */ 133 if (bcgbl == NULL || (bcgbl->c_bio_write_ex == NULL && bcgbl->c_bio_read_ex == NULL)) 134 return NULL; 135 136 if ((outbio = BIO_new_ex(libctx, BIO_s_core())) == NULL) 137 return NULL; 138 139 if (!bcgbl->c_bio_up_ref(corebio)) { 140 BIO_free(outbio); 141 return NULL; 142 } 143 BIO_set_data(outbio, corebio); 144 return outbio; 145 } 146 147 int ossl_bio_init_core(OSSL_LIB_CTX *libctx, const OSSL_DISPATCH *fns) 148 { 149 BIO_CORE_GLOBALS *bcgbl = get_globals(libctx); 150 151 if (bcgbl == NULL) 152 return 0; 153 154 for (; fns->function_id != 0; fns++) { 155 switch (fns->function_id) { 156 case OSSL_FUNC_BIO_READ_EX: 157 if (bcgbl->c_bio_read_ex == NULL) 158 bcgbl->c_bio_read_ex = OSSL_FUNC_BIO_read_ex(fns); 159 break; 160 case OSSL_FUNC_BIO_WRITE_EX: 161 if (bcgbl->c_bio_write_ex == NULL) 162 bcgbl->c_bio_write_ex = OSSL_FUNC_BIO_write_ex(fns); 163 break; 164 case OSSL_FUNC_BIO_GETS: 165 if (bcgbl->c_bio_gets == NULL) 166 bcgbl->c_bio_gets = OSSL_FUNC_BIO_gets(fns); 167 break; 168 case OSSL_FUNC_BIO_PUTS: 169 if (bcgbl->c_bio_puts == NULL) 170 bcgbl->c_bio_puts = OSSL_FUNC_BIO_puts(fns); 171 break; 172 case OSSL_FUNC_BIO_CTRL: 173 if (bcgbl->c_bio_ctrl == NULL) 174 bcgbl->c_bio_ctrl = OSSL_FUNC_BIO_ctrl(fns); 175 break; 176 case OSSL_FUNC_BIO_UP_REF: 177 if (bcgbl->c_bio_up_ref == NULL) 178 bcgbl->c_bio_up_ref = OSSL_FUNC_BIO_up_ref(fns); 179 break; 180 case OSSL_FUNC_BIO_FREE: 181 if (bcgbl->c_bio_free == NULL) 182 bcgbl->c_bio_free = OSSL_FUNC_BIO_free(fns); 183 break; 184 } 185 } 186 187 return 1; 188 } 189