1 /* 2 * Copyright (c) 2004 - 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 36 struct ks_pkcs12 { 37 hx509_certs certs; 38 char *fn; 39 }; 40 41 typedef int (*collector_func)(hx509_context, 42 struct hx509_collector *, 43 const void *, size_t, 44 const PKCS12_Attributes *); 45 46 struct type { 47 const heim_oid *oid; 48 collector_func func; 49 }; 50 51 static void 52 parse_pkcs12_type(hx509_context, struct hx509_collector *, const heim_oid *, 53 const void *, size_t, const PKCS12_Attributes *); 54 55 56 static const PKCS12_Attribute * 57 find_attribute(const PKCS12_Attributes *attrs, const heim_oid *oid) 58 { 59 size_t i; 60 if (attrs == NULL) 61 return NULL; 62 for (i = 0; i < attrs->len; i++) 63 if (der_heim_oid_cmp(oid, &attrs->val[i].attrId) == 0) 64 return &attrs->val[i]; 65 return NULL; 66 } 67 68 static int 69 keyBag_parser(hx509_context context, 70 struct hx509_collector *c, 71 const void *data, size_t length, 72 const PKCS12_Attributes *attrs) 73 { 74 const PKCS12_Attribute *attr; 75 PKCS8PrivateKeyInfo ki; 76 const heim_octet_string *os = NULL; 77 int ret; 78 79 attr = find_attribute(attrs, &asn1_oid_id_pkcs_9_at_localKeyId); 80 if (attr) 81 os = &attr->attrValues; 82 83 ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL); 84 if (ret) 85 return ret; 86 87 _hx509_collector_private_key_add(context, 88 c, 89 &ki.privateKeyAlgorithm, 90 NULL, 91 &ki.privateKey, 92 os); 93 free_PKCS8PrivateKeyInfo(&ki); 94 return 0; 95 } 96 97 static int 98 ShroudedKeyBag_parser(hx509_context context, 99 struct hx509_collector *c, 100 const void *data, size_t length, 101 const PKCS12_Attributes *attrs) 102 { 103 PKCS8EncryptedPrivateKeyInfo pk; 104 heim_octet_string content; 105 int ret; 106 107 memset(&pk, 0, sizeof(pk)); 108 109 ret = decode_PKCS8EncryptedPrivateKeyInfo(data, length, &pk, NULL); 110 if (ret) 111 return ret; 112 113 ret = _hx509_pbe_decrypt(context, 114 _hx509_collector_get_lock(c), 115 &pk.encryptionAlgorithm, 116 &pk.encryptedData, 117 &content); 118 free_PKCS8EncryptedPrivateKeyInfo(&pk); 119 if (ret) 120 return ret; 121 122 ret = keyBag_parser(context, c, content.data, content.length, attrs); 123 der_free_octet_string(&content); 124 return ret; 125 } 126 127 static int 128 certBag_parser(hx509_context context, 129 struct hx509_collector *c, 130 const void *data, size_t length, 131 const PKCS12_Attributes *attrs) 132 { 133 heim_octet_string os; 134 hx509_cert cert; 135 PKCS12_CertBag cb; 136 int ret; 137 138 ret = decode_PKCS12_CertBag(data, length, &cb, NULL); 139 if (ret) 140 return ret; 141 142 if (der_heim_oid_cmp(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType)) { 143 free_PKCS12_CertBag(&cb); 144 return 0; 145 } 146 147 ret = decode_PKCS12_OctetString(cb.certValue.data, 148 cb.certValue.length, 149 &os, 150 NULL); 151 free_PKCS12_CertBag(&cb); 152 if (ret) 153 return ret; 154 155 ret = hx509_cert_init_data(context, os.data, os.length, &cert); 156 der_free_octet_string(&os); 157 if (ret) 158 return ret; 159 160 ret = _hx509_collector_certs_add(context, c, cert); 161 if (ret) { 162 hx509_cert_free(cert); 163 return ret; 164 } 165 166 { 167 const PKCS12_Attribute *attr; 168 const heim_oid *oids[] = { 169 &asn1_oid_id_pkcs_9_at_localKeyId, &asn1_oid_id_pkcs_9_at_friendlyName 170 }; 171 size_t i; 172 173 for (i = 0; i < sizeof(oids)/sizeof(oids[0]); i++) { 174 const heim_oid *oid = oids[i]; 175 attr = find_attribute(attrs, oid); 176 if (attr) 177 _hx509_set_cert_attribute(context, cert, oid, 178 &attr->attrValues); 179 } 180 } 181 182 hx509_cert_free(cert); 183 184 return 0; 185 } 186 187 static int 188 parse_safe_content(hx509_context context, 189 struct hx509_collector *c, 190 const unsigned char *p, size_t len) 191 { 192 PKCS12_SafeContents sc; 193 int ret; 194 size_t i; 195 196 memset(&sc, 0, sizeof(sc)); 197 198 ret = decode_PKCS12_SafeContents(p, len, &sc, NULL); 199 if (ret) 200 return ret; 201 202 for (i = 0; i < sc.len ; i++) 203 parse_pkcs12_type(context, 204 c, 205 &sc.val[i].bagId, 206 sc.val[i].bagValue.data, 207 sc.val[i].bagValue.length, 208 sc.val[i].bagAttributes); 209 210 free_PKCS12_SafeContents(&sc); 211 return 0; 212 } 213 214 static int 215 safeContent_parser(hx509_context context, 216 struct hx509_collector *c, 217 const void *data, size_t length, 218 const PKCS12_Attributes *attrs) 219 { 220 heim_octet_string os; 221 int ret; 222 223 ret = decode_PKCS12_OctetString(data, length, &os, NULL); 224 if (ret) 225 return ret; 226 ret = parse_safe_content(context, c, os.data, os.length); 227 der_free_octet_string(&os); 228 return ret; 229 } 230 231 static int 232 encryptedData_parser(hx509_context context, 233 struct hx509_collector *c, 234 const void *data, size_t length, 235 const PKCS12_Attributes *attrs) 236 { 237 heim_octet_string content; 238 heim_oid contentType; 239 int ret; 240 241 memset(&contentType, 0, sizeof(contentType)); 242 243 ret = hx509_cms_decrypt_encrypted(context, 244 _hx509_collector_get_lock(c), 245 data, length, 246 &contentType, 247 &content); 248 if (ret) 249 return ret; 250 251 if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0) 252 ret = parse_safe_content(context, c, content.data, content.length); 253 254 der_free_octet_string(&content); 255 der_free_oid(&contentType); 256 return ret; 257 } 258 259 static int 260 envelopedData_parser(hx509_context context, 261 struct hx509_collector *c, 262 const void *data, size_t length, 263 const PKCS12_Attributes *attrs) 264 { 265 heim_octet_string content; 266 heim_oid contentType; 267 hx509_lock lock; 268 int ret; 269 270 memset(&contentType, 0, sizeof(contentType)); 271 272 lock = _hx509_collector_get_lock(c); 273 274 ret = hx509_cms_unenvelope(context, 275 _hx509_lock_unlock_certs(lock), 276 0, 277 data, length, 278 NULL, 279 0, 280 &contentType, 281 &content); 282 if (ret) { 283 hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 284 "PKCS12 failed to unenvelope"); 285 return ret; 286 } 287 288 if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0) 289 ret = parse_safe_content(context, c, content.data, content.length); 290 291 der_free_octet_string(&content); 292 der_free_oid(&contentType); 293 294 return ret; 295 } 296 297 298 struct type bagtypes[] = { 299 { &asn1_oid_id_pkcs12_keyBag, keyBag_parser }, 300 { &asn1_oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser }, 301 { &asn1_oid_id_pkcs12_certBag, certBag_parser }, 302 { &asn1_oid_id_pkcs7_data, safeContent_parser }, 303 { &asn1_oid_id_pkcs7_encryptedData, encryptedData_parser }, 304 { &asn1_oid_id_pkcs7_envelopedData, envelopedData_parser } 305 }; 306 307 static void 308 parse_pkcs12_type(hx509_context context, 309 struct hx509_collector *c, 310 const heim_oid *oid, 311 const void *data, size_t length, 312 const PKCS12_Attributes *attrs) 313 { 314 size_t i; 315 316 for (i = 0; i < sizeof(bagtypes)/sizeof(bagtypes[0]); i++) 317 if (der_heim_oid_cmp(bagtypes[i].oid, oid) == 0) 318 (*bagtypes[i].func)(context, c, data, length, attrs); 319 } 320 321 static int 322 p12_init(hx509_context context, 323 hx509_certs certs, void **data, int flags, 324 const char *residue, hx509_lock lock) 325 { 326 struct ks_pkcs12 *p12; 327 size_t len; 328 void *buf; 329 PKCS12_PFX pfx; 330 PKCS12_AuthenticatedSafe as; 331 int ret; 332 size_t i; 333 struct hx509_collector *c; 334 335 *data = NULL; 336 337 if (lock == NULL) 338 lock = _hx509_empty_lock; 339 340 ret = _hx509_collector_alloc(context, lock, &c); 341 if (ret) 342 return ret; 343 344 p12 = calloc(1, sizeof(*p12)); 345 if (p12 == NULL) { 346 ret = ENOMEM; 347 hx509_set_error_string(context, 0, ret, "out of memory"); 348 goto out; 349 } 350 351 p12->fn = strdup(residue); 352 if (p12->fn == NULL) { 353 ret = ENOMEM; 354 hx509_set_error_string(context, 0, ret, "out of memory"); 355 goto out; 356 } 357 358 if (flags & HX509_CERTS_CREATE) { 359 ret = hx509_certs_init(context, "MEMORY:ks-file-create", 360 0, lock, &p12->certs); 361 if (ret == 0) 362 *data = p12; 363 goto out; 364 } 365 366 ret = rk_undumpdata(residue, &buf, &len); 367 if (ret) { 368 hx509_clear_error_string(context); 369 goto out; 370 } 371 372 ret = decode_PKCS12_PFX(buf, len, &pfx, NULL); 373 rk_xfree(buf); 374 if (ret) { 375 hx509_set_error_string(context, 0, ret, 376 "Failed to decode the PFX in %s", residue); 377 goto out; 378 } 379 380 if (der_heim_oid_cmp(&pfx.authSafe.contentType, &asn1_oid_id_pkcs7_data) != 0) { 381 free_PKCS12_PFX(&pfx); 382 ret = EINVAL; 383 hx509_set_error_string(context, 0, ret, 384 "PKCS PFX isn't a pkcs7-data container"); 385 goto out; 386 } 387 388 if (pfx.authSafe.content == NULL) { 389 free_PKCS12_PFX(&pfx); 390 ret = EINVAL; 391 hx509_set_error_string(context, 0, ret, 392 "PKCS PFX missing data"); 393 goto out; 394 } 395 396 { 397 heim_octet_string asdata; 398 399 ret = decode_PKCS12_OctetString(pfx.authSafe.content->data, 400 pfx.authSafe.content->length, 401 &asdata, 402 NULL); 403 free_PKCS12_PFX(&pfx); 404 if (ret) { 405 hx509_clear_error_string(context); 406 goto out; 407 } 408 ret = decode_PKCS12_AuthenticatedSafe(asdata.data, 409 asdata.length, 410 &as, 411 NULL); 412 der_free_octet_string(&asdata); 413 if (ret) { 414 hx509_clear_error_string(context); 415 goto out; 416 } 417 } 418 419 for (i = 0; i < as.len; i++) 420 parse_pkcs12_type(context, 421 c, 422 &as.val[i].contentType, 423 as.val[i].content->data, 424 as.val[i].content->length, 425 NULL); 426 427 free_PKCS12_AuthenticatedSafe(&as); 428 429 ret = _hx509_collector_collect_certs(context, c, &p12->certs); 430 if (ret == 0) 431 *data = p12; 432 433 out: 434 _hx509_collector_free(c); 435 436 if (ret && p12) { 437 if (p12->fn) 438 free(p12->fn); 439 if (p12->certs) 440 hx509_certs_free(&p12->certs); 441 free(p12); 442 } 443 444 return ret; 445 } 446 447 static int 448 addBag(hx509_context context, 449 PKCS12_AuthenticatedSafe *as, 450 const heim_oid *oid, 451 void *data, 452 size_t length) 453 { 454 void *ptr; 455 int ret; 456 457 ptr = realloc(as->val, sizeof(as->val[0]) * (as->len + 1)); 458 if (ptr == NULL) { 459 hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 460 return ENOMEM; 461 } 462 as->val = ptr; 463 464 ret = der_copy_oid(oid, &as->val[as->len].contentType); 465 if (ret) { 466 hx509_set_error_string(context, 0, ret, "out of memory"); 467 return ret; 468 } 469 470 as->val[as->len].content = calloc(1, sizeof(*as->val[0].content)); 471 if (as->val[as->len].content == NULL) { 472 der_free_oid(&as->val[as->len].contentType); 473 hx509_set_error_string(context, 0, ENOMEM, "malloc out of memory"); 474 return ENOMEM; 475 } 476 477 as->val[as->len].content->data = data; 478 as->val[as->len].content->length = length; 479 480 as->len++; 481 482 return 0; 483 } 484 485 static int 486 store_func(hx509_context context, void *ctx, hx509_cert c) 487 { 488 PKCS12_AuthenticatedSafe *as = ctx; 489 PKCS12_OctetString os; 490 PKCS12_CertBag cb; 491 size_t size; 492 int ret; 493 494 memset(&os, 0, sizeof(os)); 495 memset(&cb, 0, sizeof(cb)); 496 497 os.data = NULL; 498 os.length = 0; 499 500 ret = hx509_cert_binary(context, c, &os); 501 if (ret) 502 return ret; 503 504 ASN1_MALLOC_ENCODE(PKCS12_OctetString, 505 cb.certValue.data,cb.certValue.length, 506 &os, &size, ret); 507 free(os.data); 508 if (ret) 509 goto out; 510 ret = der_copy_oid(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType); 511 if (ret) { 512 free_PKCS12_CertBag(&cb); 513 goto out; 514 } 515 ASN1_MALLOC_ENCODE(PKCS12_CertBag, os.data, os.length, 516 &cb, &size, ret); 517 free_PKCS12_CertBag(&cb); 518 if (ret) 519 goto out; 520 521 ret = addBag(context, as, &asn1_oid_id_pkcs12_certBag, os.data, os.length); 522 523 if (_hx509_cert_private_key_exportable(c)) { 524 hx509_private_key key = _hx509_cert_private_key(c); 525 PKCS8PrivateKeyInfo pki; 526 527 memset(&pki, 0, sizeof(pki)); 528 529 ret = der_parse_hex_heim_integer("00", &pki.version); 530 if (ret) 531 return ret; 532 ret = _hx509_private_key_oid(context, key, 533 &pki.privateKeyAlgorithm.algorithm); 534 if (ret) { 535 free_PKCS8PrivateKeyInfo(&pki); 536 return ret; 537 } 538 ret = _hx509_private_key_export(context, 539 _hx509_cert_private_key(c), 540 HX509_KEY_FORMAT_DER, 541 &pki.privateKey); 542 if (ret) { 543 free_PKCS8PrivateKeyInfo(&pki); 544 return ret; 545 } 546 /* set attribute, asn1_oid_id_pkcs_9_at_localKeyId */ 547 548 ASN1_MALLOC_ENCODE(PKCS8PrivateKeyInfo, os.data, os.length, 549 &pki, &size, ret); 550 free_PKCS8PrivateKeyInfo(&pki); 551 if (ret) 552 return ret; 553 554 ret = addBag(context, as, &asn1_oid_id_pkcs12_keyBag, os.data, os.length); 555 if (ret) 556 return ret; 557 } 558 559 out: 560 return ret; 561 } 562 563 static int 564 p12_store(hx509_context context, 565 hx509_certs certs, void *data, int flags, hx509_lock lock) 566 { 567 struct ks_pkcs12 *p12 = data; 568 PKCS12_PFX pfx; 569 PKCS12_AuthenticatedSafe as; 570 PKCS12_OctetString asdata; 571 size_t size; 572 int ret; 573 574 memset(&as, 0, sizeof(as)); 575 memset(&pfx, 0, sizeof(pfx)); 576 577 ret = hx509_certs_iter_f(context, p12->certs, store_func, &as); 578 if (ret) 579 goto out; 580 581 ASN1_MALLOC_ENCODE(PKCS12_AuthenticatedSafe, asdata.data, asdata.length, 582 &as, &size, ret); 583 free_PKCS12_AuthenticatedSafe(&as); 584 if (ret) 585 return ret; 586 587 ret = der_parse_hex_heim_integer("03", &pfx.version); 588 if (ret) { 589 free(asdata.data); 590 goto out; 591 } 592 593 pfx.authSafe.content = calloc(1, sizeof(*pfx.authSafe.content)); 594 595 ASN1_MALLOC_ENCODE(PKCS12_OctetString, 596 pfx.authSafe.content->data, 597 pfx.authSafe.content->length, 598 &asdata, &size, ret); 599 free(asdata.data); 600 if (ret) 601 goto out; 602 603 ret = der_copy_oid(&asn1_oid_id_pkcs7_data, &pfx.authSafe.contentType); 604 if (ret) 605 goto out; 606 607 ASN1_MALLOC_ENCODE(PKCS12_PFX, asdata.data, asdata.length, 608 &pfx, &size, ret); 609 if (ret) 610 goto out; 611 612 #if 0 613 const struct _hx509_password *pw; 614 615 pw = _hx509_lock_get_passwords(lock); 616 if (pw != NULL) { 617 pfx.macData = calloc(1, sizeof(*pfx.macData)); 618 if (pfx.macData == NULL) { 619 ret = ENOMEM; 620 hx509_set_error_string(context, 0, ret, "malloc out of memory"); 621 return ret; 622 } 623 if (pfx.macData == NULL) { 624 free(asdata.data); 625 goto out; 626 } 627 } 628 ret = calculate_hash(&aspath, pw, pfx.macData); 629 #endif 630 631 rk_dumpdata(p12->fn, asdata.data, asdata.length); 632 free(asdata.data); 633 634 out: 635 free_PKCS12_AuthenticatedSafe(&as); 636 free_PKCS12_PFX(&pfx); 637 638 return ret; 639 } 640 641 642 static int 643 p12_free(hx509_certs certs, void *data) 644 { 645 struct ks_pkcs12 *p12 = data; 646 hx509_certs_free(&p12->certs); 647 free(p12->fn); 648 free(p12); 649 return 0; 650 } 651 652 static int 653 p12_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c) 654 { 655 struct ks_pkcs12 *p12 = data; 656 return hx509_certs_add(context, p12->certs, c); 657 } 658 659 static int 660 p12_iter_start(hx509_context context, 661 hx509_certs certs, 662 void *data, 663 void **cursor) 664 { 665 struct ks_pkcs12 *p12 = data; 666 return hx509_certs_start_seq(context, p12->certs, cursor); 667 } 668 669 static int 670 p12_iter(hx509_context context, 671 hx509_certs certs, 672 void *data, 673 void *cursor, 674 hx509_cert *cert) 675 { 676 struct ks_pkcs12 *p12 = data; 677 return hx509_certs_next_cert(context, p12->certs, cursor, cert); 678 } 679 680 static int 681 p12_iter_end(hx509_context context, 682 hx509_certs certs, 683 void *data, 684 void *cursor) 685 { 686 struct ks_pkcs12 *p12 = data; 687 return hx509_certs_end_seq(context, p12->certs, cursor); 688 } 689 690 static struct hx509_keyset_ops keyset_pkcs12 = { 691 "PKCS12", 692 0, 693 p12_init, 694 p12_store, 695 p12_free, 696 p12_add, 697 NULL, 698 p12_iter_start, 699 p12_iter, 700 p12_iter_end 701 }; 702 703 void 704 _hx509_ks_pkcs12_register(hx509_context context) 705 { 706 _hx509_ks_register(context, &keyset_pkcs12); 707 } 708