xref: /openssl/crypto/evp/names.c (revision 7ed6de99)
1 /*
2  * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (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
8  */
9 
10 #include <stdio.h>
11 #include <openssl/evp.h>
12 #include <openssl/kdf.h>
13 #include <openssl/x509.h>
14 #include "internal/cryptlib.h"
15 #include "internal/namemap.h"
16 #include "crypto/objects.h"
17 #include "crypto/evp.h"
18 
EVP_add_cipher(const EVP_CIPHER * c)19 int EVP_add_cipher(const EVP_CIPHER *c)
20 {
21     int r;
22 
23     if (c == NULL)
24         return 0;
25 
26     r = OBJ_NAME_add(OBJ_nid2sn(c->nid), OBJ_NAME_TYPE_CIPHER_METH,
27                      (const char *)c);
28     if (r == 0)
29         return 0;
30     r = OBJ_NAME_add(OBJ_nid2ln(c->nid), OBJ_NAME_TYPE_CIPHER_METH,
31                      (const char *)c);
32     return r;
33 }
34 
EVP_add_digest(const EVP_MD * md)35 int EVP_add_digest(const EVP_MD *md)
36 {
37     int r;
38     const char *name;
39 
40     name = OBJ_nid2sn(md->type);
41     r = OBJ_NAME_add(name, OBJ_NAME_TYPE_MD_METH, (const char *)md);
42     if (r == 0)
43         return 0;
44     r = OBJ_NAME_add(OBJ_nid2ln(md->type), OBJ_NAME_TYPE_MD_METH,
45                      (const char *)md);
46     if (r == 0)
47         return 0;
48 
49     if (md->pkey_type && md->type != md->pkey_type) {
50         r = OBJ_NAME_add(OBJ_nid2sn(md->pkey_type),
51                          OBJ_NAME_TYPE_MD_METH | OBJ_NAME_ALIAS, name);
52         if (r == 0)
53             return 0;
54         r = OBJ_NAME_add(OBJ_nid2ln(md->pkey_type),
55                          OBJ_NAME_TYPE_MD_METH | OBJ_NAME_ALIAS, name);
56     }
57     return r;
58 }
59 
cipher_from_name(const char * name,void * data)60 static void cipher_from_name(const char *name, void *data)
61 {
62     const EVP_CIPHER **cipher = data;
63 
64     if (*cipher != NULL)
65         return;
66 
67     *cipher = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
68 }
69 
EVP_get_cipherbyname(const char * name)70 const EVP_CIPHER *EVP_get_cipherbyname(const char *name)
71 {
72     return evp_get_cipherbyname_ex(NULL, name);
73 }
74 
evp_get_cipherbyname_ex(OSSL_LIB_CTX * libctx,const char * name)75 const EVP_CIPHER *evp_get_cipherbyname_ex(OSSL_LIB_CTX *libctx,
76                                           const char *name)
77 {
78     const EVP_CIPHER *cp;
79     OSSL_NAMEMAP *namemap;
80     int id;
81     int do_retry = 1;
82 
83     if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL))
84         return NULL;
85 
86     cp = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
87 
88     if (cp != NULL)
89         return cp;
90 
91     /*
92      * It's not in the method database, but it might be there under a different
93      * name. So we check for aliases in the EVP namemap and try all of those
94      * in turn.
95      */
96 
97     namemap = ossl_namemap_stored(libctx);
98  retry:
99     id = ossl_namemap_name2num(namemap, name);
100     if (id == 0) {
101         EVP_CIPHER *fetched_cipher;
102 
103         /* Try to fetch it because the name might not be known yet. */
104         if (!do_retry)
105             return NULL;
106         do_retry = 0;
107         ERR_set_mark();
108         fetched_cipher = EVP_CIPHER_fetch(libctx, name, NULL);
109         EVP_CIPHER_free(fetched_cipher);
110         ERR_pop_to_mark();
111         goto retry;
112     }
113 
114     if (!ossl_namemap_doall_names(namemap, id, cipher_from_name, &cp))
115         return NULL;
116 
117     return cp;
118 }
119 
digest_from_name(const char * name,void * data)120 static void digest_from_name(const char *name, void *data)
121 {
122     const EVP_MD **md = data;
123 
124     if (*md != NULL)
125         return;
126 
127     *md = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
128 }
129 
EVP_get_digestbyname(const char * name)130 const EVP_MD *EVP_get_digestbyname(const char *name)
131 {
132     return evp_get_digestbyname_ex(NULL, name);
133 }
134 
evp_get_digestbyname_ex(OSSL_LIB_CTX * libctx,const char * name)135 const EVP_MD *evp_get_digestbyname_ex(OSSL_LIB_CTX *libctx, const char *name)
136 {
137     const EVP_MD *dp;
138     OSSL_NAMEMAP *namemap;
139     int id;
140     int do_retry = 1;
141 
142     if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL))
143         return NULL;
144 
145     dp = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
146 
147     if (dp != NULL)
148         return dp;
149 
150     /*
151      * It's not in the method database, but it might be there under a different
152      * name. So we check for aliases in the EVP namemap and try all of those
153      * in turn.
154      */
155 
156     namemap = ossl_namemap_stored(libctx);
157  retry:
158     id = ossl_namemap_name2num(namemap, name);
159     if (id == 0) {
160         EVP_MD *fetched_md;
161 
162         /* Try to fetch it because the name might not be known yet. */
163         if (!do_retry)
164             return NULL;
165         do_retry = 0;
166         ERR_set_mark();
167         fetched_md = EVP_MD_fetch(libctx, name, NULL);
168         EVP_MD_free(fetched_md);
169         ERR_pop_to_mark();
170         goto retry;
171     }
172 
173     if (!ossl_namemap_doall_names(namemap, id, digest_from_name, &dp))
174         return NULL;
175 
176     return dp;
177 }
178 
evp_cleanup_int(void)179 void evp_cleanup_int(void)
180 {
181     OBJ_NAME_cleanup(OBJ_NAME_TYPE_KDF_METH);
182     OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH);
183     OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH);
184     /*
185      * The above calls will only clean out the contents of the name hash
186      * table, but not the hash table itself.  The following line does that
187      * part.  -- Richard Levitte
188      */
189     OBJ_NAME_cleanup(-1);
190 
191     EVP_PBE_cleanup();
192     OBJ_sigid_free();
193 
194     evp_app_cleanup_int();
195 }
196 
197 struct doall_cipher {
198     void *arg;
199     void (*fn) (const EVP_CIPHER *ciph,
200                 const char *from, const char *to, void *arg);
201 };
202 
do_all_cipher_fn(const OBJ_NAME * nm,void * arg)203 static void do_all_cipher_fn(const OBJ_NAME *nm, void *arg)
204 {
205     struct doall_cipher *dc = arg;
206     if (nm->alias)
207         dc->fn(NULL, nm->name, nm->data, dc->arg);
208     else
209         dc->fn((const EVP_CIPHER *)nm->data, nm->name, NULL, dc->arg);
210 }
211 
EVP_CIPHER_do_all(void (* fn)(const EVP_CIPHER * ciph,const char * from,const char * to,void * x),void * arg)212 void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph,
213                                    const char *from, const char *to, void *x),
214                        void *arg)
215 {
216     struct doall_cipher dc;
217 
218     /* Ignore errors */
219     OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL);
220 
221     dc.fn = fn;
222     dc.arg = arg;
223     OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc);
224 }
225 
EVP_CIPHER_do_all_sorted(void (* fn)(const EVP_CIPHER * ciph,const char * from,const char * to,void * x),void * arg)226 void EVP_CIPHER_do_all_sorted(void (*fn) (const EVP_CIPHER *ciph,
227                                           const char *from, const char *to,
228                                           void *x), void *arg)
229 {
230     struct doall_cipher dc;
231 
232     /* Ignore errors */
233     OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL);
234 
235     dc.fn = fn;
236     dc.arg = arg;
237     OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc);
238 }
239 
240 struct doall_md {
241     void *arg;
242     void (*fn) (const EVP_MD *ciph,
243                 const char *from, const char *to, void *arg);
244 };
245 
do_all_md_fn(const OBJ_NAME * nm,void * arg)246 static void do_all_md_fn(const OBJ_NAME *nm, void *arg)
247 {
248     struct doall_md *dc = arg;
249     if (nm->alias)
250         dc->fn(NULL, nm->name, nm->data, dc->arg);
251     else
252         dc->fn((const EVP_MD *)nm->data, nm->name, NULL, dc->arg);
253 }
254 
EVP_MD_do_all(void (* fn)(const EVP_MD * md,const char * from,const char * to,void * x),void * arg)255 void EVP_MD_do_all(void (*fn) (const EVP_MD *md,
256                                const char *from, const char *to, void *x),
257                    void *arg)
258 {
259     struct doall_md dc;
260 
261     /* Ignore errors */
262     OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
263 
264     dc.fn = fn;
265     dc.arg = arg;
266     OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
267 }
268 
EVP_MD_do_all_sorted(void (* fn)(const EVP_MD * md,const char * from,const char * to,void * x),void * arg)269 void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md,
270                                       const char *from, const char *to,
271                                       void *x), void *arg)
272 {
273     struct doall_md dc;
274 
275     OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
276 
277     dc.fn = fn;
278     dc.arg = arg;
279     OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
280 }
281