1 /* 2 * Copyright 1995-2021 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 82 if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL)) 83 return NULL; 84 85 cp = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH); 86 87 if (cp != NULL) 88 return cp; 89 90 /* 91 * It's not in the method database, but it might be there under a different 92 * name. So we check for aliases in the EVP namemap and try all of those 93 * in turn. 94 */ 95 96 namemap = ossl_namemap_stored(libctx); 97 id = ossl_namemap_name2num(namemap, name); 98 if (id == 0) 99 return NULL; 100 101 if (!ossl_namemap_doall_names(namemap, id, cipher_from_name, &cp)) 102 return NULL; 103 104 return cp; 105 } 106 107 static void digest_from_name(const char *name, void *data) 108 { 109 const EVP_MD **md = data; 110 111 if (*md != NULL) 112 return; 113 114 *md = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH); 115 } 116 117 const EVP_MD *EVP_get_digestbyname(const char *name) 118 { 119 return evp_get_digestbyname_ex(NULL, name); 120 } 121 122 const EVP_MD *evp_get_digestbyname_ex(OSSL_LIB_CTX *libctx, const char *name) 123 { 124 const EVP_MD *dp; 125 OSSL_NAMEMAP *namemap; 126 int id; 127 128 if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)) 129 return NULL; 130 131 dp = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH); 132 133 if (dp != NULL) 134 return dp; 135 136 /* 137 * It's not in the method database, but it might be there under a different 138 * name. So we check for aliases in the EVP namemap and try all of those 139 * in turn. 140 */ 141 142 namemap = ossl_namemap_stored(libctx); 143 id = ossl_namemap_name2num(namemap, name); 144 if (id == 0) 145 return NULL; 146 147 if (!ossl_namemap_doall_names(namemap, id, digest_from_name, &dp)) 148 return NULL; 149 150 return dp; 151 } 152 153 void evp_cleanup_int(void) 154 { 155 OBJ_NAME_cleanup(OBJ_NAME_TYPE_KDF_METH); 156 OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH); 157 OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH); 158 /* 159 * The above calls will only clean out the contents of the name hash 160 * table, but not the hash table itself. The following line does that 161 * part. -- Richard Levitte 162 */ 163 OBJ_NAME_cleanup(-1); 164 165 EVP_PBE_cleanup(); 166 OBJ_sigid_free(); 167 168 evp_app_cleanup_int(); 169 } 170 171 struct doall_cipher { 172 void *arg; 173 void (*fn) (const EVP_CIPHER *ciph, 174 const char *from, const char *to, void *arg); 175 }; 176 177 static void do_all_cipher_fn(const OBJ_NAME *nm, void *arg) 178 { 179 struct doall_cipher *dc = arg; 180 if (nm->alias) 181 dc->fn(NULL, nm->name, nm->data, dc->arg); 182 else 183 dc->fn((const EVP_CIPHER *)nm->data, nm->name, NULL, dc->arg); 184 } 185 186 void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph, 187 const char *from, const char *to, void *x), 188 void *arg) 189 { 190 struct doall_cipher dc; 191 192 /* Ignore errors */ 193 OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL); 194 195 dc.fn = fn; 196 dc.arg = arg; 197 OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc); 198 } 199 200 void EVP_CIPHER_do_all_sorted(void (*fn) (const EVP_CIPHER *ciph, 201 const char *from, const char *to, 202 void *x), void *arg) 203 { 204 struct doall_cipher dc; 205 206 /* Ignore errors */ 207 OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL); 208 209 dc.fn = fn; 210 dc.arg = arg; 211 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc); 212 } 213 214 struct doall_md { 215 void *arg; 216 void (*fn) (const EVP_MD *ciph, 217 const char *from, const char *to, void *arg); 218 }; 219 220 static void do_all_md_fn(const OBJ_NAME *nm, void *arg) 221 { 222 struct doall_md *dc = arg; 223 if (nm->alias) 224 dc->fn(NULL, nm->name, nm->data, dc->arg); 225 else 226 dc->fn((const EVP_MD *)nm->data, nm->name, NULL, dc->arg); 227 } 228 229 void EVP_MD_do_all(void (*fn) (const EVP_MD *md, 230 const char *from, const char *to, void *x), 231 void *arg) 232 { 233 struct doall_md dc; 234 235 /* Ignore errors */ 236 OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); 237 238 dc.fn = fn; 239 dc.arg = arg; 240 OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc); 241 } 242 243 void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md, 244 const char *from, const char *to, 245 void *x), void *arg) 246 { 247 struct doall_md dc; 248 249 OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); 250 251 dc.fn = fn; 252 dc.arg = arg; 253 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc); 254 } 255