pmeth_lib.c revision 296341
1/* pmeth_lib.c */ 2/* 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4 * 2006. 5 */ 6/* ==================================================================== 7 * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <stdio.h> 61#include <stdlib.h> 62#include "cryptlib.h" 63#include <openssl/objects.h> 64#include <openssl/evp.h> 65#ifndef OPENSSL_NO_ENGINE 66# include <openssl/engine.h> 67#endif 68#include "asn1_locl.h" 69#include "evp_locl.h" 70 71typedef int sk_cmp_fn_type(const char *const *a, const char *const *b); 72 73DECLARE_STACK_OF(EVP_PKEY_METHOD) 74STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL; 75 76extern const EVP_PKEY_METHOD rsa_pkey_meth, dh_pkey_meth, dsa_pkey_meth; 77extern const EVP_PKEY_METHOD ec_pkey_meth, hmac_pkey_meth, cmac_pkey_meth; 78 79static const EVP_PKEY_METHOD *standard_methods[] = { 80#ifndef OPENSSL_NO_RSA 81 &rsa_pkey_meth, 82#endif 83#ifndef OPENSSL_NO_DH 84 &dh_pkey_meth, 85#endif 86#ifndef OPENSSL_NO_DSA 87 &dsa_pkey_meth, 88#endif 89#ifndef OPENSSL_NO_EC 90 &ec_pkey_meth, 91#endif 92 &hmac_pkey_meth, 93 &cmac_pkey_meth 94}; 95 96DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, 97 pmeth); 98 99static int pmeth_cmp(const EVP_PKEY_METHOD *const *a, 100 const EVP_PKEY_METHOD *const *b) 101{ 102 return ((*a)->pkey_id - (*b)->pkey_id); 103} 104 105IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, 106 pmeth); 107 108const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type) 109{ 110 EVP_PKEY_METHOD tmp; 111 const EVP_PKEY_METHOD *t = &tmp, **ret; 112 tmp.pkey_id = type; 113 if (app_pkey_methods) { 114 int idx; 115 idx = sk_EVP_PKEY_METHOD_find(app_pkey_methods, &tmp); 116 if (idx >= 0) 117 return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx); 118 } 119 ret = OBJ_bsearch_pmeth(&t, standard_methods, 120 sizeof(standard_methods) / 121 sizeof(EVP_PKEY_METHOD *)); 122 if (!ret || !*ret) 123 return NULL; 124 return *ret; 125} 126 127static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) 128{ 129 EVP_PKEY_CTX *ret; 130 const EVP_PKEY_METHOD *pmeth; 131 if (id == -1) { 132 if (!pkey || !pkey->ameth) 133 return NULL; 134 id = pkey->ameth->pkey_id; 135 } 136#ifndef OPENSSL_NO_ENGINE 137 if (pkey && pkey->engine) 138 e = pkey->engine; 139 /* Try to find an ENGINE which implements this method */ 140 if (e) { 141 if (!ENGINE_init(e)) { 142 EVPerr(EVP_F_INT_CTX_NEW, ERR_R_ENGINE_LIB); 143 return NULL; 144 } 145 } else 146 e = ENGINE_get_pkey_meth_engine(id); 147 148 /* 149 * If an ENGINE handled this method look it up. Othewise use internal 150 * tables. 151 */ 152 153 if (e) 154 pmeth = ENGINE_get_pkey_meth(e, id); 155 else 156#endif 157 pmeth = EVP_PKEY_meth_find(id); 158 159 if (pmeth == NULL) { 160 EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM); 161 return NULL; 162 } 163 164 ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX)); 165 if (!ret) { 166#ifndef OPENSSL_NO_ENGINE 167 if (e) 168 ENGINE_finish(e); 169#endif 170 EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE); 171 return NULL; 172 } 173 ret->engine = e; 174 ret->pmeth = pmeth; 175 ret->operation = EVP_PKEY_OP_UNDEFINED; 176 ret->pkey = pkey; 177 ret->peerkey = NULL; 178 ret->pkey_gencb = 0; 179 if (pkey) 180 CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); 181 ret->data = NULL; 182 183 if (pmeth->init) { 184 if (pmeth->init(ret) <= 0) { 185 EVP_PKEY_CTX_free(ret); 186 return NULL; 187 } 188 } 189 190 return ret; 191} 192 193EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags) 194{ 195 EVP_PKEY_METHOD *pmeth; 196 pmeth = OPENSSL_malloc(sizeof(EVP_PKEY_METHOD)); 197 if (!pmeth) 198 return NULL; 199 200 memset(pmeth, 0, sizeof(EVP_PKEY_METHOD)); 201 202 pmeth->pkey_id = id; 203 pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC; 204 205 pmeth->init = 0; 206 pmeth->copy = 0; 207 pmeth->cleanup = 0; 208 pmeth->paramgen_init = 0; 209 pmeth->paramgen = 0; 210 pmeth->keygen_init = 0; 211 pmeth->keygen = 0; 212 pmeth->sign_init = 0; 213 pmeth->sign = 0; 214 pmeth->verify_init = 0; 215 pmeth->verify = 0; 216 pmeth->verify_recover_init = 0; 217 pmeth->verify_recover = 0; 218 pmeth->signctx_init = 0; 219 pmeth->signctx = 0; 220 pmeth->verifyctx_init = 0; 221 pmeth->verifyctx = 0; 222 pmeth->encrypt_init = 0; 223 pmeth->encrypt = 0; 224 pmeth->decrypt_init = 0; 225 pmeth->decrypt = 0; 226 pmeth->derive_init = 0; 227 pmeth->derive = 0; 228 pmeth->ctrl = 0; 229 pmeth->ctrl_str = 0; 230 231 return pmeth; 232} 233 234void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, 235 const EVP_PKEY_METHOD *meth) 236{ 237 if (ppkey_id) 238 *ppkey_id = meth->pkey_id; 239 if (pflags) 240 *pflags = meth->flags; 241} 242 243void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src) 244{ 245 246 dst->init = src->init; 247 dst->copy = src->copy; 248 dst->cleanup = src->cleanup; 249 250 dst->paramgen_init = src->paramgen_init; 251 dst->paramgen = src->paramgen; 252 253 dst->keygen_init = src->keygen_init; 254 dst->keygen = src->keygen; 255 256 dst->sign_init = src->sign_init; 257 dst->sign = src->sign; 258 259 dst->verify_init = src->verify_init; 260 dst->verify = src->verify; 261 262 dst->verify_recover_init = src->verify_recover_init; 263 dst->verify_recover = src->verify_recover; 264 265 dst->signctx_init = src->signctx_init; 266 dst->signctx = src->signctx; 267 268 dst->verifyctx_init = src->verifyctx_init; 269 dst->verifyctx = src->verifyctx; 270 271 dst->encrypt_init = src->encrypt_init; 272 dst->encrypt = src->encrypt; 273 274 dst->decrypt_init = src->decrypt_init; 275 dst->decrypt = src->decrypt; 276 277 dst->derive_init = src->derive_init; 278 dst->derive = src->derive; 279 280 dst->ctrl = src->ctrl; 281 dst->ctrl_str = src->ctrl_str; 282} 283 284void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth) 285{ 286 if (pmeth && (pmeth->flags & EVP_PKEY_FLAG_DYNAMIC)) 287 OPENSSL_free(pmeth); 288} 289 290EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e) 291{ 292 return int_ctx_new(pkey, e, -1); 293} 294 295EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) 296{ 297 return int_ctx_new(NULL, e, id); 298} 299 300EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) 301{ 302 EVP_PKEY_CTX *rctx; 303 if (!pctx->pmeth || !pctx->pmeth->copy) 304 return NULL; 305#ifndef OPENSSL_NO_ENGINE 306 /* Make sure it's safe to copy a pkey context using an ENGINE */ 307 if (pctx->engine && !ENGINE_init(pctx->engine)) { 308 EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_ENGINE_LIB); 309 return 0; 310 } 311#endif 312 rctx = OPENSSL_malloc(sizeof(EVP_PKEY_CTX)); 313 if (!rctx) 314 return NULL; 315 316 rctx->pmeth = pctx->pmeth; 317#ifndef OPENSSL_NO_ENGINE 318 rctx->engine = pctx->engine; 319#endif 320 321 if (pctx->pkey) 322 CRYPTO_add(&pctx->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); 323 324 rctx->pkey = pctx->pkey; 325 326 if (pctx->peerkey) 327 CRYPTO_add(&pctx->peerkey->references, 1, CRYPTO_LOCK_EVP_PKEY); 328 329 rctx->peerkey = pctx->peerkey; 330 331 rctx->data = NULL; 332 rctx->app_data = NULL; 333 rctx->operation = pctx->operation; 334 335 if (pctx->pmeth->copy(rctx, pctx) > 0) 336 return rctx; 337 338 EVP_PKEY_CTX_free(rctx); 339 return NULL; 340 341} 342 343int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth) 344{ 345 if (app_pkey_methods == NULL) { 346 app_pkey_methods = sk_EVP_PKEY_METHOD_new(pmeth_cmp); 347 if (!app_pkey_methods) 348 return 0; 349 } 350 if (!sk_EVP_PKEY_METHOD_push(app_pkey_methods, pmeth)) 351 return 0; 352 sk_EVP_PKEY_METHOD_sort(app_pkey_methods); 353 return 1; 354} 355 356void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) 357{ 358 if (ctx == NULL) 359 return; 360 if (ctx->pmeth && ctx->pmeth->cleanup) 361 ctx->pmeth->cleanup(ctx); 362 if (ctx->pkey) 363 EVP_PKEY_free(ctx->pkey); 364 if (ctx->peerkey) 365 EVP_PKEY_free(ctx->peerkey); 366#ifndef OPENSSL_NO_ENGINE 367 if (ctx->engine) 368 /* 369 * The EVP_PKEY_CTX we used belongs to an ENGINE, release the 370 * functional reference we held for this reason. 371 */ 372 ENGINE_finish(ctx->engine); 373#endif 374 OPENSSL_free(ctx); 375} 376 377int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, 378 int cmd, int p1, void *p2) 379{ 380 int ret; 381 if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) { 382 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); 383 return -2; 384 } 385 if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype)) 386 return -1; 387 388 if (ctx->operation == EVP_PKEY_OP_UNDEFINED) { 389 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET); 390 return -1; 391 } 392 393 if ((optype != -1) && !(ctx->operation & optype)) { 394 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION); 395 return -1; 396 } 397 398 ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2); 399 400 if (ret == -2) 401 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); 402 403 return ret; 404 405} 406 407int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, 408 const char *name, const char *value) 409{ 410 if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) { 411 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); 412 return -2; 413 } 414 if (!strcmp(name, "digest")) { 415 const EVP_MD *md; 416 if (!value || !(md = EVP_get_digestbyname(value))) { 417 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_INVALID_DIGEST); 418 return 0; 419 } 420 return EVP_PKEY_CTX_set_signature_md(ctx, md); 421 } 422 return ctx->pmeth->ctrl_str(ctx, name, value); 423} 424 425int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx) 426{ 427 return ctx->operation; 428} 429 430void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen) 431{ 432 ctx->keygen_info = dat; 433 ctx->keygen_info_count = datlen; 434} 435 436void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data) 437{ 438 ctx->data = data; 439} 440 441void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx) 442{ 443 return ctx->data; 444} 445 446EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) 447{ 448 return ctx->pkey; 449} 450 451EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx) 452{ 453 return ctx->peerkey; 454} 455 456void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data) 457{ 458 ctx->app_data = data; 459} 460 461void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx) 462{ 463 return ctx->app_data; 464} 465 466void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth, 467 int (*init) (EVP_PKEY_CTX *ctx)) 468{ 469 pmeth->init = init; 470} 471 472void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth, 473 int (*copy) (EVP_PKEY_CTX *dst, 474 EVP_PKEY_CTX *src)) 475{ 476 pmeth->copy = copy; 477} 478 479void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth, 480 void (*cleanup) (EVP_PKEY_CTX *ctx)) 481{ 482 pmeth->cleanup = cleanup; 483} 484 485void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth, 486 int (*paramgen_init) (EVP_PKEY_CTX *ctx), 487 int (*paramgen) (EVP_PKEY_CTX *ctx, 488 EVP_PKEY *pkey)) 489{ 490 pmeth->paramgen_init = paramgen_init; 491 pmeth->paramgen = paramgen; 492} 493 494void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth, 495 int (*keygen_init) (EVP_PKEY_CTX *ctx), 496 int (*keygen) (EVP_PKEY_CTX *ctx, 497 EVP_PKEY *pkey)) 498{ 499 pmeth->keygen_init = keygen_init; 500 pmeth->keygen = keygen; 501} 502 503void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth, 504 int (*sign_init) (EVP_PKEY_CTX *ctx), 505 int (*sign) (EVP_PKEY_CTX *ctx, 506 unsigned char *sig, size_t *siglen, 507 const unsigned char *tbs, 508 size_t tbslen)) 509{ 510 pmeth->sign_init = sign_init; 511 pmeth->sign = sign; 512} 513 514void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth, 515 int (*verify_init) (EVP_PKEY_CTX *ctx), 516 int (*verify) (EVP_PKEY_CTX *ctx, 517 const unsigned char *sig, 518 size_t siglen, 519 const unsigned char *tbs, 520 size_t tbslen)) 521{ 522 pmeth->verify_init = verify_init; 523 pmeth->verify = verify; 524} 525 526void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth, 527 int (*verify_recover_init) (EVP_PKEY_CTX 528 *ctx), 529 int (*verify_recover) (EVP_PKEY_CTX 530 *ctx, 531 unsigned char 532 *sig, 533 size_t *siglen, 534 const unsigned 535 char *tbs, 536 size_t tbslen)) 537{ 538 pmeth->verify_recover_init = verify_recover_init; 539 pmeth->verify_recover = verify_recover; 540} 541 542void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth, 543 int (*signctx_init) (EVP_PKEY_CTX *ctx, 544 EVP_MD_CTX *mctx), 545 int (*signctx) (EVP_PKEY_CTX *ctx, 546 unsigned char *sig, 547 size_t *siglen, 548 EVP_MD_CTX *mctx)) 549{ 550 pmeth->signctx_init = signctx_init; 551 pmeth->signctx = signctx; 552} 553 554void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth, 555 int (*verifyctx_init) (EVP_PKEY_CTX *ctx, 556 EVP_MD_CTX *mctx), 557 int (*verifyctx) (EVP_PKEY_CTX *ctx, 558 const unsigned char *sig, 559 int siglen, 560 EVP_MD_CTX *mctx)) 561{ 562 pmeth->verifyctx_init = verifyctx_init; 563 pmeth->verifyctx = verifyctx; 564} 565 566void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth, 567 int (*encrypt_init) (EVP_PKEY_CTX *ctx), 568 int (*encryptfn) (EVP_PKEY_CTX *ctx, 569 unsigned char *out, 570 size_t *outlen, 571 const unsigned char *in, 572 size_t inlen)) 573{ 574 pmeth->encrypt_init = encrypt_init; 575 pmeth->encrypt = encryptfn; 576} 577 578void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth, 579 int (*decrypt_init) (EVP_PKEY_CTX *ctx), 580 int (*decrypt) (EVP_PKEY_CTX *ctx, 581 unsigned char *out, 582 size_t *outlen, 583 const unsigned char *in, 584 size_t inlen)) 585{ 586 pmeth->decrypt_init = decrypt_init; 587 pmeth->decrypt = decrypt; 588} 589 590void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth, 591 int (*derive_init) (EVP_PKEY_CTX *ctx), 592 int (*derive) (EVP_PKEY_CTX *ctx, 593 unsigned char *key, 594 size_t *keylen)) 595{ 596 pmeth->derive_init = derive_init; 597 pmeth->derive = derive; 598} 599 600void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, 601 int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, 602 void *p2), 603 int (*ctrl_str) (EVP_PKEY_CTX *ctx, 604 const char *type, 605 const char *value)) 606{ 607 pmeth->ctrl = ctrl; 608 pmeth->ctrl_str = ctrl_str; 609} 610