1178825Sdfr/* 2233294Sstas * Copyright (c) 2004 - 2007 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "hx_locl.h" 35178825Sdfr 36178825Sdfrstruct ks_pkcs12 { 37178825Sdfr hx509_certs certs; 38178825Sdfr char *fn; 39178825Sdfr}; 40178825Sdfr 41178825Sdfrtypedef int (*collector_func)(hx509_context, 42178825Sdfr struct hx509_collector *, 43178825Sdfr const void *, size_t, 44178825Sdfr const PKCS12_Attributes *); 45178825Sdfr 46178825Sdfrstruct type { 47233294Sstas const heim_oid *oid; 48178825Sdfr collector_func func; 49178825Sdfr}; 50178825Sdfr 51178825Sdfrstatic void 52233294Sstasparse_pkcs12_type(hx509_context, struct hx509_collector *, const heim_oid *, 53178825Sdfr const void *, size_t, const PKCS12_Attributes *); 54178825Sdfr 55178825Sdfr 56178825Sdfrstatic const PKCS12_Attribute * 57178825Sdfrfind_attribute(const PKCS12_Attributes *attrs, const heim_oid *oid) 58178825Sdfr{ 59233294Sstas size_t i; 60178825Sdfr if (attrs == NULL) 61178825Sdfr return NULL; 62178825Sdfr for (i = 0; i < attrs->len; i++) 63178825Sdfr if (der_heim_oid_cmp(oid, &attrs->val[i].attrId) == 0) 64178825Sdfr return &attrs->val[i]; 65178825Sdfr return NULL; 66178825Sdfr} 67178825Sdfr 68178825Sdfrstatic int 69178825SdfrkeyBag_parser(hx509_context context, 70233294Sstas struct hx509_collector *c, 71178825Sdfr const void *data, size_t length, 72178825Sdfr const PKCS12_Attributes *attrs) 73178825Sdfr{ 74178825Sdfr const PKCS12_Attribute *attr; 75178825Sdfr PKCS8PrivateKeyInfo ki; 76178825Sdfr const heim_octet_string *os = NULL; 77178825Sdfr int ret; 78178825Sdfr 79233294Sstas attr = find_attribute(attrs, &asn1_oid_id_pkcs_9_at_localKeyId); 80178825Sdfr if (attr) 81178825Sdfr os = &attr->attrValues; 82178825Sdfr 83178825Sdfr ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL); 84178825Sdfr if (ret) 85178825Sdfr return ret; 86233294Sstas 87178825Sdfr _hx509_collector_private_key_add(context, 88178825Sdfr c, 89178825Sdfr &ki.privateKeyAlgorithm, 90178825Sdfr NULL, 91178825Sdfr &ki.privateKey, 92178825Sdfr os); 93178825Sdfr free_PKCS8PrivateKeyInfo(&ki); 94178825Sdfr return 0; 95178825Sdfr} 96178825Sdfr 97178825Sdfrstatic int 98178825SdfrShroudedKeyBag_parser(hx509_context context, 99233294Sstas struct hx509_collector *c, 100178825Sdfr const void *data, size_t length, 101178825Sdfr const PKCS12_Attributes *attrs) 102178825Sdfr{ 103178825Sdfr PKCS8EncryptedPrivateKeyInfo pk; 104178825Sdfr heim_octet_string content; 105178825Sdfr int ret; 106233294Sstas 107178825Sdfr memset(&pk, 0, sizeof(pk)); 108233294Sstas 109178825Sdfr ret = decode_PKCS8EncryptedPrivateKeyInfo(data, length, &pk, NULL); 110178825Sdfr if (ret) 111178825Sdfr return ret; 112178825Sdfr 113178825Sdfr ret = _hx509_pbe_decrypt(context, 114178825Sdfr _hx509_collector_get_lock(c), 115178825Sdfr &pk.encryptionAlgorithm, 116178825Sdfr &pk.encryptedData, 117178825Sdfr &content); 118178825Sdfr free_PKCS8EncryptedPrivateKeyInfo(&pk); 119178825Sdfr if (ret) 120178825Sdfr return ret; 121178825Sdfr 122178825Sdfr ret = keyBag_parser(context, c, content.data, content.length, attrs); 123178825Sdfr der_free_octet_string(&content); 124178825Sdfr return ret; 125178825Sdfr} 126178825Sdfr 127178825Sdfrstatic int 128178825SdfrcertBag_parser(hx509_context context, 129233294Sstas struct hx509_collector *c, 130178825Sdfr const void *data, size_t length, 131178825Sdfr const PKCS12_Attributes *attrs) 132178825Sdfr{ 133178825Sdfr heim_octet_string os; 134178825Sdfr hx509_cert cert; 135178825Sdfr PKCS12_CertBag cb; 136178825Sdfr int ret; 137178825Sdfr 138178825Sdfr ret = decode_PKCS12_CertBag(data, length, &cb, NULL); 139178825Sdfr if (ret) 140178825Sdfr return ret; 141178825Sdfr 142233294Sstas if (der_heim_oid_cmp(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType)) { 143178825Sdfr free_PKCS12_CertBag(&cb); 144178825Sdfr return 0; 145178825Sdfr } 146178825Sdfr 147233294Sstas ret = decode_PKCS12_OctetString(cb.certValue.data, 148178825Sdfr cb.certValue.length, 149178825Sdfr &os, 150178825Sdfr NULL); 151178825Sdfr free_PKCS12_CertBag(&cb); 152178825Sdfr if (ret) 153178825Sdfr return ret; 154178825Sdfr 155178825Sdfr ret = hx509_cert_init_data(context, os.data, os.length, &cert); 156178825Sdfr der_free_octet_string(&os); 157178825Sdfr if (ret) 158178825Sdfr return ret; 159178825Sdfr 160178825Sdfr ret = _hx509_collector_certs_add(context, c, cert); 161178825Sdfr if (ret) { 162178825Sdfr hx509_cert_free(cert); 163178825Sdfr return ret; 164178825Sdfr } 165178825Sdfr 166178825Sdfr { 167178825Sdfr const PKCS12_Attribute *attr; 168233294Sstas const heim_oid *oids[] = { 169233294Sstas &asn1_oid_id_pkcs_9_at_localKeyId, &asn1_oid_id_pkcs_9_at_friendlyName 170178825Sdfr }; 171233294Sstas size_t i; 172178825Sdfr 173233294Sstas for (i = 0; i < sizeof(oids)/sizeof(oids[0]); i++) { 174233294Sstas const heim_oid *oid = oids[i]; 175178825Sdfr attr = find_attribute(attrs, oid); 176178825Sdfr if (attr) 177178825Sdfr _hx509_set_cert_attribute(context, cert, oid, 178178825Sdfr &attr->attrValues); 179233294Sstas } 180178825Sdfr } 181178825Sdfr 182178825Sdfr hx509_cert_free(cert); 183178825Sdfr 184178825Sdfr return 0; 185178825Sdfr} 186178825Sdfr 187178825Sdfrstatic int 188178825Sdfrparse_safe_content(hx509_context context, 189233294Sstas struct hx509_collector *c, 190178825Sdfr const unsigned char *p, size_t len) 191178825Sdfr{ 192178825Sdfr PKCS12_SafeContents sc; 193233294Sstas int ret; 194233294Sstas size_t i; 195178825Sdfr 196178825Sdfr memset(&sc, 0, sizeof(sc)); 197178825Sdfr 198178825Sdfr ret = decode_PKCS12_SafeContents(p, len, &sc, NULL); 199178825Sdfr if (ret) 200178825Sdfr return ret; 201178825Sdfr 202178825Sdfr for (i = 0; i < sc.len ; i++) 203178825Sdfr parse_pkcs12_type(context, 204178825Sdfr c, 205178825Sdfr &sc.val[i].bagId, 206178825Sdfr sc.val[i].bagValue.data, 207178825Sdfr sc.val[i].bagValue.length, 208178825Sdfr sc.val[i].bagAttributes); 209178825Sdfr 210178825Sdfr free_PKCS12_SafeContents(&sc); 211178825Sdfr return 0; 212178825Sdfr} 213178825Sdfr 214178825Sdfrstatic int 215178825SdfrsafeContent_parser(hx509_context context, 216233294Sstas struct hx509_collector *c, 217178825Sdfr const void *data, size_t length, 218178825Sdfr const PKCS12_Attributes *attrs) 219178825Sdfr{ 220178825Sdfr heim_octet_string os; 221178825Sdfr int ret; 222178825Sdfr 223178825Sdfr ret = decode_PKCS12_OctetString(data, length, &os, NULL); 224178825Sdfr if (ret) 225178825Sdfr return ret; 226178825Sdfr ret = parse_safe_content(context, c, os.data, os.length); 227178825Sdfr der_free_octet_string(&os); 228178825Sdfr return ret; 229178825Sdfr} 230178825Sdfr 231178825Sdfrstatic int 232178825SdfrencryptedData_parser(hx509_context context, 233178825Sdfr struct hx509_collector *c, 234178825Sdfr const void *data, size_t length, 235178825Sdfr const PKCS12_Attributes *attrs) 236178825Sdfr{ 237178825Sdfr heim_octet_string content; 238178825Sdfr heim_oid contentType; 239178825Sdfr int ret; 240233294Sstas 241178825Sdfr memset(&contentType, 0, sizeof(contentType)); 242178825Sdfr 243178825Sdfr ret = hx509_cms_decrypt_encrypted(context, 244178825Sdfr _hx509_collector_get_lock(c), 245178825Sdfr data, length, 246178825Sdfr &contentType, 247178825Sdfr &content); 248178825Sdfr if (ret) 249178825Sdfr return ret; 250178825Sdfr 251233294Sstas if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0) 252178825Sdfr ret = parse_safe_content(context, c, content.data, content.length); 253178825Sdfr 254178825Sdfr der_free_octet_string(&content); 255178825Sdfr der_free_oid(&contentType); 256178825Sdfr return ret; 257178825Sdfr} 258178825Sdfr 259178825Sdfrstatic int 260178825SdfrenvelopedData_parser(hx509_context context, 261178825Sdfr struct hx509_collector *c, 262178825Sdfr const void *data, size_t length, 263178825Sdfr const PKCS12_Attributes *attrs) 264178825Sdfr{ 265178825Sdfr heim_octet_string content; 266178825Sdfr heim_oid contentType; 267178825Sdfr hx509_lock lock; 268178825Sdfr int ret; 269233294Sstas 270178825Sdfr memset(&contentType, 0, sizeof(contentType)); 271178825Sdfr 272178825Sdfr lock = _hx509_collector_get_lock(c); 273178825Sdfr 274178825Sdfr ret = hx509_cms_unenvelope(context, 275178825Sdfr _hx509_lock_unlock_certs(lock), 276178825Sdfr 0, 277178825Sdfr data, length, 278178825Sdfr NULL, 279233294Sstas 0, 280178825Sdfr &contentType, 281178825Sdfr &content); 282178825Sdfr if (ret) { 283233294Sstas hx509_set_error_string(context, HX509_ERROR_APPEND, ret, 284178825Sdfr "PKCS12 failed to unenvelope"); 285178825Sdfr return ret; 286178825Sdfr } 287178825Sdfr 288233294Sstas if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0) 289178825Sdfr ret = parse_safe_content(context, c, content.data, content.length); 290178825Sdfr 291178825Sdfr der_free_octet_string(&content); 292178825Sdfr der_free_oid(&contentType); 293178825Sdfr 294178825Sdfr return ret; 295178825Sdfr} 296178825Sdfr 297178825Sdfr 298178825Sdfrstruct type bagtypes[] = { 299233294Sstas { &asn1_oid_id_pkcs12_keyBag, keyBag_parser }, 300233294Sstas { &asn1_oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser }, 301233294Sstas { &asn1_oid_id_pkcs12_certBag, certBag_parser }, 302233294Sstas { &asn1_oid_id_pkcs7_data, safeContent_parser }, 303233294Sstas { &asn1_oid_id_pkcs7_encryptedData, encryptedData_parser }, 304233294Sstas { &asn1_oid_id_pkcs7_envelopedData, envelopedData_parser } 305178825Sdfr}; 306178825Sdfr 307178825Sdfrstatic void 308178825Sdfrparse_pkcs12_type(hx509_context context, 309178825Sdfr struct hx509_collector *c, 310233294Sstas const heim_oid *oid, 311178825Sdfr const void *data, size_t length, 312178825Sdfr const PKCS12_Attributes *attrs) 313178825Sdfr{ 314233294Sstas size_t i; 315178825Sdfr 316178825Sdfr for (i = 0; i < sizeof(bagtypes)/sizeof(bagtypes[0]); i++) 317233294Sstas if (der_heim_oid_cmp(bagtypes[i].oid, oid) == 0) 318178825Sdfr (*bagtypes[i].func)(context, c, data, length, attrs); 319178825Sdfr} 320178825Sdfr 321178825Sdfrstatic int 322178825Sdfrp12_init(hx509_context context, 323233294Sstas hx509_certs certs, void **data, int flags, 324178825Sdfr const char *residue, hx509_lock lock) 325178825Sdfr{ 326178825Sdfr struct ks_pkcs12 *p12; 327178825Sdfr size_t len; 328178825Sdfr void *buf; 329178825Sdfr PKCS12_PFX pfx; 330178825Sdfr PKCS12_AuthenticatedSafe as; 331233294Sstas int ret; 332233294Sstas size_t i; 333178825Sdfr struct hx509_collector *c; 334178825Sdfr 335178825Sdfr *data = NULL; 336178825Sdfr 337178825Sdfr if (lock == NULL) 338178825Sdfr lock = _hx509_empty_lock; 339178825Sdfr 340178825Sdfr ret = _hx509_collector_alloc(context, lock, &c); 341178825Sdfr if (ret) 342178825Sdfr return ret; 343178825Sdfr 344178825Sdfr p12 = calloc(1, sizeof(*p12)); 345178825Sdfr if (p12 == NULL) { 346178825Sdfr ret = ENOMEM; 347178825Sdfr hx509_set_error_string(context, 0, ret, "out of memory"); 348178825Sdfr goto out; 349178825Sdfr } 350178825Sdfr 351178825Sdfr p12->fn = strdup(residue); 352178825Sdfr if (p12->fn == NULL) { 353178825Sdfr ret = ENOMEM; 354178825Sdfr hx509_set_error_string(context, 0, ret, "out of memory"); 355178825Sdfr goto out; 356178825Sdfr } 357178825Sdfr 358178825Sdfr if (flags & HX509_CERTS_CREATE) { 359178825Sdfr ret = hx509_certs_init(context, "MEMORY:ks-file-create", 360178825Sdfr 0, lock, &p12->certs); 361178825Sdfr if (ret == 0) 362178825Sdfr *data = p12; 363178825Sdfr goto out; 364178825Sdfr } 365178825Sdfr 366233294Sstas ret = rk_undumpdata(residue, &buf, &len); 367178825Sdfr if (ret) { 368178825Sdfr hx509_clear_error_string(context); 369178825Sdfr goto out; 370178825Sdfr } 371178825Sdfr 372178825Sdfr ret = decode_PKCS12_PFX(buf, len, &pfx, NULL); 373233294Sstas rk_xfree(buf); 374178825Sdfr if (ret) { 375178825Sdfr hx509_set_error_string(context, 0, ret, 376178825Sdfr "Failed to decode the PFX in %s", residue); 377178825Sdfr goto out; 378178825Sdfr } 379178825Sdfr 380233294Sstas if (der_heim_oid_cmp(&pfx.authSafe.contentType, &asn1_oid_id_pkcs7_data) != 0) { 381178825Sdfr free_PKCS12_PFX(&pfx); 382178825Sdfr ret = EINVAL; 383178825Sdfr hx509_set_error_string(context, 0, ret, 384178825Sdfr "PKCS PFX isn't a pkcs7-data container"); 385178825Sdfr goto out; 386178825Sdfr } 387178825Sdfr 388178825Sdfr if (pfx.authSafe.content == NULL) { 389178825Sdfr free_PKCS12_PFX(&pfx); 390178825Sdfr ret = EINVAL; 391178825Sdfr hx509_set_error_string(context, 0, ret, 392178825Sdfr "PKCS PFX missing data"); 393178825Sdfr goto out; 394178825Sdfr } 395178825Sdfr 396178825Sdfr { 397178825Sdfr heim_octet_string asdata; 398178825Sdfr 399178825Sdfr ret = decode_PKCS12_OctetString(pfx.authSafe.content->data, 400178825Sdfr pfx.authSafe.content->length, 401178825Sdfr &asdata, 402178825Sdfr NULL); 403178825Sdfr free_PKCS12_PFX(&pfx); 404178825Sdfr if (ret) { 405178825Sdfr hx509_clear_error_string(context); 406178825Sdfr goto out; 407178825Sdfr } 408233294Sstas ret = decode_PKCS12_AuthenticatedSafe(asdata.data, 409178825Sdfr asdata.length, 410178825Sdfr &as, 411178825Sdfr NULL); 412178825Sdfr der_free_octet_string(&asdata); 413178825Sdfr if (ret) { 414178825Sdfr hx509_clear_error_string(context); 415178825Sdfr goto out; 416178825Sdfr } 417178825Sdfr } 418178825Sdfr 419178825Sdfr for (i = 0; i < as.len; i++) 420178825Sdfr parse_pkcs12_type(context, 421178825Sdfr c, 422178825Sdfr &as.val[i].contentType, 423178825Sdfr as.val[i].content->data, 424178825Sdfr as.val[i].content->length, 425178825Sdfr NULL); 426178825Sdfr 427178825Sdfr free_PKCS12_AuthenticatedSafe(&as); 428178825Sdfr 429178825Sdfr ret = _hx509_collector_collect_certs(context, c, &p12->certs); 430178825Sdfr if (ret == 0) 431178825Sdfr *data = p12; 432178825Sdfr 433178825Sdfrout: 434178825Sdfr _hx509_collector_free(c); 435178825Sdfr 436178825Sdfr if (ret && p12) { 437178825Sdfr if (p12->fn) 438178825Sdfr free(p12->fn); 439178825Sdfr if (p12->certs) 440178825Sdfr hx509_certs_free(&p12->certs); 441178825Sdfr free(p12); 442178825Sdfr } 443178825Sdfr 444178825Sdfr return ret; 445178825Sdfr} 446178825Sdfr 447178825Sdfrstatic int 448178825SdfraddBag(hx509_context context, 449178825Sdfr PKCS12_AuthenticatedSafe *as, 450178825Sdfr const heim_oid *oid, 451178825Sdfr void *data, 452178825Sdfr size_t length) 453178825Sdfr{ 454178825Sdfr void *ptr; 455178825Sdfr int ret; 456178825Sdfr 457178825Sdfr ptr = realloc(as->val, sizeof(as->val[0]) * (as->len + 1)); 458178825Sdfr if (ptr == NULL) { 459178825Sdfr hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 460178825Sdfr return ENOMEM; 461178825Sdfr } 462178825Sdfr as->val = ptr; 463178825Sdfr 464178825Sdfr ret = der_copy_oid(oid, &as->val[as->len].contentType); 465178825Sdfr if (ret) { 466178825Sdfr hx509_set_error_string(context, 0, ret, "out of memory"); 467178825Sdfr return ret; 468178825Sdfr } 469233294Sstas 470178825Sdfr as->val[as->len].content = calloc(1, sizeof(*as->val[0].content)); 471178825Sdfr if (as->val[as->len].content == NULL) { 472178825Sdfr der_free_oid(&as->val[as->len].contentType); 473178825Sdfr hx509_set_error_string(context, 0, ENOMEM, "malloc out of memory"); 474178825Sdfr return ENOMEM; 475178825Sdfr } 476178825Sdfr 477178825Sdfr as->val[as->len].content->data = data; 478178825Sdfr as->val[as->len].content->length = length; 479178825Sdfr 480178825Sdfr as->len++; 481178825Sdfr 482178825Sdfr return 0; 483178825Sdfr} 484178825Sdfr 485178825Sdfrstatic int 486178825Sdfrstore_func(hx509_context context, void *ctx, hx509_cert c) 487178825Sdfr{ 488178825Sdfr PKCS12_AuthenticatedSafe *as = ctx; 489178825Sdfr PKCS12_OctetString os; 490178825Sdfr PKCS12_CertBag cb; 491178825Sdfr size_t size; 492178825Sdfr int ret; 493178825Sdfr 494178825Sdfr memset(&os, 0, sizeof(os)); 495178825Sdfr memset(&cb, 0, sizeof(cb)); 496178825Sdfr 497178825Sdfr os.data = NULL; 498178825Sdfr os.length = 0; 499178825Sdfr 500178825Sdfr ret = hx509_cert_binary(context, c, &os); 501178825Sdfr if (ret) 502178825Sdfr return ret; 503178825Sdfr 504178825Sdfr ASN1_MALLOC_ENCODE(PKCS12_OctetString, 505178825Sdfr cb.certValue.data,cb.certValue.length, 506178825Sdfr &os, &size, ret); 507178825Sdfr free(os.data); 508178825Sdfr if (ret) 509178825Sdfr goto out; 510233294Sstas ret = der_copy_oid(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType); 511178825Sdfr if (ret) { 512178825Sdfr free_PKCS12_CertBag(&cb); 513178825Sdfr goto out; 514178825Sdfr } 515178825Sdfr ASN1_MALLOC_ENCODE(PKCS12_CertBag, os.data, os.length, 516178825Sdfr &cb, &size, ret); 517178825Sdfr free_PKCS12_CertBag(&cb); 518178825Sdfr if (ret) 519178825Sdfr goto out; 520178825Sdfr 521233294Sstas ret = addBag(context, as, &asn1_oid_id_pkcs12_certBag, os.data, os.length); 522178825Sdfr 523178825Sdfr if (_hx509_cert_private_key_exportable(c)) { 524178825Sdfr hx509_private_key key = _hx509_cert_private_key(c); 525178825Sdfr PKCS8PrivateKeyInfo pki; 526178825Sdfr 527178825Sdfr memset(&pki, 0, sizeof(pki)); 528178825Sdfr 529178825Sdfr ret = der_parse_hex_heim_integer("00", &pki.version); 530178825Sdfr if (ret) 531178825Sdfr return ret; 532233294Sstas ret = _hx509_private_key_oid(context, key, 533178825Sdfr &pki.privateKeyAlgorithm.algorithm); 534178825Sdfr if (ret) { 535178825Sdfr free_PKCS8PrivateKeyInfo(&pki); 536178825Sdfr return ret; 537178825Sdfr } 538178825Sdfr ret = _hx509_private_key_export(context, 539178825Sdfr _hx509_cert_private_key(c), 540233294Sstas HX509_KEY_FORMAT_DER, 541178825Sdfr &pki.privateKey); 542178825Sdfr if (ret) { 543178825Sdfr free_PKCS8PrivateKeyInfo(&pki); 544178825Sdfr return ret; 545178825Sdfr } 546233294Sstas /* set attribute, asn1_oid_id_pkcs_9_at_localKeyId */ 547178825Sdfr 548178825Sdfr ASN1_MALLOC_ENCODE(PKCS8PrivateKeyInfo, os.data, os.length, 549178825Sdfr &pki, &size, ret); 550178825Sdfr free_PKCS8PrivateKeyInfo(&pki); 551178825Sdfr if (ret) 552178825Sdfr return ret; 553178825Sdfr 554233294Sstas ret = addBag(context, as, &asn1_oid_id_pkcs12_keyBag, os.data, os.length); 555178825Sdfr if (ret) 556178825Sdfr return ret; 557178825Sdfr } 558178825Sdfr 559178825Sdfrout: 560178825Sdfr return ret; 561178825Sdfr} 562178825Sdfr 563178825Sdfrstatic int 564233294Sstasp12_store(hx509_context context, 565178825Sdfr hx509_certs certs, void *data, int flags, hx509_lock lock) 566178825Sdfr{ 567178825Sdfr struct ks_pkcs12 *p12 = data; 568178825Sdfr PKCS12_PFX pfx; 569178825Sdfr PKCS12_AuthenticatedSafe as; 570178825Sdfr PKCS12_OctetString asdata; 571178825Sdfr size_t size; 572178825Sdfr int ret; 573178825Sdfr 574178825Sdfr memset(&as, 0, sizeof(as)); 575178825Sdfr memset(&pfx, 0, sizeof(pfx)); 576178825Sdfr 577233294Sstas ret = hx509_certs_iter_f(context, p12->certs, store_func, &as); 578178825Sdfr if (ret) 579178825Sdfr goto out; 580178825Sdfr 581178825Sdfr ASN1_MALLOC_ENCODE(PKCS12_AuthenticatedSafe, asdata.data, asdata.length, 582178825Sdfr &as, &size, ret); 583178825Sdfr free_PKCS12_AuthenticatedSafe(&as); 584178825Sdfr if (ret) 585178825Sdfr return ret; 586233294Sstas 587178825Sdfr ret = der_parse_hex_heim_integer("03", &pfx.version); 588178825Sdfr if (ret) { 589178825Sdfr free(asdata.data); 590178825Sdfr goto out; 591178825Sdfr } 592178825Sdfr 593178825Sdfr pfx.authSafe.content = calloc(1, sizeof(*pfx.authSafe.content)); 594178825Sdfr 595233294Sstas ASN1_MALLOC_ENCODE(PKCS12_OctetString, 596178825Sdfr pfx.authSafe.content->data, 597178825Sdfr pfx.authSafe.content->length, 598178825Sdfr &asdata, &size, ret); 599178825Sdfr free(asdata.data); 600178825Sdfr if (ret) 601178825Sdfr goto out; 602178825Sdfr 603233294Sstas ret = der_copy_oid(&asn1_oid_id_pkcs7_data, &pfx.authSafe.contentType); 604178825Sdfr if (ret) 605178825Sdfr goto out; 606178825Sdfr 607178825Sdfr ASN1_MALLOC_ENCODE(PKCS12_PFX, asdata.data, asdata.length, 608178825Sdfr &pfx, &size, ret); 609178825Sdfr if (ret) 610178825Sdfr goto out; 611178825Sdfr 612178825Sdfr#if 0 613178825Sdfr const struct _hx509_password *pw; 614178825Sdfr 615178825Sdfr pw = _hx509_lock_get_passwords(lock); 616178825Sdfr if (pw != NULL) { 617178825Sdfr pfx.macData = calloc(1, sizeof(*pfx.macData)); 618178825Sdfr if (pfx.macData == NULL) { 619178825Sdfr ret = ENOMEM; 620178825Sdfr hx509_set_error_string(context, 0, ret, "malloc out of memory"); 621178825Sdfr return ret; 622178825Sdfr } 623178825Sdfr if (pfx.macData == NULL) { 624178825Sdfr free(asdata.data); 625178825Sdfr goto out; 626178825Sdfr } 627178825Sdfr } 628178825Sdfr ret = calculate_hash(&aspath, pw, pfx.macData); 629178825Sdfr#endif 630178825Sdfr 631178825Sdfr rk_dumpdata(p12->fn, asdata.data, asdata.length); 632178825Sdfr free(asdata.data); 633178825Sdfr 634178825Sdfrout: 635178825Sdfr free_PKCS12_AuthenticatedSafe(&as); 636178825Sdfr free_PKCS12_PFX(&pfx); 637178825Sdfr 638178825Sdfr return ret; 639178825Sdfr} 640178825Sdfr 641178825Sdfr 642178825Sdfrstatic int 643178825Sdfrp12_free(hx509_certs certs, void *data) 644178825Sdfr{ 645178825Sdfr struct ks_pkcs12 *p12 = data; 646178825Sdfr hx509_certs_free(&p12->certs); 647178825Sdfr free(p12->fn); 648178825Sdfr free(p12); 649178825Sdfr return 0; 650178825Sdfr} 651178825Sdfr 652233294Sstasstatic int 653178825Sdfrp12_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c) 654178825Sdfr{ 655178825Sdfr struct ks_pkcs12 *p12 = data; 656178825Sdfr return hx509_certs_add(context, p12->certs, c); 657178825Sdfr} 658178825Sdfr 659233294Sstasstatic int 660178825Sdfrp12_iter_start(hx509_context context, 661178825Sdfr hx509_certs certs, 662178825Sdfr void *data, 663178825Sdfr void **cursor) 664178825Sdfr{ 665178825Sdfr struct ks_pkcs12 *p12 = data; 666178825Sdfr return hx509_certs_start_seq(context, p12->certs, cursor); 667178825Sdfr} 668178825Sdfr 669178825Sdfrstatic int 670178825Sdfrp12_iter(hx509_context context, 671178825Sdfr hx509_certs certs, 672178825Sdfr void *data, 673178825Sdfr void *cursor, 674178825Sdfr hx509_cert *cert) 675178825Sdfr{ 676178825Sdfr struct ks_pkcs12 *p12 = data; 677178825Sdfr return hx509_certs_next_cert(context, p12->certs, cursor, cert); 678178825Sdfr} 679178825Sdfr 680178825Sdfrstatic int 681178825Sdfrp12_iter_end(hx509_context context, 682178825Sdfr hx509_certs certs, 683178825Sdfr void *data, 684178825Sdfr void *cursor) 685178825Sdfr{ 686178825Sdfr struct ks_pkcs12 *p12 = data; 687178825Sdfr return hx509_certs_end_seq(context, p12->certs, cursor); 688178825Sdfr} 689178825Sdfr 690178825Sdfrstatic struct hx509_keyset_ops keyset_pkcs12 = { 691178825Sdfr "PKCS12", 692178825Sdfr 0, 693178825Sdfr p12_init, 694178825Sdfr p12_store, 695178825Sdfr p12_free, 696178825Sdfr p12_add, 697178825Sdfr NULL, 698178825Sdfr p12_iter_start, 699178825Sdfr p12_iter, 700178825Sdfr p12_iter_end 701178825Sdfr}; 702178825Sdfr 703178825Sdfrvoid 704178825Sdfr_hx509_ks_pkcs12_register(hx509_context context) 705178825Sdfr{ 706178825Sdfr _hx509_ks_register(context, &keyset_pkcs12); 707178825Sdfr} 708