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