1 /* 2 * Copyright 2016-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 <string.h> 11 #include "crypto/ctype.h" 12 #include <assert.h> 13 14 #include <openssl/err.h> 15 #include <openssl/lhash.h> 16 #include "store_local.h" 17 18 static CRYPTO_RWLOCK *registry_lock; 19 static CRYPTO_ONCE registry_init = CRYPTO_ONCE_STATIC_INIT; 20 21 DEFINE_RUN_ONCE_STATIC(do_registry_init) 22 { 23 registry_lock = CRYPTO_THREAD_lock_new(); 24 return registry_lock != NULL; 25 } 26 27 /* 28 * Functions for manipulating OSSL_STORE_LOADERs 29 */ 30 31 OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme) 32 { 33 OSSL_STORE_LOADER *res = NULL; 34 35 /* 36 * We usually don't check NULL arguments. For loaders, though, the 37 * scheme is crucial and must never be NULL, or the user will get 38 * mysterious errors when trying to register the created loader 39 * later on. 40 */ 41 if (scheme == NULL) { 42 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_INVALID_SCHEME); 43 return NULL; 44 } 45 46 if ((res = OPENSSL_zalloc(sizeof(*res))) == NULL) { 47 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); 48 return NULL; 49 } 50 51 res->engine = e; 52 res->scheme = scheme; 53 return res; 54 } 55 56 const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *loader) 57 { 58 return loader->engine; 59 } 60 61 const char *OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader) 62 { 63 return loader->scheme; 64 } 65 66 int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader, 67 OSSL_STORE_open_fn open_function) 68 { 69 loader->open = open_function; 70 return 1; 71 } 72 73 int OSSL_STORE_LOADER_set_open_ex 74 (OSSL_STORE_LOADER *loader, 75 OSSL_STORE_open_ex_fn open_ex_function) 76 { 77 loader->open_ex = open_ex_function; 78 return 1; 79 } 80 81 int OSSL_STORE_LOADER_set_attach(OSSL_STORE_LOADER *loader, 82 OSSL_STORE_attach_fn attach_function) 83 { 84 loader->attach = attach_function; 85 return 1; 86 } 87 88 int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader, 89 OSSL_STORE_ctrl_fn ctrl_function) 90 { 91 loader->ctrl = ctrl_function; 92 return 1; 93 } 94 95 int OSSL_STORE_LOADER_set_expect(OSSL_STORE_LOADER *loader, 96 OSSL_STORE_expect_fn expect_function) 97 { 98 loader->expect = expect_function; 99 return 1; 100 } 101 102 int OSSL_STORE_LOADER_set_find(OSSL_STORE_LOADER *loader, 103 OSSL_STORE_find_fn find_function) 104 { 105 loader->find = find_function; 106 return 1; 107 } 108 109 int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader, 110 OSSL_STORE_load_fn load_function) 111 { 112 loader->load = load_function; 113 return 1; 114 } 115 116 int OSSL_STORE_LOADER_set_eof(OSSL_STORE_LOADER *loader, 117 OSSL_STORE_eof_fn eof_function) 118 { 119 loader->eof = eof_function; 120 return 1; 121 } 122 123 int OSSL_STORE_LOADER_set_error(OSSL_STORE_LOADER *loader, 124 OSSL_STORE_error_fn error_function) 125 { 126 loader->error = error_function; 127 return 1; 128 } 129 130 int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader, 131 OSSL_STORE_close_fn close_function) 132 { 133 loader->closefn = close_function; 134 return 1; 135 } 136 137 /* 138 * Functions for registering OSSL_STORE_LOADERs 139 */ 140 141 static unsigned long store_loader_hash(const OSSL_STORE_LOADER *v) 142 { 143 return OPENSSL_LH_strhash(v->scheme); 144 } 145 146 static int store_loader_cmp(const OSSL_STORE_LOADER *a, 147 const OSSL_STORE_LOADER *b) 148 { 149 assert(a->scheme != NULL && b->scheme != NULL); 150 return strcmp(a->scheme, b->scheme); 151 } 152 153 static LHASH_OF(OSSL_STORE_LOADER) *loader_register = NULL; 154 static int ossl_store_register_init(void) 155 { 156 if (loader_register == NULL) { 157 loader_register = lh_OSSL_STORE_LOADER_new(store_loader_hash, 158 store_loader_cmp); 159 } 160 return loader_register != NULL; 161 } 162 163 int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader) 164 { 165 const char *scheme = loader->scheme; 166 int ok = 0; 167 168 /* 169 * Check that the given scheme conforms to correct scheme syntax as per 170 * RFC 3986: 171 * 172 * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) 173 */ 174 if (ossl_isalpha(*scheme)) 175 while (*scheme != '\0' 176 && (ossl_isalpha(*scheme) 177 || ossl_isdigit(*scheme) 178 || strchr("+-.", *scheme) != NULL)) 179 scheme++; 180 if (*scheme != '\0') { 181 ERR_raise_data(ERR_LIB_OSSL_STORE, OSSL_STORE_R_INVALID_SCHEME, 182 "scheme=%s", loader->scheme); 183 return 0; 184 } 185 186 /* Check that functions we absolutely require are present */ 187 if (loader->open == NULL || loader->load == NULL || loader->eof == NULL 188 || loader->error == NULL || loader->closefn == NULL) { 189 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADER_INCOMPLETE); 190 return 0; 191 } 192 193 if (!RUN_ONCE(®istry_init, do_registry_init)) { 194 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); 195 return 0; 196 } 197 if (!CRYPTO_THREAD_write_lock(registry_lock)) 198 return 0; 199 200 if (ossl_store_register_init() 201 && (lh_OSSL_STORE_LOADER_insert(loader_register, loader) != NULL 202 || lh_OSSL_STORE_LOADER_error(loader_register) == 0)) 203 ok = 1; 204 205 CRYPTO_THREAD_unlock(registry_lock); 206 207 return ok; 208 } 209 int OSSL_STORE_register_loader(OSSL_STORE_LOADER *loader) 210 { 211 return ossl_store_register_loader_int(loader); 212 } 213 214 const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme) 215 { 216 OSSL_STORE_LOADER template; 217 OSSL_STORE_LOADER *loader = NULL; 218 219 template.scheme = scheme; 220 template.open = NULL; 221 template.load = NULL; 222 template.eof = NULL; 223 template.closefn = NULL; 224 template.open_ex = NULL; 225 226 if (!RUN_ONCE(®istry_init, do_registry_init)) { 227 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); 228 return NULL; 229 } 230 if (!CRYPTO_THREAD_write_lock(registry_lock)) 231 return NULL; 232 233 if (!ossl_store_register_init()) 234 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_INTERNAL_ERROR); 235 else if ((loader = lh_OSSL_STORE_LOADER_retrieve(loader_register, 236 &template)) == NULL) 237 ERR_raise_data(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNREGISTERED_SCHEME, 238 "scheme=%s", scheme); 239 240 CRYPTO_THREAD_unlock(registry_lock); 241 242 return loader; 243 } 244 245 OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme) 246 { 247 OSSL_STORE_LOADER template; 248 OSSL_STORE_LOADER *loader = NULL; 249 250 template.scheme = scheme; 251 template.open = NULL; 252 template.load = NULL; 253 template.eof = NULL; 254 template.closefn = NULL; 255 256 if (!RUN_ONCE(®istry_init, do_registry_init)) { 257 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); 258 return NULL; 259 } 260 if (!CRYPTO_THREAD_write_lock(registry_lock)) 261 return NULL; 262 263 if (!ossl_store_register_init()) 264 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_INTERNAL_ERROR); 265 else if ((loader = lh_OSSL_STORE_LOADER_delete(loader_register, 266 &template)) == NULL) 267 ERR_raise_data(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNREGISTERED_SCHEME, 268 "scheme=%s", scheme); 269 270 CRYPTO_THREAD_unlock(registry_lock); 271 272 return loader; 273 } 274 OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme) 275 { 276 return ossl_store_unregister_loader_int(scheme); 277 } 278 279 void ossl_store_destroy_loaders_int(void) 280 { 281 lh_OSSL_STORE_LOADER_free(loader_register); 282 loader_register = NULL; 283 CRYPTO_THREAD_lock_free(registry_lock); 284 registry_lock = NULL; 285 } 286 287 /* 288 * Functions to list OSSL_STORE loaders 289 */ 290 291 IMPLEMENT_LHASH_DOALL_ARG_CONST(OSSL_STORE_LOADER, void); 292 int OSSL_STORE_do_all_loaders(void (*do_function) (const OSSL_STORE_LOADER 293 *loader, void *do_arg), 294 void *do_arg) 295 { 296 if (ossl_store_register_init()) 297 lh_OSSL_STORE_LOADER_doall_void(loader_register, do_function, do_arg); 298 return 1; 299 } 300