]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/objects/o_names.c
2 * Copyright 1998-2018 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 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
70 names_lh
= lh_OBJ_NAME_new(obj_name_hash
, obj_name_cmp
);
71 obj_lock
= CRYPTO_THREAD_lock_new();
72 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
73 return names_lh
!= NULL
&& obj_lock
!= NULL
;
76 int OBJ_NAME_init(void)
78 return RUN_ONCE(&init
, o_names_init
);
81 int OBJ_NAME_new_index(unsigned long (*hash_func
) (const char *),
82 int (*cmp_func
) (const char *, const char *),
83 void (*free_func
) (const char *, int, const char *))
86 NAME_FUNCS
*name_funcs
;
91 CRYPTO_THREAD_write_lock(obj_lock
);
93 if (name_funcs_stack
== NULL
) {
94 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
95 name_funcs_stack
= sk_NAME_FUNCS_new_null();
96 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
98 if (name_funcs_stack
== NULL
) {
102 ret
= names_type_num
;
104 for (i
= sk_NAME_FUNCS_num(name_funcs_stack
); i
< names_type_num
; i
++) {
105 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
106 name_funcs
= OPENSSL_zalloc(sizeof(*name_funcs
));
107 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
108 if (name_funcs
== NULL
) {
109 OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX
, ERR_R_MALLOC_FAILURE
);
113 name_funcs
->hash_func
= openssl_lh_strcasehash
;
114 name_funcs
->cmp_func
= obj_strcasecmp
;
115 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
117 push
= sk_NAME_FUNCS_push(name_funcs_stack
, name_funcs
);
118 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
121 OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX
, ERR_R_MALLOC_FAILURE
);
122 OPENSSL_free(name_funcs
);
127 name_funcs
= sk_NAME_FUNCS_value(name_funcs_stack
, ret
);
128 if (hash_func
!= NULL
)
129 name_funcs
->hash_func
= hash_func
;
130 if (cmp_func
!= NULL
)
131 name_funcs
->cmp_func
= cmp_func
;
132 if (free_func
!= NULL
)
133 name_funcs
->free_func
= free_func
;
136 CRYPTO_THREAD_unlock(obj_lock
);
140 static int obj_name_cmp(const OBJ_NAME
*a
, const OBJ_NAME
*b
)
144 ret
= a
->type
- b
->type
;
146 if ((name_funcs_stack
!= NULL
)
147 && (sk_NAME_FUNCS_num(name_funcs_stack
) > a
->type
)) {
148 ret
= sk_NAME_FUNCS_value(name_funcs_stack
,
149 a
->type
)->cmp_func(a
->name
, b
->name
);
151 ret
= strcasecmp(a
->name
, b
->name
);
156 static unsigned long obj_name_hash(const OBJ_NAME
*a
)
160 if ((name_funcs_stack
!= NULL
)
161 && (sk_NAME_FUNCS_num(name_funcs_stack
) > a
->type
)) {
163 sk_NAME_FUNCS_value(name_funcs_stack
,
164 a
->type
)->hash_func(a
->name
);
166 ret
= openssl_lh_strcasehash(a
->name
);
172 const char *OBJ_NAME_get(const char *name
, int type
)
176 const char *value
= NULL
;
180 if (!OBJ_NAME_init())
182 CRYPTO_THREAD_read_lock(obj_lock
);
184 alias
= type
& OBJ_NAME_ALIAS
;
185 type
&= ~OBJ_NAME_ALIAS
;
191 ret
= lh_OBJ_NAME_retrieve(names_lh
, &on
);
194 if ((ret
->alias
) && !alias
) {
204 CRYPTO_THREAD_unlock(obj_lock
);
208 int OBJ_NAME_add(const char *name
, int type
, const char *data
)
213 if (!OBJ_NAME_init())
216 alias
= type
& OBJ_NAME_ALIAS
;
217 type
&= ~OBJ_NAME_ALIAS
;
219 onp
= OPENSSL_malloc(sizeof(*onp
));
230 CRYPTO_THREAD_write_lock(obj_lock
);
232 ret
= lh_OBJ_NAME_insert(names_lh
, onp
);
235 if ((name_funcs_stack
!= NULL
)
236 && (sk_NAME_FUNCS_num(name_funcs_stack
) > ret
->type
)) {
238 * XXX: I'm not sure I understand why the free function should
239 * get three arguments... -- Richard Levitte
241 sk_NAME_FUNCS_value(name_funcs_stack
,
242 ret
->type
)->free_func(ret
->name
, ret
->type
,
247 if (lh_OBJ_NAME_error(names_lh
)) {
257 CRYPTO_THREAD_unlock(obj_lock
);
261 int OBJ_NAME_remove(const char *name
, int type
)
266 if (!OBJ_NAME_init())
269 CRYPTO_THREAD_write_lock(obj_lock
);
271 type
&= ~OBJ_NAME_ALIAS
;
274 ret
= lh_OBJ_NAME_delete(names_lh
, &on
);
277 if ((name_funcs_stack
!= NULL
)
278 && (sk_NAME_FUNCS_num(name_funcs_stack
) > ret
->type
)) {
280 * XXX: I'm not sure I understand why the free function should
281 * get three arguments... -- Richard Levitte
283 sk_NAME_FUNCS_value(name_funcs_stack
,
284 ret
->type
)->free_func(ret
->name
, ret
->type
,
291 CRYPTO_THREAD_unlock(obj_lock
);
297 void (*fn
) (const OBJ_NAME
*, void *arg
);
301 static void do_all_fn(const OBJ_NAME
*name
, OBJ_DOALL
*d
)
303 if (name
->type
== d
->type
)
307 IMPLEMENT_LHASH_DOALL_ARG_CONST(OBJ_NAME
, OBJ_DOALL
);
309 void OBJ_NAME_do_all(int type
, void (*fn
) (const OBJ_NAME
*, void *arg
),
318 lh_OBJ_NAME_doall_OBJ_DOALL(names_lh
, do_all_fn
, &d
);
321 struct doall_sorted
{
324 const OBJ_NAME
**names
;
327 static void do_all_sorted_fn(const OBJ_NAME
*name
, void *d_
)
329 struct doall_sorted
*d
= d_
;
331 if (name
->type
!= d
->type
)
334 d
->names
[d
->n
++] = name
;
337 static int do_all_sorted_cmp(const void *n1_
, const void *n2_
)
339 const OBJ_NAME
*const *n1
= n1_
;
340 const OBJ_NAME
*const *n2
= n2_
;
342 return strcmp((*n1
)->name
, (*n2
)->name
);
345 void OBJ_NAME_do_all_sorted(int type
,
346 void (*fn
) (const OBJ_NAME
*, void *arg
),
349 struct doall_sorted d
;
354 OPENSSL_malloc(sizeof(*d
.names
) * lh_OBJ_NAME_num_items(names_lh
));
355 /* Really should return an error if !d.names...but its a void function! */
356 if (d
.names
!= NULL
) {
358 OBJ_NAME_do_all(type
, do_all_sorted_fn
, &d
);
360 qsort((void *)d
.names
, d
.n
, sizeof(*d
.names
), do_all_sorted_cmp
);
362 for (n
= 0; n
< d
.n
; ++n
)
365 OPENSSL_free((void *)d
.names
);
369 static int free_type
;
371 static void names_lh_free_doall(OBJ_NAME
*onp
)
376 if (free_type
< 0 || free_type
== onp
->type
)
377 OBJ_NAME_remove(onp
->name
, onp
->type
);
380 static void name_funcs_free(NAME_FUNCS
*ptr
)
385 void OBJ_NAME_cleanup(int type
)
387 unsigned long down_load
;
389 if (names_lh
== NULL
)
393 down_load
= lh_OBJ_NAME_get_down_load(names_lh
);
394 lh_OBJ_NAME_set_down_load(names_lh
, 0);
396 lh_OBJ_NAME_doall(names_lh
, names_lh_free_doall
);
398 lh_OBJ_NAME_free(names_lh
);
399 sk_NAME_FUNCS_pop_free(name_funcs_stack
, name_funcs_free
);
400 CRYPTO_THREAD_lock_free(obj_lock
);
402 name_funcs_stack
= NULL
;
405 lh_OBJ_NAME_set_down_load(names_lh
, down_load
);