cms_sd.c revision 1.7
1/* $OpenBSD: cms_sd.c,v 1.7 2014/07/11 13:02:10 miod 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/cms.h> 56#include <openssl/err.h> 57#include <openssl/pem.h> 58#include <openssl/x509v3.h> 59 60#include "asn1_locl.h" 61#include "cms_lcl.h" 62 63/* CMS SignedData Utilities */ 64 65DECLARE_ASN1_ITEM(CMS_SignedData) 66 67static CMS_SignedData * 68cms_get0_signed(CMS_ContentInfo *cms) 69{ 70 if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) { 71 CMSerr(CMS_F_CMS_GET0_SIGNED, 72 CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA); 73 return NULL; 74 } 75 return cms->d.signedData; 76} 77 78static CMS_SignedData * 79cms_signed_data_init(CMS_ContentInfo *cms) 80{ 81 if (cms->d.other == NULL) { 82 cms->d.signedData = M_ASN1_new_of(CMS_SignedData); 83 if (!cms->d.signedData) { 84 CMSerr(CMS_F_CMS_SIGNED_DATA_INIT, 85 ERR_R_MALLOC_FAILURE); 86 return NULL; 87 } 88 cms->d.signedData->version = 1; 89 cms->d.signedData->encapContentInfo->eContentType = 90 OBJ_nid2obj(NID_pkcs7_data); 91 cms->d.signedData->encapContentInfo->partial = 1; 92 ASN1_OBJECT_free(cms->contentType); 93 cms->contentType = OBJ_nid2obj(NID_pkcs7_signed); 94 return cms->d.signedData; 95 } 96 return cms_get0_signed(cms); 97} 98 99/* Just initialize SignedData e.g. for certs only structure */ 100 101int 102CMS_SignedData_init(CMS_ContentInfo *cms) 103{ 104 if (cms_signed_data_init(cms)) 105 return 1; 106 else 107 return 0; 108} 109 110/* Check structures and fixup version numbers (if necessary) */ 111 112static void 113cms_sd_set_version(CMS_SignedData *sd) 114{ 115 int i; 116 CMS_CertificateChoices *cch; 117 CMS_RevocationInfoChoice *rch; 118 CMS_SignerInfo *si; 119 120 for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++) { 121 cch = sk_CMS_CertificateChoices_value(sd->certificates, i); 122 if (cch->type == CMS_CERTCHOICE_OTHER) { 123 if (sd->version < 5) 124 sd->version = 5; 125 } else if (cch->type == CMS_CERTCHOICE_V2ACERT) { 126 if (sd->version < 4) 127 sd->version = 4; 128 } else if (cch->type == CMS_CERTCHOICE_V1ACERT) { 129 if (sd->version < 3) 130 sd->version = 3; 131 } 132 } 133 134 for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++) { 135 rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i); 136 if (rch->type == CMS_REVCHOICE_OTHER) { 137 if (sd->version < 5) 138 sd->version = 5; 139 } 140 } 141 142 if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != 143 NID_pkcs7_data) && (sd->version < 3)) 144 sd->version = 3; 145 146 for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) { 147 si = sk_CMS_SignerInfo_value(sd->signerInfos, i); 148 if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) { 149 if (si->version < 3) 150 si->version = 3; 151 if (sd->version < 3) 152 sd->version = 3; 153 } else if (si->version < 1) 154 si->version = 1; 155 } 156 157 if (sd->version < 1) 158 sd->version = 1; 159} 160 161/* Copy an existing messageDigest value */ 162 163static int 164cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si) 165{ 166 STACK_OF(CMS_SignerInfo) *sinfos; 167 CMS_SignerInfo *sitmp; 168 int i; 169 170 sinfos = CMS_get0_SignerInfos(cms); 171 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { 172 ASN1_OCTET_STRING *messageDigest; 173 sitmp = sk_CMS_SignerInfo_value(sinfos, i); 174 if (sitmp == si) 175 continue; 176 if (CMS_signed_get_attr_count(sitmp) < 0) 177 continue; 178 if (OBJ_cmp(si->digestAlgorithm->algorithm, 179 sitmp->digestAlgorithm->algorithm)) 180 continue; 181 messageDigest = CMS_signed_get0_data_by_OBJ(sitmp, 182 OBJ_nid2obj(NID_pkcs9_messageDigest), 183 -3, V_ASN1_OCTET_STRING); 184 if (!messageDigest) { 185 CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, 186 CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE); 187 return 0; 188 } 189 190 if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, 191 V_ASN1_OCTET_STRING, 192 messageDigest, -1)) 193 return 1; 194 else 195 return 0; 196 } 197 CMSerr(CMS_F_CMS_COPY_MESSAGEDIGEST, CMS_R_NO_MATCHING_DIGEST); 198 return 0; 199} 200 201int 202cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type) 203{ 204 switch (type) { 205 case CMS_SIGNERINFO_ISSUER_SERIAL: 206 sid->d.issuerAndSerialNumber = 207 M_ASN1_new_of(CMS_IssuerAndSerialNumber); 208 if (!sid->d.issuerAndSerialNumber) 209 goto merr; 210 if (!X509_NAME_set(&sid->d.issuerAndSerialNumber->issuer, 211 X509_get_issuer_name(cert))) 212 goto merr; 213 if (!ASN1_STRING_copy( 214 sid->d.issuerAndSerialNumber->serialNumber, 215 X509_get_serialNumber(cert))) 216 goto merr; 217 break; 218 219 case CMS_SIGNERINFO_KEYIDENTIFIER: 220 if (!cert->skid) { 221 CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, 222 CMS_R_CERTIFICATE_HAS_NO_KEYID); 223 return 0; 224 } 225 sid->d.subjectKeyIdentifier = ASN1_STRING_dup(cert->skid); 226 if (!sid->d.subjectKeyIdentifier) 227 goto merr; 228 break; 229 230 default: 231 CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID); 232 return 0; 233 } 234 235 sid->type = type; 236 237 return 1; 238 239merr: 240 CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, ERR_R_MALLOC_FAILURE); 241 return 0; 242} 243 244int 245cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid, 246 ASN1_OCTET_STRING **keyid, X509_NAME **issuer, ASN1_INTEGER **sno) 247{ 248 if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) { 249 if (issuer) 250 *issuer = sid->d.issuerAndSerialNumber->issuer; 251 if (sno) 252 *sno = sid->d.issuerAndSerialNumber->serialNumber; 253 } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) { 254 if (keyid) 255 *keyid = sid->d.subjectKeyIdentifier; 256 } else 257 return 0; 258 return 1; 259} 260 261int 262cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert) 263{ 264 int ret; 265 266 if (sid->type == CMS_SIGNERINFO_ISSUER_SERIAL) { 267 ret = X509_NAME_cmp(sid->d.issuerAndSerialNumber->issuer, 268 X509_get_issuer_name(cert)); 269 if (ret) 270 return ret; 271 return ASN1_INTEGER_cmp(sid->d.issuerAndSerialNumber->serialNumber, 272 X509_get_serialNumber(cert)); 273 } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) { 274 X509_check_purpose(cert, -1, -1); 275 if (!cert->skid) 276 return -1; 277 return ASN1_OCTET_STRING_cmp(sid->d.subjectKeyIdentifier, 278 cert->skid); 279 } else 280 return -1; 281} 282 283CMS_SignerInfo * 284CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, 285 const EVP_MD *md, unsigned int flags) 286{ 287 CMS_SignedData *sd; 288 CMS_SignerInfo *si = NULL; 289 X509_ALGOR *alg; 290 int i, type; 291 292 if (!X509_check_private_key(signer, pk)) { 293 CMSerr(CMS_F_CMS_ADD1_SIGNER, 294 CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); 295 return NULL; 296 } 297 sd = cms_signed_data_init(cms); 298 if (!sd) 299 goto err; 300 si = M_ASN1_new_of(CMS_SignerInfo); 301 if (!si) 302 goto merr; 303 X509_check_purpose(signer, -1, -1); 304 305 CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY); 306 CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); 307 308 si->pkey = pk; 309 si->signer = signer; 310 311 if (flags & CMS_USE_KEYID) { 312 si->version = 3; 313 if (sd->version < 3) 314 sd->version = 3; 315 type = CMS_SIGNERINFO_KEYIDENTIFIER; 316 } else { 317 type = CMS_SIGNERINFO_ISSUER_SERIAL; 318 si->version = 1; 319 } 320 321 if (!cms_set1_SignerIdentifier(si->sid, signer, type)) 322 goto err; 323 324 if (md == NULL) { 325 int def_nid; 326 if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) 327 goto err; 328 md = EVP_get_digestbynid(def_nid); 329 if (md == NULL) { 330 CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST); 331 goto err; 332 } 333 } 334 335 if (!md) { 336 CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET); 337 goto err; 338 } 339 340 cms_DigestAlgorithm_set(si->digestAlgorithm, md); 341 342 /* See if digest is present in digestAlgorithms */ 343 for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { 344 ASN1_OBJECT *aoid; 345 alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); 346 X509_ALGOR_get0(&aoid, NULL, NULL, alg); 347 if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) 348 break; 349 } 350 351 if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { 352 alg = X509_ALGOR_new(); 353 if (!alg) 354 goto merr; 355 cms_DigestAlgorithm_set(alg, md); 356 if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { 357 X509_ALGOR_free(alg); 358 goto merr; 359 } 360 } 361 362 if (pk->ameth && pk->ameth->pkey_ctrl) { 363 i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_SIGN, 364 0, si); 365 if (i == -2) { 366 CMSerr(CMS_F_CMS_ADD1_SIGNER, 367 CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); 368 goto err; 369 } 370 if (i <= 0) { 371 CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_CTRL_FAILURE); 372 goto err; 373 } 374 } 375 376 if (!(flags & CMS_NOATTR)) { 377 /* Initialialize signed attributes strutucture so other 378 * attributes such as signing time etc are added later 379 * even if we add none here. 380 */ 381 if (!si->signedAttrs) { 382 si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); 383 if (!si->signedAttrs) 384 goto merr; 385 } 386 387 if (!(flags & CMS_NOSMIMECAP)) { 388 STACK_OF(X509_ALGOR) *smcap = NULL; 389 i = CMS_add_standard_smimecap(&smcap); 390 if (i) 391 i = CMS_add_smimecap(si, smcap); 392 sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); 393 if (!i) 394 goto merr; 395 } 396 if (flags & CMS_REUSE_DIGEST) { 397 if (!cms_copy_messageDigest(cms, si)) 398 goto err; 399 if (!(flags & CMS_PARTIAL) && 400 !CMS_SignerInfo_sign(si)) 401 goto err; 402 } 403 } 404 405 if (!(flags & CMS_NOCERTS)) { 406 /* NB ignore -1 return for duplicate cert */ 407 if (!CMS_add1_cert(cms, signer)) 408 goto merr; 409 } 410 411 if (!sd->signerInfos) 412 sd->signerInfos = sk_CMS_SignerInfo_new_null(); 413 if (!sd->signerInfos || 414 !sk_CMS_SignerInfo_push(sd->signerInfos, si)) 415 goto merr; 416 417 return si; 418 419merr: 420 CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); 421err: 422 if (si) 423 M_ASN1_free_of(si, CMS_SignerInfo); 424 return NULL; 425} 426 427static int 428cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t) 429{ 430 ASN1_TIME *tt; 431 int r = 0; 432 433 if (t) 434 tt = t; 435 else 436 tt = X509_gmtime_adj(NULL, 0); 437 438 if (!tt) 439 goto merr; 440 441 if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime, 442 tt->type, tt, -1) <= 0) 443 goto merr; 444 445 r = 1; 446 447merr: 448 if (!t) 449 ASN1_TIME_free(tt); 450 if (!r) 451 CMSerr(CMS_F_CMS_ADD1_SIGNINGTIME, ERR_R_MALLOC_FAILURE); 452 453 return r; 454} 455 456STACK_OF(CMS_SignerInfo) * 457CMS_get0_SignerInfos(CMS_ContentInfo *cms) 458{ 459 CMS_SignedData *sd; 460 461 sd = cms_get0_signed(cms); 462 if (!sd) 463 return NULL; 464 return sd->signerInfos; 465} 466 467STACK_OF(X509) * 468CMS_get0_signers(CMS_ContentInfo *cms) 469{ 470 STACK_OF(X509) *signers = NULL; 471 STACK_OF(CMS_SignerInfo) *sinfos; 472 CMS_SignerInfo *si; 473 int i; 474 475 sinfos = CMS_get0_SignerInfos(cms); 476 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { 477 si = sk_CMS_SignerInfo_value(sinfos, i); 478 if (si->signer) { 479 if (!signers) { 480 signers = sk_X509_new_null(); 481 if (!signers) 482 return NULL; 483 } 484 if (!sk_X509_push(signers, si->signer)) { 485 sk_X509_free(signers); 486 return NULL; 487 } 488 } 489 } 490 return signers; 491} 492 493void 494CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer) 495{ 496 if (signer) { 497 CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); 498 if (si->pkey) 499 EVP_PKEY_free(si->pkey); 500 si->pkey = X509_get_pubkey(signer); 501 } 502 if (si->signer) 503 X509_free(si->signer); 504 si->signer = signer; 505} 506 507int 508CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si, ASN1_OCTET_STRING **keyid, 509 X509_NAME **issuer, ASN1_INTEGER **sno) 510{ 511 return cms_SignerIdentifier_get0_signer_id(si->sid, keyid, issuer, sno); 512} 513 514int 515CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert) 516{ 517 return cms_SignerIdentifier_cert_cmp(si->sid, cert); 518} 519 520int 521CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts, 522 unsigned int flags) 523{ 524 CMS_SignedData *sd; 525 CMS_SignerInfo *si; 526 CMS_CertificateChoices *cch; 527 STACK_OF(CMS_CertificateChoices) *certs; 528 X509 *x; 529 int i, j; 530 int ret = 0; 531 532 sd = cms_get0_signed(cms); 533 if (!sd) 534 return -1; 535 certs = sd->certificates; 536 for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) { 537 si = sk_CMS_SignerInfo_value(sd->signerInfos, i); 538 if (si->signer) 539 continue; 540 541 for (j = 0; j < sk_X509_num(scerts); j++) { 542 x = sk_X509_value(scerts, j); 543 if (CMS_SignerInfo_cert_cmp(si, x) == 0) { 544 CMS_SignerInfo_set1_signer_cert(si, x); 545 ret++; 546 break; 547 } 548 } 549 550 if (si->signer || (flags & CMS_NOINTERN)) 551 continue; 552 553 for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) { 554 cch = sk_CMS_CertificateChoices_value(certs, j); 555 if (cch->type != 0) 556 continue; 557 x = cch->d.certificate; 558 if (CMS_SignerInfo_cert_cmp(si, x) == 0) { 559 CMS_SignerInfo_set1_signer_cert(si, x); 560 ret++; 561 break; 562 } 563 } 564 } 565 return ret; 566} 567 568void 569CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, X509 **signer, 570 X509_ALGOR **pdig, X509_ALGOR **psig) 571{ 572 if (pk) 573 *pk = si->pkey; 574 if (signer) 575 *signer = si->signer; 576 if (pdig) 577 *pdig = si->digestAlgorithm; 578 if (psig) 579 *psig = si->signatureAlgorithm; 580} 581 582static int 583cms_SignerInfo_content_sign(CMS_ContentInfo *cms, CMS_SignerInfo *si, 584 BIO *chain) 585{ 586 EVP_MD_CTX mctx; 587 int r = 0; 588 EVP_MD_CTX_init(&mctx); 589 590 if (!si->pkey) { 591 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY); 592 return 0; 593 } 594 595 if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm)) 596 goto err; 597 598 /* If any signed attributes calculate and add messageDigest attribute */ 599 600 if (CMS_signed_get_attr_count(si) >= 0) { 601 ASN1_OBJECT *ctype = 602 cms->d.signedData->encapContentInfo->eContentType; 603 unsigned char md[EVP_MAX_MD_SIZE]; 604 unsigned int mdlen; 605 if (!EVP_DigestFinal_ex(&mctx, md, &mdlen)) 606 goto err; 607 if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, 608 V_ASN1_OCTET_STRING, 609 md, mdlen)) 610 goto err; 611 /* Copy content type across */ 612 if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType, 613 V_ASN1_OBJECT, ctype, -1) <= 0) 614 goto err; 615 if (!CMS_SignerInfo_sign(si)) 616 goto err; 617 } else { 618 unsigned char *sig; 619 unsigned int siglen; 620 sig = malloc(EVP_PKEY_size(si->pkey)); 621 if (!sig) { 622 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, 623 ERR_R_MALLOC_FAILURE); 624 goto err; 625 } 626 if (!EVP_SignFinal(&mctx, sig, &siglen, si->pkey)) { 627 CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, 628 CMS_R_SIGNFINAL_ERROR); 629 free(sig); 630 goto err; 631 } 632 ASN1_STRING_set0(si->signature, sig, siglen); 633 } 634 635 r = 1; 636 637err: 638 EVP_MD_CTX_cleanup(&mctx); 639 return r; 640} 641 642int 643cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain) 644{ 645 STACK_OF(CMS_SignerInfo) *sinfos; 646 CMS_SignerInfo *si; 647 int i; 648 649 sinfos = CMS_get0_SignerInfos(cms); 650 for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { 651 si = sk_CMS_SignerInfo_value(sinfos, i); 652 if (!cms_SignerInfo_content_sign(cms, si, chain)) 653 return 0; 654 } 655 cms->d.signedData->encapContentInfo->partial = 0; 656 return 1; 657} 658 659int 660CMS_SignerInfo_sign(CMS_SignerInfo *si) 661{ 662 EVP_MD_CTX mctx; 663 EVP_PKEY_CTX *pctx; 664 unsigned char *abuf = NULL; 665 int alen; 666 size_t siglen; 667 const EVP_MD *md = NULL; 668 669 md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); 670 if (md == NULL) 671 return 0; 672 673 EVP_MD_CTX_init(&mctx); 674 675 if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) { 676 if (!cms_add1_signingTime(si, NULL)) 677 goto err; 678 } 679 680 if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0) 681 goto err; 682 683 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 684 EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) { 685 CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR); 686 goto err; 687 } 688 689 alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf, 690 ASN1_ITEM_rptr(CMS_Attributes_Sign)); 691 if (!abuf) 692 goto err; 693 if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0) 694 goto err; 695 if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0) 696 goto err; 697 free(abuf); 698 abuf = malloc(siglen); 699 if (!abuf) 700 goto err; 701 if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0) 702 goto err; 703 704 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, 705 EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0) { 706 CMSerr(CMS_F_CMS_SIGNERINFO_SIGN, CMS_R_CTRL_ERROR); 707 goto err; 708 } 709 710 EVP_MD_CTX_cleanup(&mctx); 711 712 ASN1_STRING_set0(si->signature, abuf, siglen); 713 714 return 1; 715 716err: 717 free(abuf); 718 EVP_MD_CTX_cleanup(&mctx); 719 return 0; 720} 721 722int 723CMS_SignerInfo_verify(CMS_SignerInfo *si) 724{ 725 EVP_MD_CTX mctx; 726 EVP_PKEY_CTX *pctx; 727 unsigned char *abuf = NULL; 728 int alen, r = -1; 729 const EVP_MD *md = NULL; 730 731 if (!si->pkey) { 732 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_NO_PUBLIC_KEY); 733 return -1; 734 } 735 736 md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); 737 if (md == NULL) 738 return -1; 739 EVP_MD_CTX_init(&mctx); 740 if (EVP_DigestVerifyInit(&mctx, &pctx, md, NULL, si->pkey) <= 0) 741 goto err; 742 743 alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf, 744 ASN1_ITEM_rptr(CMS_Attributes_Verify)); 745 if (!abuf) 746 goto err; 747 r = EVP_DigestVerifyUpdate(&mctx, abuf, alen); 748 free(abuf); 749 if (r <= 0) { 750 r = -1; 751 goto err; 752 } 753 r = EVP_DigestVerifyFinal(&mctx, 754 si->signature->data, si->signature->length); 755 if (r <= 0) 756 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE); 757 758err: 759 EVP_MD_CTX_cleanup(&mctx); 760 return r; 761} 762 763/* Create a chain of digest BIOs from a CMS ContentInfo */ 764 765BIO * 766cms_SignedData_init_bio(CMS_ContentInfo *cms) 767{ 768 int i; 769 CMS_SignedData *sd; 770 BIO *chain = NULL; 771 772 sd = cms_get0_signed(cms); 773 if (!sd) 774 return NULL; 775 if (cms->d.signedData->encapContentInfo->partial) 776 cms_sd_set_version(sd); 777 for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { 778 X509_ALGOR *digestAlgorithm; 779 BIO *mdbio; 780 digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i); 781 mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm); 782 if (!mdbio) 783 goto err; 784 if (chain) 785 BIO_push(chain, mdbio); 786 else 787 chain = mdbio; 788 } 789 return chain; 790 791err: 792 if (chain) 793 BIO_free_all(chain); 794 return NULL; 795} 796 797int 798CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) 799{ 800 ASN1_OCTET_STRING *os = NULL; 801 EVP_MD_CTX mctx; 802 int r = -1; 803 804 EVP_MD_CTX_init(&mctx); 805 /* If we have any signed attributes look for messageDigest value */ 806 if (CMS_signed_get_attr_count(si) >= 0) { 807 os = CMS_signed_get0_data_by_OBJ(si, 808 OBJ_nid2obj(NID_pkcs9_messageDigest), 809 -3, V_ASN1_OCTET_STRING); 810 if (!os) { 811 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 812 CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE); 813 goto err; 814 } 815 } 816 817 if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm)) 818 goto err; 819 820 /* If messageDigest found compare it */ 821 822 if (os) { 823 unsigned char mval[EVP_MAX_MD_SIZE]; 824 unsigned int mlen; 825 if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0) { 826 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 827 CMS_R_UNABLE_TO_FINALIZE_CONTEXT); 828 goto err; 829 } 830 if (mlen != (unsigned int)os->length) { 831 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 832 CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH); 833 goto err; 834 } 835 836 if (memcmp(mval, os->data, mlen)) { 837 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 838 CMS_R_VERIFICATION_FAILURE); 839 r = 0; 840 } else 841 r = 1; 842 } else { 843 r = EVP_VerifyFinal(&mctx, si->signature->data, 844 si->signature->length, si->pkey); 845 if (r <= 0) { 846 CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT, 847 CMS_R_VERIFICATION_FAILURE); 848 r = 0; 849 } 850 } 851 852err: 853 EVP_MD_CTX_cleanup(&mctx); 854 return r; 855} 856 857int 858CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs) 859{ 860 unsigned char *smder = NULL; 861 int smderlen, r; 862 863 smderlen = i2d_X509_ALGORS(algs, &smder); 864 if (smderlen <= 0) 865 return 0; 866 r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities, 867 V_ASN1_SEQUENCE, smder, smderlen); 868 free(smder); 869 return r; 870} 871 872int 873CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, int algnid, int keysize) 874{ 875 X509_ALGOR *alg; 876 ASN1_INTEGER *key = NULL; 877 878 if (keysize > 0) { 879 key = ASN1_INTEGER_new(); 880 if (!key || !ASN1_INTEGER_set(key, keysize)) 881 return 0; 882 } 883 alg = X509_ALGOR_new(); 884 if (!alg) { 885 if (key) 886 ASN1_INTEGER_free(key); 887 return 0; 888 } 889 890 X509_ALGOR_set0(alg, OBJ_nid2obj(algnid), 891 key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key); 892 if (!*algs) 893 *algs = sk_X509_ALGOR_new_null(); 894 if (!*algs || !sk_X509_ALGOR_push(*algs, alg)) { 895 X509_ALGOR_free(alg); 896 return 0; 897 } 898 return 1; 899} 900 901/* Check to see if a cipher exists and if so add S/MIME capabilities */ 902 903static int 904cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg) 905{ 906 if (EVP_get_cipherbynid(nid)) 907 return CMS_add_simple_smimecap(sk, nid, arg); 908 return 1; 909} 910 911static int 912cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg) 913{ 914 if (EVP_get_digestbynid(nid)) 915 return CMS_add_simple_smimecap(sk, nid, arg); 916 return 1; 917} 918 919int 920CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap) 921{ 922 if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1) || 923 !cms_add_digest_smcap(smcap, NID_id_GostR3411_94, -1) || 924 !cms_add_cipher_smcap(smcap, NID_id_Gost28147_89, -1) || 925 !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1) || 926 !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1) || 927 !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1) || 928 !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128) || 929 !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64) || 930 !cms_add_cipher_smcap(smcap, NID_des_cbc, -1) || 931 !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40)) 932 return 0; 933 return 1; 934} 935