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