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