]>
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>
22 * We define this wrapper for two reasons. Firstly, later versions of
23 * DEC C add linkage information to certain functions, which makes it
24 * tricky to use them as values to regular function pointers.
25 * Secondly, in the EDK2 build environment, the strcmp function is
26 * actually an external function (AsciiStrCmp) with the Microsoft ABI,
27 * so we can't transparently assign function pointers to it.
28 * Arguably the latter is a stupidity of the UEFI environment, but
29 * since the wrapper solves the DEC C issue too, let's just use the
32 #if defined(OPENSSL_SYS_VMS_DECC) || defined(OPENSSL_SYS_UEFI)
33 static int obj_strcmp(const char *a
, const char *b
)
38 #define obj_strcmp strcmp
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
;
48 struct name_funcs_st
{
49 unsigned long (*hash_func
) (const char *name
);
50 int (*cmp_func
) (const char *a
, const char *b
);
51 void (*free_func
) (const char *, int, const char *);
54 static STACK_OF(NAME_FUNCS
) *name_funcs_stack
;
57 * The LHASH callbacks now use the raw "void *" prototypes and do
58 * per-variable casting in the functions. This prevents function pointer
59 * casting without the need for macro-generated wrapper functions.
62 static unsigned long obj_name_hash(const OBJ_NAME
*a
);
63 static int obj_name_cmp(const OBJ_NAME
*a
, const OBJ_NAME
*b
);
65 int OBJ_NAME_init(void)
69 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
70 names_lh
= lh_OBJ_NAME_new(obj_name_hash
, obj_name_cmp
);
71 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
72 return (names_lh
!= NULL
);
75 int OBJ_NAME_new_index(unsigned long (*hash_func
) (const char *),
76 int (*cmp_func
) (const char *, const char *),
77 void (*free_func
) (const char *, int, const char *))
80 NAME_FUNCS
*name_funcs
;
82 if (name_funcs_stack
== NULL
) {
83 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
84 name_funcs_stack
= sk_NAME_FUNCS_new_null();
85 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
87 if (name_funcs_stack
== NULL
) {
93 for (i
= sk_NAME_FUNCS_num(name_funcs_stack
); i
< names_type_num
; i
++) {
94 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
95 name_funcs
= OPENSSL_zalloc(sizeof(*name_funcs
));
96 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
97 if (name_funcs
== NULL
) {
98 OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX
, ERR_R_MALLOC_FAILURE
);
101 name_funcs
->hash_func
= OPENSSL_LH_strhash
;
102 name_funcs
->cmp_func
= obj_strcmp
;
103 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
105 push
= sk_NAME_FUNCS_push(name_funcs_stack
, name_funcs
);
106 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
109 OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX
, ERR_R_MALLOC_FAILURE
);
110 OPENSSL_free(name_funcs
);
114 name_funcs
= sk_NAME_FUNCS_value(name_funcs_stack
, ret
);
115 if (hash_func
!= NULL
)
116 name_funcs
->hash_func
= hash_func
;
117 if (cmp_func
!= NULL
)
118 name_funcs
->cmp_func
= cmp_func
;
119 if (free_func
!= NULL
)
120 name_funcs
->free_func
= free_func
;
124 static int obj_name_cmp(const OBJ_NAME
*a
, const OBJ_NAME
*b
)
128 ret
= a
->type
- b
->type
;
130 if ((name_funcs_stack
!= NULL
)
131 && (sk_NAME_FUNCS_num(name_funcs_stack
) > a
->type
)) {
132 ret
= sk_NAME_FUNCS_value(name_funcs_stack
,
133 a
->type
)->cmp_func(a
->name
, b
->name
);
135 ret
= strcmp(a
->name
, b
->name
);
140 static unsigned long obj_name_hash(const OBJ_NAME
*a
)
144 if ((name_funcs_stack
!= NULL
)
145 && (sk_NAME_FUNCS_num(name_funcs_stack
) > a
->type
)) {
147 sk_NAME_FUNCS_value(name_funcs_stack
,
148 a
->type
)->hash_func(a
->name
);
150 ret
= OPENSSL_LH_strhash(a
->name
);
156 const char *OBJ_NAME_get(const char *name
, int type
)
163 if ((names_lh
== NULL
) && !OBJ_NAME_init())
166 alias
= type
& OBJ_NAME_ALIAS
;
167 type
&= ~OBJ_NAME_ALIAS
;
173 ret
= lh_OBJ_NAME_retrieve(names_lh
, &on
);
176 if ((ret
->alias
) && !alias
) {
186 int OBJ_NAME_add(const char *name
, int type
, const char *data
)
191 if ((names_lh
== NULL
) && !OBJ_NAME_init())
194 alias
= type
& OBJ_NAME_ALIAS
;
195 type
&= ~OBJ_NAME_ALIAS
;
197 onp
= OPENSSL_malloc(sizeof(*onp
));
208 ret
= lh_OBJ_NAME_insert(names_lh
, onp
);
211 if ((name_funcs_stack
!= NULL
)
212 && (sk_NAME_FUNCS_num(name_funcs_stack
) > ret
->type
)) {
214 * XXX: I'm not sure I understand why the free function should
215 * get three arguments... -- Richard Levitte
217 sk_NAME_FUNCS_value(name_funcs_stack
,
218 ret
->type
)->free_func(ret
->name
, ret
->type
,
223 if (lh_OBJ_NAME_error(names_lh
)) {
232 int OBJ_NAME_remove(const char *name
, int type
)
236 if (names_lh
== NULL
)
239 type
&= ~OBJ_NAME_ALIAS
;
242 ret
= lh_OBJ_NAME_delete(names_lh
, &on
);
245 if ((name_funcs_stack
!= NULL
)
246 && (sk_NAME_FUNCS_num(name_funcs_stack
) > ret
->type
)) {
248 * XXX: I'm not sure I understand why the free function should
249 * get three arguments... -- Richard Levitte
251 sk_NAME_FUNCS_value(name_funcs_stack
,
252 ret
->type
)->free_func(ret
->name
, ret
->type
,
263 void (*fn
) (const OBJ_NAME
*, void *arg
);
267 static void do_all_fn(const OBJ_NAME
*name
, OBJ_DOALL
*d
)
269 if (name
->type
== d
->type
)
273 IMPLEMENT_LHASH_DOALL_ARG_CONST(OBJ_NAME
, OBJ_DOALL
);
275 void OBJ_NAME_do_all(int type
, void (*fn
) (const OBJ_NAME
*, void *arg
),
284 lh_OBJ_NAME_doall_OBJ_DOALL(names_lh
, do_all_fn
, &d
);
287 struct doall_sorted
{
290 const OBJ_NAME
**names
;
293 static void do_all_sorted_fn(const OBJ_NAME
*name
, void *d_
)
295 struct doall_sorted
*d
= d_
;
297 if (name
->type
!= d
->type
)
300 d
->names
[d
->n
++] = name
;
303 static int do_all_sorted_cmp(const void *n1_
, const void *n2_
)
305 const OBJ_NAME
*const *n1
= n1_
;
306 const OBJ_NAME
*const *n2
= n2_
;
308 return strcmp((*n1
)->name
, (*n2
)->name
);
311 void OBJ_NAME_do_all_sorted(int type
,
312 void (*fn
) (const OBJ_NAME
*, void *arg
),
315 struct doall_sorted d
;
320 OPENSSL_malloc(sizeof(*d
.names
) * lh_OBJ_NAME_num_items(names_lh
));
321 /* Really should return an error if !d.names...but its a void function! */
322 if (d
.names
!= NULL
) {
324 OBJ_NAME_do_all(type
, do_all_sorted_fn
, &d
);
326 qsort((void *)d
.names
, d
.n
, sizeof(*d
.names
), do_all_sorted_cmp
);
328 for (n
= 0; n
< d
.n
; ++n
)
331 OPENSSL_free((void *)d
.names
);
335 static int free_type
;
337 static void names_lh_free_doall(OBJ_NAME
*onp
)
342 if (free_type
< 0 || free_type
== onp
->type
)
343 OBJ_NAME_remove(onp
->name
, onp
->type
);
346 static void name_funcs_free(NAME_FUNCS
*ptr
)
351 void OBJ_NAME_cleanup(int type
)
353 unsigned long down_load
;
355 if (names_lh
== NULL
)
359 down_load
= lh_OBJ_NAME_get_down_load(names_lh
);
360 lh_OBJ_NAME_set_down_load(names_lh
, 0);
362 lh_OBJ_NAME_doall(names_lh
, names_lh_free_doall
);
364 lh_OBJ_NAME_free(names_lh
);
365 sk_NAME_FUNCS_pop_free(name_funcs_stack
, name_funcs_free
);
367 name_funcs_stack
= NULL
;
369 lh_OBJ_NAME_set_down_load(names_lh
, down_load
);