]>
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 *))
81 NAME_FUNCS
*name_funcs
;
83 if (name_funcs_stack
== NULL
) {
84 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
85 name_funcs_stack
= sk_NAME_FUNCS_new_null();
86 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
88 if (name_funcs_stack
== NULL
) {
94 for (i
= sk_NAME_FUNCS_num(name_funcs_stack
); i
< names_type_num
; i
++) {
95 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
96 name_funcs
= OPENSSL_zalloc(sizeof(*name_funcs
));
97 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
98 if (name_funcs
== NULL
) {
99 OBJerr(OBJ_F_OBJ_NAME_NEW_INDEX
, ERR_R_MALLOC_FAILURE
);
102 name_funcs
->hash_func
= OPENSSL_LH_strhash
;
103 name_funcs
->cmp_func
= obj_strcmp
;
104 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE
);
105 sk_NAME_FUNCS_push(name_funcs_stack
, name_funcs
);
106 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE
);
108 name_funcs
= sk_NAME_FUNCS_value(name_funcs_stack
, ret
);
109 if (hash_func
!= NULL
)
110 name_funcs
->hash_func
= hash_func
;
111 if (cmp_func
!= NULL
)
112 name_funcs
->cmp_func
= cmp_func
;
113 if (free_func
!= NULL
)
114 name_funcs
->free_func
= free_func
;
118 static int obj_name_cmp(const OBJ_NAME
*a
, const OBJ_NAME
*b
)
122 ret
= a
->type
- b
->type
;
124 if ((name_funcs_stack
!= NULL
)
125 && (sk_NAME_FUNCS_num(name_funcs_stack
) > a
->type
)) {
126 ret
= sk_NAME_FUNCS_value(name_funcs_stack
,
127 a
->type
)->cmp_func(a
->name
, b
->name
);
129 ret
= strcmp(a
->name
, b
->name
);
134 static unsigned long obj_name_hash(const OBJ_NAME
*a
)
138 if ((name_funcs_stack
!= NULL
)
139 && (sk_NAME_FUNCS_num(name_funcs_stack
) > a
->type
)) {
141 sk_NAME_FUNCS_value(name_funcs_stack
,
142 a
->type
)->hash_func(a
->name
);
144 ret
= OPENSSL_LH_strhash(a
->name
);
150 const char *OBJ_NAME_get(const char *name
, int type
)
157 if ((names_lh
== NULL
) && !OBJ_NAME_init())
160 alias
= type
& OBJ_NAME_ALIAS
;
161 type
&= ~OBJ_NAME_ALIAS
;
167 ret
= lh_OBJ_NAME_retrieve(names_lh
, &on
);
170 if ((ret
->alias
) && !alias
) {
180 int OBJ_NAME_add(const char *name
, int type
, const char *data
)
185 if ((names_lh
== NULL
) && !OBJ_NAME_init())
188 alias
= type
& OBJ_NAME_ALIAS
;
189 type
&= ~OBJ_NAME_ALIAS
;
191 onp
= OPENSSL_malloc(sizeof(*onp
));
202 ret
= lh_OBJ_NAME_insert(names_lh
, onp
);
205 if ((name_funcs_stack
!= NULL
)
206 && (sk_NAME_FUNCS_num(name_funcs_stack
) > ret
->type
)) {
208 * XXX: I'm not sure I understand why the free function should
209 * get three arguments... -- Richard Levitte
211 sk_NAME_FUNCS_value(name_funcs_stack
,
212 ret
->type
)->free_func(ret
->name
, ret
->type
,
217 if (lh_OBJ_NAME_error(names_lh
)) {
225 int OBJ_NAME_remove(const char *name
, int type
)
229 if (names_lh
== NULL
)
232 type
&= ~OBJ_NAME_ALIAS
;
235 ret
= lh_OBJ_NAME_delete(names_lh
, &on
);
238 if ((name_funcs_stack
!= NULL
)
239 && (sk_NAME_FUNCS_num(name_funcs_stack
) > ret
->type
)) {
241 * XXX: I'm not sure I understand why the free function should
242 * get three arguments... -- Richard Levitte
244 sk_NAME_FUNCS_value(name_funcs_stack
,
245 ret
->type
)->free_func(ret
->name
, ret
->type
,
256 void (*fn
) (const OBJ_NAME
*, void *arg
);
260 static void do_all_fn(const OBJ_NAME
*name
, OBJ_DOALL
*d
)
262 if (name
->type
== d
->type
)
266 IMPLEMENT_LHASH_DOALL_ARG_CONST(OBJ_NAME
, OBJ_DOALL
);
268 void OBJ_NAME_do_all(int type
, void (*fn
) (const OBJ_NAME
*, void *arg
),
277 lh_OBJ_NAME_doall_OBJ_DOALL(names_lh
, do_all_fn
, &d
);
280 struct doall_sorted
{
283 const OBJ_NAME
**names
;
286 static void do_all_sorted_fn(const OBJ_NAME
*name
, void *d_
)
288 struct doall_sorted
*d
= d_
;
290 if (name
->type
!= d
->type
)
293 d
->names
[d
->n
++] = name
;
296 static int do_all_sorted_cmp(const void *n1_
, const void *n2_
)
298 const OBJ_NAME
*const *n1
= n1_
;
299 const OBJ_NAME
*const *n2
= n2_
;
301 return strcmp((*n1
)->name
, (*n2
)->name
);
304 void OBJ_NAME_do_all_sorted(int type
,
305 void (*fn
) (const OBJ_NAME
*, void *arg
),
308 struct doall_sorted d
;
313 OPENSSL_malloc(sizeof(*d
.names
) * lh_OBJ_NAME_num_items(names_lh
));
314 /* Really should return an error if !d.names...but its a void function! */
315 if (d
.names
!= NULL
) {
317 OBJ_NAME_do_all(type
, do_all_sorted_fn
, &d
);
319 qsort((void *)d
.names
, d
.n
, sizeof(*d
.names
), do_all_sorted_cmp
);
321 for (n
= 0; n
< d
.n
; ++n
)
324 OPENSSL_free((void *)d
.names
);
328 static int free_type
;
330 static void names_lh_free_doall(OBJ_NAME
*onp
)
335 if (free_type
< 0 || free_type
== onp
->type
)
336 OBJ_NAME_remove(onp
->name
, onp
->type
);
339 static void name_funcs_free(NAME_FUNCS
*ptr
)
344 void OBJ_NAME_cleanup(int type
)
346 unsigned long down_load
;
348 if (names_lh
== NULL
)
352 down_load
= lh_OBJ_NAME_get_down_load(names_lh
);
353 lh_OBJ_NAME_set_down_load(names_lh
, 0);
355 lh_OBJ_NAME_doall(names_lh
, names_lh_free_doall
);
357 lh_OBJ_NAME_free(names_lh
);
358 sk_NAME_FUNCS_pop_free(name_funcs_stack
, name_funcs_free
);
360 name_funcs_stack
= NULL
;
362 lh_OBJ_NAME_set_down_load(names_lh
, down_load
);