1 /* $OpenBSD: ameth_lib.c,v 1.19 2018/08/24 20:22:15 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 73 extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[]; 74 extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[]; 75 extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth; 76 extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth; 77 extern const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[]; 78 extern const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth; 79 extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth; 80 extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth; 81 82 /* Keep this sorted in type order !! */ 83 static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { 84 #ifndef OPENSSL_NO_RSA 85 &rsa_asn1_meths[0], 86 &rsa_asn1_meths[1], 87 #endif 88 #ifndef OPENSSL_NO_DH 89 &dh_asn1_meth, 90 #endif 91 #ifndef OPENSSL_NO_DSA 92 &dsa_asn1_meths[0], 93 &dsa_asn1_meths[1], 94 &dsa_asn1_meths[2], 95 &dsa_asn1_meths[3], 96 &dsa_asn1_meths[4], 97 #endif 98 #ifndef OPENSSL_NO_EC 99 &eckey_asn1_meth, 100 #endif 101 #ifndef OPENSSL_NO_GOST 102 &gostr01_asn1_meths[0], 103 &gostimit_asn1_meth, 104 #endif 105 &hmac_asn1_meth, 106 &cmac_asn1_meth, 107 #ifndef OPENSSL_NO_GOST 108 &gostr01_asn1_meths[1], 109 &gostr01_asn1_meths[2], 110 #endif 111 }; 112 113 typedef int sk_cmp_fn_type(const char * const *a, const char * const *b); 114 DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD) 115 static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL; 116 117 static int ameth_cmp_BSEARCH_CMP_FN(const void *, const void *); 118 static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *, const EVP_PKEY_ASN1_METHOD * const *); 119 static const EVP_PKEY_ASN1_METHOD * *OBJ_bsearch_ameth(const EVP_PKEY_ASN1_METHOD * *key, const EVP_PKEY_ASN1_METHOD * const *base, int num); 120 121 static int 122 ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a, 123 const EVP_PKEY_ASN1_METHOD * const *b) 124 { 125 return ((*a)->pkey_id - (*b)->pkey_id); 126 } 127 128 129 static int 130 ameth_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) 131 { 132 const EVP_PKEY_ASN1_METHOD * const *a = a_; 133 const EVP_PKEY_ASN1_METHOD * const *b = b_; 134 return ameth_cmp(a, b); 135 } 136 137 static const EVP_PKEY_ASN1_METHOD * * 138 OBJ_bsearch_ameth(const EVP_PKEY_ASN1_METHOD * *key, const EVP_PKEY_ASN1_METHOD * const *base, int num) 139 { 140 return (const EVP_PKEY_ASN1_METHOD * *)OBJ_bsearch_(key, base, num, sizeof(const EVP_PKEY_ASN1_METHOD *), 141 ameth_cmp_BSEARCH_CMP_FN); 142 } 143 144 int 145 EVP_PKEY_asn1_get_count(void) 146 { 147 int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *); 148 if (app_methods) 149 num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods); 150 return num; 151 } 152 153 const EVP_PKEY_ASN1_METHOD * 154 EVP_PKEY_asn1_get0(int idx) 155 { 156 int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *); 157 if (idx < 0) 158 return NULL; 159 if (idx < num) 160 return standard_methods[idx]; 161 idx -= num; 162 return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); 163 } 164 165 static const EVP_PKEY_ASN1_METHOD * 166 pkey_asn1_find(int type) 167 { 168 EVP_PKEY_ASN1_METHOD tmp; 169 const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret; 170 tmp.pkey_id = type; 171 if (app_methods) { 172 int idx; 173 idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp); 174 if (idx >= 0) 175 return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); 176 } 177 ret = OBJ_bsearch_ameth(&t, standard_methods, 178 sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *)); 179 if (!ret || !*ret) 180 return NULL; 181 return *ret; 182 } 183 184 /* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL 185 * also search through engines and set *pe to a functional reference 186 * to the engine implementing 'type' or NULL if no engine implements 187 * it. 188 */ 189 190 const EVP_PKEY_ASN1_METHOD * 191 EVP_PKEY_asn1_find(ENGINE **pe, int type) 192 { 193 const EVP_PKEY_ASN1_METHOD *t; 194 195 for (;;) { 196 t = pkey_asn1_find(type); 197 if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS)) 198 break; 199 type = t->pkey_base_id; 200 } 201 if (pe) { 202 #ifndef OPENSSL_NO_ENGINE 203 ENGINE *e; 204 /* type will contain the final unaliased type */ 205 e = ENGINE_get_pkey_asn1_meth_engine(type); 206 if (e) { 207 *pe = e; 208 return ENGINE_get_pkey_asn1_meth(e, type); 209 } 210 #endif 211 *pe = NULL; 212 } 213 return t; 214 } 215 216 const EVP_PKEY_ASN1_METHOD * 217 EVP_PKEY_asn1_find_str(ENGINE **pe, const char *str, int len) 218 { 219 int i; 220 const EVP_PKEY_ASN1_METHOD *ameth; 221 if (len == -1) 222 len = strlen(str); 223 if (pe) { 224 #ifndef OPENSSL_NO_ENGINE 225 ENGINE *e; 226 ameth = ENGINE_pkey_asn1_find_str(&e, str, len); 227 if (ameth) { 228 /* Convert structural into 229 * functional reference 230 */ 231 if (!ENGINE_init(e)) 232 ameth = NULL; 233 ENGINE_free(e); 234 *pe = e; 235 return ameth; 236 } 237 #endif 238 *pe = NULL; 239 } 240 for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { 241 ameth = EVP_PKEY_asn1_get0(i); 242 if (ameth->pkey_flags & ASN1_PKEY_ALIAS) 243 continue; 244 if (((int)strlen(ameth->pem_str) == len) && 245 !strncasecmp(ameth->pem_str, str, len)) 246 return ameth; 247 } 248 return NULL; 249 } 250 251 int 252 EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth) 253 { 254 if (app_methods == NULL) { 255 app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp); 256 if (!app_methods) 257 return 0; 258 } 259 if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth)) 260 return 0; 261 sk_EVP_PKEY_ASN1_METHOD_sort(app_methods); 262 return 1; 263 } 264 265 int 266 EVP_PKEY_asn1_add_alias(int to, int from) 267 { 268 EVP_PKEY_ASN1_METHOD *ameth; 269 270 ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL); 271 if (!ameth) 272 return 0; 273 ameth->pkey_base_id = to; 274 if (!EVP_PKEY_asn1_add0(ameth)) { 275 EVP_PKEY_asn1_free(ameth); 276 return 0; 277 } 278 return 1; 279 } 280 281 int 282 EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags, 283 const char **pinfo, const char **ppem_str, 284 const EVP_PKEY_ASN1_METHOD *ameth) 285 { 286 if (!ameth) 287 return 0; 288 if (ppkey_id) 289 *ppkey_id = ameth->pkey_id; 290 if (ppkey_base_id) 291 *ppkey_base_id = ameth->pkey_base_id; 292 if (ppkey_flags) 293 *ppkey_flags = ameth->pkey_flags; 294 if (pinfo) 295 *pinfo = ameth->info; 296 if (ppem_str) 297 *ppem_str = ameth->pem_str; 298 return 1; 299 } 300 301 const EVP_PKEY_ASN1_METHOD* 302 EVP_PKEY_get0_asn1(const EVP_PKEY *pkey) 303 { 304 return pkey->ameth; 305 } 306 307 EVP_PKEY_ASN1_METHOD* 308 EVP_PKEY_asn1_new(int id, int flags, const char *pem_str, const char *info) 309 { 310 EVP_PKEY_ASN1_METHOD *ameth; 311 312 if ((ameth = calloc(1, sizeof(EVP_PKEY_ASN1_METHOD))) == NULL) 313 return NULL; 314 315 ameth->pkey_id = id; 316 ameth->pkey_base_id = id; 317 ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC; 318 319 if (info != NULL) { 320 if ((ameth->info = strdup(info)) == NULL) 321 goto err; 322 } 323 324 if (pem_str != NULL) { 325 if ((ameth->pem_str = strdup(pem_str)) == NULL) 326 goto err; 327 } 328 329 return ameth; 330 331 err: 332 EVP_PKEY_asn1_free(ameth); 333 return NULL; 334 } 335 336 void 337 EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, const EVP_PKEY_ASN1_METHOD *src) 338 { 339 dst->pub_decode = src->pub_decode; 340 dst->pub_encode = src->pub_encode; 341 dst->pub_cmp = src->pub_cmp; 342 dst->pub_print = src->pub_print; 343 344 dst->priv_decode = src->priv_decode; 345 dst->priv_encode = src->priv_encode; 346 dst->priv_print = src->priv_print; 347 348 dst->old_priv_encode = src->old_priv_encode; 349 dst->old_priv_decode = src->old_priv_decode; 350 351 dst->pkey_size = src->pkey_size; 352 dst->pkey_bits = src->pkey_bits; 353 354 dst->param_decode = src->param_decode; 355 dst->param_encode = src->param_encode; 356 dst->param_missing = src->param_missing; 357 dst->param_copy = src->param_copy; 358 dst->param_cmp = src->param_cmp; 359 dst->param_print = src->param_print; 360 dst->sig_print = src->sig_print; 361 362 dst->pkey_free = src->pkey_free; 363 dst->pkey_ctrl = src->pkey_ctrl; 364 365 dst->item_sign = src->item_sign; 366 dst->item_verify = src->item_verify; 367 } 368 369 void 370 EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth) 371 { 372 if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) { 373 free(ameth->pem_str); 374 free(ameth->info); 375 free(ameth); 376 } 377 } 378 379 void 380 EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth, 381 int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub), 382 int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk), 383 int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b), 384 int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, 385 ASN1_PCTX *pctx), 386 int (*pkey_size)(const EVP_PKEY *pk), 387 int (*pkey_bits)(const EVP_PKEY *pk)) 388 { 389 ameth->pub_decode = pub_decode; 390 ameth->pub_encode = pub_encode; 391 ameth->pub_cmp = pub_cmp; 392 ameth->pub_print = pub_print; 393 ameth->pkey_size = pkey_size; 394 ameth->pkey_bits = pkey_bits; 395 } 396 397 void 398 EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth, 399 int (*priv_decode)(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf), 400 int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk), 401 int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent, 402 ASN1_PCTX *pctx)) 403 { 404 ameth->priv_decode = priv_decode; 405 ameth->priv_encode = priv_encode; 406 ameth->priv_print = priv_print; 407 } 408 409 void 410 EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth, 411 int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder, int derlen), 412 int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder), 413 int (*param_missing)(const EVP_PKEY *pk), 414 int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from), 415 int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b), 416 int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent, 417 ASN1_PCTX *pctx)) 418 { 419 ameth->param_decode = param_decode; 420 ameth->param_encode = param_encode; 421 ameth->param_missing = param_missing; 422 ameth->param_copy = param_copy; 423 ameth->param_cmp = param_cmp; 424 ameth->param_print = param_print; 425 } 426 427 void 428 EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth, 429 void (*pkey_free)(EVP_PKEY *pkey)) 430 { 431 ameth->pkey_free = pkey_free; 432 } 433 434 void 435 EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, 436 int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2)) 437 { 438 ameth->pkey_ctrl = pkey_ctrl; 439 } 440