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