1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include "internal/namemap.h" 11e1051a39Sopenharmony_ci#include <openssl/lhash.h> 12e1051a39Sopenharmony_ci#include "crypto/lhash.h" /* ossl_lh_strcasehash */ 13e1051a39Sopenharmony_ci#include "internal/tsan_assist.h" 14e1051a39Sopenharmony_ci#include "internal/sizes.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci/*- 17e1051a39Sopenharmony_ci * The namenum entry 18e1051a39Sopenharmony_ci * ================= 19e1051a39Sopenharmony_ci */ 20e1051a39Sopenharmony_citypedef struct { 21e1051a39Sopenharmony_ci char *name; 22e1051a39Sopenharmony_ci int number; 23e1051a39Sopenharmony_ci} NAMENUM_ENTRY; 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ciDEFINE_LHASH_OF(NAMENUM_ENTRY); 26e1051a39Sopenharmony_ci 27e1051a39Sopenharmony_ci/*- 28e1051a39Sopenharmony_ci * The namemap itself 29e1051a39Sopenharmony_ci * ================== 30e1051a39Sopenharmony_ci */ 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_cistruct ossl_namemap_st { 33e1051a39Sopenharmony_ci /* Flags */ 34e1051a39Sopenharmony_ci unsigned int stored:1; /* If 1, it's stored in a library context */ 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci CRYPTO_RWLOCK *lock; 37e1051a39Sopenharmony_ci LHASH_OF(NAMENUM_ENTRY) *namenum; /* Name->number mapping */ 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ci TSAN_QUALIFIER int max_number; /* Current max number */ 40e1051a39Sopenharmony_ci}; 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ci/* LHASH callbacks */ 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_cistatic unsigned long namenum_hash(const NAMENUM_ENTRY *n) 45e1051a39Sopenharmony_ci{ 46e1051a39Sopenharmony_ci return ossl_lh_strcasehash(n->name); 47e1051a39Sopenharmony_ci} 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_cistatic int namenum_cmp(const NAMENUM_ENTRY *a, const NAMENUM_ENTRY *b) 50e1051a39Sopenharmony_ci{ 51e1051a39Sopenharmony_ci return OPENSSL_strcasecmp(a->name, b->name); 52e1051a39Sopenharmony_ci} 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_cistatic void namenum_free(NAMENUM_ENTRY *n) 55e1051a39Sopenharmony_ci{ 56e1051a39Sopenharmony_ci if (n != NULL) 57e1051a39Sopenharmony_ci OPENSSL_free(n->name); 58e1051a39Sopenharmony_ci OPENSSL_free(n); 59e1051a39Sopenharmony_ci} 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_ci/* OSSL_LIB_CTX_METHOD functions for a namemap stored in a library context */ 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_cistatic void *stored_namemap_new(OSSL_LIB_CTX *libctx) 64e1051a39Sopenharmony_ci{ 65e1051a39Sopenharmony_ci OSSL_NAMEMAP *namemap = ossl_namemap_new(); 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_ci if (namemap != NULL) 68e1051a39Sopenharmony_ci namemap->stored = 1; 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci return namemap; 71e1051a39Sopenharmony_ci} 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_cistatic void stored_namemap_free(void *vnamemap) 74e1051a39Sopenharmony_ci{ 75e1051a39Sopenharmony_ci OSSL_NAMEMAP *namemap = vnamemap; 76e1051a39Sopenharmony_ci 77e1051a39Sopenharmony_ci if (namemap != NULL) { 78e1051a39Sopenharmony_ci /* Pretend it isn't stored, or ossl_namemap_free() will do nothing */ 79e1051a39Sopenharmony_ci namemap->stored = 0; 80e1051a39Sopenharmony_ci ossl_namemap_free(namemap); 81e1051a39Sopenharmony_ci } 82e1051a39Sopenharmony_ci} 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_cistatic const OSSL_LIB_CTX_METHOD stored_namemap_method = { 85e1051a39Sopenharmony_ci OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, 86e1051a39Sopenharmony_ci stored_namemap_new, 87e1051a39Sopenharmony_ci stored_namemap_free, 88e1051a39Sopenharmony_ci}; 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci/*- 91e1051a39Sopenharmony_ci * API functions 92e1051a39Sopenharmony_ci * ============= 93e1051a39Sopenharmony_ci */ 94e1051a39Sopenharmony_ci 95e1051a39Sopenharmony_ciint ossl_namemap_empty(OSSL_NAMEMAP *namemap) 96e1051a39Sopenharmony_ci{ 97e1051a39Sopenharmony_ci#ifdef TSAN_REQUIRES_LOCKING 98e1051a39Sopenharmony_ci /* No TSAN support */ 99e1051a39Sopenharmony_ci int rv; 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci if (namemap == NULL) 102e1051a39Sopenharmony_ci return 1; 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_read_lock(namemap->lock)) 105e1051a39Sopenharmony_ci return -1; 106e1051a39Sopenharmony_ci rv = namemap->max_number == 0; 107e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(namemap->lock); 108e1051a39Sopenharmony_ci return rv; 109e1051a39Sopenharmony_ci#else 110e1051a39Sopenharmony_ci /* Have TSAN support */ 111e1051a39Sopenharmony_ci return namemap == NULL || tsan_load(&namemap->max_number) == 0; 112e1051a39Sopenharmony_ci#endif 113e1051a39Sopenharmony_ci} 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_citypedef struct doall_names_data_st { 116e1051a39Sopenharmony_ci int number; 117e1051a39Sopenharmony_ci const char **names; 118e1051a39Sopenharmony_ci int found; 119e1051a39Sopenharmony_ci} DOALL_NAMES_DATA; 120e1051a39Sopenharmony_ci 121e1051a39Sopenharmony_cistatic void do_name(const NAMENUM_ENTRY *namenum, DOALL_NAMES_DATA *data) 122e1051a39Sopenharmony_ci{ 123e1051a39Sopenharmony_ci if (namenum->number == data->number) 124e1051a39Sopenharmony_ci data->names[data->found++] = namenum->name; 125e1051a39Sopenharmony_ci} 126e1051a39Sopenharmony_ci 127e1051a39Sopenharmony_ciIMPLEMENT_LHASH_DOALL_ARG_CONST(NAMENUM_ENTRY, DOALL_NAMES_DATA); 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ci/* 130e1051a39Sopenharmony_ci * Call the callback for all names in the namemap with the given number. 131e1051a39Sopenharmony_ci * A return value 1 means that the callback was called for all names. A 132e1051a39Sopenharmony_ci * return value of 0 means that the callback was not called for any names. 133e1051a39Sopenharmony_ci */ 134e1051a39Sopenharmony_ciint ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number, 135e1051a39Sopenharmony_ci void (*fn)(const char *name, void *data), 136e1051a39Sopenharmony_ci void *data) 137e1051a39Sopenharmony_ci{ 138e1051a39Sopenharmony_ci DOALL_NAMES_DATA cbdata; 139e1051a39Sopenharmony_ci size_t num_names; 140e1051a39Sopenharmony_ci int i; 141e1051a39Sopenharmony_ci 142e1051a39Sopenharmony_ci cbdata.number = number; 143e1051a39Sopenharmony_ci cbdata.found = 0; 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci /* 146e1051a39Sopenharmony_ci * We collect all the names first under a read lock. Subsequently we call 147e1051a39Sopenharmony_ci * the user function, so that we're not holding the read lock when in user 148e1051a39Sopenharmony_ci * code. This could lead to deadlocks. 149e1051a39Sopenharmony_ci */ 150e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_read_lock(namemap->lock)) 151e1051a39Sopenharmony_ci return 0; 152e1051a39Sopenharmony_ci 153e1051a39Sopenharmony_ci num_names = lh_NAMENUM_ENTRY_num_items(namemap->namenum); 154e1051a39Sopenharmony_ci if (num_names == 0) { 155e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(namemap->lock); 156e1051a39Sopenharmony_ci return 0; 157e1051a39Sopenharmony_ci } 158e1051a39Sopenharmony_ci cbdata.names = OPENSSL_malloc(sizeof(*cbdata.names) * num_names); 159e1051a39Sopenharmony_ci if (cbdata.names == NULL) { 160e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(namemap->lock); 161e1051a39Sopenharmony_ci return 0; 162e1051a39Sopenharmony_ci } 163e1051a39Sopenharmony_ci lh_NAMENUM_ENTRY_doall_DOALL_NAMES_DATA(namemap->namenum, do_name, 164e1051a39Sopenharmony_ci &cbdata); 165e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(namemap->lock); 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_ci for (i = 0; i < cbdata.found; i++) 168e1051a39Sopenharmony_ci fn(cbdata.names[i], data); 169e1051a39Sopenharmony_ci 170e1051a39Sopenharmony_ci OPENSSL_free(cbdata.names); 171e1051a39Sopenharmony_ci return 1; 172e1051a39Sopenharmony_ci} 173e1051a39Sopenharmony_ci 174e1051a39Sopenharmony_cistatic int namemap_name2num_n(const OSSL_NAMEMAP *namemap, 175e1051a39Sopenharmony_ci const char *name, size_t name_len) 176e1051a39Sopenharmony_ci{ 177e1051a39Sopenharmony_ci NAMENUM_ENTRY *namenum_entry, namenum_tmpl; 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci if ((namenum_tmpl.name = OPENSSL_strndup(name, name_len)) == NULL) 180e1051a39Sopenharmony_ci return 0; 181e1051a39Sopenharmony_ci namenum_tmpl.number = 0; 182e1051a39Sopenharmony_ci namenum_entry = 183e1051a39Sopenharmony_ci lh_NAMENUM_ENTRY_retrieve(namemap->namenum, &namenum_tmpl); 184e1051a39Sopenharmony_ci OPENSSL_free(namenum_tmpl.name); 185e1051a39Sopenharmony_ci return namenum_entry != NULL ? namenum_entry->number : 0; 186e1051a39Sopenharmony_ci} 187e1051a39Sopenharmony_ci 188e1051a39Sopenharmony_ciint ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap, 189e1051a39Sopenharmony_ci const char *name, size_t name_len) 190e1051a39Sopenharmony_ci{ 191e1051a39Sopenharmony_ci int number; 192e1051a39Sopenharmony_ci 193e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 194e1051a39Sopenharmony_ci if (namemap == NULL) 195e1051a39Sopenharmony_ci namemap = ossl_namemap_stored(NULL); 196e1051a39Sopenharmony_ci#endif 197e1051a39Sopenharmony_ci 198e1051a39Sopenharmony_ci if (namemap == NULL) 199e1051a39Sopenharmony_ci return 0; 200e1051a39Sopenharmony_ci 201e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_read_lock(namemap->lock)) 202e1051a39Sopenharmony_ci return 0; 203e1051a39Sopenharmony_ci number = namemap_name2num_n(namemap, name, name_len); 204e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(namemap->lock); 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_ci return number; 207e1051a39Sopenharmony_ci} 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_ciint ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name) 210e1051a39Sopenharmony_ci{ 211e1051a39Sopenharmony_ci if (name == NULL) 212e1051a39Sopenharmony_ci return 0; 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ci return ossl_namemap_name2num_n(namemap, name, strlen(name)); 215e1051a39Sopenharmony_ci} 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_cistruct num2name_data_st { 218e1051a39Sopenharmony_ci size_t idx; /* Countdown */ 219e1051a39Sopenharmony_ci const char *name; /* Result */ 220e1051a39Sopenharmony_ci}; 221e1051a39Sopenharmony_ci 222e1051a39Sopenharmony_cistatic void do_num2name(const char *name, void *vdata) 223e1051a39Sopenharmony_ci{ 224e1051a39Sopenharmony_ci struct num2name_data_st *data = vdata; 225e1051a39Sopenharmony_ci 226e1051a39Sopenharmony_ci if (data->idx > 0) 227e1051a39Sopenharmony_ci data->idx--; 228e1051a39Sopenharmony_ci else if (data->name == NULL) 229e1051a39Sopenharmony_ci data->name = name; 230e1051a39Sopenharmony_ci} 231e1051a39Sopenharmony_ci 232e1051a39Sopenharmony_ciconst char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number, 233e1051a39Sopenharmony_ci size_t idx) 234e1051a39Sopenharmony_ci{ 235e1051a39Sopenharmony_ci struct num2name_data_st data; 236e1051a39Sopenharmony_ci 237e1051a39Sopenharmony_ci data.idx = idx; 238e1051a39Sopenharmony_ci data.name = NULL; 239e1051a39Sopenharmony_ci if (!ossl_namemap_doall_names(namemap, number, do_num2name, &data)) 240e1051a39Sopenharmony_ci return NULL; 241e1051a39Sopenharmony_ci return data.name; 242e1051a39Sopenharmony_ci} 243e1051a39Sopenharmony_ci 244e1051a39Sopenharmony_cistatic int namemap_add_name_n(OSSL_NAMEMAP *namemap, int number, 245e1051a39Sopenharmony_ci const char *name, size_t name_len) 246e1051a39Sopenharmony_ci{ 247e1051a39Sopenharmony_ci NAMENUM_ENTRY *namenum = NULL; 248e1051a39Sopenharmony_ci int tmp_number; 249e1051a39Sopenharmony_ci 250e1051a39Sopenharmony_ci /* If it already exists, we don't add it */ 251e1051a39Sopenharmony_ci if ((tmp_number = namemap_name2num_n(namemap, name, name_len)) != 0) 252e1051a39Sopenharmony_ci return tmp_number; 253e1051a39Sopenharmony_ci 254e1051a39Sopenharmony_ci if ((namenum = OPENSSL_zalloc(sizeof(*namenum))) == NULL 255e1051a39Sopenharmony_ci || (namenum->name = OPENSSL_strndup(name, name_len)) == NULL) 256e1051a39Sopenharmony_ci goto err; 257e1051a39Sopenharmony_ci 258e1051a39Sopenharmony_ci /* The tsan_counter use here is safe since we're under lock */ 259e1051a39Sopenharmony_ci namenum->number = 260e1051a39Sopenharmony_ci number != 0 ? number : 1 + tsan_counter(&namemap->max_number); 261e1051a39Sopenharmony_ci (void)lh_NAMENUM_ENTRY_insert(namemap->namenum, namenum); 262e1051a39Sopenharmony_ci 263e1051a39Sopenharmony_ci if (lh_NAMENUM_ENTRY_error(namemap->namenum)) 264e1051a39Sopenharmony_ci goto err; 265e1051a39Sopenharmony_ci return namenum->number; 266e1051a39Sopenharmony_ci 267e1051a39Sopenharmony_ci err: 268e1051a39Sopenharmony_ci namenum_free(namenum); 269e1051a39Sopenharmony_ci return 0; 270e1051a39Sopenharmony_ci} 271e1051a39Sopenharmony_ci 272e1051a39Sopenharmony_ciint ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number, 273e1051a39Sopenharmony_ci const char *name, size_t name_len) 274e1051a39Sopenharmony_ci{ 275e1051a39Sopenharmony_ci int tmp_number; 276e1051a39Sopenharmony_ci 277e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 278e1051a39Sopenharmony_ci if (namemap == NULL) 279e1051a39Sopenharmony_ci namemap = ossl_namemap_stored(NULL); 280e1051a39Sopenharmony_ci#endif 281e1051a39Sopenharmony_ci 282e1051a39Sopenharmony_ci if (name == NULL || name_len == 0 || namemap == NULL) 283e1051a39Sopenharmony_ci return 0; 284e1051a39Sopenharmony_ci 285e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(namemap->lock)) 286e1051a39Sopenharmony_ci return 0; 287e1051a39Sopenharmony_ci tmp_number = namemap_add_name_n(namemap, number, name, name_len); 288e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(namemap->lock); 289e1051a39Sopenharmony_ci return tmp_number; 290e1051a39Sopenharmony_ci} 291e1051a39Sopenharmony_ci 292e1051a39Sopenharmony_ciint ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name) 293e1051a39Sopenharmony_ci{ 294e1051a39Sopenharmony_ci if (name == NULL) 295e1051a39Sopenharmony_ci return 0; 296e1051a39Sopenharmony_ci 297e1051a39Sopenharmony_ci return ossl_namemap_add_name_n(namemap, number, name, strlen(name)); 298e1051a39Sopenharmony_ci} 299e1051a39Sopenharmony_ci 300e1051a39Sopenharmony_ciint ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number, 301e1051a39Sopenharmony_ci const char *names, const char separator) 302e1051a39Sopenharmony_ci{ 303e1051a39Sopenharmony_ci const char *p, *q; 304e1051a39Sopenharmony_ci size_t l; 305e1051a39Sopenharmony_ci 306e1051a39Sopenharmony_ci /* Check that we have a namemap */ 307e1051a39Sopenharmony_ci if (!ossl_assert(namemap != NULL)) { 308e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); 309e1051a39Sopenharmony_ci return 0; 310e1051a39Sopenharmony_ci } 311e1051a39Sopenharmony_ci 312e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(namemap->lock)) 313e1051a39Sopenharmony_ci return 0; 314e1051a39Sopenharmony_ci /* 315e1051a39Sopenharmony_ci * Check that no name is an empty string, and that all names have at 316e1051a39Sopenharmony_ci * most one numeric identity together. 317e1051a39Sopenharmony_ci */ 318e1051a39Sopenharmony_ci for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) { 319e1051a39Sopenharmony_ci int this_number; 320e1051a39Sopenharmony_ci 321e1051a39Sopenharmony_ci if ((q = strchr(p, separator)) == NULL) 322e1051a39Sopenharmony_ci l = strlen(p); /* offset to \0 */ 323e1051a39Sopenharmony_ci else 324e1051a39Sopenharmony_ci l = q - p; /* offset to the next separator */ 325e1051a39Sopenharmony_ci 326e1051a39Sopenharmony_ci this_number = namemap_name2num_n(namemap, p, l); 327e1051a39Sopenharmony_ci 328e1051a39Sopenharmony_ci if (*p == '\0' || *p == separator) { 329e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME); 330e1051a39Sopenharmony_ci goto err; 331e1051a39Sopenharmony_ci } 332e1051a39Sopenharmony_ci if (number == 0) { 333e1051a39Sopenharmony_ci number = this_number; 334e1051a39Sopenharmony_ci } else if (this_number != 0 && this_number != number) { 335e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_CONFLICTING_NAMES, 336e1051a39Sopenharmony_ci "\"%.*s\" has an existing different identity %d (from \"%s\")", 337e1051a39Sopenharmony_ci l, p, this_number, names); 338e1051a39Sopenharmony_ci goto err; 339e1051a39Sopenharmony_ci } 340e1051a39Sopenharmony_ci } 341e1051a39Sopenharmony_ci 342e1051a39Sopenharmony_ci /* Now that we have checked, register all names */ 343e1051a39Sopenharmony_ci for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) { 344e1051a39Sopenharmony_ci int this_number; 345e1051a39Sopenharmony_ci 346e1051a39Sopenharmony_ci if ((q = strchr(p, separator)) == NULL) 347e1051a39Sopenharmony_ci l = strlen(p); /* offset to \0 */ 348e1051a39Sopenharmony_ci else 349e1051a39Sopenharmony_ci l = q - p; /* offset to the next separator */ 350e1051a39Sopenharmony_ci 351e1051a39Sopenharmony_ci this_number = namemap_add_name_n(namemap, number, p, l); 352e1051a39Sopenharmony_ci if (number == 0) { 353e1051a39Sopenharmony_ci number = this_number; 354e1051a39Sopenharmony_ci } else if (this_number != number) { 355e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR, 356e1051a39Sopenharmony_ci "Got number %d when expecting %d", 357e1051a39Sopenharmony_ci this_number, number); 358e1051a39Sopenharmony_ci goto err; 359e1051a39Sopenharmony_ci } 360e1051a39Sopenharmony_ci } 361e1051a39Sopenharmony_ci 362e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(namemap->lock); 363e1051a39Sopenharmony_ci return number; 364e1051a39Sopenharmony_ci 365e1051a39Sopenharmony_ci err: 366e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(namemap->lock); 367e1051a39Sopenharmony_ci return 0; 368e1051a39Sopenharmony_ci} 369e1051a39Sopenharmony_ci 370e1051a39Sopenharmony_ci/*- 371e1051a39Sopenharmony_ci * Pre-population 372e1051a39Sopenharmony_ci * ============== 373e1051a39Sopenharmony_ci */ 374e1051a39Sopenharmony_ci 375e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 376e1051a39Sopenharmony_ci#include <openssl/evp.h> 377e1051a39Sopenharmony_ci 378e1051a39Sopenharmony_ci/* Creates an initial namemap with names found in the legacy method db */ 379e1051a39Sopenharmony_cistatic void get_legacy_evp_names(int base_nid, int nid, const char *pem_name, 380e1051a39Sopenharmony_ci void *arg) 381e1051a39Sopenharmony_ci{ 382e1051a39Sopenharmony_ci int num = 0; 383e1051a39Sopenharmony_ci ASN1_OBJECT *obj; 384e1051a39Sopenharmony_ci 385e1051a39Sopenharmony_ci if (base_nid != NID_undef) { 386e1051a39Sopenharmony_ci num = ossl_namemap_add_name(arg, num, OBJ_nid2sn(base_nid)); 387e1051a39Sopenharmony_ci num = ossl_namemap_add_name(arg, num, OBJ_nid2ln(base_nid)); 388e1051a39Sopenharmony_ci } 389e1051a39Sopenharmony_ci 390e1051a39Sopenharmony_ci if (nid != NID_undef) { 391e1051a39Sopenharmony_ci num = ossl_namemap_add_name(arg, num, OBJ_nid2sn(nid)); 392e1051a39Sopenharmony_ci num = ossl_namemap_add_name(arg, num, OBJ_nid2ln(nid)); 393e1051a39Sopenharmony_ci if ((obj = OBJ_nid2obj(nid)) != NULL) { 394e1051a39Sopenharmony_ci char txtoid[OSSL_MAX_NAME_SIZE]; 395e1051a39Sopenharmony_ci 396e1051a39Sopenharmony_ci if (OBJ_obj2txt(txtoid, sizeof(txtoid), obj, 1) > 0) 397e1051a39Sopenharmony_ci num = ossl_namemap_add_name(arg, num, txtoid); 398e1051a39Sopenharmony_ci } 399e1051a39Sopenharmony_ci } 400e1051a39Sopenharmony_ci if (pem_name != NULL) 401e1051a39Sopenharmony_ci num = ossl_namemap_add_name(arg, num, pem_name); 402e1051a39Sopenharmony_ci} 403e1051a39Sopenharmony_ci 404e1051a39Sopenharmony_cistatic void get_legacy_cipher_names(const OBJ_NAME *on, void *arg) 405e1051a39Sopenharmony_ci{ 406e1051a39Sopenharmony_ci const EVP_CIPHER *cipher = (void *)OBJ_NAME_get(on->name, on->type); 407e1051a39Sopenharmony_ci 408e1051a39Sopenharmony_ci if (cipher != NULL) 409e1051a39Sopenharmony_ci get_legacy_evp_names(NID_undef, EVP_CIPHER_get_type(cipher), NULL, arg); 410e1051a39Sopenharmony_ci} 411e1051a39Sopenharmony_ci 412e1051a39Sopenharmony_cistatic void get_legacy_md_names(const OBJ_NAME *on, void *arg) 413e1051a39Sopenharmony_ci{ 414e1051a39Sopenharmony_ci const EVP_MD *md = (void *)OBJ_NAME_get(on->name, on->type); 415e1051a39Sopenharmony_ci 416e1051a39Sopenharmony_ci if (md != NULL) 417e1051a39Sopenharmony_ci get_legacy_evp_names(0, EVP_MD_get_type(md), NULL, arg); 418e1051a39Sopenharmony_ci} 419e1051a39Sopenharmony_ci 420e1051a39Sopenharmony_cistatic void get_legacy_pkey_meth_names(const EVP_PKEY_ASN1_METHOD *ameth, 421e1051a39Sopenharmony_ci void *arg) 422e1051a39Sopenharmony_ci{ 423e1051a39Sopenharmony_ci int nid = 0, base_nid = 0, flags = 0; 424e1051a39Sopenharmony_ci const char *pem_name = NULL; 425e1051a39Sopenharmony_ci 426e1051a39Sopenharmony_ci EVP_PKEY_asn1_get0_info(&nid, &base_nid, &flags, NULL, &pem_name, ameth); 427e1051a39Sopenharmony_ci if (nid != NID_undef) { 428e1051a39Sopenharmony_ci if ((flags & ASN1_PKEY_ALIAS) == 0) { 429e1051a39Sopenharmony_ci switch (nid) { 430e1051a39Sopenharmony_ci case EVP_PKEY_DHX: 431e1051a39Sopenharmony_ci /* We know that the name "DHX" is used too */ 432e1051a39Sopenharmony_ci get_legacy_evp_names(0, nid, "DHX", arg); 433e1051a39Sopenharmony_ci /* FALLTHRU */ 434e1051a39Sopenharmony_ci default: 435e1051a39Sopenharmony_ci get_legacy_evp_names(0, nid, pem_name, arg); 436e1051a39Sopenharmony_ci } 437e1051a39Sopenharmony_ci } else { 438e1051a39Sopenharmony_ci /* 439e1051a39Sopenharmony_ci * Treat aliases carefully, some of them are undesirable, or 440e1051a39Sopenharmony_ci * should not be treated as such for providers. 441e1051a39Sopenharmony_ci */ 442e1051a39Sopenharmony_ci 443e1051a39Sopenharmony_ci switch (nid) { 444e1051a39Sopenharmony_ci case EVP_PKEY_SM2: 445e1051a39Sopenharmony_ci /* 446e1051a39Sopenharmony_ci * SM2 is a separate keytype with providers, not an alias for 447e1051a39Sopenharmony_ci * EC. 448e1051a39Sopenharmony_ci */ 449e1051a39Sopenharmony_ci get_legacy_evp_names(0, nid, pem_name, arg); 450e1051a39Sopenharmony_ci break; 451e1051a39Sopenharmony_ci default: 452e1051a39Sopenharmony_ci /* Use the short name of the base nid as the common reference */ 453e1051a39Sopenharmony_ci get_legacy_evp_names(base_nid, nid, pem_name, arg); 454e1051a39Sopenharmony_ci } 455e1051a39Sopenharmony_ci } 456e1051a39Sopenharmony_ci } 457e1051a39Sopenharmony_ci} 458e1051a39Sopenharmony_ci#endif 459e1051a39Sopenharmony_ci 460e1051a39Sopenharmony_ci/*- 461e1051a39Sopenharmony_ci * Constructors / destructors 462e1051a39Sopenharmony_ci * ========================== 463e1051a39Sopenharmony_ci */ 464e1051a39Sopenharmony_ci 465e1051a39Sopenharmony_ciOSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx) 466e1051a39Sopenharmony_ci{ 467e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 468e1051a39Sopenharmony_ci int nms; 469e1051a39Sopenharmony_ci#endif 470e1051a39Sopenharmony_ci OSSL_NAMEMAP *namemap = 471e1051a39Sopenharmony_ci ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_NAMEMAP_INDEX, 472e1051a39Sopenharmony_ci &stored_namemap_method); 473e1051a39Sopenharmony_ci 474e1051a39Sopenharmony_ci if (namemap == NULL) 475e1051a39Sopenharmony_ci return NULL; 476e1051a39Sopenharmony_ci 477e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 478e1051a39Sopenharmony_ci nms = ossl_namemap_empty(namemap); 479e1051a39Sopenharmony_ci if (nms < 0) { 480e1051a39Sopenharmony_ci /* 481e1051a39Sopenharmony_ci * Could not get lock to make the count, so maybe internal objects 482e1051a39Sopenharmony_ci * weren't added. This seems safest. 483e1051a39Sopenharmony_ci */ 484e1051a39Sopenharmony_ci return NULL; 485e1051a39Sopenharmony_ci } 486e1051a39Sopenharmony_ci if (nms == 1) { 487e1051a39Sopenharmony_ci int i, end; 488e1051a39Sopenharmony_ci 489e1051a39Sopenharmony_ci /* Before pilfering, we make sure the legacy database is populated */ 490e1051a39Sopenharmony_ci OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS 491e1051a39Sopenharmony_ci | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); 492e1051a39Sopenharmony_ci 493e1051a39Sopenharmony_ci OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH, 494e1051a39Sopenharmony_ci get_legacy_cipher_names, namemap); 495e1051a39Sopenharmony_ci OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, 496e1051a39Sopenharmony_ci get_legacy_md_names, namemap); 497e1051a39Sopenharmony_ci 498e1051a39Sopenharmony_ci /* We also pilfer data from the legacy EVP_PKEY_ASN1_METHODs */ 499e1051a39Sopenharmony_ci for (i = 0, end = EVP_PKEY_asn1_get_count(); i < end; i++) 500e1051a39Sopenharmony_ci get_legacy_pkey_meth_names(EVP_PKEY_asn1_get0(i), namemap); 501e1051a39Sopenharmony_ci } 502e1051a39Sopenharmony_ci#endif 503e1051a39Sopenharmony_ci 504e1051a39Sopenharmony_ci return namemap; 505e1051a39Sopenharmony_ci} 506e1051a39Sopenharmony_ci 507e1051a39Sopenharmony_ciOSSL_NAMEMAP *ossl_namemap_new(void) 508e1051a39Sopenharmony_ci{ 509e1051a39Sopenharmony_ci OSSL_NAMEMAP *namemap; 510e1051a39Sopenharmony_ci 511e1051a39Sopenharmony_ci if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) != NULL 512e1051a39Sopenharmony_ci && (namemap->lock = CRYPTO_THREAD_lock_new()) != NULL 513e1051a39Sopenharmony_ci && (namemap->namenum = 514e1051a39Sopenharmony_ci lh_NAMENUM_ENTRY_new(namenum_hash, namenum_cmp)) != NULL) 515e1051a39Sopenharmony_ci return namemap; 516e1051a39Sopenharmony_ci 517e1051a39Sopenharmony_ci ossl_namemap_free(namemap); 518e1051a39Sopenharmony_ci return NULL; 519e1051a39Sopenharmony_ci} 520e1051a39Sopenharmony_ci 521e1051a39Sopenharmony_civoid ossl_namemap_free(OSSL_NAMEMAP *namemap) 522e1051a39Sopenharmony_ci{ 523e1051a39Sopenharmony_ci if (namemap == NULL || namemap->stored) 524e1051a39Sopenharmony_ci return; 525e1051a39Sopenharmony_ci 526e1051a39Sopenharmony_ci lh_NAMENUM_ENTRY_doall(namemap->namenum, namenum_free); 527e1051a39Sopenharmony_ci lh_NAMENUM_ENTRY_free(namemap->namenum); 528e1051a39Sopenharmony_ci 529e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(namemap->lock); 530e1051a39Sopenharmony_ci OPENSSL_free(namemap); 531e1051a39Sopenharmony_ci} 532