cms.c revision 1.1.1.2
1/* $NetBSD: cms.c,v 1.1.1.2 2014/04/24 12:45:41 pettai Exp $ */ 2 3/* 4 * Copyright (c) 2003 - 2007 Kungliga Tekniska H��gskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * 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 the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "hx_locl.h" 37 38/** 39 * @page page_cms CMS/PKCS7 message functions. 40 * 41 * CMS is defined in RFC 3369 and is an continuation of the RSA Labs 42 * standard PKCS7. The basic messages in CMS is 43 * 44 * - SignedData 45 * Data signed with private key (RSA, DSA, ECDSA) or secret 46 * (symmetric) key 47 * - EnvelopedData 48 * Data encrypted with private key (RSA) 49 * - EncryptedData 50 * Data encrypted with secret (symmetric) key. 51 * - ContentInfo 52 * Wrapper structure including type and data. 53 * 54 * 55 * See the library functions here: @ref hx509_cms 56 */ 57 58#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) 59#define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0) 60 61/** 62 * Wrap data and oid in a ContentInfo and encode it. 63 * 64 * @param oid type of the content. 65 * @param buf data to be wrapped. If a NULL pointer is passed in, the 66 * optional content field in the ContentInfo is not going be filled 67 * in. 68 * @param res the encoded buffer, the result should be freed with 69 * der_free_octet_string(). 70 * 71 * @return Returns an hx509 error code. 72 * 73 * @ingroup hx509_cms 74 */ 75 76int 77hx509_cms_wrap_ContentInfo(const heim_oid *oid, 78 const heim_octet_string *buf, 79 heim_octet_string *res) 80{ 81 ContentInfo ci; 82 size_t size; 83 int ret; 84 85 memset(res, 0, sizeof(*res)); 86 memset(&ci, 0, sizeof(ci)); 87 88 ret = der_copy_oid(oid, &ci.contentType); 89 if (ret) 90 return ret; 91 if (buf) { 92 ALLOC(ci.content, 1); 93 if (ci.content == NULL) { 94 free_ContentInfo(&ci); 95 return ENOMEM; 96 } 97 ci.content->data = malloc(buf->length); 98 if (ci.content->data == NULL) { 99 free_ContentInfo(&ci); 100 return ENOMEM; 101 } 102 memcpy(ci.content->data, buf->data, buf->length); 103 ci.content->length = buf->length; 104 } 105 106 ASN1_MALLOC_ENCODE(ContentInfo, res->data, res->length, &ci, &size, ret); 107 free_ContentInfo(&ci); 108 if (ret) 109 return ret; 110 if (res->length != size) 111 _hx509_abort("internal ASN.1 encoder error"); 112 113 return 0; 114} 115 116/** 117 * Decode an ContentInfo and unwrap data and oid it. 118 * 119 * @param in the encoded buffer. 120 * @param oid type of the content. 121 * @param out data to be wrapped. 122 * @param have_data since the data is optional, this flags show dthe 123 * diffrence between no data and the zero length data. 124 * 125 * @return Returns an hx509 error code. 126 * 127 * @ingroup hx509_cms 128 */ 129 130int 131hx509_cms_unwrap_ContentInfo(const heim_octet_string *in, 132 heim_oid *oid, 133 heim_octet_string *out, 134 int *have_data) 135{ 136 ContentInfo ci; 137 size_t size; 138 int ret; 139 140 memset(oid, 0, sizeof(*oid)); 141 memset(out, 0, sizeof(*out)); 142 143 ret = decode_ContentInfo(in->data, in->length, &ci, &size); 144 if (ret) 145 return ret; 146 147 ret = der_copy_oid(&ci.contentType, oid); 148 if (ret) { 149 free_ContentInfo(&ci); 150 return ret; 151 } 152 if (ci.content) { 153 ret = der_copy_octet_string(ci.content, out); 154 if (ret) { 155 der_free_oid(oid); 156 free_ContentInfo(&ci); 157 return ret; 158 } 159 } else 160 memset(out, 0, sizeof(*out)); 161 162 if (have_data) 163 *have_data = (ci.content != NULL) ? 1 : 0; 164 165 free_ContentInfo(&ci); 166 167 return 0; 168} 169 170#define CMS_ID_SKI 0 171#define CMS_ID_NAME 1 172 173static int 174fill_CMSIdentifier(const hx509_cert cert, 175 int type, 176 CMSIdentifier *id) 177{ 178 int ret; 179 180 switch (type) { 181 case CMS_ID_SKI: 182 id->element = choice_CMSIdentifier_subjectKeyIdentifier; 183 ret = _hx509_find_extension_subject_key_id(_hx509_get_cert(cert), 184 &id->u.subjectKeyIdentifier); 185 if (ret == 0) 186 break; 187 /* FALL THOUGH */ 188 case CMS_ID_NAME: { 189 hx509_name name; 190 191 id->element = choice_CMSIdentifier_issuerAndSerialNumber; 192 ret = hx509_cert_get_issuer(cert, &name); 193 if (ret) 194 return ret; 195 ret = hx509_name_to_Name(name, &id->u.issuerAndSerialNumber.issuer); 196 hx509_name_free(&name); 197 if (ret) 198 return ret; 199 200 ret = hx509_cert_get_serialnumber(cert, &id->u.issuerAndSerialNumber.serialNumber); 201 break; 202 } 203 default: 204 _hx509_abort("CMS fill identifier with unknown type"); 205 } 206 return ret; 207} 208 209static int 210unparse_CMSIdentifier(hx509_context context, 211 CMSIdentifier *id, 212 char **str) 213{ 214 int ret; 215 216 *str = NULL; 217 switch (id->element) { 218 case choice_CMSIdentifier_issuerAndSerialNumber: { 219 IssuerAndSerialNumber *iasn; 220 char *serial, *name; 221 222 iasn = &id->u.issuerAndSerialNumber; 223 224 ret = _hx509_Name_to_string(&iasn->issuer, &name); 225 if(ret) 226 return ret; 227 ret = der_print_hex_heim_integer(&iasn->serialNumber, &serial); 228 if (ret) { 229 free(name); 230 return ret; 231 } 232 asprintf(str, "certificate issued by %s with serial number %s", 233 name, serial); 234 free(name); 235 free(serial); 236 break; 237 } 238 case choice_CMSIdentifier_subjectKeyIdentifier: { 239 KeyIdentifier *ki = &id->u.subjectKeyIdentifier; 240 char *keyid; 241 ssize_t len; 242 243 len = hex_encode(ki->data, ki->length, &keyid); 244 if (len < 0) 245 return ENOMEM; 246 247 asprintf(str, "certificate with id %s", keyid); 248 free(keyid); 249 break; 250 } 251 default: 252 asprintf(str, "certificate have unknown CMSidentifier type"); 253 break; 254 } 255 if (*str == NULL) 256 return ENOMEM; 257 return 0; 258} 259 260static int 261find_CMSIdentifier(hx509_context context, 262 CMSIdentifier *client, 263 hx509_certs certs, 264 time_t time_now, 265 hx509_cert *signer_cert, 266 int match) 267{ 268 hx509_query q; 269 hx509_cert cert; 270 Certificate c; 271 int ret; 272 273 memset(&c, 0, sizeof(c)); 274 _hx509_query_clear(&q); 275 276 *signer_cert = NULL; 277 278 switch (client->element) { 279 case choice_CMSIdentifier_issuerAndSerialNumber: 280 q.serial = &client->u.issuerAndSerialNumber.serialNumber; 281 q.issuer_name = &client->u.issuerAndSerialNumber.issuer; 282 q.match = HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME; 283 break; 284 case choice_CMSIdentifier_subjectKeyIdentifier: 285 q.subject_id = &client->u.subjectKeyIdentifier; 286 q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID; 287 break; 288 default: 289 hx509_set_error_string(context, 0, HX509_CMS_NO_RECIPIENT_CERTIFICATE, 290 "unknown CMS identifier element"); 291 return HX509_CMS_NO_RECIPIENT_CERTIFICATE; 292 } 293 294 q.match |= match; 295 296 q.match |= HX509_QUERY_MATCH_TIME; 297 if (time_now) 298 q.timenow = time_now; 299 else 300 q.timenow = time(NULL); 301 302 ret = hx509_certs_find(context, certs, &q, &cert); 303 if (ret == HX509_CERT_NOT_FOUND) { 304 char *str; 305 306 ret = unparse_CMSIdentifier(context, client, &str); 307 if (ret == 0) { 308 hx509_set_error_string(context, 0, 309 HX509_CMS_NO_RECIPIENT_CERTIFICATE, 310 "Failed to find %s", str); 311 } else 312 hx509_clear_error_string(context); 313 return HX509_CMS_NO_RECIPIENT_CERTIFICATE; 314 } else if (ret) { 315 hx509_set_error_string(context, HX509_ERROR_APPEND, 316 HX509_CMS_NO_RECIPIENT_CERTIFICATE, 317 "Failed to find CMS id in cert store"); 318 return HX509_CMS_NO_RECIPIENT_CERTIFICATE; 319 } 320 321 *signer_cert = cert; 322 323 return 0; 324} 325 326/** 327 * Decode and unencrypt EnvelopedData. 328 * 329 * Extract data and parameteres from from the EnvelopedData. Also 330 * supports using detached EnvelopedData. 331 * 332 * @param context A hx509 context. 333 * @param certs Certificate that can decrypt the EnvelopedData 334 * encryption key. 335 * @param flags HX509_CMS_UE flags to control the behavior. 336 * @param data pointer the structure the contains the DER/BER encoded 337 * EnvelopedData stucture. 338 * @param length length of the data that data point to. 339 * @param encryptedContent in case of detached signature, this 340 * contains the actual encrypted data, othersize its should be NULL. 341 * @param time_now set the current time, if zero the library uses now as the date. 342 * @param contentType output type oid, should be freed with der_free_oid(). 343 * @param content the data, free with der_free_octet_string(). 344 * 345 * @ingroup hx509_cms 346 */ 347 348int 349hx509_cms_unenvelope(hx509_context context, 350 hx509_certs certs, 351 int flags, 352 const void *data, 353 size_t length, 354 const heim_octet_string *encryptedContent, 355 time_t time_now, 356 heim_oid *contentType, 357 heim_octet_string *content) 358{ 359 heim_octet_string key; 360 EnvelopedData ed; 361 hx509_cert cert; 362 AlgorithmIdentifier *ai; 363 const heim_octet_string *enccontent; 364 heim_octet_string *params, params_data; 365 heim_octet_string ivec; 366 size_t size; 367 int ret, matched = 0, findflags = 0; 368 size_t i; 369 370 371 memset(&key, 0, sizeof(key)); 372 memset(&ed, 0, sizeof(ed)); 373 memset(&ivec, 0, sizeof(ivec)); 374 memset(content, 0, sizeof(*content)); 375 memset(contentType, 0, sizeof(*contentType)); 376 377 if ((flags & HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT) == 0) 378 findflags |= HX509_QUERY_KU_ENCIPHERMENT; 379 380 ret = decode_EnvelopedData(data, length, &ed, &size); 381 if (ret) { 382 hx509_set_error_string(context, 0, ret, 383 "Failed to decode EnvelopedData"); 384 return ret; 385 } 386 387 if (ed.recipientInfos.len == 0) { 388 ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE; 389 hx509_set_error_string(context, 0, ret, 390 "No recipient info in enveloped data"); 391 goto out; 392 } 393 394 enccontent = ed.encryptedContentInfo.encryptedContent; 395 if (enccontent == NULL) { 396 if (encryptedContent == NULL) { 397 ret = HX509_CMS_NO_DATA_AVAILABLE; 398 hx509_set_error_string(context, 0, ret, 399 "Content missing from encrypted data"); 400 goto out; 401 } 402 enccontent = encryptedContent; 403 } else if (encryptedContent != NULL) { 404 ret = HX509_CMS_NO_DATA_AVAILABLE; 405 hx509_set_error_string(context, 0, ret, 406 "Both internal and external encrypted data"); 407 goto out; 408 } 409 410 cert = NULL; 411 for (i = 0; i < ed.recipientInfos.len; i++) { 412 KeyTransRecipientInfo *ri; 413 char *str; 414 int ret2; 415 416 ri = &ed.recipientInfos.val[i]; 417 418 ret = find_CMSIdentifier(context, &ri->rid, certs, 419 time_now, &cert, 420 HX509_QUERY_PRIVATE_KEY|findflags); 421 if (ret) 422 continue; 423 424 matched = 1; /* found a matching certificate, let decrypt */ 425 426 ret = _hx509_cert_private_decrypt(context, 427 &ri->encryptedKey, 428 &ri->keyEncryptionAlgorithm.algorithm, 429 cert, &key); 430 431 hx509_cert_free(cert); 432 if (ret == 0) 433 break; /* succuessfully decrypted cert */ 434 cert = NULL; 435 ret2 = unparse_CMSIdentifier(context, &ri->rid, &str); 436 if (ret2 == 0) { 437 hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 438 "Failed to decrypt with %s", str); 439 free(str); 440 } 441 } 442 443 if (!matched) { 444 ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE; 445 hx509_set_error_string(context, 0, ret, 446 "No private key matched any certificate"); 447 goto out; 448 } 449 450 if (cert == NULL) { 451 ret = HX509_CMS_NO_RECIPIENT_CERTIFICATE; 452 hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 453 "No private key decrypted the transfer key"); 454 goto out; 455 } 456 457 ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType); 458 if (ret) { 459 hx509_set_error_string(context, 0, ret, 460 "Failed to copy EnvelopedData content oid"); 461 goto out; 462 } 463 464 ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm; 465 if (ai->parameters) { 466 params_data.data = ai->parameters->data; 467 params_data.length = ai->parameters->length; 468 params = ¶ms_data; 469 } else 470 params = NULL; 471 472 { 473 hx509_crypto crypto; 474 475 ret = hx509_crypto_init(context, NULL, &ai->algorithm, &crypto); 476 if (ret) 477 goto out; 478 479 if (flags & HX509_CMS_UE_ALLOW_WEAK) 480 hx509_crypto_allow_weak(crypto); 481 482 if (params) { 483 ret = hx509_crypto_set_params(context, crypto, params, &ivec); 484 if (ret) { 485 hx509_crypto_destroy(crypto); 486 goto out; 487 } 488 } 489 490 ret = hx509_crypto_set_key_data(crypto, key.data, key.length); 491 if (ret) { 492 hx509_crypto_destroy(crypto); 493 hx509_set_error_string(context, 0, ret, 494 "Failed to set key for decryption " 495 "of EnvelopedData"); 496 goto out; 497 } 498 499 ret = hx509_crypto_decrypt(crypto, 500 enccontent->data, 501 enccontent->length, 502 ivec.length ? &ivec : NULL, 503 content); 504 hx509_crypto_destroy(crypto); 505 if (ret) { 506 hx509_set_error_string(context, 0, ret, 507 "Failed to decrypt EnvelopedData"); 508 goto out; 509 } 510 } 511 512out: 513 514 free_EnvelopedData(&ed); 515 der_free_octet_string(&key); 516 if (ivec.length) 517 der_free_octet_string(&ivec); 518 if (ret) { 519 der_free_oid(contentType); 520 der_free_octet_string(content); 521 } 522 523 return ret; 524} 525 526/** 527 * Encrypt end encode EnvelopedData. 528 * 529 * Encrypt and encode EnvelopedData. The data is encrypted with a 530 * random key and the the random key is encrypted with the 531 * certificates private key. This limits what private key type can be 532 * used to RSA. 533 * 534 * @param context A hx509 context. 535 * @param flags flags to control the behavior. 536 * - HX509_CMS_EV_NO_KU_CHECK - Dont check KU on certificate 537 * - HX509_CMS_EV_ALLOW_WEAK - Allow weak crytpo 538 * - HX509_CMS_EV_ID_NAME - prefer issuer name and serial number 539 * @param cert Certificate to encrypt the EnvelopedData encryption key 540 * with. 541 * @param data pointer the data to encrypt. 542 * @param length length of the data that data point to. 543 * @param encryption_type Encryption cipher to use for the bulk data, 544 * use NULL to get default. 545 * @param contentType type of the data that is encrypted 546 * @param content the output of the function, 547 * free with der_free_octet_string(). 548 * 549 * @ingroup hx509_cms 550 */ 551 552int 553hx509_cms_envelope_1(hx509_context context, 554 int flags, 555 hx509_cert cert, 556 const void *data, 557 size_t length, 558 const heim_oid *encryption_type, 559 const heim_oid *contentType, 560 heim_octet_string *content) 561{ 562 KeyTransRecipientInfo *ri; 563 heim_octet_string ivec; 564 heim_octet_string key; 565 hx509_crypto crypto = NULL; 566 int ret, cmsidflag; 567 EnvelopedData ed; 568 size_t size; 569 570 memset(&ivec, 0, sizeof(ivec)); 571 memset(&key, 0, sizeof(key)); 572 memset(&ed, 0, sizeof(ed)); 573 memset(content, 0, sizeof(*content)); 574 575 if (encryption_type == NULL) 576 encryption_type = &asn1_oid_id_aes_256_cbc; 577 578 if ((flags & HX509_CMS_EV_NO_KU_CHECK) == 0) { 579 ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE); 580 if (ret) 581 goto out; 582 } 583 584 ret = hx509_crypto_init(context, NULL, encryption_type, &crypto); 585 if (ret) 586 goto out; 587 588 if (flags & HX509_CMS_EV_ALLOW_WEAK) 589 hx509_crypto_allow_weak(crypto); 590 591 ret = hx509_crypto_set_random_key(crypto, &key); 592 if (ret) { 593 hx509_set_error_string(context, 0, ret, 594 "Create random key for EnvelopedData content"); 595 goto out; 596 } 597 598 ret = hx509_crypto_random_iv(crypto, &ivec); 599 if (ret) { 600 hx509_set_error_string(context, 0, ret, 601 "Failed to create a random iv"); 602 goto out; 603 } 604 605 ret = hx509_crypto_encrypt(crypto, 606 data, 607 length, 608 &ivec, 609 &ed.encryptedContentInfo.encryptedContent); 610 if (ret) { 611 hx509_set_error_string(context, 0, ret, 612 "Failed to encrypt EnvelopedData content"); 613 goto out; 614 } 615 616 { 617 AlgorithmIdentifier *enc_alg; 618 enc_alg = &ed.encryptedContentInfo.contentEncryptionAlgorithm; 619 ret = der_copy_oid(encryption_type, &enc_alg->algorithm); 620 if (ret) { 621 hx509_set_error_string(context, 0, ret, 622 "Failed to set crypto oid " 623 "for EnvelopedData"); 624 goto out; 625 } 626 ALLOC(enc_alg->parameters, 1); 627 if (enc_alg->parameters == NULL) { 628 ret = ENOMEM; 629 hx509_set_error_string(context, 0, ret, 630 "Failed to allocate crypto paramaters " 631 "for EnvelopedData"); 632 goto out; 633 } 634 635 ret = hx509_crypto_get_params(context, 636 crypto, 637 &ivec, 638 enc_alg->parameters); 639 if (ret) { 640 goto out; 641 } 642 } 643 644 ALLOC_SEQ(&ed.recipientInfos, 1); 645 if (ed.recipientInfos.val == NULL) { 646 ret = ENOMEM; 647 hx509_set_error_string(context, 0, ret, 648 "Failed to allocate recipients info " 649 "for EnvelopedData"); 650 goto out; 651 } 652 653 ri = &ed.recipientInfos.val[0]; 654 655 if (flags & HX509_CMS_EV_ID_NAME) { 656 ri->version = 0; 657 cmsidflag = CMS_ID_NAME; 658 } else { 659 ri->version = 2; 660 cmsidflag = CMS_ID_SKI; 661 } 662 663 ret = fill_CMSIdentifier(cert, cmsidflag, &ri->rid); 664 if (ret) { 665 hx509_set_error_string(context, 0, ret, 666 "Failed to set CMS identifier info " 667 "for EnvelopedData"); 668 goto out; 669 } 670 671 ret = hx509_cert_public_encrypt(context, 672 &key, cert, 673 &ri->keyEncryptionAlgorithm.algorithm, 674 &ri->encryptedKey); 675 if (ret) { 676 hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 677 "Failed to encrypt transport key for " 678 "EnvelopedData"); 679 goto out; 680 } 681 682 /* 683 * 684 */ 685 686 ed.version = 0; 687 ed.originatorInfo = NULL; 688 689 ret = der_copy_oid(contentType, &ed.encryptedContentInfo.contentType); 690 if (ret) { 691 hx509_set_error_string(context, 0, ret, 692 "Failed to copy content oid for " 693 "EnvelopedData"); 694 goto out; 695 } 696 697 ed.unprotectedAttrs = NULL; 698 699 ASN1_MALLOC_ENCODE(EnvelopedData, content->data, content->length, 700 &ed, &size, ret); 701 if (ret) { 702 hx509_set_error_string(context, 0, ret, 703 "Failed to encode EnvelopedData"); 704 goto out; 705 } 706 if (size != content->length) 707 _hx509_abort("internal ASN.1 encoder error"); 708 709out: 710 if (crypto) 711 hx509_crypto_destroy(crypto); 712 if (ret) 713 der_free_octet_string(content); 714 der_free_octet_string(&key); 715 der_free_octet_string(&ivec); 716 free_EnvelopedData(&ed); 717 718 return ret; 719} 720 721static int 722any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs) 723{ 724 int ret; 725 size_t i; 726 727 if (sd->certificates == NULL) 728 return 0; 729 730 for (i = 0; i < sd->certificates->len; i++) { 731 hx509_cert c; 732 733 ret = hx509_cert_init_data(context, 734 sd->certificates->val[i].data, 735 sd->certificates->val[i].length, 736 &c); 737 if (ret) 738 return ret; 739 ret = hx509_certs_add(context, certs, c); 740 hx509_cert_free(c); 741 if (ret) 742 return ret; 743 } 744 745 return 0; 746} 747 748static const Attribute * 749find_attribute(const CMSAttributes *attr, const heim_oid *oid) 750{ 751 size_t i; 752 for (i = 0; i < attr->len; i++) 753 if (der_heim_oid_cmp(&attr->val[i].type, oid) == 0) 754 return &attr->val[i]; 755 return NULL; 756} 757 758/** 759 * Decode SignedData and verify that the signature is correct. 760 * 761 * @param context A hx509 context. 762 * @param ctx a hx509 verify context. 763 * @param flags to control the behaivor of the function. 764 * - HX509_CMS_VS_NO_KU_CHECK - Don't check KeyUsage 765 * - HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH - allow oid mismatch 766 * - HX509_CMS_VS_ALLOW_ZERO_SIGNER - no signer, see below. 767 * @param data pointer to CMS SignedData encoded data. 768 * @param length length of the data that data point to. 769 * @param signedContent external data used for signature. 770 * @param pool certificate pool to build certificates paths. 771 * @param contentType free with der_free_oid(). 772 * @param content the output of the function, free with 773 * der_free_octet_string(). 774 * @param signer_certs list of the cerficates used to sign this 775 * request, free with hx509_certs_free(). 776 * 777 * @ingroup hx509_cms 778 */ 779 780int 781hx509_cms_verify_signed(hx509_context context, 782 hx509_verify_ctx ctx, 783 unsigned int flags, 784 const void *data, 785 size_t length, 786 const heim_octet_string *signedContent, 787 hx509_certs pool, 788 heim_oid *contentType, 789 heim_octet_string *content, 790 hx509_certs *signer_certs) 791{ 792 SignerInfo *signer_info; 793 hx509_cert cert = NULL; 794 hx509_certs certs = NULL; 795 SignedData sd; 796 size_t size; 797 int ret, found_valid_sig; 798 size_t i; 799 800 *signer_certs = NULL; 801 content->data = NULL; 802 content->length = 0; 803 contentType->length = 0; 804 contentType->components = NULL; 805 806 memset(&sd, 0, sizeof(sd)); 807 808 ret = decode_SignedData(data, length, &sd, &size); 809 if (ret) { 810 hx509_set_error_string(context, 0, ret, 811 "Failed to decode SignedData"); 812 goto out; 813 } 814 815 if (sd.encapContentInfo.eContent == NULL && signedContent == NULL) { 816 ret = HX509_CMS_NO_DATA_AVAILABLE; 817 hx509_set_error_string(context, 0, ret, 818 "No content data in SignedData"); 819 goto out; 820 } 821 if (sd.encapContentInfo.eContent && signedContent) { 822 ret = HX509_CMS_NO_DATA_AVAILABLE; 823 hx509_set_error_string(context, 0, ret, 824 "Both external and internal SignedData"); 825 goto out; 826 } 827 828 if (sd.encapContentInfo.eContent) 829 ret = der_copy_octet_string(sd.encapContentInfo.eContent, content); 830 else 831 ret = der_copy_octet_string(signedContent, content); 832 if (ret) { 833 hx509_set_error_string(context, 0, ret, "malloc: out of memory"); 834 goto out; 835 } 836 837 ret = hx509_certs_init(context, "MEMORY:cms-cert-buffer", 838 0, NULL, &certs); 839 if (ret) 840 goto out; 841 842 ret = hx509_certs_init(context, "MEMORY:cms-signer-certs", 843 0, NULL, signer_certs); 844 if (ret) 845 goto out; 846 847 /* XXX Check CMS version */ 848 849 ret = any_to_certs(context, &sd, certs); 850 if (ret) 851 goto out; 852 853 if (pool) { 854 ret = hx509_certs_merge(context, certs, pool); 855 if (ret) 856 goto out; 857 } 858 859 for (found_valid_sig = 0, i = 0; i < sd.signerInfos.len; i++) { 860 heim_octet_string signed_data; 861 const heim_oid *match_oid; 862 heim_oid decode_oid; 863 864 signer_info = &sd.signerInfos.val[i]; 865 match_oid = NULL; 866 867 if (signer_info->signature.length == 0) { 868 ret = HX509_CMS_MISSING_SIGNER_DATA; 869 hx509_set_error_string(context, 0, ret, 870 "SignerInfo %d in SignedData " 871 "missing sigature", i); 872 continue; 873 } 874 875 ret = find_CMSIdentifier(context, &signer_info->sid, certs, 876 _hx509_verify_get_time(ctx), &cert, 877 HX509_QUERY_KU_DIGITALSIGNATURE); 878 if (ret) { 879 /** 880 * If HX509_CMS_VS_NO_KU_CHECK is set, allow more liberal 881 * search for matching certificates by not considering 882 * KeyUsage bits on the certificates. 883 */ 884 if ((flags & HX509_CMS_VS_NO_KU_CHECK) == 0) 885 continue; 886 887 ret = find_CMSIdentifier(context, &signer_info->sid, certs, 888 _hx509_verify_get_time(ctx), &cert, 889 0); 890 if (ret) 891 continue; 892 893 } 894 895 if (signer_info->signedAttrs) { 896 const Attribute *attr; 897 898 CMSAttributes sa; 899 heim_octet_string os; 900 901 sa.val = signer_info->signedAttrs->val; 902 sa.len = signer_info->signedAttrs->len; 903 904 /* verify that sigature exists */ 905 attr = find_attribute(&sa, &asn1_oid_id_pkcs9_messageDigest); 906 if (attr == NULL) { 907 ret = HX509_CRYPTO_SIGNATURE_MISSING; 908 hx509_set_error_string(context, 0, ret, 909 "SignerInfo have signed attributes " 910 "but messageDigest (signature) " 911 "is missing"); 912 goto next_sigature; 913 } 914 if (attr->value.len != 1) { 915 ret = HX509_CRYPTO_SIGNATURE_MISSING; 916 hx509_set_error_string(context, 0, ret, 917 "SignerInfo have more then one " 918 "messageDigest (signature)"); 919 goto next_sigature; 920 } 921 922 ret = decode_MessageDigest(attr->value.val[0].data, 923 attr->value.val[0].length, 924 &os, 925 &size); 926 if (ret) { 927 hx509_set_error_string(context, 0, ret, 928 "Failed to decode " 929 "messageDigest (signature)"); 930 goto next_sigature; 931 } 932 933 ret = _hx509_verify_signature(context, 934 NULL, 935 &signer_info->digestAlgorithm, 936 content, 937 &os); 938 der_free_octet_string(&os); 939 if (ret) { 940 hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 941 "Failed to verify messageDigest"); 942 goto next_sigature; 943 } 944 945 /* 946 * Fetch content oid inside signedAttrs or set it to 947 * id-pkcs7-data. 948 */ 949 attr = find_attribute(&sa, &asn1_oid_id_pkcs9_contentType); 950 if (attr == NULL) { 951 match_oid = &asn1_oid_id_pkcs7_data; 952 } else { 953 if (attr->value.len != 1) { 954 ret = HX509_CMS_DATA_OID_MISMATCH; 955 hx509_set_error_string(context, 0, ret, 956 "More then one oid in signedAttrs"); 957 goto next_sigature; 958 959 } 960 ret = decode_ContentType(attr->value.val[0].data, 961 attr->value.val[0].length, 962 &decode_oid, 963 &size); 964 if (ret) { 965 hx509_set_error_string(context, 0, ret, 966 "Failed to decode " 967 "oid in signedAttrs"); 968 goto next_sigature; 969 } 970 match_oid = &decode_oid; 971 } 972 973 ASN1_MALLOC_ENCODE(CMSAttributes, 974 signed_data.data, 975 signed_data.length, 976 &sa, 977 &size, ret); 978 if (ret) { 979 if (match_oid == &decode_oid) 980 der_free_oid(&decode_oid); 981 hx509_clear_error_string(context); 982 goto next_sigature; 983 } 984 if (size != signed_data.length) 985 _hx509_abort("internal ASN.1 encoder error"); 986 987 } else { 988 signed_data.data = content->data; 989 signed_data.length = content->length; 990 match_oid = &asn1_oid_id_pkcs7_data; 991 } 992 993 /** 994 * If HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH, allow 995 * encapContentInfo mismatch with the oid in signedAttributes 996 * (or if no signedAttributes where use, pkcs7-data oid). 997 * This is only needed to work with broken CMS implementations 998 * that doesn't follow CMS signedAttributes rules. 999 */ 1000 1001 if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType) && 1002 (flags & HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH) == 0) { 1003 ret = HX509_CMS_DATA_OID_MISMATCH; 1004 hx509_set_error_string(context, 0, ret, 1005 "Oid in message mismatch from the expected"); 1006 } 1007 if (match_oid == &decode_oid) 1008 der_free_oid(&decode_oid); 1009 1010 if (ret == 0) { 1011 ret = hx509_verify_signature(context, 1012 cert, 1013 &signer_info->signatureAlgorithm, 1014 &signed_data, 1015 &signer_info->signature); 1016 if (ret) 1017 hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 1018 "Failed to verify signature in " 1019 "CMS SignedData"); 1020 } 1021 if (signer_info->signedAttrs) 1022 free(signed_data.data); 1023 if (ret) 1024 goto next_sigature; 1025 1026 /** 1027 * If HX509_CMS_VS_NO_VALIDATE flags is set, do not verify the 1028 * signing certificates and leave that up to the caller. 1029 */ 1030 1031 if ((flags & HX509_CMS_VS_NO_VALIDATE) == 0) { 1032 ret = hx509_verify_path(context, ctx, cert, certs); 1033 if (ret) 1034 goto next_sigature; 1035 } 1036 1037 ret = hx509_certs_add(context, *signer_certs, cert); 1038 if (ret) 1039 goto next_sigature; 1040 1041 found_valid_sig++; 1042 1043 next_sigature: 1044 if (cert) 1045 hx509_cert_free(cert); 1046 cert = NULL; 1047 } 1048 /** 1049 * If HX509_CMS_VS_ALLOW_ZERO_SIGNER is set, allow empty 1050 * SignerInfo (no signatures). If SignedData have no signatures, 1051 * the function will return 0 with signer_certs set to NULL. Zero 1052 * signers is allowed by the standard, but since its only useful 1053 * in corner cases, it make into a flag that the caller have to 1054 * turn on. 1055 */ 1056 if (sd.signerInfos.len == 0 && (flags & HX509_CMS_VS_ALLOW_ZERO_SIGNER)) { 1057 if (*signer_certs) 1058 hx509_certs_free(signer_certs); 1059 } else if (found_valid_sig == 0) { 1060 if (ret == 0) { 1061 ret = HX509_CMS_SIGNER_NOT_FOUND; 1062 hx509_set_error_string(context, 0, ret, 1063 "No signers where found"); 1064 } 1065 goto out; 1066 } 1067 1068 ret = der_copy_oid(&sd.encapContentInfo.eContentType, contentType); 1069 if (ret) { 1070 hx509_clear_error_string(context); 1071 goto out; 1072 } 1073 1074out: 1075 free_SignedData(&sd); 1076 if (certs) 1077 hx509_certs_free(&certs); 1078 if (ret) { 1079 if (content->data) 1080 der_free_octet_string(content); 1081 if (*signer_certs) 1082 hx509_certs_free(signer_certs); 1083 der_free_oid(contentType); 1084 der_free_octet_string(content); 1085 } 1086 1087 return ret; 1088} 1089 1090static int 1091add_one_attribute(Attribute **attr, 1092 unsigned int *len, 1093 const heim_oid *oid, 1094 heim_octet_string *data) 1095{ 1096 void *d; 1097 int ret; 1098 1099 d = realloc(*attr, sizeof((*attr)[0]) * (*len + 1)); 1100 if (d == NULL) 1101 return ENOMEM; 1102 (*attr) = d; 1103 1104 ret = der_copy_oid(oid, &(*attr)[*len].type); 1105 if (ret) 1106 return ret; 1107 1108 ALLOC_SEQ(&(*attr)[*len].value, 1); 1109 if ((*attr)[*len].value.val == NULL) { 1110 der_free_oid(&(*attr)[*len].type); 1111 return ENOMEM; 1112 } 1113 1114 (*attr)[*len].value.val[0].data = data->data; 1115 (*attr)[*len].value.val[0].length = data->length; 1116 1117 *len += 1; 1118 1119 return 0; 1120} 1121 1122/** 1123 * Decode SignedData and verify that the signature is correct. 1124 * 1125 * @param context A hx509 context. 1126 * @param flags 1127 * @param eContentType the type of the data. 1128 * @param data data to sign 1129 * @param length length of the data that data point to. 1130 * @param digest_alg digest algorithm to use, use NULL to get the 1131 * default or the peer determined algorithm. 1132 * @param cert certificate to use for sign the data. 1133 * @param peer info about the peer the message to send the message to, 1134 * like what digest algorithm to use. 1135 * @param anchors trust anchors that the client will use, used to 1136 * polulate the certificates included in the message 1137 * @param pool certificates to use in try to build the path to the 1138 * trust anchors. 1139 * @param signed_data the output of the function, free with 1140 * der_free_octet_string(). 1141 * 1142 * @ingroup hx509_cms 1143 */ 1144 1145int 1146hx509_cms_create_signed_1(hx509_context context, 1147 int flags, 1148 const heim_oid *eContentType, 1149 const void *data, size_t length, 1150 const AlgorithmIdentifier *digest_alg, 1151 hx509_cert cert, 1152 hx509_peer_info peer, 1153 hx509_certs anchors, 1154 hx509_certs pool, 1155 heim_octet_string *signed_data) 1156{ 1157 hx509_certs certs; 1158 int ret = 0; 1159 1160 signed_data->data = NULL; 1161 signed_data->length = 0; 1162 1163 ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs); 1164 if (ret) 1165 return ret; 1166 ret = hx509_certs_add(context, certs, cert); 1167 if (ret) 1168 goto out; 1169 1170 ret = hx509_cms_create_signed(context, flags, eContentType, data, length, 1171 digest_alg, certs, peer, anchors, pool, 1172 signed_data); 1173 1174 out: 1175 hx509_certs_free(&certs); 1176 return ret; 1177} 1178 1179struct sigctx { 1180 SignedData sd; 1181 const AlgorithmIdentifier *digest_alg; 1182 const heim_oid *eContentType; 1183 heim_octet_string content; 1184 hx509_peer_info peer; 1185 int cmsidflag; 1186 int leafonly; 1187 hx509_certs certs; 1188 hx509_certs anchors; 1189 hx509_certs pool; 1190}; 1191 1192static int 1193sig_process(hx509_context context, void *ctx, hx509_cert cert) 1194{ 1195 struct sigctx *sigctx = ctx; 1196 heim_octet_string buf, sigdata = { 0, NULL }; 1197 SignerInfo *signer_info = NULL; 1198 AlgorithmIdentifier digest; 1199 size_t size; 1200 void *ptr; 1201 int ret; 1202 SignedData *sd = &sigctx->sd; 1203 hx509_path path; 1204 1205 memset(&digest, 0, sizeof(digest)); 1206 memset(&path, 0, sizeof(path)); 1207 1208 if (_hx509_cert_private_key(cert) == NULL) { 1209 hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, 1210 "Private key missing for signing"); 1211 return HX509_PRIVATE_KEY_MISSING; 1212 } 1213 1214 if (sigctx->digest_alg) { 1215 ret = copy_AlgorithmIdentifier(sigctx->digest_alg, &digest); 1216 if (ret) 1217 hx509_clear_error_string(context); 1218 } else { 1219 ret = hx509_crypto_select(context, HX509_SELECT_DIGEST, 1220 _hx509_cert_private_key(cert), 1221 sigctx->peer, &digest); 1222 } 1223 if (ret) 1224 goto out; 1225 1226 /* 1227 * Allocate on more signerInfo and do the signature processing 1228 */ 1229 1230 ptr = realloc(sd->signerInfos.val, 1231 (sd->signerInfos.len + 1) * sizeof(sd->signerInfos.val[0])); 1232 if (ptr == NULL) { 1233 ret = ENOMEM; 1234 goto out; 1235 } 1236 sd->signerInfos.val = ptr; 1237 1238 signer_info = &sd->signerInfos.val[sd->signerInfos.len]; 1239 1240 memset(signer_info, 0, sizeof(*signer_info)); 1241 1242 signer_info->version = 1; 1243 1244 ret = fill_CMSIdentifier(cert, sigctx->cmsidflag, &signer_info->sid); 1245 if (ret) { 1246 hx509_clear_error_string(context); 1247 goto out; 1248 } 1249 1250 signer_info->signedAttrs = NULL; 1251 signer_info->unsignedAttrs = NULL; 1252 1253 ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm); 1254 if (ret) { 1255 hx509_clear_error_string(context); 1256 goto out; 1257 } 1258 1259 /* 1260 * If it isn't pkcs7-data send signedAttributes 1261 */ 1262 1263 if (der_heim_oid_cmp(sigctx->eContentType, &asn1_oid_id_pkcs7_data) != 0) { 1264 CMSAttributes sa; 1265 heim_octet_string sig; 1266 1267 ALLOC(signer_info->signedAttrs, 1); 1268 if (signer_info->signedAttrs == NULL) { 1269 ret = ENOMEM; 1270 goto out; 1271 } 1272 1273 ret = _hx509_create_signature(context, 1274 NULL, 1275 &digest, 1276 &sigctx->content, 1277 NULL, 1278 &sig); 1279 if (ret) 1280 goto out; 1281 1282 ASN1_MALLOC_ENCODE(MessageDigest, 1283 buf.data, 1284 buf.length, 1285 &sig, 1286 &size, 1287 ret); 1288 der_free_octet_string(&sig); 1289 if (ret) { 1290 hx509_clear_error_string(context); 1291 goto out; 1292 } 1293 if (size != buf.length) 1294 _hx509_abort("internal ASN.1 encoder error"); 1295 1296 ret = add_one_attribute(&signer_info->signedAttrs->val, 1297 &signer_info->signedAttrs->len, 1298 &asn1_oid_id_pkcs9_messageDigest, 1299 &buf); 1300 if (ret) { 1301 free(buf.data); 1302 hx509_clear_error_string(context); 1303 goto out; 1304 } 1305 1306 1307 ASN1_MALLOC_ENCODE(ContentType, 1308 buf.data, 1309 buf.length, 1310 sigctx->eContentType, 1311 &size, 1312 ret); 1313 if (ret) 1314 goto out; 1315 if (size != buf.length) 1316 _hx509_abort("internal ASN.1 encoder error"); 1317 1318 ret = add_one_attribute(&signer_info->signedAttrs->val, 1319 &signer_info->signedAttrs->len, 1320 &asn1_oid_id_pkcs9_contentType, 1321 &buf); 1322 if (ret) { 1323 free(buf.data); 1324 hx509_clear_error_string(context); 1325 goto out; 1326 } 1327 1328 sa.val = signer_info->signedAttrs->val; 1329 sa.len = signer_info->signedAttrs->len; 1330 1331 ASN1_MALLOC_ENCODE(CMSAttributes, 1332 sigdata.data, 1333 sigdata.length, 1334 &sa, 1335 &size, 1336 ret); 1337 if (ret) { 1338 hx509_clear_error_string(context); 1339 goto out; 1340 } 1341 if (size != sigdata.length) 1342 _hx509_abort("internal ASN.1 encoder error"); 1343 } else { 1344 sigdata.data = sigctx->content.data; 1345 sigdata.length = sigctx->content.length; 1346 } 1347 1348 { 1349 AlgorithmIdentifier sigalg; 1350 1351 ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG, 1352 _hx509_cert_private_key(cert), sigctx->peer, 1353 &sigalg); 1354 if (ret) 1355 goto out; 1356 1357 ret = _hx509_create_signature(context, 1358 _hx509_cert_private_key(cert), 1359 &sigalg, 1360 &sigdata, 1361 &signer_info->signatureAlgorithm, 1362 &signer_info->signature); 1363 free_AlgorithmIdentifier(&sigalg); 1364 if (ret) 1365 goto out; 1366 } 1367 1368 sigctx->sd.signerInfos.len++; 1369 signer_info = NULL; 1370 1371 /* 1372 * Provide best effort path 1373 */ 1374 if (sigctx->certs) { 1375 unsigned int i; 1376 1377 if (sigctx->pool && sigctx->leafonly == 0) { 1378 _hx509_calculate_path(context, 1379 HX509_CALCULATE_PATH_NO_ANCHOR, 1380 time(NULL), 1381 sigctx->anchors, 1382 0, 1383 cert, 1384 sigctx->pool, 1385 &path); 1386 } else 1387 _hx509_path_append(context, &path, cert); 1388 1389 for (i = 0; i < path.len; i++) { 1390 /* XXX remove dups */ 1391 ret = hx509_certs_add(context, sigctx->certs, path.val[i]); 1392 if (ret) { 1393 hx509_clear_error_string(context); 1394 goto out; 1395 } 1396 } 1397 } 1398 1399 out: 1400 if (signer_info) 1401 free_SignerInfo(signer_info); 1402 if (sigdata.data != sigctx->content.data) 1403 der_free_octet_string(&sigdata); 1404 _hx509_path_free(&path); 1405 free_AlgorithmIdentifier(&digest); 1406 1407 return ret; 1408} 1409 1410static int 1411cert_process(hx509_context context, void *ctx, hx509_cert cert) 1412{ 1413 struct sigctx *sigctx = ctx; 1414 const unsigned int i = sigctx->sd.certificates->len; 1415 void *ptr; 1416 int ret; 1417 1418 ptr = realloc(sigctx->sd.certificates->val, 1419 (i + 1) * sizeof(sigctx->sd.certificates->val[0])); 1420 if (ptr == NULL) 1421 return ENOMEM; 1422 sigctx->sd.certificates->val = ptr; 1423 1424 ret = hx509_cert_binary(context, cert, 1425 &sigctx->sd.certificates->val[i]); 1426 if (ret == 0) 1427 sigctx->sd.certificates->len++; 1428 1429 return ret; 1430} 1431 1432static int 1433cmp_AlgorithmIdentifier(const AlgorithmIdentifier *p, const AlgorithmIdentifier *q) 1434{ 1435 return der_heim_oid_cmp(&p->algorithm, &q->algorithm); 1436} 1437 1438int 1439hx509_cms_create_signed(hx509_context context, 1440 int flags, 1441 const heim_oid *eContentType, 1442 const void *data, size_t length, 1443 const AlgorithmIdentifier *digest_alg, 1444 hx509_certs certs, 1445 hx509_peer_info peer, 1446 hx509_certs anchors, 1447 hx509_certs pool, 1448 heim_octet_string *signed_data) 1449{ 1450 unsigned int i, j; 1451 hx509_name name; 1452 int ret; 1453 size_t size; 1454 struct sigctx sigctx; 1455 1456 memset(&sigctx, 0, sizeof(sigctx)); 1457 memset(&name, 0, sizeof(name)); 1458 1459 if (eContentType == NULL) 1460 eContentType = &asn1_oid_id_pkcs7_data; 1461 1462 sigctx.digest_alg = digest_alg; 1463 sigctx.content.data = rk_UNCONST(data); 1464 sigctx.content.length = length; 1465 sigctx.eContentType = eContentType; 1466 sigctx.peer = peer; 1467 /** 1468 * Use HX509_CMS_SIGNATURE_ID_NAME to preferred use of issuer name 1469 * and serial number if possible. Otherwise subject key identifier 1470 * will preferred. 1471 */ 1472 if (flags & HX509_CMS_SIGNATURE_ID_NAME) 1473 sigctx.cmsidflag = CMS_ID_NAME; 1474 else 1475 sigctx.cmsidflag = CMS_ID_SKI; 1476 1477 /** 1478 * Use HX509_CMS_SIGNATURE_LEAF_ONLY to only request leaf 1479 * certificates to be added to the SignedData. 1480 */ 1481 sigctx.leafonly = (flags & HX509_CMS_SIGNATURE_LEAF_ONLY) ? 1 : 0; 1482 1483 /** 1484 * Use HX509_CMS_NO_CERTS to make the SignedData contain no 1485 * certificates, overrides HX509_CMS_SIGNATURE_LEAF_ONLY. 1486 */ 1487 1488 if ((flags & HX509_CMS_SIGNATURE_NO_CERTS) == 0) { 1489 ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &sigctx.certs); 1490 if (ret) 1491 return ret; 1492 } 1493 1494 sigctx.anchors = anchors; 1495 sigctx.pool = pool; 1496 1497 sigctx.sd.version = CMSVersion_v3; 1498 1499 der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType); 1500 1501 /** 1502 * Use HX509_CMS_SIGNATURE_DETACHED to create detached signatures. 1503 */ 1504 if ((flags & HX509_CMS_SIGNATURE_DETACHED) == 0) { 1505 ALLOC(sigctx.sd.encapContentInfo.eContent, 1); 1506 if (sigctx.sd.encapContentInfo.eContent == NULL) { 1507 hx509_clear_error_string(context); 1508 ret = ENOMEM; 1509 goto out; 1510 } 1511 1512 sigctx.sd.encapContentInfo.eContent->data = malloc(length); 1513 if (sigctx.sd.encapContentInfo.eContent->data == NULL) { 1514 hx509_clear_error_string(context); 1515 ret = ENOMEM; 1516 goto out; 1517 } 1518 memcpy(sigctx.sd.encapContentInfo.eContent->data, data, length); 1519 sigctx.sd.encapContentInfo.eContent->length = length; 1520 } 1521 1522 /** 1523 * Use HX509_CMS_SIGNATURE_NO_SIGNER to create no sigInfo (no 1524 * signatures). 1525 */ 1526 if ((flags & HX509_CMS_SIGNATURE_NO_SIGNER) == 0) { 1527 ret = hx509_certs_iter_f(context, certs, sig_process, &sigctx); 1528 if (ret) 1529 goto out; 1530 } 1531 1532 if (sigctx.sd.signerInfos.len) { 1533 1534 /* 1535 * For each signerInfo, collect all different digest types. 1536 */ 1537 for (i = 0; i < sigctx.sd.signerInfos.len; i++) { 1538 AlgorithmIdentifier *di = 1539 &sigctx.sd.signerInfos.val[i].digestAlgorithm; 1540 1541 for (j = 0; j < sigctx.sd.digestAlgorithms.len; j++) 1542 if (cmp_AlgorithmIdentifier(di, &sigctx.sd.digestAlgorithms.val[j]) == 0) 1543 break; 1544 if (j == sigctx.sd.digestAlgorithms.len) { 1545 ret = add_DigestAlgorithmIdentifiers(&sigctx.sd.digestAlgorithms, di); 1546 if (ret) { 1547 hx509_clear_error_string(context); 1548 goto out; 1549 } 1550 } 1551 } 1552 } 1553 1554 /* 1555 * Add certs we think are needed, build as part of sig_process 1556 */ 1557 if (sigctx.certs) { 1558 ALLOC(sigctx.sd.certificates, 1); 1559 if (sigctx.sd.certificates == NULL) { 1560 hx509_clear_error_string(context); 1561 ret = ENOMEM; 1562 goto out; 1563 } 1564 1565 ret = hx509_certs_iter_f(context, sigctx.certs, cert_process, &sigctx); 1566 if (ret) 1567 goto out; 1568 } 1569 1570 ASN1_MALLOC_ENCODE(SignedData, 1571 signed_data->data, signed_data->length, 1572 &sigctx.sd, &size, ret); 1573 if (ret) { 1574 hx509_clear_error_string(context); 1575 goto out; 1576 } 1577 if (signed_data->length != size) 1578 _hx509_abort("internal ASN.1 encoder error"); 1579 1580out: 1581 hx509_certs_free(&sigctx.certs); 1582 free_SignedData(&sigctx.sd); 1583 1584 return ret; 1585} 1586 1587int 1588hx509_cms_decrypt_encrypted(hx509_context context, 1589 hx509_lock lock, 1590 const void *data, 1591 size_t length, 1592 heim_oid *contentType, 1593 heim_octet_string *content) 1594{ 1595 heim_octet_string cont; 1596 CMSEncryptedData ed; 1597 AlgorithmIdentifier *ai; 1598 int ret; 1599 1600 memset(content, 0, sizeof(*content)); 1601 memset(&cont, 0, sizeof(cont)); 1602 1603 ret = decode_CMSEncryptedData(data, length, &ed, NULL); 1604 if (ret) { 1605 hx509_set_error_string(context, 0, ret, 1606 "Failed to decode CMSEncryptedData"); 1607 return ret; 1608 } 1609 1610 if (ed.encryptedContentInfo.encryptedContent == NULL) { 1611 ret = HX509_CMS_NO_DATA_AVAILABLE; 1612 hx509_set_error_string(context, 0, ret, 1613 "No content in EncryptedData"); 1614 goto out; 1615 } 1616 1617 ret = der_copy_oid(&ed.encryptedContentInfo.contentType, contentType); 1618 if (ret) { 1619 hx509_clear_error_string(context); 1620 goto out; 1621 } 1622 1623 ai = &ed.encryptedContentInfo.contentEncryptionAlgorithm; 1624 if (ai->parameters == NULL) { 1625 ret = HX509_ALG_NOT_SUPP; 1626 hx509_clear_error_string(context); 1627 goto out; 1628 } 1629 1630 ret = _hx509_pbe_decrypt(context, 1631 lock, 1632 ai, 1633 ed.encryptedContentInfo.encryptedContent, 1634 &cont); 1635 if (ret) 1636 goto out; 1637 1638 *content = cont; 1639 1640out: 1641 if (ret) { 1642 if (cont.data) 1643 free(cont.data); 1644 } 1645 free_CMSEncryptedData(&ed); 1646 return ret; 1647} 1648