1 /* $OpenBSD: ameth_lib.c,v 1.26 2022/06/27 12:36:05 tb Exp $ */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project 2006. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59 #include <stdio.h> 60 #include <string.h> 61 62 #include <openssl/opensslconf.h> 63 64 #include <openssl/asn1t.h> 65 #include <openssl/x509.h> 66 67 #ifndef OPENSSL_NO_ENGINE 68 #include <openssl/engine.h> 69 #endif 70 71 #include "asn1_locl.h" 72 #include "evp_locl.h" 73 74 extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[]; 75 extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth; 76 extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[]; 77 extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth; 78 extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth; 79 extern const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[]; 80 extern const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth; 81 extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth; 82 extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth; 83 84 /* Keep this sorted in type order !! */ 85 static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { 86 #ifndef OPENSSL_NO_RSA 87 &rsa_asn1_meths[0], 88 &rsa_asn1_meths[1], 89 #endif 90 #ifndef OPENSSL_NO_DH 91 &dh_asn1_meth, 92 #endif 93 #ifndef OPENSSL_NO_DSA 94 &dsa_asn1_meths[0], 95 &dsa_asn1_meths[1], 96 &dsa_asn1_meths[2], 97 &dsa_asn1_meths[3], 98 &dsa_asn1_meths[4], 99 #endif 100 #ifndef OPENSSL_NO_EC 101 &eckey_asn1_meth, 102 #endif 103 #ifndef OPENSSL_NO_GOST 104 &gostr01_asn1_meths[0], 105 &gostimit_asn1_meth, 106 #endif 107 &hmac_asn1_meth, 108 &cmac_asn1_meth, 109 #ifndef OPENSSL_NO_RSA 110 &rsa_pss_asn1_meth, 111 #endif 112 #ifndef OPENSSL_NO_GOST 113 &gostr01_asn1_meths[1], 114 &gostr01_asn1_meths[2], 115 #endif 116 }; 117 118 typedef int sk_cmp_fn_type(const char * const *a, const char * const *b); 119 DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD) 120 static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL; 121 122 static int ameth_cmp_BSEARCH_CMP_FN(const void *, const void *); 123 static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *, const EVP_PKEY_ASN1_METHOD * const *); 124 static const EVP_PKEY_ASN1_METHOD * *OBJ_bsearch_ameth(const EVP_PKEY_ASN1_METHOD * *key, const EVP_PKEY_ASN1_METHOD * const *base, int num); 125 126 static int 127 ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a, 128 const EVP_PKEY_ASN1_METHOD * const *b) 129 { 130 return ((*a)->pkey_id - (*b)->pkey_id); 131 } 132 133 134 static int 135 ameth_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) 136 { 137 const EVP_PKEY_ASN1_METHOD * const *a = a_; 138 const EVP_PKEY_ASN1_METHOD * const *b = b_; 139 return ameth_cmp(a, b); 140 } 141 142 static const EVP_PKEY_ASN1_METHOD * * 143 OBJ_bsearch_ameth(const EVP_PKEY_ASN1_METHOD * *key, const EVP_PKEY_ASN1_METHOD * const *base, int num) 144 { 145 return (const EVP_PKEY_ASN1_METHOD * *)OBJ_bsearch_(key, base, num, sizeof(const EVP_PKEY_ASN1_METHOD *), 146 ameth_cmp_BSEARCH_CMP_FN); 147 } 148 149 int 150 EVP_PKEY_asn1_get_count(void) 151 { 152 int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *); 153 if (app_methods) 154 num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods); 155 return num; 156 } 157 158 const EVP_PKEY_ASN1_METHOD * 159 EVP_PKEY_asn1_get0(int idx) 160 { 161 int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *); 162 if (idx < 0) 163 return NULL; 164 if (idx < num) 165 return standard_methods[idx]; 166 idx -= num; 167 return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); 168 } 169 170 static const EVP_PKEY_ASN1_METHOD * 171 pkey_asn1_find(int type) 172 { 173 EVP_PKEY_ASN1_METHOD tmp; 174 const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret; 175 tmp.pkey_id = type; 176 if (app_methods) { 177 int idx; 178 idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp); 179 if (idx >= 0) 180 return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); 181 } 182 ret = OBJ_bsearch_ameth(&t, standard_methods, 183 sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *)); 184 if (!ret || !*ret) 185 return NULL; 186 return *ret; 187 } 188 189 /* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL 190 * also search through engines and set *pe to a functional reference 191 * to the engine implementing 'type' or NULL if no engine implements 192 * it. 193 */ 194 195 const EVP_PKEY_ASN1_METHOD * 196 EVP_PKEY_asn1_find(ENGINE **pe, int type) 197 { 198 const EVP_PKEY_ASN1_METHOD *t; 199 200 for (;;) { 201 t = pkey_asn1_find(type); 202 if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS)) 203 break; 204 type = t->pkey_base_id; 205 } 206 if (pe) { 207 #ifndef OPENSSL_NO_ENGINE 208 ENGINE *e; 209 /* type will contain the final unaliased type */ 210 e = ENGINE_get_pkey_asn1_meth_engine(type); 211 if (e) { 212 *pe = e; 213 return ENGINE_get_pkey_asn1_meth(e, type); 214 } 215 #endif 216 *pe = NULL; 217 } 218 return t; 219 } 220 221 const EVP_PKEY_ASN1_METHOD * 222 EVP_PKEY_asn1_find_str(ENGINE **pe, const char *str, int len) 223 { 224 int i; 225 const EVP_PKEY_ASN1_METHOD *ameth; 226 if (len == -1) 227 len = strlen(str); 228 if (pe) { 229 #ifndef OPENSSL_NO_ENGINE 230 ENGINE *e; 231 ameth = ENGINE_pkey_asn1_find_str(&e, str, len); 232 if (ameth) { 233 /* Convert structural into 234 * functional reference 235 */ 236 if (!ENGINE_init(e)) 237 ameth = NULL; 238 ENGINE_free(e); 239 *pe = e; 240 return ameth; 241 } 242 #endif 243 *pe = NULL; 244 } 245 for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { 246 ameth = EVP_PKEY_asn1_get0(i); 247 if (ameth->pkey_flags & ASN1_PKEY_ALIAS) 248 continue; 249 if (((int)strlen(ameth->pem_str) == len) && 250 !strncasecmp(ameth->pem_str, str, len)) 251 return ameth; 252 } 253 return NULL; 254 } 255 256 int 257 EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth) 258 { 259 if (app_methods == NULL) { 260 app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp); 261 if (!app_methods) 262 return 0; 263 } 264 if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth)) 265 return 0; 266 sk_EVP_PKEY_ASN1_METHOD_sort(app_methods); 267 return 1; 268 } 269 270 int 271 EVP_PKEY_asn1_add_alias(int to, int from) 272 { 273 EVP_PKEY_ASN1_METHOD *ameth; 274 275 ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL); 276 if (!ameth) 277 return 0; 278 ameth->pkey_base_id = to; 279 if (!EVP_PKEY_asn1_add0(ameth)) { 280 EVP_PKEY_asn1_free(ameth); 281 return 0; 282 } 283 return 1; 284 } 285 286 int 287 EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags, 288 const char **pinfo, const char **ppem_str, 289 const EVP_PKEY_ASN1_METHOD *ameth) 290 { 291 if (!ameth) 292 return 0; 293 if (ppkey_id) 294 *ppkey_id = ameth->pkey_id; 295 if (ppkey_base_id) 296 *ppkey_base_id = ameth->pkey_base_id; 297 if (ppkey_flags) 298 *ppkey_flags = ameth->pkey_flags; 299 if (pinfo) 300 *pinfo = ameth->info; 301 if (ppem_str) 302 *ppem_str = ameth->pem_str; 303 return 1; 304 } 305 306 const EVP_PKEY_ASN1_METHOD* 307 EVP_PKEY_get0_asn1(const EVP_PKEY *pkey) 308 { 309 return pkey->ameth; 310 } 311 312 EVP_PKEY_ASN1_METHOD* 313 EVP_PKEY_asn1_new(int id, int flags, const char *pem_str, const char *info) 314 { 315 EVP_PKEY_ASN1_METHOD *ameth; 316 317 if ((ameth = calloc(1, sizeof(EVP_PKEY_ASN1_METHOD))) == NULL) 318 return NULL; 319 320 ameth->pkey_id = id; 321 ameth->pkey_base_id = id; 322 ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC; 323 324 if (info != NULL) { 325 if ((ameth->info = strdup(info)) == NULL) 326 goto err; 327 } 328 329 if (pem_str != NULL) { 330 if ((ameth->pem_str = strdup(pem_str)) == NULL) 331 goto err; 332 } 333 334 return ameth; 335 336 err: 337 EVP_PKEY_asn1_free(ameth); 338 return NULL; 339 } 340 341 void 342 EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, const EVP_PKEY_ASN1_METHOD *src) 343 { 344 EVP_PKEY_ASN1_METHOD preserve; 345 346 preserve.pkey_id = dst->pkey_id; 347 preserve.pkey_base_id = dst->pkey_base_id; 348 preserve.pkey_flags = dst->pkey_flags; 349 preserve.pem_str = dst->pem_str; 350 preserve.info = dst->info; 351 352 *dst = *src; 353 354 dst->pkey_id = preserve.pkey_id; 355 dst->pkey_base_id = preserve.pkey_base_id; 356 dst->pkey_flags = preserve.pkey_flags; 357 dst->pem_str = preserve.pem_str; 358 dst->info = preserve.info; 359 } 360 361 void 362 EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth) 363 { 364 if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) { 365 free(ameth->pem_str); 366 free(ameth->info); 367 free(ameth); 368 } 369 } 370 371 void 372 EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth, 373 int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub), 374 int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk), 375 int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b), 376 int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, 377 ASN1_PCTX *pctx), 378 int (*pkey_size)(const EVP_PKEY *pk), 379 int (*pkey_bits)(const EVP_PKEY *pk)) 380 { 381 ameth->pub_decode = pub_decode; 382 ameth->pub_encode = pub_encode; 383 ameth->pub_cmp = pub_cmp; 384 ameth->pub_print = pub_print; 385 ameth->pkey_size = pkey_size; 386 ameth->pkey_bits = pkey_bits; 387 } 388 389 void 390 EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth, 391 int (*priv_decode)(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf), 392 int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk), 393 int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent, 394 ASN1_PCTX *pctx)) 395 { 396 ameth->priv_decode = priv_decode; 397 ameth->priv_encode = priv_encode; 398 ameth->priv_print = priv_print; 399 } 400 401 void 402 EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth, 403 int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder, int derlen), 404 int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder), 405 int (*param_missing)(const EVP_PKEY *pk), 406 int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from), 407 int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b), 408 int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent, 409 ASN1_PCTX *pctx)) 410 { 411 ameth->param_decode = param_decode; 412 ameth->param_encode = param_encode; 413 ameth->param_missing = param_missing; 414 ameth->param_copy = param_copy; 415 ameth->param_cmp = param_cmp; 416 ameth->param_print = param_print; 417 } 418 419 void 420 EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth, 421 void (*pkey_free)(EVP_PKEY *pkey)) 422 { 423 ameth->pkey_free = pkey_free; 424 } 425 426 void 427 EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, 428 int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2)) 429 { 430 ameth->pkey_ctrl = pkey_ctrl; 431 } 432 433 void 434 EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, 435 int (*pkey_security_bits)(const EVP_PKEY *pkey)) 436 { 437 ameth->pkey_security_bits = pkey_security_bits; 438 } 439 440 void 441 EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth, 442 int (*pkey_check)(const EVP_PKEY *pk)) 443 { 444 ameth->pkey_check = pkey_check; 445 } 446 447 void 448 EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth, 449 int (*pkey_public_check)(const EVP_PKEY *pk)) 450 { 451 ameth->pkey_public_check = pkey_public_check; 452 } 453 454 void 455 EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth, 456 int (*pkey_param_check)(const EVP_PKEY *pk)) 457 { 458 ameth->pkey_param_check = pkey_param_check; 459 } 460