1 /* crypto/cms/cms_lib.c */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 2008 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 54 #include <openssl/asn1t.h> 55 #include <openssl/x509.h> 56 #include <openssl/err.h> 57 #include <openssl/pem.h> 58 #include <openssl/bio.h> 59 #include <openssl/asn1.h> 60 #include "cms.h" 61 #include "cms_lcl.h" 62 63 IMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo) 64 IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo) 65 66 DECLARE_ASN1_ITEM(CMS_CertificateChoices) 67 DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice) 68 DECLARE_STACK_OF(CMS_CertificateChoices) 69 DECLARE_STACK_OF(CMS_RevocationInfoChoice) 70 71 const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms) 72 { 73 return cms->contentType; 74 } 75 76 CMS_ContentInfo *cms_Data_create(void) 77 { 78 CMS_ContentInfo *cms; 79 cms = CMS_ContentInfo_new(); 80 if (cms) 81 { 82 cms->contentType = OBJ_nid2obj(NID_pkcs7_data); 83 /* Never detached */ 84 CMS_set_detached(cms, 0); 85 } 86 return cms; 87 } 88 89 BIO *cms_content_bio(CMS_ContentInfo *cms) 90 { 91 ASN1_OCTET_STRING **pos = CMS_get0_content(cms); 92 if (!pos) 93 return NULL; 94 /* If content detached data goes nowhere: create NULL BIO */ 95 if (!*pos) 96 return BIO_new(BIO_s_null()); 97 /* If content not detached and created return memory BIO 98 */ 99 if (!*pos || ((*pos)->flags == ASN1_STRING_FLAG_CONT)) 100 return BIO_new(BIO_s_mem()); 101 /* Else content was read in: return read only BIO for it */ 102 return BIO_new_mem_buf((*pos)->data, (*pos)->length); 103 } 104 105 BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) 106 { 107 BIO *cmsbio, *cont; 108 if (icont) 109 cont = icont; 110 else 111 cont = cms_content_bio(cms); 112 if (!cont) 113 { 114 CMSerr(CMS_F_CMS_DATAINIT, CMS_R_NO_CONTENT); 115 return NULL; 116 } 117 switch (OBJ_obj2nid(cms->contentType)) 118 { 119 120 case NID_pkcs7_data: 121 return cont; 122 123 case NID_pkcs7_signed: 124 cmsbio = cms_SignedData_init_bio(cms); 125 break; 126 127 case NID_pkcs7_digest: 128 cmsbio = cms_DigestedData_init_bio(cms); 129 break; 130 #ifdef ZLIB 131 case NID_id_smime_ct_compressedData: 132 cmsbio = cms_CompressedData_init_bio(cms); 133 break; 134 #endif 135 136 case NID_pkcs7_encrypted: 137 cmsbio = cms_EncryptedData_init_bio(cms); 138 break; 139 140 case NID_pkcs7_enveloped: 141 cmsbio = cms_EnvelopedData_init_bio(cms); 142 break; 143 144 default: 145 CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE); 146 return NULL; 147 } 148 149 if (cmsbio) 150 return BIO_push(cmsbio, cont); 151 152 if (!icont) 153 BIO_free(cont); 154 return NULL; 155 156 } 157 158 int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) 159 { 160 ASN1_OCTET_STRING **pos = CMS_get0_content(cms); 161 if (!pos) 162 return 0; 163 /* If ebmedded content find memory BIO and set content */ 164 if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) 165 { 166 BIO *mbio; 167 unsigned char *cont; 168 long contlen; 169 mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); 170 if (!mbio) 171 { 172 CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND); 173 return 0; 174 } 175 contlen = BIO_get_mem_data(mbio, &cont); 176 /* Set bio as read only so its content can't be clobbered */ 177 BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); 178 BIO_set_mem_eof_return(mbio, 0); 179 ASN1_STRING_set0(*pos, cont, contlen); 180 (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; 181 } 182 183 switch (OBJ_obj2nid(cms->contentType)) 184 { 185 186 case NID_pkcs7_data: 187 case NID_pkcs7_enveloped: 188 case NID_pkcs7_encrypted: 189 case NID_id_smime_ct_compressedData: 190 /* Nothing to do */ 191 return 1; 192 193 case NID_pkcs7_signed: 194 return cms_SignedData_final(cms, cmsbio); 195 196 case NID_pkcs7_digest: 197 return cms_DigestedData_do_final(cms, cmsbio, 0); 198 199 default: 200 CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE); 201 return 0; 202 } 203 } 204 205 /* Return an OCTET STRING pointer to content. This allows it to 206 * be accessed or set later. 207 */ 208 209 ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms) 210 { 211 switch (OBJ_obj2nid(cms->contentType)) 212 { 213 214 case NID_pkcs7_data: 215 return &cms->d.data; 216 217 case NID_pkcs7_signed: 218 return &cms->d.signedData->encapContentInfo->eContent; 219 220 case NID_pkcs7_enveloped: 221 return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; 222 223 case NID_pkcs7_digest: 224 return &cms->d.digestedData->encapContentInfo->eContent; 225 226 case NID_pkcs7_encrypted: 227 return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; 228 229 case NID_id_smime_ct_authData: 230 return &cms->d.authenticatedData->encapContentInfo->eContent; 231 232 case NID_id_smime_ct_compressedData: 233 return &cms->d.compressedData->encapContentInfo->eContent; 234 235 default: 236 if (cms->d.other->type == V_ASN1_OCTET_STRING) 237 return &cms->d.other->value.octet_string; 238 CMSerr(CMS_F_CMS_GET0_CONTENT, CMS_R_UNSUPPORTED_CONTENT_TYPE); 239 return NULL; 240 241 } 242 } 243 244 /* Return an ASN1_OBJECT pointer to content type. This allows it to 245 * be accessed or set later. 246 */ 247 248 static ASN1_OBJECT **cms_get0_econtent_type(CMS_ContentInfo *cms) 249 { 250 switch (OBJ_obj2nid(cms->contentType)) 251 { 252 253 case NID_pkcs7_signed: 254 return &cms->d.signedData->encapContentInfo->eContentType; 255 256 case NID_pkcs7_enveloped: 257 return &cms->d.envelopedData->encryptedContentInfo->contentType; 258 259 case NID_pkcs7_digest: 260 return &cms->d.digestedData->encapContentInfo->eContentType; 261 262 case NID_pkcs7_encrypted: 263 return &cms->d.encryptedData->encryptedContentInfo->contentType; 264 265 case NID_id_smime_ct_authData: 266 return &cms->d.authenticatedData->encapContentInfo->eContentType; 267 268 case NID_id_smime_ct_compressedData: 269 return &cms->d.compressedData->encapContentInfo->eContentType; 270 271 default: 272 CMSerr(CMS_F_CMS_GET0_ECONTENT_TYPE, 273 CMS_R_UNSUPPORTED_CONTENT_TYPE); 274 return NULL; 275 276 } 277 } 278 279 const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms) 280 { 281 ASN1_OBJECT **petype; 282 petype = cms_get0_econtent_type(cms); 283 if (petype) 284 return *petype; 285 return NULL; 286 } 287 288 int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid) 289 { 290 ASN1_OBJECT **petype, *etype; 291 petype = cms_get0_econtent_type(cms); 292 if (!petype) 293 return 0; 294 if (!oid) 295 return 1; 296 etype = OBJ_dup(oid); 297 if (!etype) 298 return 0; 299 ASN1_OBJECT_free(*petype); 300 *petype = etype; 301 return 1; 302 } 303 304 int CMS_is_detached(CMS_ContentInfo *cms) 305 { 306 ASN1_OCTET_STRING **pos; 307 pos = CMS_get0_content(cms); 308 if (!pos) 309 return -1; 310 if (*pos) 311 return 0; 312 return 1; 313 } 314 315 int CMS_set_detached(CMS_ContentInfo *cms, int detached) 316 { 317 ASN1_OCTET_STRING **pos; 318 pos = CMS_get0_content(cms); 319 if (!pos) 320 return 0; 321 if (detached) 322 { 323 if (*pos) 324 { 325 ASN1_OCTET_STRING_free(*pos); 326 *pos = NULL; 327 } 328 return 1; 329 } 330 if (!*pos) 331 *pos = ASN1_OCTET_STRING_new(); 332 if (*pos) 333 { 334 /* NB: special flag to show content is created and not 335 * read in. 336 */ 337 (*pos)->flags |= ASN1_STRING_FLAG_CONT; 338 return 1; 339 } 340 CMSerr(CMS_F_CMS_SET_DETACHED, ERR_R_MALLOC_FAILURE); 341 return 0; 342 } 343 344 /* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */ 345 346 void cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md) 347 { 348 int param_type; 349 350 if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT) 351 param_type = V_ASN1_UNDEF; 352 else 353 param_type = V_ASN1_NULL; 354 355 X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL); 356 357 } 358 359 /* Create a digest BIO from an X509_ALGOR structure */ 360 361 BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm) 362 { 363 BIO *mdbio = NULL; 364 ASN1_OBJECT *digestoid; 365 const EVP_MD *digest; 366 X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); 367 digest = EVP_get_digestbyobj(digestoid); 368 if (!digest) 369 { 370 CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, 371 CMS_R_UNKNOWN_DIGEST_ALGORIHM); 372 goto err; 373 } 374 mdbio = BIO_new(BIO_f_md()); 375 if (!mdbio || !BIO_set_md(mdbio, digest)) 376 { 377 CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, 378 CMS_R_MD_BIO_INIT_ERROR); 379 goto err; 380 } 381 return mdbio; 382 err: 383 if (mdbio) 384 BIO_free(mdbio); 385 return NULL; 386 } 387 388 /* Locate a message digest content from a BIO chain based on SignerInfo */ 389 390 int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain, 391 X509_ALGOR *mdalg) 392 { 393 int nid; 394 ASN1_OBJECT *mdoid; 395 X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg); 396 nid = OBJ_obj2nid(mdoid); 397 /* Look for digest type to match signature */ 398 for (;;) 399 { 400 EVP_MD_CTX *mtmp; 401 chain = BIO_find_type(chain, BIO_TYPE_MD); 402 if (chain == NULL) 403 { 404 CMSerr(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX, 405 CMS_R_NO_MATCHING_DIGEST); 406 return 0; 407 } 408 BIO_get_md_ctx(chain, &mtmp); 409 if (EVP_MD_CTX_type(mtmp) == nid 410 /* Workaround for broken implementations that use signature 411 * algorithm OID instead of digest. 412 */ 413 || EVP_MD_pkey_type(EVP_MD_CTX_md(mtmp)) == nid) 414 { 415 EVP_MD_CTX_copy_ex(mctx, mtmp); 416 return 1; 417 } 418 chain = BIO_next(chain); 419 } 420 } 421 422 static STACK_OF(CMS_CertificateChoices) **cms_get0_certificate_choices(CMS_ContentInfo *cms) 423 { 424 switch (OBJ_obj2nid(cms->contentType)) 425 { 426 427 case NID_pkcs7_signed: 428 return &cms->d.signedData->certificates; 429 430 case NID_pkcs7_enveloped: 431 return &cms->d.envelopedData->originatorInfo->certificates; 432 433 default: 434 CMSerr(CMS_F_CMS_GET0_CERTIFICATE_CHOICES, 435 CMS_R_UNSUPPORTED_CONTENT_TYPE); 436 return NULL; 437 438 } 439 } 440 441 CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms) 442 { 443 STACK_OF(CMS_CertificateChoices) **pcerts; 444 CMS_CertificateChoices *cch; 445 pcerts = cms_get0_certificate_choices(cms); 446 if (!pcerts) 447 return NULL; 448 if (!*pcerts) 449 *pcerts = sk_CMS_CertificateChoices_new_null(); 450 if (!*pcerts) 451 return NULL; 452 cch = M_ASN1_new_of(CMS_CertificateChoices); 453 if (!cch) 454 return NULL; 455 if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) 456 { 457 M_ASN1_free_of(cch, CMS_CertificateChoices); 458 return NULL; 459 } 460 return cch; 461 } 462 463 int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) 464 { 465 CMS_CertificateChoices *cch; 466 STACK_OF(CMS_CertificateChoices) **pcerts; 467 int i; 468 pcerts = cms_get0_certificate_choices(cms); 469 if (!pcerts) 470 return 0; 471 if (!pcerts) 472 return 0; 473 for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) 474 { 475 cch = sk_CMS_CertificateChoices_value(*pcerts, i); 476 if (cch->type == CMS_CERTCHOICE_CERT) 477 { 478 if (!X509_cmp(cch->d.certificate, cert)) 479 { 480 CMSerr(CMS_F_CMS_ADD0_CERT, 481 CMS_R_CERTIFICATE_ALREADY_PRESENT); 482 return 0; 483 } 484 } 485 } 486 cch = CMS_add0_CertificateChoices(cms); 487 if (!cch) 488 return 0; 489 cch->type = CMS_CERTCHOICE_CERT; 490 cch->d.certificate = cert; 491 return 1; 492 } 493 494 int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert) 495 { 496 int r; 497 r = CMS_add0_cert(cms, cert); 498 if (r > 0) 499 CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); 500 return r; 501 } 502 503 static STACK_OF(CMS_RevocationInfoChoice) **cms_get0_revocation_choices(CMS_ContentInfo *cms) 504 { 505 switch (OBJ_obj2nid(cms->contentType)) 506 { 507 508 case NID_pkcs7_signed: 509 return &cms->d.signedData->crls; 510 511 case NID_pkcs7_enveloped: 512 return &cms->d.envelopedData->originatorInfo->crls; 513 514 default: 515 CMSerr(CMS_F_CMS_GET0_REVOCATION_CHOICES, 516 CMS_R_UNSUPPORTED_CONTENT_TYPE); 517 return NULL; 518 519 } 520 } 521 522 CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) 523 { 524 STACK_OF(CMS_RevocationInfoChoice) **pcrls; 525 CMS_RevocationInfoChoice *rch; 526 pcrls = cms_get0_revocation_choices(cms); 527 if (!pcrls) 528 return NULL; 529 if (!*pcrls) 530 *pcrls = sk_CMS_RevocationInfoChoice_new_null(); 531 if (!*pcrls) 532 return NULL; 533 rch = M_ASN1_new_of(CMS_RevocationInfoChoice); 534 if (!rch) 535 return NULL; 536 if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) 537 { 538 M_ASN1_free_of(rch, CMS_RevocationInfoChoice); 539 return NULL; 540 } 541 return rch; 542 } 543 544 int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) 545 { 546 CMS_RevocationInfoChoice *rch; 547 rch = CMS_add0_RevocationInfoChoice(cms); 548 if (!rch) 549 return 0; 550 rch->type = CMS_REVCHOICE_CRL; 551 rch->d.crl = crl; 552 return 1; 553 } 554 555 int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl) 556 { 557 int r; 558 r = CMS_add0_crl(cms, crl); 559 if (r > 0) 560 CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); 561 return r; 562 } 563 564 STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms) 565 { 566 STACK_OF(X509) *certs = NULL; 567 CMS_CertificateChoices *cch; 568 STACK_OF(CMS_CertificateChoices) **pcerts; 569 int i; 570 pcerts = cms_get0_certificate_choices(cms); 571 if (!pcerts) 572 return NULL; 573 for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) 574 { 575 cch = sk_CMS_CertificateChoices_value(*pcerts, i); 576 if (cch->type == 0) 577 { 578 if (!certs) 579 { 580 certs = sk_X509_new_null(); 581 if (!certs) 582 return NULL; 583 } 584 if (!sk_X509_push(certs, cch->d.certificate)) 585 { 586 sk_X509_pop_free(certs, X509_free); 587 return NULL; 588 } 589 CRYPTO_add(&cch->d.certificate->references, 590 1, CRYPTO_LOCK_X509); 591 } 592 } 593 return certs; 594 595 } 596 597 STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms) 598 { 599 STACK_OF(X509_CRL) *crls = NULL; 600 STACK_OF(CMS_RevocationInfoChoice) **pcrls; 601 CMS_RevocationInfoChoice *rch; 602 int i; 603 pcrls = cms_get0_revocation_choices(cms); 604 if (!pcrls) 605 return NULL; 606 for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) 607 { 608 rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); 609 if (rch->type == 0) 610 { 611 if (!crls) 612 { 613 crls = sk_X509_CRL_new_null(); 614 if (!crls) 615 return NULL; 616 } 617 if (!sk_X509_CRL_push(crls, rch->d.crl)) 618 { 619 sk_X509_CRL_pop_free(crls, X509_CRL_free); 620 return NULL; 621 } 622 CRYPTO_add(&rch->d.crl->references, 623 1, CRYPTO_LOCK_X509_CRL); 624 } 625 } 626 return crls; 627 } 628