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