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