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