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