1b077aed3SPierre Pronchery /*
2*aa795734SPierre Pronchery * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery *
4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery */
9b077aed3SPierre Pronchery
10b077aed3SPierre Pronchery #include "internal/namemap.h"
11b077aed3SPierre Pronchery #include <openssl/lhash.h>
12b077aed3SPierre Pronchery #include "crypto/lhash.h" /* ossl_lh_strcasehash */
13b077aed3SPierre Pronchery #include "internal/tsan_assist.h"
14b077aed3SPierre Pronchery #include "internal/sizes.h"
15b077aed3SPierre Pronchery
16b077aed3SPierre Pronchery /*-
17b077aed3SPierre Pronchery * The namenum entry
18b077aed3SPierre Pronchery * =================
19b077aed3SPierre Pronchery */
20b077aed3SPierre Pronchery typedef struct {
21b077aed3SPierre Pronchery char *name;
22b077aed3SPierre Pronchery int number;
23b077aed3SPierre Pronchery } NAMENUM_ENTRY;
24b077aed3SPierre Pronchery
25b077aed3SPierre Pronchery DEFINE_LHASH_OF(NAMENUM_ENTRY);
26b077aed3SPierre Pronchery
27b077aed3SPierre Pronchery /*-
28b077aed3SPierre Pronchery * The namemap itself
29b077aed3SPierre Pronchery * ==================
30b077aed3SPierre Pronchery */
31b077aed3SPierre Pronchery
32b077aed3SPierre Pronchery struct ossl_namemap_st {
33b077aed3SPierre Pronchery /* Flags */
34b077aed3SPierre Pronchery unsigned int stored:1; /* If 1, it's stored in a library context */
35b077aed3SPierre Pronchery
36b077aed3SPierre Pronchery CRYPTO_RWLOCK *lock;
37b077aed3SPierre Pronchery LHASH_OF(NAMENUM_ENTRY) *namenum; /* Name->number mapping */
38b077aed3SPierre Pronchery
39b077aed3SPierre Pronchery TSAN_QUALIFIER int max_number; /* Current max number */
40b077aed3SPierre Pronchery };
41b077aed3SPierre Pronchery
42b077aed3SPierre Pronchery /* LHASH callbacks */
43b077aed3SPierre Pronchery
namenum_hash(const NAMENUM_ENTRY * n)44b077aed3SPierre Pronchery static unsigned long namenum_hash(const NAMENUM_ENTRY *n)
45b077aed3SPierre Pronchery {
46b077aed3SPierre Pronchery return ossl_lh_strcasehash(n->name);
47b077aed3SPierre Pronchery }
48b077aed3SPierre Pronchery
namenum_cmp(const NAMENUM_ENTRY * a,const NAMENUM_ENTRY * b)49b077aed3SPierre Pronchery static int namenum_cmp(const NAMENUM_ENTRY *a, const NAMENUM_ENTRY *b)
50b077aed3SPierre Pronchery {
51b077aed3SPierre Pronchery return OPENSSL_strcasecmp(a->name, b->name);
52b077aed3SPierre Pronchery }
53b077aed3SPierre Pronchery
namenum_free(NAMENUM_ENTRY * n)54b077aed3SPierre Pronchery static void namenum_free(NAMENUM_ENTRY *n)
55b077aed3SPierre Pronchery {
56b077aed3SPierre Pronchery if (n != NULL)
57b077aed3SPierre Pronchery OPENSSL_free(n->name);
58b077aed3SPierre Pronchery OPENSSL_free(n);
59b077aed3SPierre Pronchery }
60b077aed3SPierre Pronchery
61b077aed3SPierre Pronchery /* OSSL_LIB_CTX_METHOD functions for a namemap stored in a library context */
62b077aed3SPierre Pronchery
stored_namemap_new(OSSL_LIB_CTX * libctx)63b077aed3SPierre Pronchery static void *stored_namemap_new(OSSL_LIB_CTX *libctx)
64b077aed3SPierre Pronchery {
65b077aed3SPierre Pronchery OSSL_NAMEMAP *namemap = ossl_namemap_new();
66b077aed3SPierre Pronchery
67b077aed3SPierre Pronchery if (namemap != NULL)
68b077aed3SPierre Pronchery namemap->stored = 1;
69b077aed3SPierre Pronchery
70b077aed3SPierre Pronchery return namemap;
71b077aed3SPierre Pronchery }
72b077aed3SPierre Pronchery
stored_namemap_free(void * vnamemap)73b077aed3SPierre Pronchery static void stored_namemap_free(void *vnamemap)
74b077aed3SPierre Pronchery {
75b077aed3SPierre Pronchery OSSL_NAMEMAP *namemap = vnamemap;
76b077aed3SPierre Pronchery
77b077aed3SPierre Pronchery if (namemap != NULL) {
78b077aed3SPierre Pronchery /* Pretend it isn't stored, or ossl_namemap_free() will do nothing */
79b077aed3SPierre Pronchery namemap->stored = 0;
80b077aed3SPierre Pronchery ossl_namemap_free(namemap);
81b077aed3SPierre Pronchery }
82b077aed3SPierre Pronchery }
83b077aed3SPierre Pronchery
84b077aed3SPierre Pronchery static const OSSL_LIB_CTX_METHOD stored_namemap_method = {
85b077aed3SPierre Pronchery OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
86b077aed3SPierre Pronchery stored_namemap_new,
87b077aed3SPierre Pronchery stored_namemap_free,
88b077aed3SPierre Pronchery };
89b077aed3SPierre Pronchery
90b077aed3SPierre Pronchery /*-
91b077aed3SPierre Pronchery * API functions
92b077aed3SPierre Pronchery * =============
93b077aed3SPierre Pronchery */
94b077aed3SPierre Pronchery
ossl_namemap_empty(OSSL_NAMEMAP * namemap)95b077aed3SPierre Pronchery int ossl_namemap_empty(OSSL_NAMEMAP *namemap)
96b077aed3SPierre Pronchery {
97b077aed3SPierre Pronchery #ifdef TSAN_REQUIRES_LOCKING
98b077aed3SPierre Pronchery /* No TSAN support */
99b077aed3SPierre Pronchery int rv;
100b077aed3SPierre Pronchery
101b077aed3SPierre Pronchery if (namemap == NULL)
102b077aed3SPierre Pronchery return 1;
103b077aed3SPierre Pronchery
104b077aed3SPierre Pronchery if (!CRYPTO_THREAD_read_lock(namemap->lock))
105b077aed3SPierre Pronchery return -1;
106b077aed3SPierre Pronchery rv = namemap->max_number == 0;
107b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(namemap->lock);
108b077aed3SPierre Pronchery return rv;
109b077aed3SPierre Pronchery #else
110b077aed3SPierre Pronchery /* Have TSAN support */
111b077aed3SPierre Pronchery return namemap == NULL || tsan_load(&namemap->max_number) == 0;
112b077aed3SPierre Pronchery #endif
113b077aed3SPierre Pronchery }
114b077aed3SPierre Pronchery
115b077aed3SPierre Pronchery typedef struct doall_names_data_st {
116b077aed3SPierre Pronchery int number;
117b077aed3SPierre Pronchery const char **names;
118b077aed3SPierre Pronchery int found;
119b077aed3SPierre Pronchery } DOALL_NAMES_DATA;
120b077aed3SPierre Pronchery
do_name(const NAMENUM_ENTRY * namenum,DOALL_NAMES_DATA * data)121b077aed3SPierre Pronchery static void do_name(const NAMENUM_ENTRY *namenum, DOALL_NAMES_DATA *data)
122b077aed3SPierre Pronchery {
123b077aed3SPierre Pronchery if (namenum->number == data->number)
124b077aed3SPierre Pronchery data->names[data->found++] = namenum->name;
125b077aed3SPierre Pronchery }
126b077aed3SPierre Pronchery
127b077aed3SPierre Pronchery IMPLEMENT_LHASH_DOALL_ARG_CONST(NAMENUM_ENTRY, DOALL_NAMES_DATA);
128b077aed3SPierre Pronchery
129b077aed3SPierre Pronchery /*
130b077aed3SPierre Pronchery * Call the callback for all names in the namemap with the given number.
131b077aed3SPierre Pronchery * A return value 1 means that the callback was called for all names. A
132b077aed3SPierre Pronchery * return value of 0 means that the callback was not called for any names.
133b077aed3SPierre Pronchery */
ossl_namemap_doall_names(const OSSL_NAMEMAP * namemap,int number,void (* fn)(const char * name,void * data),void * data)134b077aed3SPierre Pronchery int ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
135b077aed3SPierre Pronchery void (*fn)(const char *name, void *data),
136b077aed3SPierre Pronchery void *data)
137b077aed3SPierre Pronchery {
138b077aed3SPierre Pronchery DOALL_NAMES_DATA cbdata;
139b077aed3SPierre Pronchery size_t num_names;
140b077aed3SPierre Pronchery int i;
141b077aed3SPierre Pronchery
142b077aed3SPierre Pronchery cbdata.number = number;
143b077aed3SPierre Pronchery cbdata.found = 0;
144b077aed3SPierre Pronchery
145*aa795734SPierre Pronchery if (namemap == NULL)
146*aa795734SPierre Pronchery return 0;
147*aa795734SPierre Pronchery
148b077aed3SPierre Pronchery /*
149b077aed3SPierre Pronchery * We collect all the names first under a read lock. Subsequently we call
150b077aed3SPierre Pronchery * the user function, so that we're not holding the read lock when in user
151b077aed3SPierre Pronchery * code. This could lead to deadlocks.
152b077aed3SPierre Pronchery */
153b077aed3SPierre Pronchery if (!CRYPTO_THREAD_read_lock(namemap->lock))
154b077aed3SPierre Pronchery return 0;
155b077aed3SPierre Pronchery
156b077aed3SPierre Pronchery num_names = lh_NAMENUM_ENTRY_num_items(namemap->namenum);
157b077aed3SPierre Pronchery if (num_names == 0) {
158b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(namemap->lock);
159b077aed3SPierre Pronchery return 0;
160b077aed3SPierre Pronchery }
161b077aed3SPierre Pronchery cbdata.names = OPENSSL_malloc(sizeof(*cbdata.names) * num_names);
162b077aed3SPierre Pronchery if (cbdata.names == NULL) {
163b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(namemap->lock);
164b077aed3SPierre Pronchery return 0;
165b077aed3SPierre Pronchery }
166b077aed3SPierre Pronchery lh_NAMENUM_ENTRY_doall_DOALL_NAMES_DATA(namemap->namenum, do_name,
167b077aed3SPierre Pronchery &cbdata);
168b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(namemap->lock);
169b077aed3SPierre Pronchery
170b077aed3SPierre Pronchery for (i = 0; i < cbdata.found; i++)
171b077aed3SPierre Pronchery fn(cbdata.names[i], data);
172b077aed3SPierre Pronchery
173b077aed3SPierre Pronchery OPENSSL_free(cbdata.names);
174b077aed3SPierre Pronchery return 1;
175b077aed3SPierre Pronchery }
176b077aed3SPierre Pronchery
namemap_name2num_n(const OSSL_NAMEMAP * namemap,const char * name,size_t name_len)177b077aed3SPierre Pronchery static int namemap_name2num_n(const OSSL_NAMEMAP *namemap,
178b077aed3SPierre Pronchery const char *name, size_t name_len)
179b077aed3SPierre Pronchery {
180b077aed3SPierre Pronchery NAMENUM_ENTRY *namenum_entry, namenum_tmpl;
181b077aed3SPierre Pronchery
182b077aed3SPierre Pronchery if ((namenum_tmpl.name = OPENSSL_strndup(name, name_len)) == NULL)
183b077aed3SPierre Pronchery return 0;
184b077aed3SPierre Pronchery namenum_tmpl.number = 0;
185b077aed3SPierre Pronchery namenum_entry =
186b077aed3SPierre Pronchery lh_NAMENUM_ENTRY_retrieve(namemap->namenum, &namenum_tmpl);
187b077aed3SPierre Pronchery OPENSSL_free(namenum_tmpl.name);
188b077aed3SPierre Pronchery return namenum_entry != NULL ? namenum_entry->number : 0;
189b077aed3SPierre Pronchery }
190b077aed3SPierre Pronchery
ossl_namemap_name2num_n(const OSSL_NAMEMAP * namemap,const char * name,size_t name_len)191b077aed3SPierre Pronchery int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
192b077aed3SPierre Pronchery const char *name, size_t name_len)
193b077aed3SPierre Pronchery {
194b077aed3SPierre Pronchery int number;
195b077aed3SPierre Pronchery
196b077aed3SPierre Pronchery #ifndef FIPS_MODULE
197b077aed3SPierre Pronchery if (namemap == NULL)
198b077aed3SPierre Pronchery namemap = ossl_namemap_stored(NULL);
199b077aed3SPierre Pronchery #endif
200b077aed3SPierre Pronchery
201b077aed3SPierre Pronchery if (namemap == NULL)
202b077aed3SPierre Pronchery return 0;
203b077aed3SPierre Pronchery
204b077aed3SPierre Pronchery if (!CRYPTO_THREAD_read_lock(namemap->lock))
205b077aed3SPierre Pronchery return 0;
206b077aed3SPierre Pronchery number = namemap_name2num_n(namemap, name, name_len);
207b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(namemap->lock);
208b077aed3SPierre Pronchery
209b077aed3SPierre Pronchery return number;
210b077aed3SPierre Pronchery }
211b077aed3SPierre Pronchery
ossl_namemap_name2num(const OSSL_NAMEMAP * namemap,const char * name)212b077aed3SPierre Pronchery int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name)
213b077aed3SPierre Pronchery {
214b077aed3SPierre Pronchery if (name == NULL)
215b077aed3SPierre Pronchery return 0;
216b077aed3SPierre Pronchery
217b077aed3SPierre Pronchery return ossl_namemap_name2num_n(namemap, name, strlen(name));
218b077aed3SPierre Pronchery }
219b077aed3SPierre Pronchery
220b077aed3SPierre Pronchery struct num2name_data_st {
221b077aed3SPierre Pronchery size_t idx; /* Countdown */
222b077aed3SPierre Pronchery const char *name; /* Result */
223b077aed3SPierre Pronchery };
224b077aed3SPierre Pronchery
do_num2name(const char * name,void * vdata)225b077aed3SPierre Pronchery static void do_num2name(const char *name, void *vdata)
226b077aed3SPierre Pronchery {
227b077aed3SPierre Pronchery struct num2name_data_st *data = vdata;
228b077aed3SPierre Pronchery
229b077aed3SPierre Pronchery if (data->idx > 0)
230b077aed3SPierre Pronchery data->idx--;
231b077aed3SPierre Pronchery else if (data->name == NULL)
232b077aed3SPierre Pronchery data->name = name;
233b077aed3SPierre Pronchery }
234b077aed3SPierre Pronchery
ossl_namemap_num2name(const OSSL_NAMEMAP * namemap,int number,size_t idx)235b077aed3SPierre Pronchery const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number,
236b077aed3SPierre Pronchery size_t idx)
237b077aed3SPierre Pronchery {
238b077aed3SPierre Pronchery struct num2name_data_st data;
239b077aed3SPierre Pronchery
240b077aed3SPierre Pronchery data.idx = idx;
241b077aed3SPierre Pronchery data.name = NULL;
242b077aed3SPierre Pronchery if (!ossl_namemap_doall_names(namemap, number, do_num2name, &data))
243b077aed3SPierre Pronchery return NULL;
244b077aed3SPierre Pronchery return data.name;
245b077aed3SPierre Pronchery }
246b077aed3SPierre Pronchery
namemap_add_name_n(OSSL_NAMEMAP * namemap,int number,const char * name,size_t name_len)247b077aed3SPierre Pronchery static int namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
248b077aed3SPierre Pronchery const char *name, size_t name_len)
249b077aed3SPierre Pronchery {
250b077aed3SPierre Pronchery NAMENUM_ENTRY *namenum = NULL;
251b077aed3SPierre Pronchery int tmp_number;
252b077aed3SPierre Pronchery
253b077aed3SPierre Pronchery /* If it already exists, we don't add it */
254b077aed3SPierre Pronchery if ((tmp_number = namemap_name2num_n(namemap, name, name_len)) != 0)
255b077aed3SPierre Pronchery return tmp_number;
256b077aed3SPierre Pronchery
257b077aed3SPierre Pronchery if ((namenum = OPENSSL_zalloc(sizeof(*namenum))) == NULL
258b077aed3SPierre Pronchery || (namenum->name = OPENSSL_strndup(name, name_len)) == NULL)
259b077aed3SPierre Pronchery goto err;
260b077aed3SPierre Pronchery
261b077aed3SPierre Pronchery /* The tsan_counter use here is safe since we're under lock */
262b077aed3SPierre Pronchery namenum->number =
263b077aed3SPierre Pronchery number != 0 ? number : 1 + tsan_counter(&namemap->max_number);
264b077aed3SPierre Pronchery (void)lh_NAMENUM_ENTRY_insert(namemap->namenum, namenum);
265b077aed3SPierre Pronchery
266b077aed3SPierre Pronchery if (lh_NAMENUM_ENTRY_error(namemap->namenum))
267b077aed3SPierre Pronchery goto err;
268b077aed3SPierre Pronchery return namenum->number;
269b077aed3SPierre Pronchery
270b077aed3SPierre Pronchery err:
271b077aed3SPierre Pronchery namenum_free(namenum);
272b077aed3SPierre Pronchery return 0;
273b077aed3SPierre Pronchery }
274b077aed3SPierre Pronchery
ossl_namemap_add_name_n(OSSL_NAMEMAP * namemap,int number,const char * name,size_t name_len)275b077aed3SPierre Pronchery int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
276b077aed3SPierre Pronchery const char *name, size_t name_len)
277b077aed3SPierre Pronchery {
278b077aed3SPierre Pronchery int tmp_number;
279b077aed3SPierre Pronchery
280b077aed3SPierre Pronchery #ifndef FIPS_MODULE
281b077aed3SPierre Pronchery if (namemap == NULL)
282b077aed3SPierre Pronchery namemap = ossl_namemap_stored(NULL);
283b077aed3SPierre Pronchery #endif
284b077aed3SPierre Pronchery
285b077aed3SPierre Pronchery if (name == NULL || name_len == 0 || namemap == NULL)
286b077aed3SPierre Pronchery return 0;
287b077aed3SPierre Pronchery
288b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(namemap->lock))
289b077aed3SPierre Pronchery return 0;
290b077aed3SPierre Pronchery tmp_number = namemap_add_name_n(namemap, number, name, name_len);
291b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(namemap->lock);
292b077aed3SPierre Pronchery return tmp_number;
293b077aed3SPierre Pronchery }
294b077aed3SPierre Pronchery
ossl_namemap_add_name(OSSL_NAMEMAP * namemap,int number,const char * name)295b077aed3SPierre Pronchery int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name)
296b077aed3SPierre Pronchery {
297b077aed3SPierre Pronchery if (name == NULL)
298b077aed3SPierre Pronchery return 0;
299b077aed3SPierre Pronchery
300b077aed3SPierre Pronchery return ossl_namemap_add_name_n(namemap, number, name, strlen(name));
301b077aed3SPierre Pronchery }
302b077aed3SPierre Pronchery
ossl_namemap_add_names(OSSL_NAMEMAP * namemap,int number,const char * names,const char separator)303b077aed3SPierre Pronchery int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
304b077aed3SPierre Pronchery const char *names, const char separator)
305b077aed3SPierre Pronchery {
306b077aed3SPierre Pronchery const char *p, *q;
307b077aed3SPierre Pronchery size_t l;
308b077aed3SPierre Pronchery
309b077aed3SPierre Pronchery /* Check that we have a namemap */
310b077aed3SPierre Pronchery if (!ossl_assert(namemap != NULL)) {
311b077aed3SPierre Pronchery ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
312b077aed3SPierre Pronchery return 0;
313b077aed3SPierre Pronchery }
314b077aed3SPierre Pronchery
315b077aed3SPierre Pronchery if (!CRYPTO_THREAD_write_lock(namemap->lock))
316b077aed3SPierre Pronchery return 0;
317b077aed3SPierre Pronchery /*
318b077aed3SPierre Pronchery * Check that no name is an empty string, and that all names have at
319b077aed3SPierre Pronchery * most one numeric identity together.
320b077aed3SPierre Pronchery */
321b077aed3SPierre Pronchery for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) {
322b077aed3SPierre Pronchery int this_number;
323b077aed3SPierre Pronchery
324b077aed3SPierre Pronchery if ((q = strchr(p, separator)) == NULL)
325b077aed3SPierre Pronchery l = strlen(p); /* offset to \0 */
326b077aed3SPierre Pronchery else
327b077aed3SPierre Pronchery l = q - p; /* offset to the next separator */
328b077aed3SPierre Pronchery
329b077aed3SPierre Pronchery this_number = namemap_name2num_n(namemap, p, l);
330b077aed3SPierre Pronchery
331b077aed3SPierre Pronchery if (*p == '\0' || *p == separator) {
332b077aed3SPierre Pronchery ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME);
333b077aed3SPierre Pronchery goto err;
334b077aed3SPierre Pronchery }
335b077aed3SPierre Pronchery if (number == 0) {
336b077aed3SPierre Pronchery number = this_number;
337b077aed3SPierre Pronchery } else if (this_number != 0 && this_number != number) {
338b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_CONFLICTING_NAMES,
339b077aed3SPierre Pronchery "\"%.*s\" has an existing different identity %d (from \"%s\")",
340b077aed3SPierre Pronchery l, p, this_number, names);
341b077aed3SPierre Pronchery goto err;
342b077aed3SPierre Pronchery }
343b077aed3SPierre Pronchery }
344b077aed3SPierre Pronchery
345b077aed3SPierre Pronchery /* Now that we have checked, register all names */
346b077aed3SPierre Pronchery for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) {
347b077aed3SPierre Pronchery int this_number;
348b077aed3SPierre Pronchery
349b077aed3SPierre Pronchery if ((q = strchr(p, separator)) == NULL)
350b077aed3SPierre Pronchery l = strlen(p); /* offset to \0 */
351b077aed3SPierre Pronchery else
352b077aed3SPierre Pronchery l = q - p; /* offset to the next separator */
353b077aed3SPierre Pronchery
354b077aed3SPierre Pronchery this_number = namemap_add_name_n(namemap, number, p, l);
355b077aed3SPierre Pronchery if (number == 0) {
356b077aed3SPierre Pronchery number = this_number;
357b077aed3SPierre Pronchery } else if (this_number != number) {
358b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
359b077aed3SPierre Pronchery "Got number %d when expecting %d",
360b077aed3SPierre Pronchery this_number, number);
361b077aed3SPierre Pronchery goto err;
362b077aed3SPierre Pronchery }
363b077aed3SPierre Pronchery }
364b077aed3SPierre Pronchery
365b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(namemap->lock);
366b077aed3SPierre Pronchery return number;
367b077aed3SPierre Pronchery
368b077aed3SPierre Pronchery err:
369b077aed3SPierre Pronchery CRYPTO_THREAD_unlock(namemap->lock);
370b077aed3SPierre Pronchery return 0;
371b077aed3SPierre Pronchery }
372b077aed3SPierre Pronchery
373b077aed3SPierre Pronchery /*-
374b077aed3SPierre Pronchery * Pre-population
375b077aed3SPierre Pronchery * ==============
376b077aed3SPierre Pronchery */
377b077aed3SPierre Pronchery
378b077aed3SPierre Pronchery #ifndef FIPS_MODULE
379b077aed3SPierre Pronchery #include <openssl/evp.h>
380b077aed3SPierre Pronchery
381b077aed3SPierre Pronchery /* Creates an initial namemap with names found in the legacy method db */
get_legacy_evp_names(int base_nid,int nid,const char * pem_name,void * arg)382b077aed3SPierre Pronchery static void get_legacy_evp_names(int base_nid, int nid, const char *pem_name,
383b077aed3SPierre Pronchery void *arg)
384b077aed3SPierre Pronchery {
385b077aed3SPierre Pronchery int num = 0;
386b077aed3SPierre Pronchery ASN1_OBJECT *obj;
387b077aed3SPierre Pronchery
388b077aed3SPierre Pronchery if (base_nid != NID_undef) {
389b077aed3SPierre Pronchery num = ossl_namemap_add_name(arg, num, OBJ_nid2sn(base_nid));
390b077aed3SPierre Pronchery num = ossl_namemap_add_name(arg, num, OBJ_nid2ln(base_nid));
391b077aed3SPierre Pronchery }
392b077aed3SPierre Pronchery
393b077aed3SPierre Pronchery if (nid != NID_undef) {
394b077aed3SPierre Pronchery num = ossl_namemap_add_name(arg, num, OBJ_nid2sn(nid));
395b077aed3SPierre Pronchery num = ossl_namemap_add_name(arg, num, OBJ_nid2ln(nid));
396b077aed3SPierre Pronchery if ((obj = OBJ_nid2obj(nid)) != NULL) {
397b077aed3SPierre Pronchery char txtoid[OSSL_MAX_NAME_SIZE];
398b077aed3SPierre Pronchery
399b077aed3SPierre Pronchery if (OBJ_obj2txt(txtoid, sizeof(txtoid), obj, 1) > 0)
400b077aed3SPierre Pronchery num = ossl_namemap_add_name(arg, num, txtoid);
401b077aed3SPierre Pronchery }
402b077aed3SPierre Pronchery }
403b077aed3SPierre Pronchery if (pem_name != NULL)
404b077aed3SPierre Pronchery num = ossl_namemap_add_name(arg, num, pem_name);
405b077aed3SPierre Pronchery }
406b077aed3SPierre Pronchery
get_legacy_cipher_names(const OBJ_NAME * on,void * arg)407b077aed3SPierre Pronchery static void get_legacy_cipher_names(const OBJ_NAME *on, void *arg)
408b077aed3SPierre Pronchery {
409b077aed3SPierre Pronchery const EVP_CIPHER *cipher = (void *)OBJ_NAME_get(on->name, on->type);
410b077aed3SPierre Pronchery
411b077aed3SPierre Pronchery if (cipher != NULL)
412b077aed3SPierre Pronchery get_legacy_evp_names(NID_undef, EVP_CIPHER_get_type(cipher), NULL, arg);
413b077aed3SPierre Pronchery }
414b077aed3SPierre Pronchery
get_legacy_md_names(const OBJ_NAME * on,void * arg)415b077aed3SPierre Pronchery static void get_legacy_md_names(const OBJ_NAME *on, void *arg)
416b077aed3SPierre Pronchery {
417b077aed3SPierre Pronchery const EVP_MD *md = (void *)OBJ_NAME_get(on->name, on->type);
418b077aed3SPierre Pronchery
419b077aed3SPierre Pronchery if (md != NULL)
420b077aed3SPierre Pronchery get_legacy_evp_names(0, EVP_MD_get_type(md), NULL, arg);
421b077aed3SPierre Pronchery }
422b077aed3SPierre Pronchery
get_legacy_pkey_meth_names(const EVP_PKEY_ASN1_METHOD * ameth,void * arg)423b077aed3SPierre Pronchery static void get_legacy_pkey_meth_names(const EVP_PKEY_ASN1_METHOD *ameth,
424b077aed3SPierre Pronchery void *arg)
425b077aed3SPierre Pronchery {
426b077aed3SPierre Pronchery int nid = 0, base_nid = 0, flags = 0;
427b077aed3SPierre Pronchery const char *pem_name = NULL;
428b077aed3SPierre Pronchery
429b077aed3SPierre Pronchery EVP_PKEY_asn1_get0_info(&nid, &base_nid, &flags, NULL, &pem_name, ameth);
430b077aed3SPierre Pronchery if (nid != NID_undef) {
431b077aed3SPierre Pronchery if ((flags & ASN1_PKEY_ALIAS) == 0) {
432b077aed3SPierre Pronchery switch (nid) {
433b077aed3SPierre Pronchery case EVP_PKEY_DHX:
434b077aed3SPierre Pronchery /* We know that the name "DHX" is used too */
435b077aed3SPierre Pronchery get_legacy_evp_names(0, nid, "DHX", arg);
436b077aed3SPierre Pronchery /* FALLTHRU */
437b077aed3SPierre Pronchery default:
438b077aed3SPierre Pronchery get_legacy_evp_names(0, nid, pem_name, arg);
439b077aed3SPierre Pronchery }
440b077aed3SPierre Pronchery } else {
441b077aed3SPierre Pronchery /*
442b077aed3SPierre Pronchery * Treat aliases carefully, some of them are undesirable, or
443b077aed3SPierre Pronchery * should not be treated as such for providers.
444b077aed3SPierre Pronchery */
445b077aed3SPierre Pronchery
446b077aed3SPierre Pronchery switch (nid) {
447b077aed3SPierre Pronchery case EVP_PKEY_SM2:
448b077aed3SPierre Pronchery /*
449b077aed3SPierre Pronchery * SM2 is a separate keytype with providers, not an alias for
450b077aed3SPierre Pronchery * EC.
451b077aed3SPierre Pronchery */
452b077aed3SPierre Pronchery get_legacy_evp_names(0, nid, pem_name, arg);
453b077aed3SPierre Pronchery break;
454b077aed3SPierre Pronchery default:
455b077aed3SPierre Pronchery /* Use the short name of the base nid as the common reference */
456b077aed3SPierre Pronchery get_legacy_evp_names(base_nid, nid, pem_name, arg);
457b077aed3SPierre Pronchery }
458b077aed3SPierre Pronchery }
459b077aed3SPierre Pronchery }
460b077aed3SPierre Pronchery }
461b077aed3SPierre Pronchery #endif
462b077aed3SPierre Pronchery
463b077aed3SPierre Pronchery /*-
464b077aed3SPierre Pronchery * Constructors / destructors
465b077aed3SPierre Pronchery * ==========================
466b077aed3SPierre Pronchery */
467b077aed3SPierre Pronchery
ossl_namemap_stored(OSSL_LIB_CTX * libctx)468b077aed3SPierre Pronchery OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx)
469b077aed3SPierre Pronchery {
470b077aed3SPierre Pronchery #ifndef FIPS_MODULE
471b077aed3SPierre Pronchery int nms;
472b077aed3SPierre Pronchery #endif
473b077aed3SPierre Pronchery OSSL_NAMEMAP *namemap =
474b077aed3SPierre Pronchery ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_NAMEMAP_INDEX,
475b077aed3SPierre Pronchery &stored_namemap_method);
476b077aed3SPierre Pronchery
477b077aed3SPierre Pronchery if (namemap == NULL)
478b077aed3SPierre Pronchery return NULL;
479b077aed3SPierre Pronchery
480b077aed3SPierre Pronchery #ifndef FIPS_MODULE
481b077aed3SPierre Pronchery nms = ossl_namemap_empty(namemap);
482b077aed3SPierre Pronchery if (nms < 0) {
483b077aed3SPierre Pronchery /*
484b077aed3SPierre Pronchery * Could not get lock to make the count, so maybe internal objects
485b077aed3SPierre Pronchery * weren't added. This seems safest.
486b077aed3SPierre Pronchery */
487b077aed3SPierre Pronchery return NULL;
488b077aed3SPierre Pronchery }
489b077aed3SPierre Pronchery if (nms == 1) {
490b077aed3SPierre Pronchery int i, end;
491b077aed3SPierre Pronchery
492b077aed3SPierre Pronchery /* Before pilfering, we make sure the legacy database is populated */
493b077aed3SPierre Pronchery OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
494b077aed3SPierre Pronchery | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
495b077aed3SPierre Pronchery
496b077aed3SPierre Pronchery OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH,
497b077aed3SPierre Pronchery get_legacy_cipher_names, namemap);
498b077aed3SPierre Pronchery OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH,
499b077aed3SPierre Pronchery get_legacy_md_names, namemap);
500b077aed3SPierre Pronchery
501b077aed3SPierre Pronchery /* We also pilfer data from the legacy EVP_PKEY_ASN1_METHODs */
502b077aed3SPierre Pronchery for (i = 0, end = EVP_PKEY_asn1_get_count(); i < end; i++)
503b077aed3SPierre Pronchery get_legacy_pkey_meth_names(EVP_PKEY_asn1_get0(i), namemap);
504b077aed3SPierre Pronchery }
505b077aed3SPierre Pronchery #endif
506b077aed3SPierre Pronchery
507b077aed3SPierre Pronchery return namemap;
508b077aed3SPierre Pronchery }
509b077aed3SPierre Pronchery
ossl_namemap_new(void)510b077aed3SPierre Pronchery OSSL_NAMEMAP *ossl_namemap_new(void)
511b077aed3SPierre Pronchery {
512b077aed3SPierre Pronchery OSSL_NAMEMAP *namemap;
513b077aed3SPierre Pronchery
514b077aed3SPierre Pronchery if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) != NULL
515b077aed3SPierre Pronchery && (namemap->lock = CRYPTO_THREAD_lock_new()) != NULL
516b077aed3SPierre Pronchery && (namemap->namenum =
517b077aed3SPierre Pronchery lh_NAMENUM_ENTRY_new(namenum_hash, namenum_cmp)) != NULL)
518b077aed3SPierre Pronchery return namemap;
519b077aed3SPierre Pronchery
520b077aed3SPierre Pronchery ossl_namemap_free(namemap);
521b077aed3SPierre Pronchery return NULL;
522b077aed3SPierre Pronchery }
523b077aed3SPierre Pronchery
ossl_namemap_free(OSSL_NAMEMAP * namemap)524b077aed3SPierre Pronchery void ossl_namemap_free(OSSL_NAMEMAP *namemap)
525b077aed3SPierre Pronchery {
526b077aed3SPierre Pronchery if (namemap == NULL || namemap->stored)
527b077aed3SPierre Pronchery return;
528b077aed3SPierre Pronchery
529b077aed3SPierre Pronchery lh_NAMENUM_ENTRY_doall(namemap->namenum, namenum_free);
530b077aed3SPierre Pronchery lh_NAMENUM_ENTRY_free(namemap->namenum);
531b077aed3SPierre Pronchery
532b077aed3SPierre Pronchery CRYPTO_THREAD_lock_free(namemap->lock);
533b077aed3SPierre Pronchery OPENSSL_free(namemap);
534b077aed3SPierre Pronchery }
535