1 /* $OpenBSD: p_lib.c,v 1.16 2014/07/12 22:26:01 miod Exp $ */ 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59 #include <stdio.h> 60 61 #include <openssl/opensslconf.h> 62 63 #include <openssl/bn.h> 64 #include <openssl/err.h> 65 #include <openssl/evp.h> 66 #include <openssl/objects.h> 67 #include <openssl/x509.h> 68 69 #ifndef OPENSSL_NO_DH 70 #include <openssl/dh.h> 71 #endif 72 #ifndef OPENSSL_NO_DSA 73 #include <openssl/dsa.h> 74 #endif 75 #ifndef OPENSSL_NO_RSA 76 #include <openssl/rsa.h> 77 #endif 78 79 #ifndef OPENSSL_NO_ENGINE 80 #include <openssl/engine.h> 81 #endif 82 83 #include "asn1_locl.h" 84 85 static void EVP_PKEY_free_it(EVP_PKEY *x); 86 87 int 88 EVP_PKEY_bits(EVP_PKEY *pkey) 89 { 90 if (pkey && pkey->ameth && pkey->ameth->pkey_bits) 91 return pkey->ameth->pkey_bits(pkey); 92 return 0; 93 } 94 95 int 96 EVP_PKEY_size(EVP_PKEY *pkey) 97 { 98 if (pkey && pkey->ameth && pkey->ameth->pkey_size) 99 return pkey->ameth->pkey_size(pkey); 100 return 0; 101 } 102 103 int 104 EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) 105 { 106 #ifndef OPENSSL_NO_DSA 107 if (pkey->type == EVP_PKEY_DSA) { 108 int ret = pkey->save_parameters; 109 110 if (mode >= 0) 111 pkey->save_parameters = mode; 112 return (ret); 113 } 114 #endif 115 #ifndef OPENSSL_NO_EC 116 if (pkey->type == EVP_PKEY_EC) { 117 int ret = pkey->save_parameters; 118 119 if (mode >= 0) 120 pkey->save_parameters = mode; 121 return (ret); 122 } 123 #endif 124 return (0); 125 } 126 127 int 128 EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) 129 { 130 if (to->type != from->type) { 131 EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, 132 EVP_R_DIFFERENT_KEY_TYPES); 133 goto err; 134 } 135 136 if (EVP_PKEY_missing_parameters(from)) { 137 EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, 138 EVP_R_MISSING_PARAMETERS); 139 goto err; 140 } 141 if (from->ameth && from->ameth->param_copy) 142 return from->ameth->param_copy(to, from); 143 144 err: 145 return 0; 146 } 147 148 int 149 EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) 150 { 151 if (pkey->ameth && pkey->ameth->param_missing) 152 return pkey->ameth->param_missing(pkey); 153 return 0; 154 } 155 156 int 157 EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) 158 { 159 if (a->type != b->type) 160 return -1; 161 if (a->ameth && a->ameth->param_cmp) 162 return a->ameth->param_cmp(a, b); 163 return -2; 164 } 165 166 int 167 EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) 168 { 169 if (a->type != b->type) 170 return -1; 171 172 if (a->ameth) { 173 int ret; 174 /* Compare parameters if the algorithm has them */ 175 if (a->ameth->param_cmp) { 176 ret = a->ameth->param_cmp(a, b); 177 if (ret <= 0) 178 return ret; 179 } 180 181 if (a->ameth->pub_cmp) 182 return a->ameth->pub_cmp(a, b); 183 } 184 185 return -2; 186 } 187 188 EVP_PKEY * 189 EVP_PKEY_new(void) 190 { 191 EVP_PKEY *ret; 192 193 ret = malloc(sizeof(EVP_PKEY)); 194 if (ret == NULL) { 195 EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); 196 return (NULL); 197 } 198 ret->type = EVP_PKEY_NONE; 199 ret->save_type = EVP_PKEY_NONE; 200 ret->references = 1; 201 ret->ameth = NULL; 202 ret->engine = NULL; 203 ret->pkey.ptr = NULL; 204 ret->attributes = NULL; 205 ret->save_parameters = 1; 206 return (ret); 207 } 208 209 /* Setup a public key ASN1 method and ENGINE from a NID or a string. 210 * If pkey is NULL just return 1 or 0 if the algorithm exists. 211 */ 212 213 static int 214 pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len) 215 { 216 const EVP_PKEY_ASN1_METHOD *ameth; 217 ENGINE *e = NULL; 218 if (pkey) { 219 if (pkey->pkey.ptr) 220 EVP_PKEY_free_it(pkey); 221 /* If key type matches and a method exists then this 222 * lookup has succeeded once so just indicate success. 223 */ 224 if ((type == pkey->save_type) && pkey->ameth) 225 return 1; 226 #ifndef OPENSSL_NO_ENGINE 227 /* If we have an ENGINE release it */ 228 if (pkey->engine) { 229 ENGINE_finish(pkey->engine); 230 pkey->engine = NULL; 231 } 232 #endif 233 } 234 if (str) 235 ameth = EVP_PKEY_asn1_find_str(&e, str, len); 236 else 237 ameth = EVP_PKEY_asn1_find(&e, type); 238 #ifndef OPENSSL_NO_ENGINE 239 if (!pkey && e) 240 ENGINE_finish(e); 241 #endif 242 if (!ameth) { 243 EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM); 244 return 0; 245 } 246 if (pkey) { 247 pkey->ameth = ameth; 248 pkey->engine = e; 249 250 pkey->type = pkey->ameth->pkey_id; 251 pkey->save_type = type; 252 } 253 return 1; 254 } 255 256 int 257 EVP_PKEY_set_type(EVP_PKEY *pkey, int type) 258 { 259 return pkey_set_type(pkey, type, NULL, -1); 260 } 261 262 int 263 EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len) 264 { 265 return pkey_set_type(pkey, EVP_PKEY_NONE, str, len); 266 } 267 268 int 269 EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) 270 { 271 if (!EVP_PKEY_set_type(pkey, type)) 272 return 0; 273 pkey->pkey.ptr = key; 274 return (key != NULL); 275 } 276 277 void * 278 EVP_PKEY_get0(EVP_PKEY *pkey) 279 { 280 return pkey->pkey.ptr; 281 } 282 283 #ifndef OPENSSL_NO_RSA 284 int 285 EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) 286 { 287 int ret = EVP_PKEY_assign_RSA(pkey, key); 288 if (ret) 289 RSA_up_ref(key); 290 return ret; 291 } 292 293 RSA * 294 EVP_PKEY_get1_RSA(EVP_PKEY *pkey) 295 { 296 if (pkey->type != EVP_PKEY_RSA) { 297 EVPerr(EVP_F_EVP_PKEY_GET1_RSA, EVP_R_EXPECTING_AN_RSA_KEY); 298 return NULL; 299 } 300 RSA_up_ref(pkey->pkey.rsa); 301 return pkey->pkey.rsa; 302 } 303 #endif 304 305 #ifndef OPENSSL_NO_DSA 306 int 307 EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) 308 { 309 int ret = EVP_PKEY_assign_DSA(pkey, key); 310 if (ret) 311 DSA_up_ref(key); 312 return ret; 313 } 314 315 DSA * 316 EVP_PKEY_get1_DSA(EVP_PKEY *pkey) 317 { 318 if (pkey->type != EVP_PKEY_DSA) { 319 EVPerr(EVP_F_EVP_PKEY_GET1_DSA, EVP_R_EXPECTING_A_DSA_KEY); 320 return NULL; 321 } 322 DSA_up_ref(pkey->pkey.dsa); 323 return pkey->pkey.dsa; 324 } 325 #endif 326 327 #ifndef OPENSSL_NO_EC 328 329 int 330 EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) 331 { 332 int ret = EVP_PKEY_assign_EC_KEY(pkey, key); 333 if (ret) 334 EC_KEY_up_ref(key); 335 return ret; 336 } 337 338 EC_KEY * 339 EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) 340 { 341 if (pkey->type != EVP_PKEY_EC) { 342 EVPerr(EVP_F_EVP_PKEY_GET1_EC_KEY, EVP_R_EXPECTING_A_EC_KEY); 343 return NULL; 344 } 345 EC_KEY_up_ref(pkey->pkey.ec); 346 return pkey->pkey.ec; 347 } 348 #endif 349 350 351 #ifndef OPENSSL_NO_DH 352 353 int 354 EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) 355 { 356 int ret = EVP_PKEY_assign_DH(pkey, key); 357 if (ret) 358 DH_up_ref(key); 359 return ret; 360 } 361 362 DH * 363 EVP_PKEY_get1_DH(EVP_PKEY *pkey) 364 { 365 if (pkey->type != EVP_PKEY_DH) { 366 EVPerr(EVP_F_EVP_PKEY_GET1_DH, EVP_R_EXPECTING_A_DH_KEY); 367 return NULL; 368 } 369 DH_up_ref(pkey->pkey.dh); 370 return pkey->pkey.dh; 371 } 372 #endif 373 374 int 375 EVP_PKEY_type(int type) 376 { 377 int ret; 378 const EVP_PKEY_ASN1_METHOD *ameth; 379 ENGINE *e; 380 ameth = EVP_PKEY_asn1_find(&e, type); 381 if (ameth) 382 ret = ameth->pkey_id; 383 else 384 ret = NID_undef; 385 #ifndef OPENSSL_NO_ENGINE 386 if (e) 387 ENGINE_finish(e); 388 #endif 389 return ret; 390 } 391 392 int 393 EVP_PKEY_id(const EVP_PKEY *pkey) 394 { 395 return pkey->type; 396 } 397 398 int 399 EVP_PKEY_base_id(const EVP_PKEY *pkey) 400 { 401 return EVP_PKEY_type(pkey->type); 402 } 403 404 void 405 EVP_PKEY_free(EVP_PKEY *x) 406 { 407 int i; 408 409 if (x == NULL) 410 return; 411 412 i = CRYPTO_add(&x->references, -1, CRYPTO_LOCK_EVP_PKEY); 413 if (i > 0) 414 return; 415 416 EVP_PKEY_free_it(x); 417 if (x->attributes) 418 sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); 419 free(x); 420 } 421 422 static void 423 EVP_PKEY_free_it(EVP_PKEY *x) 424 { 425 if (x->ameth && x->ameth->pkey_free) { 426 x->ameth->pkey_free(x); 427 x->pkey.ptr = NULL; 428 } 429 #ifndef OPENSSL_NO_ENGINE 430 if (x->engine) { 431 ENGINE_finish(x->engine); 432 x->engine = NULL; 433 } 434 #endif 435 } 436 437 static int 438 unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent, const char *kstr) 439 { 440 BIO_indent(out, indent, 128); 441 BIO_printf(out, "%s algorithm \"%s\" unsupported\n", 442 kstr, OBJ_nid2ln(pkey->type)); 443 return 1; 444 } 445 446 int 447 EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent, 448 ASN1_PCTX *pctx) 449 { 450 if (pkey->ameth && pkey->ameth->pub_print) 451 return pkey->ameth->pub_print(out, pkey, indent, pctx); 452 453 return unsup_alg(out, pkey, indent, "Public Key"); 454 } 455 456 int 457 EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent, 458 ASN1_PCTX *pctx) 459 { 460 if (pkey->ameth && pkey->ameth->priv_print) 461 return pkey->ameth->priv_print(out, pkey, indent, pctx); 462 463 return unsup_alg(out, pkey, indent, "Private Key"); 464 } 465 466 int 467 EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent, 468 ASN1_PCTX *pctx) 469 { 470 if (pkey->ameth && pkey->ameth->param_print) 471 return pkey->ameth->param_print(out, pkey, indent, pctx); 472 return unsup_alg(out, pkey, indent, "Parameters"); 473 } 474 475 int 476 EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid) 477 { 478 if (!pkey->ameth || !pkey->ameth->pkey_ctrl) 479 return -2; 480 return pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, 481 0, pnid); 482 } 483 484