xref: /minix3/crypto/external/bsd/heimdal/dist/lib/hx509/ks_p12.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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