1 /* 2 * Copyright 2019-2021 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 <assert.h> 11 #include <openssl/core_dispatch.h> 12 #include "internal/cryptlib.h" 13 #include "prov/bio.h" 14 15 static OSSL_FUNC_BIO_new_file_fn *c_bio_new_file = NULL; 16 static OSSL_FUNC_BIO_new_membuf_fn *c_bio_new_membuf = NULL; 17 static OSSL_FUNC_BIO_read_ex_fn *c_bio_read_ex = NULL; 18 static OSSL_FUNC_BIO_write_ex_fn *c_bio_write_ex = NULL; 19 static OSSL_FUNC_BIO_gets_fn *c_bio_gets = NULL; 20 static OSSL_FUNC_BIO_puts_fn *c_bio_puts = NULL; 21 static OSSL_FUNC_BIO_ctrl_fn *c_bio_ctrl = NULL; 22 static OSSL_FUNC_BIO_up_ref_fn *c_bio_up_ref = NULL; 23 static OSSL_FUNC_BIO_free_fn *c_bio_free = NULL; 24 static OSSL_FUNC_BIO_vprintf_fn *c_bio_vprintf = NULL; 25 26 int ossl_prov_bio_from_dispatch(const OSSL_DISPATCH *fns) 27 { 28 for (; fns->function_id != 0; fns++) { 29 switch (fns->function_id) { 30 case OSSL_FUNC_BIO_NEW_FILE: 31 if (c_bio_new_file == NULL) 32 c_bio_new_file = OSSL_FUNC_BIO_new_file(fns); 33 break; 34 case OSSL_FUNC_BIO_NEW_MEMBUF: 35 if (c_bio_new_membuf == NULL) 36 c_bio_new_membuf = OSSL_FUNC_BIO_new_membuf(fns); 37 break; 38 case OSSL_FUNC_BIO_READ_EX: 39 if (c_bio_read_ex == NULL) 40 c_bio_read_ex = OSSL_FUNC_BIO_read_ex(fns); 41 break; 42 case OSSL_FUNC_BIO_WRITE_EX: 43 if (c_bio_write_ex == NULL) 44 c_bio_write_ex = OSSL_FUNC_BIO_write_ex(fns); 45 break; 46 case OSSL_FUNC_BIO_GETS: 47 if (c_bio_gets == NULL) 48 c_bio_gets = OSSL_FUNC_BIO_gets(fns); 49 break; 50 case OSSL_FUNC_BIO_PUTS: 51 if (c_bio_puts == NULL) 52 c_bio_puts = OSSL_FUNC_BIO_puts(fns); 53 break; 54 case OSSL_FUNC_BIO_CTRL: 55 if (c_bio_ctrl == NULL) 56 c_bio_ctrl = OSSL_FUNC_BIO_ctrl(fns); 57 break; 58 case OSSL_FUNC_BIO_UP_REF: 59 if (c_bio_up_ref == NULL) 60 c_bio_up_ref = OSSL_FUNC_BIO_up_ref(fns); 61 break; 62 case OSSL_FUNC_BIO_FREE: 63 if (c_bio_free == NULL) 64 c_bio_free = OSSL_FUNC_BIO_free(fns); 65 break; 66 case OSSL_FUNC_BIO_VPRINTF: 67 if (c_bio_vprintf == NULL) 68 c_bio_vprintf = OSSL_FUNC_BIO_vprintf(fns); 69 break; 70 } 71 } 72 73 return 1; 74 } 75 76 OSSL_CORE_BIO *ossl_prov_bio_new_file(const char *filename, const char *mode) 77 { 78 if (c_bio_new_file == NULL) 79 return NULL; 80 return c_bio_new_file(filename, mode); 81 } 82 83 OSSL_CORE_BIO *ossl_prov_bio_new_membuf(const char *filename, int len) 84 { 85 if (c_bio_new_membuf == NULL) 86 return NULL; 87 return c_bio_new_membuf(filename, len); 88 } 89 90 int ossl_prov_bio_read_ex(OSSL_CORE_BIO *bio, void *data, size_t data_len, 91 size_t *bytes_read) 92 { 93 if (c_bio_read_ex == NULL) 94 return 0; 95 return c_bio_read_ex(bio, data, data_len, bytes_read); 96 } 97 98 int ossl_prov_bio_write_ex(OSSL_CORE_BIO *bio, const void *data, size_t data_len, 99 size_t *written) 100 { 101 if (c_bio_write_ex == NULL) 102 return 0; 103 return c_bio_write_ex(bio, data, data_len, written); 104 } 105 106 int ossl_prov_bio_gets(OSSL_CORE_BIO *bio, char *buf, int size) 107 { 108 if (c_bio_gets == NULL) 109 return -1; 110 return c_bio_gets(bio, buf, size); 111 } 112 113 int ossl_prov_bio_puts(OSSL_CORE_BIO *bio, const char *str) 114 { 115 if (c_bio_puts == NULL) 116 return -1; 117 return c_bio_puts(bio, str); 118 } 119 120 int ossl_prov_bio_ctrl(OSSL_CORE_BIO *bio, int cmd, long num, void *ptr) 121 { 122 if (c_bio_ctrl == NULL) 123 return -1; 124 return c_bio_ctrl(bio, cmd, num, ptr); 125 } 126 127 int ossl_prov_bio_up_ref(OSSL_CORE_BIO *bio) 128 { 129 if (c_bio_up_ref == NULL) 130 return 0; 131 return c_bio_up_ref(bio); 132 } 133 134 int ossl_prov_bio_free(OSSL_CORE_BIO *bio) 135 { 136 if (c_bio_free == NULL) 137 return 0; 138 return c_bio_free(bio); 139 } 140 141 int ossl_prov_bio_vprintf(OSSL_CORE_BIO *bio, const char *format, va_list ap) 142 { 143 if (c_bio_vprintf == NULL) 144 return -1; 145 return c_bio_vprintf(bio, format, ap); 146 } 147 148 int ossl_prov_bio_printf(OSSL_CORE_BIO *bio, const char *format, ...) 149 { 150 va_list ap; 151 int ret; 152 153 va_start(ap, format); 154 ret = ossl_prov_bio_vprintf(bio, format, ap); 155 va_end(ap); 156 157 return ret; 158 } 159 160 #ifndef FIPS_MODULE 161 162 /* No direct BIO support in the FIPS module */ 163 164 static int bio_core_read_ex(BIO *bio, char *data, size_t data_len, 165 size_t *bytes_read) 166 { 167 return ossl_prov_bio_read_ex(BIO_get_data(bio), data, data_len, bytes_read); 168 } 169 170 static int bio_core_write_ex(BIO *bio, const char *data, size_t data_len, 171 size_t *written) 172 { 173 return ossl_prov_bio_write_ex(BIO_get_data(bio), data, data_len, written); 174 } 175 176 static long bio_core_ctrl(BIO *bio, int cmd, long num, void *ptr) 177 { 178 return ossl_prov_bio_ctrl(BIO_get_data(bio), cmd, num, ptr); 179 } 180 181 static int bio_core_gets(BIO *bio, char *buf, int size) 182 { 183 return ossl_prov_bio_gets(BIO_get_data(bio), buf, size); 184 } 185 186 static int bio_core_puts(BIO *bio, const char *str) 187 { 188 return ossl_prov_bio_puts(BIO_get_data(bio), str); 189 } 190 191 static int bio_core_new(BIO *bio) 192 { 193 BIO_set_init(bio, 1); 194 195 return 1; 196 } 197 198 static int bio_core_free(BIO *bio) 199 { 200 BIO_set_init(bio, 0); 201 ossl_prov_bio_free(BIO_get_data(bio)); 202 203 return 1; 204 } 205 206 BIO_METHOD *ossl_bio_prov_init_bio_method(void) 207 { 208 BIO_METHOD *corebiometh = NULL; 209 210 corebiometh = BIO_meth_new(BIO_TYPE_CORE_TO_PROV, "BIO to Core filter"); 211 if (corebiometh == NULL 212 || !BIO_meth_set_write_ex(corebiometh, bio_core_write_ex) 213 || !BIO_meth_set_read_ex(corebiometh, bio_core_read_ex) 214 || !BIO_meth_set_puts(corebiometh, bio_core_puts) 215 || !BIO_meth_set_gets(corebiometh, bio_core_gets) 216 || !BIO_meth_set_ctrl(corebiometh, bio_core_ctrl) 217 || !BIO_meth_set_create(corebiometh, bio_core_new) 218 || !BIO_meth_set_destroy(corebiometh, bio_core_free)) { 219 BIO_meth_free(corebiometh); 220 return NULL; 221 } 222 223 return corebiometh; 224 } 225 226 BIO *ossl_bio_new_from_core_bio(PROV_CTX *provctx, OSSL_CORE_BIO *corebio) 227 { 228 BIO *outbio; 229 BIO_METHOD *corebiometh = ossl_prov_ctx_get0_core_bio_method(provctx); 230 231 if (corebiometh == NULL) 232 return NULL; 233 234 if ((outbio = BIO_new(corebiometh)) == NULL) 235 return NULL; 236 if (!ossl_prov_bio_up_ref(corebio)) { 237 BIO_free(outbio); 238 return NULL; 239 } 240 BIO_set_data(outbio, corebio); 241 return outbio; 242 } 243 244 #endif 245