]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/objects/o_names.c
2 * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (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"
23 * We define this wrapper for two reasons. Firstly, later versions of
24 * DEC C add linkage information to certain functions, which makes it
25 * tricky to use them as values to regular function pointers.
26 * Secondly, in the EDK2 build environment, the strcmp function is
27 * actually an external function (AsciiStrCmp) with the Microsoft ABI,
28 * so we can't transparently assign function pointers to it.
29 * Arguably the latter is a stupidity of the UEFI environment, but
30 * since the wrapper solves the DEC C issue too, let's just use the
33 #if defined(OPENSSL_SYS_VMS_DECC) || defined(OPENSSL_SYS_UEFI)
34 static int obj_strcmp(const char *a
, const char *b
)
39 #define obj_strcmp strcmp
43 * I use the ex_data stuff to manage the identifiers for the obj_name_types
44 * that applications may define. I only really use the free function field.
46 static LHASH_OF(OBJ_NAME
) *names_lh
= NULL
;
47 static int names_type_num
= OBJ_NAME_TYPE_NUM
;
48 static CRYPTO_RWLOCK
*obj_lock
= NULL
;
50 struct name_funcs_st
{
51 unsigned long (*hash_func
) (const char *name
);
52 int (*cmp_func
) (const char *a
, const char *b
);
53 void (*free_func
) (const char *, int, const char *);
56 static STACK_OF(NAME_FUNCS
) *name_funcs_stack
;
59 * The LHASH callbacks now use the raw "void *" prototypes and do
60 * per-variable casting in the functions. This prevents function pointer
61 * casting without the need for macro-generated wrapper functions.
64 static unsigned long obj_name_hash(const OBJ_NAME
*a
);
65 static int obj_name_cmp(const OBJ_NAME
*a
, const OBJ_NAME
*b
);
67 static CRYPTO_ONCE init
= CRYPTO_ONCE_STATIC_INIT
;
68 DEFINE_RUN_ONCE_STATIC(o_names_init
)
70 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
71 names_lh
= lh_OBJ_NAME_new(obj_name_hash
, obj_name_cmp
);
72 obj_lock
= CRYPTO_THREAD_lock_new();
73 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
74 return names_lh
!= NULL
&& obj_lock
!= NULL
;
77 int OBJ_NAME_init(void)
79 return RUN_ONCE(&init
, o_names_init
);
82 int OBJ_NAME_new_index(unsigned long (*hash_func
) (const char *),
83 int (*cmp_func
) (const char *, const char *),
84 void (*free_func
) (const char *, int, const char *))
87 NAME_FUNCS
*name_funcs
;
92 CRYPTO_THREAD_write_lock(obj_lock
);
94 if (name_funcs_stack
== NULL
) {
95 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
96 name_funcs_stack
= sk_NAME_FUNCS_new_null();
97 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
99 if (name_funcs_stack
== NULL
) {
103 ret
= names_type_num
;
105 for (i
= sk_NAME_FUNCS_num(name_funcs_stack
); i
< names_type_num
; i
++) {
106 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
107 name_funcs
= OPENSSL_zalloc(sizeof(*name_funcs
));
108 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
109 if (name_funcs
== NULL
) {
110 OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX
, ERR_R_MALLOC_FAILURE
);
114 name_funcs
->hash_func
= OPENSSL_LH_strhash
;
115 name_funcs
->cmp_func
= obj_strcmp
;
116 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
118 push
= sk_NAME_FUNCS_push(name_funcs_stack
, name_funcs
);
119 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
122 OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX
, ERR_R_MALLOC_FAILURE
);
123 OPENSSL_free(name_funcs
);
128 name_funcs
= sk_NAME_FUNCS_value(name_funcs_stack
, ret
);
129 if (hash_func
!= NULL
)
130 name_funcs
->hash_func
= hash_func
;
131 if (cmp_func
!= NULL
)
132 name_funcs
->cmp_func
= cmp_func
;
133 if (free_func
!= NULL
)
134 name_funcs
->free_func
= free_func
;
137 CRYPTO_THREAD_unlock(obj_lock
);
141 static int obj_name_cmp(const OBJ_NAME
*a
, const OBJ_NAME
*b
)
145 ret
= a
->type
- b
->type
;
147 if ((name_funcs_stack
!= NULL
)
148 && (sk_NAME_FUNCS_num(name_funcs_stack
) > a
->type
)) {
149 ret
= sk_NAME_FUNCS_value(name_funcs_stack
,
150 a
->type
)->cmp_func(a
->name
, b
->name
);
152 ret
= strcmp(a
->name
, b
->name
);
157 static unsigned long obj_name_hash(const OBJ_NAME
*a
)
161 if ((name_funcs_stack
!= NULL
)
162 && (sk_NAME_FUNCS_num(name_funcs_stack
) > a
->type
)) {
164 sk_NAME_FUNCS_value(name_funcs_stack
,
165 a
->type
)->hash_func(a
->name
);
167 ret
= OPENSSL_LH_strhash(a
->name
);
173 const char *OBJ_NAME_get(const char *name
, int type
)
177 const char *value
= NULL
;
181 if (!OBJ_NAME_init())
183 CRYPTO_THREAD_read_lock(obj_lock
);
185 alias
= type
& OBJ_NAME_ALIAS
;
186 type
&= ~OBJ_NAME_ALIAS
;
192 ret
= lh_OBJ_NAME_retrieve(names_lh
, &on
);
195 if ((ret
->alias
) && !alias
) {
205 CRYPTO_THREAD_unlock(obj_lock
);
209 int OBJ_NAME_add(const char *name
, int type
, const char *data
)
214 if (!OBJ_NAME_init())
217 CRYPTO_THREAD_write_lock(obj_lock
);
219 alias
= type
& OBJ_NAME_ALIAS
;
220 type
&= ~OBJ_NAME_ALIAS
;
222 onp
= OPENSSL_malloc(sizeof(*onp
));
233 ret
= lh_OBJ_NAME_insert(names_lh
, onp
);
236 if ((name_funcs_stack
!= NULL
)
237 && (sk_NAME_FUNCS_num(name_funcs_stack
) > ret
->type
)) {
239 * XXX: I'm not sure I understand why the free function should
240 * get three arguments... -- Richard Levitte
242 sk_NAME_FUNCS_value(name_funcs_stack
,
243 ret
->type
)->free_func(ret
->name
, ret
->type
,
248 if (lh_OBJ_NAME_error(names_lh
)) {
258 CRYPTO_THREAD_unlock(obj_lock
);
262 int OBJ_NAME_remove(const char *name
, int type
)
267 if (!OBJ_NAME_init())
270 CRYPTO_THREAD_write_lock(obj_lock
);
272 type
&= ~OBJ_NAME_ALIAS
;
275 ret
= lh_OBJ_NAME_delete(names_lh
, &on
);
278 if ((name_funcs_stack
!= NULL
)
279 && (sk_NAME_FUNCS_num(name_funcs_stack
) > ret
->type
)) {
281 * XXX: I'm not sure I understand why the free function should
282 * get three arguments... -- Richard Levitte
284 sk_NAME_FUNCS_value(name_funcs_stack
,
285 ret
->type
)->free_func(ret
->name
, ret
->type
,
292 CRYPTO_THREAD_unlock(obj_lock
);
298 void (*fn
) (const OBJ_NAME
*, void *arg
);
302 static void do_all_fn(const OBJ_NAME
*name
, OBJ_DOALL
*d
)
304 if (name
->type
== d
->type
)
308 IMPLEMENT_LHASH_DOALL_ARG_CONST(OBJ_NAME
, OBJ_DOALL
);
310 void OBJ_NAME_do_all(int type
, void (*fn
) (const OBJ_NAME
*, void *arg
),
319 lh_OBJ_NAME_doall_OBJ_DOALL(names_lh
, do_all_fn
, &d
);
322 struct doall_sorted
{
325 const OBJ_NAME
**names
;
328 static void do_all_sorted_fn(const OBJ_NAME
*name
, void *d_
)
330 struct doall_sorted
*d
= d_
;
332 if (name
->type
!= d
->type
)
335 d
->names
[d
->n
++] = name
;
338 static int do_all_sorted_cmp(const void *n1_
, const void *n2_
)
340 const OBJ_NAME
*const *n1
= n1_
;
341 const OBJ_NAME
*const *n2
= n2_
;
343 return strcmp((*n1
)->name
, (*n2
)->name
);
346 void OBJ_NAME_do_all_sorted(int type
,
347 void (*fn
) (const OBJ_NAME
*, void *arg
),
350 struct doall_sorted d
;
355 OPENSSL_malloc(sizeof(*d
.names
) * lh_OBJ_NAME_num_items(names_lh
));
356 /* Really should return an error if !d.names...but its a void function! */
357 if (d
.names
!= NULL
) {
359 OBJ_NAME_do_all(type
, do_all_sorted_fn
, &d
);
361 qsort((void *)d
.names
, d
.n
, sizeof(*d
.names
), do_all_sorted_cmp
);
363 for (n
= 0; n
< d
.n
; ++n
)
366 OPENSSL_free((void *)d
.names
);
370 static int free_type
;
372 static void names_lh_free_doall(OBJ_NAME
*onp
)
377 if (free_type
< 0 || free_type
== onp
->type
)
378 OBJ_NAME_remove(onp
->name
, onp
->type
);
381 static void name_funcs_free(NAME_FUNCS
*ptr
)
386 void OBJ_NAME_cleanup(int type
)
388 unsigned long down_load
;
390 if (names_lh
== NULL
)
394 down_load
= lh_OBJ_NAME_get_down_load(names_lh
);
395 lh_OBJ_NAME_set_down_load(names_lh
, 0);
397 lh_OBJ_NAME_doall(names_lh
, names_lh_free_doall
);
399 lh_OBJ_NAME_free(names_lh
);
400 sk_NAME_FUNCS_pop_free(name_funcs_stack
, name_funcs_free
);
401 CRYPTO_THREAD_lock_free(obj_lock
);
403 name_funcs_stack
= NULL
;
406 lh_OBJ_NAME_set_down_load(names_lh
, down_load
);