]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/objects/o_names.c
2 * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
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
14 #include <openssl/err.h>
15 #include <openssl/lhash.h>
16 #include <openssl/objects.h>
17 #include <openssl/safestack.h>
18 #include <openssl/e_os2.h>
19 #include "internal/thread_once.h"
20 #include "crypto/lhash.h"
21 #include "obj_local.h"
25 * We define this wrapper for two reasons. Firstly, later versions of
26 * DEC C add linkage information to certain functions, which makes it
27 * tricky to use them as values to regular function pointers.
28 * Secondly, in the EDK2 build environment, the strcasecmp function is
29 * actually an external function with the Microsoft ABI, so we can't
30 * transparently assign function pointers to it.
32 #if defined(OPENSSL_SYS_VMS_DECC) || defined(OPENSSL_SYS_UEFI)
33 static int obj_strcasecmp(const char *a
, const char *b
)
35 return strcasecmp(a
, b
);
38 #define obj_strcasecmp strcasecmp
42 * I use the ex_data stuff to manage the identifiers for the obj_name_types
43 * that applications may define. I only really use the free function field.
45 static LHASH_OF(OBJ_NAME
) *names_lh
= NULL
;
46 static int names_type_num
= OBJ_NAME_TYPE_NUM
;
47 static CRYPTO_RWLOCK
*obj_lock
= NULL
;
49 struct name_funcs_st
{
50 unsigned long (*hash_func
) (const char *name
);
51 int (*cmp_func
) (const char *a
, const char *b
);
52 void (*free_func
) (const char *, int, const char *);
55 static STACK_OF(NAME_FUNCS
) *name_funcs_stack
;
58 * The LHASH callbacks now use the raw "void *" prototypes and do
59 * per-variable casting in the functions. This prevents function pointer
60 * casting without the need for macro-generated wrapper functions.
63 static unsigned long obj_name_hash(const OBJ_NAME
*a
);
64 static int obj_name_cmp(const OBJ_NAME
*a
, const OBJ_NAME
*b
);
66 static CRYPTO_ONCE init
= CRYPTO_ONCE_STATIC_INIT
;
67 DEFINE_RUN_ONCE_STATIC(o_names_init
)
69 names_lh
= lh_OBJ_NAME_new(obj_name_hash
, obj_name_cmp
);
70 obj_lock
= CRYPTO_THREAD_lock_new();
71 return names_lh
!= NULL
&& obj_lock
!= NULL
;
74 int OBJ_NAME_init(void)
76 return RUN_ONCE(&init
, o_names_init
);
79 int OBJ_NAME_new_index(unsigned long (*hash_func
) (const char *),
80 int (*cmp_func
) (const char *, const char *),
81 void (*free_func
) (const char *, int, const char *))
84 NAME_FUNCS
*name_funcs
;
89 if (!CRYPTO_THREAD_write_lock(obj_lock
))
92 if (name_funcs_stack
== NULL
)
93 name_funcs_stack
= sk_NAME_FUNCS_new_null();
94 if (name_funcs_stack
== NULL
) {
100 for (i
= sk_NAME_FUNCS_num(name_funcs_stack
); i
< names_type_num
; i
++) {
101 name_funcs
= OPENSSL_zalloc(sizeof(*name_funcs
));
102 if (name_funcs
== NULL
) {
103 ERR_raise(ERR_LIB_OBJ
, ERR_R_MALLOC_FAILURE
);
107 name_funcs
->hash_func
= ossl_lh_strcasehash
;
108 name_funcs
->cmp_func
= obj_strcasecmp
;
109 push
= sk_NAME_FUNCS_push(name_funcs_stack
, name_funcs
);
112 ERR_raise(ERR_LIB_OBJ
, ERR_R_MALLOC_FAILURE
);
113 OPENSSL_free(name_funcs
);
118 name_funcs
= sk_NAME_FUNCS_value(name_funcs_stack
, ret
);
119 if (hash_func
!= NULL
)
120 name_funcs
->hash_func
= hash_func
;
121 if (cmp_func
!= NULL
)
122 name_funcs
->cmp_func
= cmp_func
;
123 if (free_func
!= NULL
)
124 name_funcs
->free_func
= free_func
;
127 CRYPTO_THREAD_unlock(obj_lock
);
131 static int obj_name_cmp(const OBJ_NAME
*a
, const OBJ_NAME
*b
)
135 ret
= a
->type
- b
->type
;
137 if ((name_funcs_stack
!= NULL
)
138 && (sk_NAME_FUNCS_num(name_funcs_stack
) > a
->type
)) {
139 ret
= sk_NAME_FUNCS_value(name_funcs_stack
,
140 a
->type
)->cmp_func(a
->name
, b
->name
);
142 ret
= strcasecmp(a
->name
, b
->name
);
147 static unsigned long obj_name_hash(const OBJ_NAME
*a
)
151 if ((name_funcs_stack
!= NULL
)
152 && (sk_NAME_FUNCS_num(name_funcs_stack
) > a
->type
)) {
154 sk_NAME_FUNCS_value(name_funcs_stack
,
155 a
->type
)->hash_func(a
->name
);
157 ret
= ossl_lh_strcasehash(a
->name
);
163 const char *OBJ_NAME_get(const char *name
, int type
)
167 const char *value
= NULL
;
171 if (!OBJ_NAME_init())
173 if (!CRYPTO_THREAD_read_lock(obj_lock
))
176 alias
= type
& OBJ_NAME_ALIAS
;
177 type
&= ~OBJ_NAME_ALIAS
;
183 ret
= lh_OBJ_NAME_retrieve(names_lh
, &on
);
186 if ((ret
->alias
) && !alias
) {
196 CRYPTO_THREAD_unlock(obj_lock
);
200 int OBJ_NAME_add(const char *name
, int type
, const char *data
)
205 if (!OBJ_NAME_init())
208 alias
= type
& OBJ_NAME_ALIAS
;
209 type
&= ~OBJ_NAME_ALIAS
;
211 onp
= OPENSSL_malloc(sizeof(*onp
));
220 if (!CRYPTO_THREAD_write_lock(obj_lock
)) {
225 ret
= lh_OBJ_NAME_insert(names_lh
, onp
);
228 if ((name_funcs_stack
!= NULL
)
229 && (sk_NAME_FUNCS_num(name_funcs_stack
) > ret
->type
)) {
231 * XXX: I'm not sure I understand why the free function should
232 * get three arguments... -- Richard Levitte
234 sk_NAME_FUNCS_value(name_funcs_stack
,
235 ret
->type
)->free_func(ret
->name
, ret
->type
,
240 if (lh_OBJ_NAME_error(names_lh
)) {
250 CRYPTO_THREAD_unlock(obj_lock
);
254 int OBJ_NAME_remove(const char *name
, int type
)
259 if (!OBJ_NAME_init())
262 if (!CRYPTO_THREAD_write_lock(obj_lock
))
265 type
&= ~OBJ_NAME_ALIAS
;
268 ret
= lh_OBJ_NAME_delete(names_lh
, &on
);
271 if ((name_funcs_stack
!= NULL
)
272 && (sk_NAME_FUNCS_num(name_funcs_stack
) > ret
->type
)) {
274 * XXX: I'm not sure I understand why the free function should
275 * get three arguments... -- Richard Levitte
277 sk_NAME_FUNCS_value(name_funcs_stack
,
278 ret
->type
)->free_func(ret
->name
, ret
->type
,
285 CRYPTO_THREAD_unlock(obj_lock
);
291 void (*fn
) (const OBJ_NAME
*, void *arg
);
295 static void do_all_fn(const OBJ_NAME
*name
, OBJ_DOALL
*d
)
297 if (name
->type
== d
->type
)
301 IMPLEMENT_LHASH_DOALL_ARG_CONST(OBJ_NAME
, OBJ_DOALL
);
303 void OBJ_NAME_do_all(int type
, void (*fn
) (const OBJ_NAME
*, void *arg
),
312 lh_OBJ_NAME_doall_OBJ_DOALL(names_lh
, do_all_fn
, &d
);
315 struct doall_sorted
{
318 const OBJ_NAME
**names
;
321 static void do_all_sorted_fn(const OBJ_NAME
*name
, void *d_
)
323 struct doall_sorted
*d
= d_
;
325 if (name
->type
!= d
->type
)
328 d
->names
[d
->n
++] = name
;
331 static int do_all_sorted_cmp(const void *n1_
, const void *n2_
)
333 const OBJ_NAME
*const *n1
= n1_
;
334 const OBJ_NAME
*const *n2
= n2_
;
336 return strcmp((*n1
)->name
, (*n2
)->name
);
339 void OBJ_NAME_do_all_sorted(int type
,
340 void (*fn
) (const OBJ_NAME
*, void *arg
),
343 struct doall_sorted d
;
348 OPENSSL_malloc(sizeof(*d
.names
) * lh_OBJ_NAME_num_items(names_lh
));
349 /* Really should return an error if !d.names...but its a void function! */
350 if (d
.names
!= NULL
) {
352 OBJ_NAME_do_all(type
, do_all_sorted_fn
, &d
);
354 qsort((void *)d
.names
, d
.n
, sizeof(*d
.names
), do_all_sorted_cmp
);
356 for (n
= 0; n
< d
.n
; ++n
)
359 OPENSSL_free((void *)d
.names
);
363 static int free_type
;
365 static void names_lh_free_doall(OBJ_NAME
*onp
)
370 if (free_type
< 0 || free_type
== onp
->type
)
371 OBJ_NAME_remove(onp
->name
, onp
->type
);
374 static void name_funcs_free(NAME_FUNCS
*ptr
)
379 void OBJ_NAME_cleanup(int type
)
381 unsigned long down_load
;
383 if (names_lh
== NULL
)
387 down_load
= lh_OBJ_NAME_get_down_load(names_lh
);
388 lh_OBJ_NAME_set_down_load(names_lh
, 0);
390 lh_OBJ_NAME_doall(names_lh
, names_lh_free_doall
);
392 lh_OBJ_NAME_free(names_lh
);
393 sk_NAME_FUNCS_pop_free(name_funcs_stack
, name_funcs_free
);
394 CRYPTO_THREAD_lock_free(obj_lock
);
396 name_funcs_stack
= NULL
;
399 lh_OBJ_NAME_set_down_load(names_lh
, down_load
);