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