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 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 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 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 70 const EVP_CIPHER *EVP_get_cipherbyname(const char *name) 71 { 72 return evp_get_cipherbyname_ex(NULL, name); 73 } 74 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 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 130 const EVP_MD *EVP_get_digestbyname(const char *name) 131 { 132 return evp_get_digestbyname_ex(NULL, name); 133 } 134 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 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 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 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 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 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 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 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