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