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 <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 OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_LOADER_NEW, 43 OSSL_STORE_R_INVALID_SCHEME); 44 return NULL; 45 } 46 47 if ((res = OPENSSL_zalloc(sizeof(*res))) == NULL) { 48 OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_LOADER_NEW, ERR_R_MALLOC_FAILURE); 49 return NULL; 50 } 51 52 res->engine = e; 53 res->scheme = scheme; 54 return res; 55 } 56 57 const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *loader) 58 { 59 return loader->engine; 60 } 61 62 const char *OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader) 63 { 64 return loader->scheme; 65 } 66 67 int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader, 68 OSSL_STORE_open_fn open_function) 69 { 70 loader->open = open_function; 71 return 1; 72 } 73 74 int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader, 75 OSSL_STORE_ctrl_fn ctrl_function) 76 { 77 loader->ctrl = ctrl_function; 78 return 1; 79 } 80 81 int OSSL_STORE_LOADER_set_expect(OSSL_STORE_LOADER *loader, 82 OSSL_STORE_expect_fn expect_function) 83 { 84 loader->expect = expect_function; 85 return 1; 86 } 87 88 int OSSL_STORE_LOADER_set_find(OSSL_STORE_LOADER *loader, 89 OSSL_STORE_find_fn find_function) 90 { 91 loader->find = find_function; 92 return 1; 93 } 94 95 int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader, 96 OSSL_STORE_load_fn load_function) 97 { 98 loader->load = load_function; 99 return 1; 100 } 101 102 int OSSL_STORE_LOADER_set_eof(OSSL_STORE_LOADER *loader, 103 OSSL_STORE_eof_fn eof_function) 104 { 105 loader->eof = eof_function; 106 return 1; 107 } 108 109 int OSSL_STORE_LOADER_set_error(OSSL_STORE_LOADER *loader, 110 OSSL_STORE_error_fn error_function) 111 { 112 loader->error = error_function; 113 return 1; 114 } 115 116 int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader, 117 OSSL_STORE_close_fn close_function) 118 { 119 loader->close = close_function; 120 return 1; 121 } 122 123 void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader) 124 { 125 OPENSSL_free(loader); 126 } 127 128 /* 129 * Functions for registering OSSL_STORE_LOADERs 130 */ 131 132 static unsigned long store_loader_hash(const OSSL_STORE_LOADER *v) 133 { 134 return OPENSSL_LH_strhash(v->scheme); 135 } 136 137 static int store_loader_cmp(const OSSL_STORE_LOADER *a, 138 const OSSL_STORE_LOADER *b) 139 { 140 assert(a->scheme != NULL && b->scheme != NULL); 141 return strcmp(a->scheme, b->scheme); 142 } 143 144 static LHASH_OF(OSSL_STORE_LOADER) *loader_register = NULL; 145 146 int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader) 147 { 148 const char *scheme = loader->scheme; 149 int ok = 0; 150 151 /* 152 * Check that the given scheme conforms to correct scheme syntax as per 153 * RFC 3986: 154 * 155 * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) 156 */ 157 if (ossl_isalpha(*scheme)) 158 while (*scheme != '\0' 159 && (ossl_isalpha(*scheme) 160 || ossl_isdigit(*scheme) 161 || strchr("+-.", *scheme) != NULL)) 162 scheme++; 163 if (*scheme != '\0') { 164 OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT, 165 OSSL_STORE_R_INVALID_SCHEME); 166 ERR_add_error_data(2, "scheme=", loader->scheme); 167 return 0; 168 } 169 170 /* Check that functions we absolutely require are present */ 171 if (loader->open == NULL || loader->load == NULL || loader->eof == NULL 172 || loader->error == NULL || loader->close == NULL) { 173 OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT, 174 OSSL_STORE_R_LOADER_INCOMPLETE); 175 return 0; 176 } 177 178 if (!RUN_ONCE(®istry_init, do_registry_init)) { 179 OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_REGISTER_LOADER_INT, 180 ERR_R_MALLOC_FAILURE); 181 return 0; 182 } 183 CRYPTO_THREAD_write_lock(registry_lock); 184 185 if (loader_register == NULL) { 186 loader_register = lh_OSSL_STORE_LOADER_new(store_loader_hash, 187 store_loader_cmp); 188 } 189 190 if (loader_register != NULL 191 && (lh_OSSL_STORE_LOADER_insert(loader_register, loader) != NULL 192 || lh_OSSL_STORE_LOADER_error(loader_register) == 0)) 193 ok = 1; 194 195 CRYPTO_THREAD_unlock(registry_lock); 196 197 return ok; 198 } 199 int OSSL_STORE_register_loader(OSSL_STORE_LOADER *loader) 200 { 201 if (!ossl_store_init_once()) 202 return 0; 203 return ossl_store_register_loader_int(loader); 204 } 205 206 const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme) 207 { 208 OSSL_STORE_LOADER template; 209 OSSL_STORE_LOADER *loader = NULL; 210 211 template.scheme = scheme; 212 template.open = NULL; 213 template.load = NULL; 214 template.eof = NULL; 215 template.close = NULL; 216 217 if (!ossl_store_init_once()) 218 return NULL; 219 220 if (!RUN_ONCE(®istry_init, do_registry_init)) { 221 OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT, 222 ERR_R_MALLOC_FAILURE); 223 return NULL; 224 } 225 CRYPTO_THREAD_write_lock(registry_lock); 226 227 loader = lh_OSSL_STORE_LOADER_retrieve(loader_register, &template); 228 229 if (loader == NULL) { 230 OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT, 231 OSSL_STORE_R_UNREGISTERED_SCHEME); 232 ERR_add_error_data(2, "scheme=", scheme); 233 } 234 235 CRYPTO_THREAD_unlock(registry_lock); 236 237 return loader; 238 } 239 240 OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme) 241 { 242 OSSL_STORE_LOADER template; 243 OSSL_STORE_LOADER *loader = NULL; 244 245 template.scheme = scheme; 246 template.open = NULL; 247 template.load = NULL; 248 template.eof = NULL; 249 template.close = NULL; 250 251 if (!RUN_ONCE(®istry_init, do_registry_init)) { 252 OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT, 253 ERR_R_MALLOC_FAILURE); 254 return NULL; 255 } 256 CRYPTO_THREAD_write_lock(registry_lock); 257 258 loader = lh_OSSL_STORE_LOADER_delete(loader_register, &template); 259 260 if (loader == NULL) { 261 OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT, 262 OSSL_STORE_R_UNREGISTERED_SCHEME); 263 ERR_add_error_data(2, "scheme=", scheme); 264 } 265 266 CRYPTO_THREAD_unlock(registry_lock); 267 268 return loader; 269 } 270 OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme) 271 { 272 if (!ossl_store_init_once()) 273 return 0; 274 return ossl_store_unregister_loader_int(scheme); 275 } 276 277 void ossl_store_destroy_loaders_int(void) 278 { 279 assert(lh_OSSL_STORE_LOADER_num_items(loader_register) == 0); 280 lh_OSSL_STORE_LOADER_free(loader_register); 281 loader_register = NULL; 282 CRYPTO_THREAD_lock_free(registry_lock); 283 registry_lock = NULL; 284 } 285 286 /* 287 * Functions to list OSSL_STORE loaders 288 */ 289 290 IMPLEMENT_LHASH_DOALL_ARG_CONST(OSSL_STORE_LOADER, void); 291 int OSSL_STORE_do_all_loaders(void (*do_function) (const OSSL_STORE_LOADER 292 *loader, void *do_arg), 293 void *do_arg) 294 { 295 lh_OSSL_STORE_LOADER_doall_void(loader_register, do_function, do_arg); 296 return 1; 297 } 298