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