1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1998-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 <stdio.h> 11e1051a39Sopenharmony_ci#include <stdlib.h> 12e1051a39Sopenharmony_ci#include <string.h> 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci#include <openssl/err.h> 15e1051a39Sopenharmony_ci#include <openssl/lhash.h> 16e1051a39Sopenharmony_ci#include <openssl/objects.h> 17e1051a39Sopenharmony_ci#include <openssl/safestack.h> 18e1051a39Sopenharmony_ci#include <openssl/e_os2.h> 19e1051a39Sopenharmony_ci#include "internal/thread_once.h" 20e1051a39Sopenharmony_ci#include "crypto/lhash.h" 21e1051a39Sopenharmony_ci#include "obj_local.h" 22e1051a39Sopenharmony_ci#include "e_os.h" 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci/* 25e1051a39Sopenharmony_ci * I use the ex_data stuff to manage the identifiers for the obj_name_types 26e1051a39Sopenharmony_ci * that applications may define. I only really use the free function field. 27e1051a39Sopenharmony_ci */ 28e1051a39Sopenharmony_cistatic LHASH_OF(OBJ_NAME) *names_lh = NULL; 29e1051a39Sopenharmony_cistatic int names_type_num = OBJ_NAME_TYPE_NUM; 30e1051a39Sopenharmony_cistatic CRYPTO_RWLOCK *obj_lock = NULL; 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_cistruct name_funcs_st { 33e1051a39Sopenharmony_ci unsigned long (*hash_func) (const char *name); 34e1051a39Sopenharmony_ci int (*cmp_func) (const char *a, const char *b); 35e1051a39Sopenharmony_ci void (*free_func) (const char *, int, const char *); 36e1051a39Sopenharmony_ci}; 37e1051a39Sopenharmony_ci 38e1051a39Sopenharmony_cistatic STACK_OF(NAME_FUNCS) *name_funcs_stack; 39e1051a39Sopenharmony_ci 40e1051a39Sopenharmony_ci/* 41e1051a39Sopenharmony_ci * The LHASH callbacks now use the raw "void *" prototypes and do 42e1051a39Sopenharmony_ci * per-variable casting in the functions. This prevents function pointer 43e1051a39Sopenharmony_ci * casting without the need for macro-generated wrapper functions. 44e1051a39Sopenharmony_ci */ 45e1051a39Sopenharmony_ci 46e1051a39Sopenharmony_cistatic unsigned long obj_name_hash(const OBJ_NAME *a); 47e1051a39Sopenharmony_cistatic int obj_name_cmp(const OBJ_NAME *a, const OBJ_NAME *b); 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_cistatic CRYPTO_ONCE init = CRYPTO_ONCE_STATIC_INIT; 50e1051a39Sopenharmony_ciDEFINE_RUN_ONCE_STATIC(o_names_init) 51e1051a39Sopenharmony_ci{ 52e1051a39Sopenharmony_ci names_lh = NULL; 53e1051a39Sopenharmony_ci obj_lock = CRYPTO_THREAD_lock_new(); 54e1051a39Sopenharmony_ci if (obj_lock != NULL) 55e1051a39Sopenharmony_ci names_lh = lh_OBJ_NAME_new(obj_name_hash, obj_name_cmp); 56e1051a39Sopenharmony_ci if (names_lh == NULL) { 57e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(obj_lock); 58e1051a39Sopenharmony_ci obj_lock = NULL; 59e1051a39Sopenharmony_ci } 60e1051a39Sopenharmony_ci return names_lh != NULL && obj_lock != NULL; 61e1051a39Sopenharmony_ci} 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_ciint OBJ_NAME_init(void) 64e1051a39Sopenharmony_ci{ 65e1051a39Sopenharmony_ci return RUN_ONCE(&init, o_names_init); 66e1051a39Sopenharmony_ci} 67e1051a39Sopenharmony_ci 68e1051a39Sopenharmony_ciint OBJ_NAME_new_index(unsigned long (*hash_func) (const char *), 69e1051a39Sopenharmony_ci int (*cmp_func) (const char *, const char *), 70e1051a39Sopenharmony_ci void (*free_func) (const char *, int, const char *)) 71e1051a39Sopenharmony_ci{ 72e1051a39Sopenharmony_ci int ret = 0, i, push; 73e1051a39Sopenharmony_ci NAME_FUNCS *name_funcs; 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_ci if (!OBJ_NAME_init()) 76e1051a39Sopenharmony_ci return 0; 77e1051a39Sopenharmony_ci 78e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(obj_lock)) 79e1051a39Sopenharmony_ci return 0; 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci if (name_funcs_stack == NULL) 82e1051a39Sopenharmony_ci name_funcs_stack = sk_NAME_FUNCS_new_null(); 83e1051a39Sopenharmony_ci if (name_funcs_stack == NULL) { 84e1051a39Sopenharmony_ci /* ERROR */ 85e1051a39Sopenharmony_ci goto out; 86e1051a39Sopenharmony_ci } 87e1051a39Sopenharmony_ci ret = names_type_num; 88e1051a39Sopenharmony_ci names_type_num++; 89e1051a39Sopenharmony_ci for (i = sk_NAME_FUNCS_num(name_funcs_stack); i < names_type_num; i++) { 90e1051a39Sopenharmony_ci name_funcs = OPENSSL_zalloc(sizeof(*name_funcs)); 91e1051a39Sopenharmony_ci if (name_funcs == NULL) { 92e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE); 93e1051a39Sopenharmony_ci ret = 0; 94e1051a39Sopenharmony_ci goto out; 95e1051a39Sopenharmony_ci } 96e1051a39Sopenharmony_ci name_funcs->hash_func = ossl_lh_strcasehash; 97e1051a39Sopenharmony_ci name_funcs->cmp_func = OPENSSL_strcasecmp; 98e1051a39Sopenharmony_ci push = sk_NAME_FUNCS_push(name_funcs_stack, name_funcs); 99e1051a39Sopenharmony_ci 100e1051a39Sopenharmony_ci if (!push) { 101e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE); 102e1051a39Sopenharmony_ci OPENSSL_free(name_funcs); 103e1051a39Sopenharmony_ci ret = 0; 104e1051a39Sopenharmony_ci goto out; 105e1051a39Sopenharmony_ci } 106e1051a39Sopenharmony_ci } 107e1051a39Sopenharmony_ci name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret); 108e1051a39Sopenharmony_ci if (hash_func != NULL) 109e1051a39Sopenharmony_ci name_funcs->hash_func = hash_func; 110e1051a39Sopenharmony_ci if (cmp_func != NULL) 111e1051a39Sopenharmony_ci name_funcs->cmp_func = cmp_func; 112e1051a39Sopenharmony_ci if (free_func != NULL) 113e1051a39Sopenharmony_ci name_funcs->free_func = free_func; 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ciout: 116e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(obj_lock); 117e1051a39Sopenharmony_ci return ret; 118e1051a39Sopenharmony_ci} 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_cistatic int obj_name_cmp(const OBJ_NAME *a, const OBJ_NAME *b) 121e1051a39Sopenharmony_ci{ 122e1051a39Sopenharmony_ci int ret; 123e1051a39Sopenharmony_ci 124e1051a39Sopenharmony_ci ret = a->type - b->type; 125e1051a39Sopenharmony_ci if (ret == 0) { 126e1051a39Sopenharmony_ci if ((name_funcs_stack != NULL) 127e1051a39Sopenharmony_ci && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) { 128e1051a39Sopenharmony_ci ret = sk_NAME_FUNCS_value(name_funcs_stack, 129e1051a39Sopenharmony_ci a->type)->cmp_func(a->name, b->name); 130e1051a39Sopenharmony_ci } else 131e1051a39Sopenharmony_ci ret = OPENSSL_strcasecmp(a->name, b->name); 132e1051a39Sopenharmony_ci } 133e1051a39Sopenharmony_ci return ret; 134e1051a39Sopenharmony_ci} 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_cistatic unsigned long obj_name_hash(const OBJ_NAME *a) 137e1051a39Sopenharmony_ci{ 138e1051a39Sopenharmony_ci unsigned long ret; 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ci if ((name_funcs_stack != NULL) 141e1051a39Sopenharmony_ci && (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) { 142e1051a39Sopenharmony_ci ret = 143e1051a39Sopenharmony_ci sk_NAME_FUNCS_value(name_funcs_stack, 144e1051a39Sopenharmony_ci a->type)->hash_func(a->name); 145e1051a39Sopenharmony_ci } else { 146e1051a39Sopenharmony_ci ret = ossl_lh_strcasehash(a->name); 147e1051a39Sopenharmony_ci } 148e1051a39Sopenharmony_ci ret ^= a->type; 149e1051a39Sopenharmony_ci return ret; 150e1051a39Sopenharmony_ci} 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_ciconst char *OBJ_NAME_get(const char *name, int type) 153e1051a39Sopenharmony_ci{ 154e1051a39Sopenharmony_ci OBJ_NAME on, *ret; 155e1051a39Sopenharmony_ci int num = 0, alias; 156e1051a39Sopenharmony_ci const char *value = NULL; 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_ci if (name == NULL) 159e1051a39Sopenharmony_ci return NULL; 160e1051a39Sopenharmony_ci if (!OBJ_NAME_init()) 161e1051a39Sopenharmony_ci return NULL; 162e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_read_lock(obj_lock)) 163e1051a39Sopenharmony_ci return NULL; 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_ci alias = type & OBJ_NAME_ALIAS; 166e1051a39Sopenharmony_ci type &= ~OBJ_NAME_ALIAS; 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci on.name = name; 169e1051a39Sopenharmony_ci on.type = type; 170e1051a39Sopenharmony_ci 171e1051a39Sopenharmony_ci for (;;) { 172e1051a39Sopenharmony_ci ret = lh_OBJ_NAME_retrieve(names_lh, &on); 173e1051a39Sopenharmony_ci if (ret == NULL) 174e1051a39Sopenharmony_ci break; 175e1051a39Sopenharmony_ci if ((ret->alias) && !alias) { 176e1051a39Sopenharmony_ci if (++num > 10) 177e1051a39Sopenharmony_ci break; 178e1051a39Sopenharmony_ci on.name = ret->data; 179e1051a39Sopenharmony_ci } else { 180e1051a39Sopenharmony_ci value = ret->data; 181e1051a39Sopenharmony_ci break; 182e1051a39Sopenharmony_ci } 183e1051a39Sopenharmony_ci } 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(obj_lock); 186e1051a39Sopenharmony_ci return value; 187e1051a39Sopenharmony_ci} 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_ciint OBJ_NAME_add(const char *name, int type, const char *data) 190e1051a39Sopenharmony_ci{ 191e1051a39Sopenharmony_ci OBJ_NAME *onp, *ret; 192e1051a39Sopenharmony_ci int alias, ok = 0; 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ci if (!OBJ_NAME_init()) 195e1051a39Sopenharmony_ci return 0; 196e1051a39Sopenharmony_ci 197e1051a39Sopenharmony_ci alias = type & OBJ_NAME_ALIAS; 198e1051a39Sopenharmony_ci type &= ~OBJ_NAME_ALIAS; 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci onp = OPENSSL_malloc(sizeof(*onp)); 201e1051a39Sopenharmony_ci if (onp == NULL) 202e1051a39Sopenharmony_ci return 0; 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ci onp->name = name; 205e1051a39Sopenharmony_ci onp->alias = alias; 206e1051a39Sopenharmony_ci onp->type = type; 207e1051a39Sopenharmony_ci onp->data = data; 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(obj_lock)) { 210e1051a39Sopenharmony_ci OPENSSL_free(onp); 211e1051a39Sopenharmony_ci return 0; 212e1051a39Sopenharmony_ci } 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ci ret = lh_OBJ_NAME_insert(names_lh, onp); 215e1051a39Sopenharmony_ci if (ret != NULL) { 216e1051a39Sopenharmony_ci /* free things */ 217e1051a39Sopenharmony_ci if ((name_funcs_stack != NULL) 218e1051a39Sopenharmony_ci && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) { 219e1051a39Sopenharmony_ci /* 220e1051a39Sopenharmony_ci * XXX: I'm not sure I understand why the free function should 221e1051a39Sopenharmony_ci * get three arguments... -- Richard Levitte 222e1051a39Sopenharmony_ci */ 223e1051a39Sopenharmony_ci sk_NAME_FUNCS_value(name_funcs_stack, 224e1051a39Sopenharmony_ci ret->type)->free_func(ret->name, ret->type, 225e1051a39Sopenharmony_ci ret->data); 226e1051a39Sopenharmony_ci } 227e1051a39Sopenharmony_ci OPENSSL_free(ret); 228e1051a39Sopenharmony_ci } else { 229e1051a39Sopenharmony_ci if (lh_OBJ_NAME_error(names_lh)) { 230e1051a39Sopenharmony_ci /* ERROR */ 231e1051a39Sopenharmony_ci OPENSSL_free(onp); 232e1051a39Sopenharmony_ci goto unlock; 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci 236e1051a39Sopenharmony_ci ok = 1; 237e1051a39Sopenharmony_ci 238e1051a39Sopenharmony_ciunlock: 239e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(obj_lock); 240e1051a39Sopenharmony_ci return ok; 241e1051a39Sopenharmony_ci} 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ciint OBJ_NAME_remove(const char *name, int type) 244e1051a39Sopenharmony_ci{ 245e1051a39Sopenharmony_ci OBJ_NAME on, *ret; 246e1051a39Sopenharmony_ci int ok = 0; 247e1051a39Sopenharmony_ci 248e1051a39Sopenharmony_ci if (!OBJ_NAME_init()) 249e1051a39Sopenharmony_ci return 0; 250e1051a39Sopenharmony_ci 251e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(obj_lock)) 252e1051a39Sopenharmony_ci return 0; 253e1051a39Sopenharmony_ci 254e1051a39Sopenharmony_ci type &= ~OBJ_NAME_ALIAS; 255e1051a39Sopenharmony_ci on.name = name; 256e1051a39Sopenharmony_ci on.type = type; 257e1051a39Sopenharmony_ci ret = lh_OBJ_NAME_delete(names_lh, &on); 258e1051a39Sopenharmony_ci if (ret != NULL) { 259e1051a39Sopenharmony_ci /* free things */ 260e1051a39Sopenharmony_ci if ((name_funcs_stack != NULL) 261e1051a39Sopenharmony_ci && (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) { 262e1051a39Sopenharmony_ci /* 263e1051a39Sopenharmony_ci * XXX: I'm not sure I understand why the free function should 264e1051a39Sopenharmony_ci * get three arguments... -- Richard Levitte 265e1051a39Sopenharmony_ci */ 266e1051a39Sopenharmony_ci sk_NAME_FUNCS_value(name_funcs_stack, 267e1051a39Sopenharmony_ci ret->type)->free_func(ret->name, ret->type, 268e1051a39Sopenharmony_ci ret->data); 269e1051a39Sopenharmony_ci } 270e1051a39Sopenharmony_ci OPENSSL_free(ret); 271e1051a39Sopenharmony_ci ok = 1; 272e1051a39Sopenharmony_ci } 273e1051a39Sopenharmony_ci 274e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(obj_lock); 275e1051a39Sopenharmony_ci return ok; 276e1051a39Sopenharmony_ci} 277e1051a39Sopenharmony_ci 278e1051a39Sopenharmony_citypedef struct { 279e1051a39Sopenharmony_ci int type; 280e1051a39Sopenharmony_ci void (*fn) (const OBJ_NAME *, void *arg); 281e1051a39Sopenharmony_ci void *arg; 282e1051a39Sopenharmony_ci} OBJ_DOALL; 283e1051a39Sopenharmony_ci 284e1051a39Sopenharmony_cistatic void do_all_fn(const OBJ_NAME *name, OBJ_DOALL *d) 285e1051a39Sopenharmony_ci{ 286e1051a39Sopenharmony_ci if (name->type == d->type) 287e1051a39Sopenharmony_ci d->fn(name, d->arg); 288e1051a39Sopenharmony_ci} 289e1051a39Sopenharmony_ci 290e1051a39Sopenharmony_ciIMPLEMENT_LHASH_DOALL_ARG_CONST(OBJ_NAME, OBJ_DOALL); 291e1051a39Sopenharmony_ci 292e1051a39Sopenharmony_civoid OBJ_NAME_do_all(int type, void (*fn) (const OBJ_NAME *, void *arg), 293e1051a39Sopenharmony_ci void *arg) 294e1051a39Sopenharmony_ci{ 295e1051a39Sopenharmony_ci OBJ_DOALL d; 296e1051a39Sopenharmony_ci 297e1051a39Sopenharmony_ci d.type = type; 298e1051a39Sopenharmony_ci d.fn = fn; 299e1051a39Sopenharmony_ci d.arg = arg; 300e1051a39Sopenharmony_ci 301e1051a39Sopenharmony_ci lh_OBJ_NAME_doall_OBJ_DOALL(names_lh, do_all_fn, &d); 302e1051a39Sopenharmony_ci} 303e1051a39Sopenharmony_ci 304e1051a39Sopenharmony_cistruct doall_sorted { 305e1051a39Sopenharmony_ci int type; 306e1051a39Sopenharmony_ci int n; 307e1051a39Sopenharmony_ci const OBJ_NAME **names; 308e1051a39Sopenharmony_ci}; 309e1051a39Sopenharmony_ci 310e1051a39Sopenharmony_cistatic void do_all_sorted_fn(const OBJ_NAME *name, void *d_) 311e1051a39Sopenharmony_ci{ 312e1051a39Sopenharmony_ci struct doall_sorted *d = d_; 313e1051a39Sopenharmony_ci 314e1051a39Sopenharmony_ci if (name->type != d->type) 315e1051a39Sopenharmony_ci return; 316e1051a39Sopenharmony_ci 317e1051a39Sopenharmony_ci d->names[d->n++] = name; 318e1051a39Sopenharmony_ci} 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_cistatic int do_all_sorted_cmp(const void *n1_, const void *n2_) 321e1051a39Sopenharmony_ci{ 322e1051a39Sopenharmony_ci const OBJ_NAME *const *n1 = n1_; 323e1051a39Sopenharmony_ci const OBJ_NAME *const *n2 = n2_; 324e1051a39Sopenharmony_ci 325e1051a39Sopenharmony_ci return strcmp((*n1)->name, (*n2)->name); 326e1051a39Sopenharmony_ci} 327e1051a39Sopenharmony_ci 328e1051a39Sopenharmony_civoid OBJ_NAME_do_all_sorted(int type, 329e1051a39Sopenharmony_ci void (*fn) (const OBJ_NAME *, void *arg), 330e1051a39Sopenharmony_ci void *arg) 331e1051a39Sopenharmony_ci{ 332e1051a39Sopenharmony_ci struct doall_sorted d; 333e1051a39Sopenharmony_ci int n; 334e1051a39Sopenharmony_ci 335e1051a39Sopenharmony_ci d.type = type; 336e1051a39Sopenharmony_ci d.names = 337e1051a39Sopenharmony_ci OPENSSL_malloc(sizeof(*d.names) * lh_OBJ_NAME_num_items(names_lh)); 338e1051a39Sopenharmony_ci /* Really should return an error if !d.names...but its a void function! */ 339e1051a39Sopenharmony_ci if (d.names != NULL) { 340e1051a39Sopenharmony_ci d.n = 0; 341e1051a39Sopenharmony_ci OBJ_NAME_do_all(type, do_all_sorted_fn, &d); 342e1051a39Sopenharmony_ci 343e1051a39Sopenharmony_ci qsort((void *)d.names, d.n, sizeof(*d.names), do_all_sorted_cmp); 344e1051a39Sopenharmony_ci 345e1051a39Sopenharmony_ci for (n = 0; n < d.n; ++n) 346e1051a39Sopenharmony_ci fn(d.names[n], arg); 347e1051a39Sopenharmony_ci 348e1051a39Sopenharmony_ci OPENSSL_free((void *)d.names); 349e1051a39Sopenharmony_ci } 350e1051a39Sopenharmony_ci} 351e1051a39Sopenharmony_ci 352e1051a39Sopenharmony_cistatic int free_type; 353e1051a39Sopenharmony_ci 354e1051a39Sopenharmony_cistatic void names_lh_free_doall(OBJ_NAME *onp) 355e1051a39Sopenharmony_ci{ 356e1051a39Sopenharmony_ci if (onp == NULL) 357e1051a39Sopenharmony_ci return; 358e1051a39Sopenharmony_ci 359e1051a39Sopenharmony_ci if (free_type < 0 || free_type == onp->type) 360e1051a39Sopenharmony_ci OBJ_NAME_remove(onp->name, onp->type); 361e1051a39Sopenharmony_ci} 362e1051a39Sopenharmony_ci 363e1051a39Sopenharmony_cistatic void name_funcs_free(NAME_FUNCS *ptr) 364e1051a39Sopenharmony_ci{ 365e1051a39Sopenharmony_ci OPENSSL_free(ptr); 366e1051a39Sopenharmony_ci} 367e1051a39Sopenharmony_ci 368e1051a39Sopenharmony_civoid OBJ_NAME_cleanup(int type) 369e1051a39Sopenharmony_ci{ 370e1051a39Sopenharmony_ci unsigned long down_load; 371e1051a39Sopenharmony_ci 372e1051a39Sopenharmony_ci if (names_lh == NULL) 373e1051a39Sopenharmony_ci return; 374e1051a39Sopenharmony_ci 375e1051a39Sopenharmony_ci free_type = type; 376e1051a39Sopenharmony_ci down_load = lh_OBJ_NAME_get_down_load(names_lh); 377e1051a39Sopenharmony_ci lh_OBJ_NAME_set_down_load(names_lh, 0); 378e1051a39Sopenharmony_ci 379e1051a39Sopenharmony_ci lh_OBJ_NAME_doall(names_lh, names_lh_free_doall); 380e1051a39Sopenharmony_ci if (type < 0) { 381e1051a39Sopenharmony_ci lh_OBJ_NAME_free(names_lh); 382e1051a39Sopenharmony_ci sk_NAME_FUNCS_pop_free(name_funcs_stack, name_funcs_free); 383e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(obj_lock); 384e1051a39Sopenharmony_ci names_lh = NULL; 385e1051a39Sopenharmony_ci name_funcs_stack = NULL; 386e1051a39Sopenharmony_ci obj_lock = NULL; 387e1051a39Sopenharmony_ci } else 388e1051a39Sopenharmony_ci lh_OBJ_NAME_set_down_load(names_lh, down_load); 389e1051a39Sopenharmony_ci} 390