2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
39 unsigned int store_no_priv_keys
;
42 typedef int (*collector_func
)(hx509_context
,
43 struct hx509_collector
*,
46 const PKCS12_Attributes
*);
54 parse_pkcs12_type(hx509_context
, struct hx509_collector
*, int,
55 const heim_oid
*, const void *, size_t,
56 const PKCS12_Attributes
*);
59 static const PKCS12_Attribute
*
60 find_attribute(const PKCS12_Attributes
*attrs
, const heim_oid
*oid
)
65 for (i
= 0; i
< attrs
->len
; i
++)
66 if (der_heim_oid_cmp(oid
, &attrs
->val
[i
].attrId
) == 0)
67 return &attrs
->val
[i
];
72 keyBag_parser(hx509_context context
,
73 struct hx509_collector
*c
,
75 const void *data
, size_t length
,
76 const PKCS12_Attributes
*attrs
)
78 const PKCS12_Attribute
*attr
;
79 PKCS8PrivateKeyInfo ki
;
80 const heim_octet_string
*os
= NULL
;
83 if (flags
& HX509_CERTS_NO_PRIVATE_KEYS
)
86 attr
= find_attribute(attrs
, &asn1_oid_id_pkcs_9_at_localKeyId
);
88 os
= &attr
->attrValues
;
90 ret
= decode_PKCS8PrivateKeyInfo(data
, length
, &ki
, NULL
);
94 ret
= _hx509_collector_private_key_add(context
,
96 &ki
.privateKeyAlgorithm
,
100 free_PKCS8PrivateKeyInfo(&ki
);
105 ShroudedKeyBag_parser(hx509_context context
,
106 struct hx509_collector
*c
,
108 const void *data
, size_t length
,
109 const PKCS12_Attributes
*attrs
)
111 PKCS8EncryptedPrivateKeyInfo pk
;
112 heim_octet_string content
;
115 memset(&pk
, 0, sizeof(pk
));
117 ret
= decode_PKCS8EncryptedPrivateKeyInfo(data
, length
, &pk
, NULL
);
121 ret
= _hx509_pbe_decrypt(context
,
122 _hx509_collector_get_lock(c
),
123 &pk
.encryptionAlgorithm
,
126 free_PKCS8EncryptedPrivateKeyInfo(&pk
);
130 ret
= keyBag_parser(context
, c
, flags
, content
.data
, content
.length
,
132 der_free_octet_string(&content
);
137 certBag_parser(hx509_context context
,
138 struct hx509_collector
*c
,
140 const void *data
, size_t length
,
141 const PKCS12_Attributes
*attrs
)
143 heim_error_t error
= NULL
;
144 heim_octet_string os
;
149 ret
= decode_PKCS12_CertBag(data
, length
, &cb
, NULL
);
153 if (der_heim_oid_cmp(&asn1_oid_id_pkcs_9_at_certTypes_x509
, &cb
.certType
)) {
154 free_PKCS12_CertBag(&cb
);
158 ret
= decode_PKCS12_OctetString(cb
.certValue
.data
,
162 free_PKCS12_CertBag(&cb
);
166 cert
= hx509_cert_init_data(context
, os
.data
, os
.length
, &error
);
167 der_free_octet_string(&os
);
169 ret
= heim_error_get_code(error
);
174 ret
= _hx509_collector_certs_add(context
, c
, cert
);
176 hx509_cert_free(cert
);
181 const PKCS12_Attribute
*attr
;
182 const heim_oid
*oids
[] = {
183 &asn1_oid_id_pkcs_9_at_localKeyId
, &asn1_oid_id_pkcs_9_at_friendlyName
187 for (i
= 0; i
< sizeof(oids
)/sizeof(oids
[0]); i
++) {
188 const heim_oid
*oid
= oids
[i
];
189 attr
= find_attribute(attrs
, oid
);
191 _hx509_set_cert_attribute(context
, cert
, oid
,
196 hx509_cert_free(cert
);
202 parse_safe_content(hx509_context context
,
203 struct hx509_collector
*c
,
205 const unsigned char *p
, size_t len
)
207 PKCS12_SafeContents sc
;
211 memset(&sc
, 0, sizeof(sc
));
213 ret
= decode_PKCS12_SafeContents(p
, len
, &sc
, NULL
);
217 for (i
= 0; i
< sc
.len
; i
++)
218 parse_pkcs12_type(context
,
222 sc
.val
[i
].bagValue
.data
,
223 sc
.val
[i
].bagValue
.length
,
224 sc
.val
[i
].bagAttributes
);
226 free_PKCS12_SafeContents(&sc
);
231 safeContent_parser(hx509_context context
,
232 struct hx509_collector
*c
,
234 const void *data
, size_t length
,
235 const PKCS12_Attributes
*attrs
)
237 heim_octet_string os
;
240 ret
= decode_PKCS12_OctetString(data
, length
, &os
, NULL
);
243 ret
= parse_safe_content(context
, c
, flags
, os
.data
, os
.length
);
244 der_free_octet_string(&os
);
249 encryptedData_parser(hx509_context context
,
250 struct hx509_collector
*c
,
252 const void *data
, size_t length
,
253 const PKCS12_Attributes
*attrs
)
255 heim_octet_string content
;
256 heim_oid contentType
;
259 memset(&contentType
, 0, sizeof(contentType
));
261 ret
= hx509_cms_decrypt_encrypted(context
,
262 _hx509_collector_get_lock(c
),
269 if (der_heim_oid_cmp(&contentType
, &asn1_oid_id_pkcs7_data
) == 0)
270 ret
= parse_safe_content(context
, c
, flags
,
271 content
.data
, content
.length
);
273 der_free_octet_string(&content
);
274 der_free_oid(&contentType
);
279 envelopedData_parser(hx509_context context
,
280 struct hx509_collector
*c
,
282 const void *data
, size_t length
,
283 const PKCS12_Attributes
*attrs
)
285 heim_octet_string content
;
286 heim_oid contentType
;
290 memset(&contentType
, 0, sizeof(contentType
));
292 lock
= _hx509_collector_get_lock(c
);
294 ret
= hx509_cms_unenvelope(context
,
295 _hx509_lock_unlock_certs(lock
),
303 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
304 "PKCS12 failed to unenvelope");
308 if (der_heim_oid_cmp(&contentType
, &asn1_oid_id_pkcs7_data
) == 0)
309 ret
= parse_safe_content(context
, c
, flags
,
310 content
.data
, content
.length
);
312 der_free_octet_string(&content
);
313 der_free_oid(&contentType
);
319 struct type bagtypes
[] = {
320 { &asn1_oid_id_pkcs12_keyBag
, keyBag_parser
},
321 { &asn1_oid_id_pkcs12_pkcs8ShroudedKeyBag
, ShroudedKeyBag_parser
},
322 { &asn1_oid_id_pkcs12_certBag
, certBag_parser
},
323 { &asn1_oid_id_pkcs7_data
, safeContent_parser
},
324 { &asn1_oid_id_pkcs7_encryptedData
, encryptedData_parser
},
325 { &asn1_oid_id_pkcs7_envelopedData
, envelopedData_parser
}
329 parse_pkcs12_type(hx509_context context
,
330 struct hx509_collector
*c
,
333 const void *data
, size_t length
,
334 const PKCS12_Attributes
*attrs
)
338 for (i
= 0; i
< sizeof(bagtypes
)/sizeof(bagtypes
[0]); i
++)
339 if (der_heim_oid_cmp(bagtypes
[i
].oid
, oid
) == 0)
340 (*bagtypes
[i
].func
)(context
, c
, flags
, data
, length
, attrs
);
344 p12_init(hx509_context context
,
345 hx509_certs certs
, void **data
, int flags
,
346 const char *residue
, hx509_lock lock
)
348 struct ks_pkcs12
*p12
;
352 PKCS12_AuthenticatedSafe as
;
355 struct hx509_collector
*c
;
359 if (residue
== NULL
|| residue
[0] == '\0') {
360 hx509_set_error_string(context
, 0, EINVAL
,
361 "PKCS#12 file not specified");
366 lock
= _hx509_empty_lock
;
368 ret
= _hx509_collector_alloc(context
, lock
, &c
);
372 p12
= calloc(1, sizeof(*p12
));
375 hx509_set_error_string(context
, 0, ret
, "out of memory");
379 p12
->fn
= strdup(residue
);
380 if (p12
->fn
== NULL
) {
382 hx509_set_error_string(context
, 0, ret
, "out of memory");
386 if (flags
& HX509_CERTS_CREATE
) {
387 ret
= hx509_certs_init(context
, "MEMORY:ks-file-create",
388 0, lock
, &p12
->certs
);
394 ret
= rk_undumpdata(residue
, &buf
, &len
);
396 hx509_clear_error_string(context
);
400 ret
= decode_PKCS12_PFX(buf
, len
, &pfx
, NULL
);
403 hx509_set_error_string(context
, 0, ret
,
404 "Failed to decode the PFX in %s", residue
);
408 if (der_heim_oid_cmp(&pfx
.authSafe
.contentType
, &asn1_oid_id_pkcs7_data
) != 0) {
409 free_PKCS12_PFX(&pfx
);
411 hx509_set_error_string(context
, 0, ret
,
412 "PKCS PFX isn't a pkcs7-data container");
416 if (pfx
.authSafe
.content
== NULL
) {
417 free_PKCS12_PFX(&pfx
);
419 hx509_set_error_string(context
, 0, ret
,
420 "PKCS PFX missing data");
425 heim_octet_string asdata
;
427 ret
= decode_PKCS12_OctetString(pfx
.authSafe
.content
->data
,
428 pfx
.authSafe
.content
->length
,
431 free_PKCS12_PFX(&pfx
);
433 hx509_clear_error_string(context
);
436 ret
= decode_PKCS12_AuthenticatedSafe(asdata
.data
,
440 der_free_octet_string(&asdata
);
442 hx509_clear_error_string(context
);
447 for (i
= 0; i
< as
.len
; i
++)
448 parse_pkcs12_type(context
,
451 &as
.val
[i
].contentType
,
452 as
.val
[i
].content
->data
,
453 as
.val
[i
].content
->length
,
456 free_PKCS12_AuthenticatedSafe(&as
);
458 ret
= _hx509_collector_collect_certs(context
, c
, &p12
->certs
);
463 _hx509_collector_free(c
);
469 hx509_certs_free(&p12
->certs
);
477 addBag(hx509_context context
,
478 PKCS12_AuthenticatedSafe
*as
,
486 ptr
= realloc(as
->val
, sizeof(as
->val
[0]) * (as
->len
+ 1));
488 hx509_set_error_string(context
, 0, ENOMEM
, "out of memory");
493 ret
= der_copy_oid(oid
, &as
->val
[as
->len
].contentType
);
495 hx509_set_error_string(context
, 0, ret
, "out of memory");
499 as
->val
[as
->len
].content
= calloc(1, sizeof(*as
->val
[0].content
));
500 if (as
->val
[as
->len
].content
== NULL
) {
501 der_free_oid(&as
->val
[as
->len
].contentType
);
502 hx509_set_error_string(context
, 0, ENOMEM
, "malloc out of memory");
506 as
->val
[as
->len
].content
->data
= data
;
507 as
->val
[as
->len
].content
->length
= length
;
514 struct store_func_ctx
{
515 PKCS12_AuthenticatedSafe as
;
519 static int HX509_LIB_CALL
520 store_func(hx509_context context
, void *d
, hx509_cert c
)
522 struct store_func_ctx
*ctx
= d
;
523 PKCS12_OctetString os
;
528 if ((ctx
->store_flags
& HX509_CERTS_STORE_NO_ROOTS
)) {
531 ret
= hx509_cert_is_root(context
, c
, &is_root
);
536 memset(&os
, 0, sizeof(os
));
537 memset(&cb
, 0, sizeof(cb
));
542 ret
= hx509_cert_binary(context
, c
, &os
);
546 ASN1_MALLOC_ENCODE(PKCS12_OctetString
,
547 cb
.certValue
.data
,cb
.certValue
.length
,
552 ret
= der_copy_oid(&asn1_oid_id_pkcs_9_at_certTypes_x509
, &cb
.certType
);
554 free_PKCS12_CertBag(&cb
);
557 ASN1_MALLOC_ENCODE(PKCS12_CertBag
, os
.data
, os
.length
,
559 free_PKCS12_CertBag(&cb
);
563 ret
= addBag(context
, &ctx
->as
, &asn1_oid_id_pkcs12_certBag
, os
.data
,
566 if (_hx509_cert_private_key_exportable(c
) &&
567 !(ctx
->store_flags
& HX509_CERTS_STORE_NO_PRIVATE_KEYS
)) {
568 hx509_private_key key
= _hx509_cert_private_key(c
);
569 PKCS8PrivateKeyInfo pki
;
571 memset(&pki
, 0, sizeof(pki
));
573 ret
= der_parse_hex_heim_integer("00", &pki
.version
);
576 ret
= _hx509_private_key_oid(context
, key
,
577 &pki
.privateKeyAlgorithm
.algorithm
);
579 free_PKCS8PrivateKeyInfo(&pki
);
582 ret
= _hx509_private_key_export(context
,
583 _hx509_cert_private_key(c
),
584 HX509_KEY_FORMAT_DER
,
587 free_PKCS8PrivateKeyInfo(&pki
);
590 /* set attribute, asn1_oid_id_pkcs_9_at_localKeyId */
592 ASN1_MALLOC_ENCODE(PKCS8PrivateKeyInfo
, os
.data
, os
.length
,
594 free_PKCS8PrivateKeyInfo(&pki
);
598 ret
= addBag(context
, &ctx
->as
, &asn1_oid_id_pkcs12_keyBag
, os
.data
,
609 p12_store(hx509_context context
,
610 hx509_certs certs
, void *data
, int flags
, hx509_lock lock
)
612 struct ks_pkcs12
*p12
= data
;
614 struct store_func_ctx ctx
;
615 PKCS12_OctetString asdata
;
619 memset(&ctx
, 0, sizeof(ctx
));
620 memset(&pfx
, 0, sizeof(pfx
));
621 ctx
.store_flags
= flags
;
623 ret
= hx509_certs_iter_f(context
, p12
->certs
, store_func
, &ctx
);
627 ASN1_MALLOC_ENCODE(PKCS12_AuthenticatedSafe
, asdata
.data
, asdata
.length
,
628 &ctx
.as
, &size
, ret
);
629 free_PKCS12_AuthenticatedSafe(&ctx
.as
);
633 ret
= der_parse_hex_heim_integer("03", &pfx
.version
);
639 pfx
.authSafe
.content
= calloc(1, sizeof(*pfx
.authSafe
.content
));
641 ASN1_MALLOC_ENCODE(PKCS12_OctetString
,
642 pfx
.authSafe
.content
->data
,
643 pfx
.authSafe
.content
->length
,
644 &asdata
, &size
, ret
);
649 ret
= der_copy_oid(&asn1_oid_id_pkcs7_data
, &pfx
.authSafe
.contentType
);
653 ASN1_MALLOC_ENCODE(PKCS12_PFX
, asdata
.data
, asdata
.length
,
659 const struct _hx509_password
*pw
;
661 pw
= _hx509_lock_get_passwords(lock
);
663 pfx
.macData
= calloc(1, sizeof(*pfx
.macData
));
664 if (pfx
.macData
== NULL
) {
666 hx509_set_error_string(context
, 0, ret
, "malloc out of memory");
669 if (pfx
.macData
== NULL
) {
674 ret
= calculate_hash(&aspath
, pw
, pfx
.macData
);
677 rk_dumpdata(p12
->fn
, asdata
.data
, asdata
.length
);
681 free_PKCS12_AuthenticatedSafe(&ctx
.as
);
682 free_PKCS12_PFX(&pfx
);
689 p12_free(hx509_certs certs
, void *data
)
691 struct ks_pkcs12
*p12
= data
;
692 hx509_certs_free(&p12
->certs
);
699 p12_add(hx509_context context
, hx509_certs certs
, void *data
, hx509_cert c
)
701 struct ks_pkcs12
*p12
= data
;
702 return hx509_certs_add(context
, p12
->certs
, c
);
706 p12_iter_start(hx509_context context
,
711 struct ks_pkcs12
*p12
= data
;
712 return hx509_certs_start_seq(context
, p12
->certs
, cursor
);
716 p12_iter(hx509_context context
,
722 struct ks_pkcs12
*p12
= data
;
723 return hx509_certs_next_cert(context
, p12
->certs
, cursor
, cert
);
727 p12_iter_end(hx509_context context
,
732 struct ks_pkcs12
*p12
= data
;
733 return hx509_certs_end_seq(context
, p12
->certs
, cursor
);
737 p12_destroy(hx509_context context
, hx509_certs certs
, void *data
)
739 struct ks_pkcs12
*p12
= data
;
740 return _hx509_erase_file(context
, p12
->fn
);
743 static struct hx509_keyset_ops keyset_pkcs12
= {
760 HX509_LIB_FUNCTION
void HX509_LIB_CALL
761 _hx509_ks_pkcs12_register(hx509_context context
)
763 _hx509_ks_register(context
, &keyset_pkcs12
);