1 /* $OpenBSD: pk7_lib.c,v 1.20 2019/03/13 20:34:00 tb 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/err.h> 62 #include <openssl/objects.h> 63 #include <openssl/x509.h> 64 65 #include "asn1_locl.h" 66 67 long 68 PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg) 69 { 70 int nid; 71 long ret; 72 73 nid = OBJ_obj2nid(p7->type); 74 75 switch (cmd) { 76 case PKCS7_OP_SET_DETACHED_SIGNATURE: 77 if (nid == NID_pkcs7_signed) { 78 ret = p7->detached = (int)larg; 79 if (ret && PKCS7_type_is_data(p7->d.sign->contents)) { 80 ASN1_OCTET_STRING *os; 81 os = p7->d.sign->contents->d.data; 82 ASN1_OCTET_STRING_free(os); 83 p7->d.sign->contents->d.data = NULL; 84 } 85 } else { 86 PKCS7error(PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE); 87 ret = 0; 88 } 89 break; 90 case PKCS7_OP_GET_DETACHED_SIGNATURE: 91 if (nid == NID_pkcs7_signed) { 92 if (!p7->d.sign || !p7->d.sign->contents->d.ptr) 93 ret = 1; 94 else 95 ret = 0; 96 97 p7->detached = ret; 98 } else { 99 PKCS7error(PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE); 100 ret = 0; 101 } 102 103 break; 104 default: 105 PKCS7error(PKCS7_R_UNKNOWN_OPERATION); 106 ret = 0; 107 } 108 return (ret); 109 } 110 111 int 112 PKCS7_content_new(PKCS7 *p7, int type) 113 { 114 PKCS7 *ret = NULL; 115 116 if ((ret = PKCS7_new()) == NULL) 117 goto err; 118 if (!PKCS7_set_type(ret, type)) 119 goto err; 120 if (!PKCS7_set_content(p7, ret)) 121 goto err; 122 123 return (1); 124 err: 125 if (ret != NULL) 126 PKCS7_free(ret); 127 return (0); 128 } 129 130 int 131 PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data) 132 { 133 int i; 134 135 i = OBJ_obj2nid(p7->type); 136 switch (i) { 137 case NID_pkcs7_signed: 138 if (p7->d.sign->contents != NULL) 139 PKCS7_free(p7->d.sign->contents); 140 p7->d.sign->contents = p7_data; 141 break; 142 case NID_pkcs7_digest: 143 if (p7->d.digest->contents != NULL) 144 PKCS7_free(p7->d.digest->contents); 145 p7->d.digest->contents = p7_data; 146 break; 147 case NID_pkcs7_data: 148 case NID_pkcs7_enveloped: 149 case NID_pkcs7_signedAndEnveloped: 150 case NID_pkcs7_encrypted: 151 default: 152 PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 153 goto err; 154 } 155 return (1); 156 err: 157 return (0); 158 } 159 160 int 161 PKCS7_set_type(PKCS7 *p7, int type) 162 { 163 ASN1_OBJECT *obj; 164 165 /*PKCS7_content_free(p7);*/ 166 obj=OBJ_nid2obj(type); /* will not fail */ 167 168 switch (type) { 169 case NID_pkcs7_signed: 170 p7->type = obj; 171 if ((p7->d.sign = PKCS7_SIGNED_new()) == NULL) 172 goto err; 173 if (!ASN1_INTEGER_set(p7->d.sign->version, 1)) { 174 PKCS7_SIGNED_free(p7->d.sign); 175 p7->d.sign = NULL; 176 goto err; 177 } 178 break; 179 case NID_pkcs7_data: 180 p7->type = obj; 181 if ((p7->d.data = ASN1_OCTET_STRING_new()) == NULL) 182 goto err; 183 break; 184 case NID_pkcs7_signedAndEnveloped: 185 p7->type = obj; 186 if ((p7->d.signed_and_enveloped = 187 PKCS7_SIGN_ENVELOPE_new()) == NULL) 188 goto err; 189 ASN1_INTEGER_set(p7->d.signed_and_enveloped->version, 1); 190 if (!ASN1_INTEGER_set(p7->d.signed_and_enveloped->version, 1)) 191 goto err; 192 p7->d.signed_and_enveloped->enc_data->content_type = 193 OBJ_nid2obj(NID_pkcs7_data); 194 break; 195 case NID_pkcs7_enveloped: 196 p7->type = obj; 197 if ((p7->d.enveloped = PKCS7_ENVELOPE_new()) == NULL) 198 goto err; 199 if (!ASN1_INTEGER_set(p7->d.enveloped->version, 0)) 200 goto err; 201 p7->d.enveloped->enc_data->content_type = 202 OBJ_nid2obj(NID_pkcs7_data); 203 break; 204 case NID_pkcs7_encrypted: 205 p7->type = obj; 206 if ((p7->d.encrypted = PKCS7_ENCRYPT_new()) == NULL) 207 goto err; 208 if (!ASN1_INTEGER_set(p7->d.encrypted->version, 0)) 209 goto err; 210 p7->d.encrypted->enc_data->content_type = 211 OBJ_nid2obj(NID_pkcs7_data); 212 break; 213 214 case NID_pkcs7_digest: 215 p7->type = obj; 216 if ((p7->d.digest = PKCS7_DIGEST_new()) == NULL) 217 goto err; 218 if (!ASN1_INTEGER_set(p7->d.digest->version, 0)) 219 goto err; 220 break; 221 default: 222 PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE); 223 goto err; 224 } 225 return (1); 226 err: 227 return (0); 228 } 229 230 int 231 PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other) 232 { 233 p7->type = OBJ_nid2obj(type); 234 p7->d.other = other; 235 return 1; 236 } 237 238 int 239 PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) 240 { 241 int i, j, nid; 242 X509_ALGOR *alg; 243 STACK_OF(PKCS7_SIGNER_INFO) *signer_sk; 244 STACK_OF(X509_ALGOR) *md_sk; 245 246 i = OBJ_obj2nid(p7->type); 247 switch (i) { 248 case NID_pkcs7_signed: 249 signer_sk = p7->d.sign->signer_info; 250 md_sk = p7->d.sign->md_algs; 251 break; 252 case NID_pkcs7_signedAndEnveloped: 253 signer_sk = p7->d.signed_and_enveloped->signer_info; 254 md_sk = p7->d.signed_and_enveloped->md_algs; 255 break; 256 default: 257 PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE); 258 return (0); 259 } 260 261 nid = OBJ_obj2nid(psi->digest_alg->algorithm); 262 263 /* If the digest is not currently listed, add it */ 264 j = 0; 265 for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { 266 alg = sk_X509_ALGOR_value(md_sk, i); 267 if (OBJ_obj2nid(alg->algorithm) == nid) { 268 j = 1; 269 break; 270 } 271 } 272 if (!j) /* we need to add another algorithm */ 273 { 274 if (!(alg = X509_ALGOR_new()) || 275 !(alg->parameter = ASN1_TYPE_new())) { 276 X509_ALGOR_free(alg); 277 PKCS7error(ERR_R_MALLOC_FAILURE); 278 return (0); 279 } 280 alg->algorithm = OBJ_nid2obj(nid); 281 alg->parameter->type = V_ASN1_NULL; 282 if (!sk_X509_ALGOR_push(md_sk, alg)) { 283 X509_ALGOR_free(alg); 284 return 0; 285 } 286 } 287 288 if (!sk_PKCS7_SIGNER_INFO_push(signer_sk, psi)) 289 return 0; 290 return (1); 291 } 292 293 int 294 PKCS7_add_certificate(PKCS7 *p7, X509 *x509) 295 { 296 int i; 297 STACK_OF(X509) **sk; 298 299 i = OBJ_obj2nid(p7->type); 300 switch (i) { 301 case NID_pkcs7_signed: 302 sk = &(p7->d.sign->cert); 303 break; 304 case NID_pkcs7_signedAndEnveloped: 305 sk = &(p7->d.signed_and_enveloped->cert); 306 break; 307 default: 308 PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE); 309 return (0); 310 } 311 312 if (*sk == NULL) 313 *sk = sk_X509_new_null(); 314 if (*sk == NULL) { 315 PKCS7error(ERR_R_MALLOC_FAILURE); 316 return 0; 317 } 318 CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509); 319 if (!sk_X509_push(*sk, x509)) { 320 X509_free(x509); 321 return 0; 322 } 323 return (1); 324 } 325 326 int 327 PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) 328 { 329 int i; 330 STACK_OF(X509_CRL) **sk; 331 332 i = OBJ_obj2nid(p7->type); 333 switch (i) { 334 case NID_pkcs7_signed: 335 sk = &(p7->d.sign->crl); 336 break; 337 case NID_pkcs7_signedAndEnveloped: 338 sk = &(p7->d.signed_and_enveloped->crl); 339 break; 340 default: 341 PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE); 342 return (0); 343 } 344 345 if (*sk == NULL) 346 *sk = sk_X509_CRL_new_null(); 347 if (*sk == NULL) { 348 PKCS7error(ERR_R_MALLOC_FAILURE); 349 return 0; 350 } 351 352 CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); 353 if (!sk_X509_CRL_push(*sk, crl)) { 354 X509_CRL_free(crl); 355 return 0; 356 } 357 return (1); 358 } 359 360 int 361 PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, 362 const EVP_MD *dgst) 363 { 364 int ret; 365 366 /* We now need to add another PKCS7_SIGNER_INFO entry */ 367 if (!ASN1_INTEGER_set(p7i->version, 1)) 368 goto err; 369 if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, 370 X509_get_issuer_name(x509))) 371 goto err; 372 373 /* because ASN1_INTEGER_set is used to set a 'long' we will do 374 * things the ugly way. */ 375 ASN1_INTEGER_free(p7i->issuer_and_serial->serial); 376 if (!(p7i->issuer_and_serial->serial = 377 ASN1_INTEGER_dup(X509_get_serialNumber(x509)))) 378 goto err; 379 380 /* lets keep the pkey around for a while */ 381 CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); 382 p7i->pkey = pkey; 383 384 /* Set the algorithms */ 385 386 X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_type(dgst)), 387 V_ASN1_NULL, NULL); 388 389 if (pkey->ameth && pkey->ameth->pkey_ctrl) { 390 ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN, 391 0, p7i); 392 if (ret > 0) 393 return 1; 394 if (ret != -2) { 395 PKCS7error(PKCS7_R_SIGNING_CTRL_FAILURE); 396 return 0; 397 } 398 } 399 PKCS7error(PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); 400 err: 401 return 0; 402 } 403 404 PKCS7_SIGNER_INFO * 405 PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, const EVP_MD *dgst) 406 { 407 PKCS7_SIGNER_INFO *si = NULL; 408 409 if (dgst == NULL) { 410 int def_nid; 411 if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) 412 goto err; 413 dgst = EVP_get_digestbynid(def_nid); 414 if (dgst == NULL) { 415 PKCS7error(PKCS7_R_NO_DEFAULT_DIGEST); 416 goto err; 417 } 418 } 419 420 if ((si = PKCS7_SIGNER_INFO_new()) == NULL) 421 goto err; 422 if (!PKCS7_SIGNER_INFO_set(si, x509, pkey, dgst)) 423 goto err; 424 if (!PKCS7_add_signer(p7, si)) 425 goto err; 426 return (si); 427 err: 428 if (si) 429 PKCS7_SIGNER_INFO_free(si); 430 return (NULL); 431 } 432 433 int 434 PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) 435 { 436 if (PKCS7_type_is_digest(p7)) { 437 if (!(p7->d.digest->md->parameter = ASN1_TYPE_new())) { 438 PKCS7error(ERR_R_MALLOC_FAILURE); 439 return 0; 440 } 441 p7->d.digest->md->parameter->type = V_ASN1_NULL; 442 p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md)); 443 return 1; 444 } 445 446 PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE); 447 return 1; 448 } 449 450 STACK_OF(PKCS7_SIGNER_INFO) * 451 PKCS7_get_signer_info(PKCS7 *p7) 452 { 453 if (p7 == NULL || p7->d.ptr == NULL) 454 return (NULL); 455 if (PKCS7_type_is_signed(p7)) { 456 return (p7->d.sign->signer_info); 457 } else if (PKCS7_type_is_signedAndEnveloped(p7)) { 458 return (p7->d.signed_and_enveloped->signer_info); 459 } else 460 return (NULL); 461 } 462 463 void 464 PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk, 465 X509_ALGOR **pdig, X509_ALGOR **psig) 466 { 467 if (pk) 468 *pk = si->pkey; 469 if (pdig) 470 *pdig = si->digest_alg; 471 if (psig) 472 *psig = si->digest_enc_alg; 473 } 474 475 void 476 PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc) 477 { 478 if (penc) 479 *penc = ri->key_enc_algor; 480 } 481 482 PKCS7_RECIP_INFO * 483 PKCS7_add_recipient(PKCS7 *p7, X509 *x509) 484 { 485 PKCS7_RECIP_INFO *ri; 486 487 if ((ri = PKCS7_RECIP_INFO_new()) == NULL) 488 goto err; 489 if (!PKCS7_RECIP_INFO_set(ri, x509)) 490 goto err; 491 if (!PKCS7_add_recipient_info(p7, ri)) 492 goto err; 493 return ri; 494 err: 495 if (ri) 496 PKCS7_RECIP_INFO_free(ri); 497 return NULL; 498 } 499 500 int 501 PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri) 502 { 503 int i; 504 STACK_OF(PKCS7_RECIP_INFO) *sk; 505 506 i = OBJ_obj2nid(p7->type); 507 switch (i) { 508 case NID_pkcs7_signedAndEnveloped: 509 sk = p7->d.signed_and_enveloped->recipientinfo; 510 break; 511 case NID_pkcs7_enveloped: 512 sk = p7->d.enveloped->recipientinfo; 513 break; 514 default: 515 PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE); 516 return (0); 517 } 518 519 if (!sk_PKCS7_RECIP_INFO_push(sk, ri)) 520 return 0; 521 return (1); 522 } 523 524 int 525 PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) 526 { 527 int ret; 528 EVP_PKEY *pkey = NULL; 529 if (!ASN1_INTEGER_set(p7i->version, 0)) 530 return 0; 531 if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, 532 X509_get_issuer_name(x509))) 533 return 0; 534 535 ASN1_INTEGER_free(p7i->issuer_and_serial->serial); 536 if (!(p7i->issuer_and_serial->serial = 537 ASN1_INTEGER_dup(X509_get_serialNumber(x509)))) 538 return 0; 539 540 pkey = X509_get_pubkey(x509); 541 542 if (!pkey || !pkey->ameth || !pkey->ameth->pkey_ctrl) { 543 PKCS7error(PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); 544 goto err; 545 } 546 547 ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_ENCRYPT, 548 0, p7i); 549 if (ret == -2) { 550 PKCS7error(PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); 551 goto err; 552 } 553 if (ret <= 0) { 554 PKCS7error(PKCS7_R_ENCRYPTION_CTRL_FAILURE); 555 goto err; 556 } 557 558 EVP_PKEY_free(pkey); 559 560 CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509); 561 p7i->cert = x509; 562 563 return 1; 564 565 err: 566 EVP_PKEY_free(pkey); 567 return 0; 568 } 569 570 X509 * 571 PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) 572 { 573 if (PKCS7_type_is_signed(p7)) 574 return(X509_find_by_issuer_and_serial(p7->d.sign->cert, 575 si->issuer_and_serial->issuer, 576 si->issuer_and_serial->serial)); 577 else 578 return (NULL); 579 } 580 581 int 582 PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) 583 { 584 int i; 585 PKCS7_ENC_CONTENT *ec; 586 587 i = OBJ_obj2nid(p7->type); 588 switch (i) { 589 case NID_pkcs7_signedAndEnveloped: 590 ec = p7->d.signed_and_enveloped->enc_data; 591 break; 592 case NID_pkcs7_enveloped: 593 ec = p7->d.enveloped->enc_data; 594 break; 595 default: 596 PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE); 597 return (0); 598 } 599 600 /* Check cipher OID exists and has data in it*/ 601 i = EVP_CIPHER_type(cipher); 602 if (i == NID_undef) { 603 PKCS7error(PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); 604 return (0); 605 } 606 607 ec->cipher = cipher; 608 return 1; 609 } 610 611 int 612 PKCS7_stream(unsigned char ***boundary, PKCS7 *p7) 613 { 614 ASN1_OCTET_STRING *os = NULL; 615 616 switch (OBJ_obj2nid(p7->type)) { 617 case NID_pkcs7_data: 618 os = p7->d.data; 619 break; 620 621 case NID_pkcs7_signedAndEnveloped: 622 os = p7->d.signed_and_enveloped->enc_data->enc_data; 623 if (os == NULL) { 624 os = ASN1_OCTET_STRING_new(); 625 p7->d.signed_and_enveloped->enc_data->enc_data = os; 626 } 627 break; 628 629 case NID_pkcs7_enveloped: 630 os = p7->d.enveloped->enc_data->enc_data; 631 if (os == NULL) { 632 os = ASN1_OCTET_STRING_new(); 633 p7->d.enveloped->enc_data->enc_data = os; 634 } 635 break; 636 637 case NID_pkcs7_signed: 638 os = p7->d.sign->contents->d.data; 639 break; 640 641 default: 642 os = NULL; 643 break; 644 } 645 646 if (os == NULL) 647 return 0; 648 649 os->flags |= ASN1_STRING_FLAG_NDEF; 650 *boundary = &os->data; 651 652 return 1; 653 } 654