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