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