simplified base64 encoding/decoding functions by using a datum.
[gnutls.git] / lib / x509 / pkcs12.c
blobd66f91a9e0d245bb0bad2fa9970338eff9bcf51a
1 /*
2 * Copyright (C) 2003-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* Functions that relate on PKCS12 packet parsing.
26 #include <gnutls_int.h>
27 #include <libtasn1.h>
29 #include <gnutls_datum.h>
30 #include <gnutls_global.h>
31 #include <gnutls_errors.h>
32 #include <gnutls_num.h>
33 #include <common.h>
34 #include <x509_b64.h>
35 #include "x509_int.h"
36 #include <random.h>
39 /* Decodes the PKCS #12 auth_safe, and returns the allocated raw data,
40 * which holds them. Returns an ASN1_TYPE of authenticatedSafe.
42 static int
43 _decode_pkcs12_auth_safe (ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe,
44 gnutls_datum_t * raw)
46 char oid[MAX_OID_SIZE];
47 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
48 gnutls_datum_t auth_safe = { NULL, 0 };
49 int len, result;
50 char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
52 len = sizeof (oid) - 1;
53 result = asn1_read_value (pkcs12, "authSafe.contentType", oid, &len);
54 if (result != ASN1_SUCCESS)
56 gnutls_assert ();
57 return _gnutls_asn2err (result);
60 if (strcmp (oid, DATA_OID) != 0)
62 gnutls_assert ();
63 _gnutls_debug_log ("Unknown PKCS12 Content OID '%s'\n", oid);
64 return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
67 /* Step 1. Read the content data
70 result =
71 _gnutls_x509_read_value (pkcs12, "authSafe.content", &auth_safe, 1);
72 if (result < 0)
74 gnutls_assert ();
75 goto cleanup;
78 /* Step 2. Extract the authenticatedSafe.
81 if ((result = asn1_create_element
82 (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
83 &c2)) != ASN1_SUCCESS)
85 gnutls_assert ();
86 result = _gnutls_asn2err (result);
87 goto cleanup;
90 result = asn1_der_decoding (&c2, auth_safe.data, auth_safe.size, error_str);
91 if (result != ASN1_SUCCESS)
93 gnutls_assert ();
94 _gnutls_debug_log ("DER error: %s\n", error_str);
95 result = _gnutls_asn2err (result);
96 goto cleanup;
99 if (raw == NULL)
101 _gnutls_free_datum (&auth_safe);
103 else
105 raw->data = auth_safe.data;
106 raw->size = auth_safe.size;
109 if (authen_safe)
110 *authen_safe = c2;
111 else
112 asn1_delete_structure (&c2);
114 return 0;
116 cleanup:
117 if (c2)
118 asn1_delete_structure (&c2);
119 _gnutls_free_datum (&auth_safe);
120 return result;
124 * gnutls_pkcs12_init:
125 * @pkcs12: The structure to be initialized
127 * This function will initialize a PKCS12 structure. PKCS12 structures
128 * usually contain lists of X.509 Certificates and X.509 Certificate
129 * revocation lists.
131 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
132 * negative error value.
135 gnutls_pkcs12_init (gnutls_pkcs12_t * pkcs12)
137 *pkcs12 = gnutls_calloc (1, sizeof (gnutls_pkcs12_int));
139 if (*pkcs12)
141 int result = asn1_create_element (_gnutls_get_pkix (),
142 "PKIX1.pkcs-12-PFX",
143 &(*pkcs12)->pkcs12);
144 if (result != ASN1_SUCCESS)
146 gnutls_assert ();
147 gnutls_free (*pkcs12);
148 return _gnutls_asn2err (result);
150 return 0; /* success */
152 return GNUTLS_E_MEMORY_ERROR;
156 * gnutls_pkcs12_deinit:
157 * @pkcs12: The structure to be initialized
159 * This function will deinitialize a PKCS12 structure.
161 void
162 gnutls_pkcs12_deinit (gnutls_pkcs12_t pkcs12)
164 if (!pkcs12)
165 return;
167 if (pkcs12->pkcs12)
168 asn1_delete_structure (&pkcs12->pkcs12);
170 gnutls_free (pkcs12);
174 * gnutls_pkcs12_import:
175 * @pkcs12: The structure to store the parsed PKCS12.
176 * @data: The DER or PEM encoded PKCS12.
177 * @format: One of DER or PEM
178 * @flags: an ORed sequence of gnutls_privkey_pkcs8_flags
180 * This function will convert the given DER or PEM encoded PKCS12
181 * to the native gnutls_pkcs12_t format. The output will be stored in 'pkcs12'.
183 * If the PKCS12 is PEM encoded it should have a header of "PKCS12".
185 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
186 * negative error value.
189 gnutls_pkcs12_import (gnutls_pkcs12_t pkcs12,
190 const gnutls_datum_t * data,
191 gnutls_x509_crt_fmt_t format, unsigned int flags)
193 int result = 0, need_free = 0;
194 gnutls_datum_t _data;
195 char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
197 _data.data = data->data;
198 _data.size = data->size;
200 if (pkcs12 == NULL)
202 gnutls_assert ();
203 return GNUTLS_E_INVALID_REQUEST;
206 /* If the PKCS12 is in PEM format then decode it
208 if (format == GNUTLS_X509_FMT_PEM)
210 result = _gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size,
211 &_data);
213 if (result < 0)
215 gnutls_assert ();
216 return result;
219 need_free = 1;
222 result =
223 asn1_der_decoding (&pkcs12->pkcs12, _data.data, _data.size, error_str);
224 if (result != ASN1_SUCCESS)
226 result = _gnutls_asn2err (result);
227 _gnutls_debug_log ("DER error: %s\n", error_str);
228 gnutls_assert ();
229 goto cleanup;
232 if (need_free)
233 _gnutls_free_datum (&_data);
235 return 0;
237 cleanup:
238 if (need_free)
239 _gnutls_free_datum (&_data);
240 return result;
245 * gnutls_pkcs12_export:
246 * @pkcs12: Holds the pkcs12 structure
247 * @format: the format of output params. One of PEM or DER.
248 * @output_data: will contain a structure PEM or DER encoded
249 * @output_data_size: holds the size of output_data (and will be
250 * replaced by the actual size of parameters)
252 * This function will export the pkcs12 structure to DER or PEM format.
254 * If the buffer provided is not long enough to hold the output, then
255 * *output_data_size will be updated and GNUTLS_E_SHORT_MEMORY_BUFFER
256 * will be returned.
258 * If the structure is PEM encoded, it will have a header
259 * of "BEGIN PKCS12".
261 * Returns: In case of failure a negative error code will be
262 * returned, and 0 on success.
265 gnutls_pkcs12_export (gnutls_pkcs12_t pkcs12,
266 gnutls_x509_crt_fmt_t format, void *output_data,
267 size_t * output_data_size)
269 if (pkcs12 == NULL)
271 gnutls_assert ();
272 return GNUTLS_E_INVALID_REQUEST;
275 return _gnutls_x509_export_int (pkcs12->pkcs12, format, PEM_PKCS12,
276 output_data, output_data_size);
279 static int
280 oid2bag (const char *oid)
282 if (strcmp (oid, BAG_PKCS8_KEY) == 0)
283 return GNUTLS_BAG_PKCS8_KEY;
284 if (strcmp (oid, BAG_PKCS8_ENCRYPTED_KEY) == 0)
285 return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY;
286 if (strcmp (oid, BAG_CERTIFICATE) == 0)
287 return GNUTLS_BAG_CERTIFICATE;
288 if (strcmp (oid, BAG_CRL) == 0)
289 return GNUTLS_BAG_CRL;
290 if (strcmp (oid, BAG_SECRET) == 0)
291 return GNUTLS_BAG_SECRET;
293 return GNUTLS_BAG_UNKNOWN;
296 static const char *
297 bag_to_oid (int bag)
299 switch (bag)
301 case GNUTLS_BAG_PKCS8_KEY:
302 return BAG_PKCS8_KEY;
303 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
304 return BAG_PKCS8_ENCRYPTED_KEY;
305 case GNUTLS_BAG_CERTIFICATE:
306 return BAG_CERTIFICATE;
307 case GNUTLS_BAG_CRL:
308 return BAG_CRL;
309 case GNUTLS_BAG_SECRET:
310 return BAG_SECRET;
312 return NULL;
315 static inline char *
316 ucs2_to_ascii (char *data, int size)
318 int i, j;
320 for (i = 0; i < size / 2; i++)
322 j = 2 * i + 1;
323 if (isascii (data[j]))
324 data[i] = data[i * 2 + 1];
325 else
326 data[i] = '?';
328 data[i] = 0;
330 return data;
333 /* Decodes the SafeContents, and puts the output in
334 * the given bag.
337 _pkcs12_decode_safe_contents (const gnutls_datum_t * content,
338 gnutls_pkcs12_bag_t bag)
340 char oid[MAX_OID_SIZE], root[ASN1_MAX_NAME_SIZE];
341 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
342 int len, result;
343 int bag_type;
344 gnutls_datum_t attr_val;
345 int count = 0, i, attributes, j;
346 size_t size;
348 /* Step 1. Extract the SEQUENCE.
351 if ((result = asn1_create_element
352 (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
353 &c2)) != ASN1_SUCCESS)
355 gnutls_assert ();
356 result = _gnutls_asn2err (result);
357 goto cleanup;
360 result = asn1_der_decoding (&c2, content->data, content->size, NULL);
361 if (result != ASN1_SUCCESS)
363 gnutls_assert ();
364 result = _gnutls_asn2err (result);
365 goto cleanup;
368 /* Count the number of bags
370 result = asn1_number_of_elements (c2, "", &count);
371 if (result != ASN1_SUCCESS)
373 gnutls_assert ();
374 result = _gnutls_asn2err (result);
375 goto cleanup;
378 bag->bag_elements = MIN (MAX_BAG_ELEMENTS, count);
380 for (i = 0; i < bag->bag_elements; i++)
383 snprintf (root, sizeof (root), "?%u.bagId", i + 1);
385 len = sizeof (oid);
386 result = asn1_read_value (c2, root, oid, &len);
387 if (result != ASN1_SUCCESS)
389 gnutls_assert ();
390 result = _gnutls_asn2err (result);
391 goto cleanup;
394 /* Read the Bag type
396 bag_type = oid2bag (oid);
398 if (bag_type < 0)
400 gnutls_assert ();
401 goto cleanup;
404 /* Read the Bag Value
407 snprintf (root, sizeof (root), "?%u.bagValue", i + 1);
409 result = _gnutls_x509_read_value (c2, root, &bag->element[i].data, 0);
410 if (result < 0)
412 gnutls_assert ();
413 goto cleanup;
416 if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL
417 || bag_type == GNUTLS_BAG_SECRET)
419 gnutls_datum_t tmp = bag->element[i].data;
421 result =
422 _pkcs12_decode_crt_bag (bag_type, &tmp, &bag->element[i].data);
423 if (result < 0)
425 gnutls_assert ();
426 goto cleanup;
429 _gnutls_free_datum (&tmp);
432 /* read the bag attributes
434 snprintf (root, sizeof (root), "?%u.bagAttributes", i + 1);
436 result = asn1_number_of_elements (c2, root, &attributes);
437 if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND)
439 gnutls_assert ();
440 result = _gnutls_asn2err (result);
441 goto cleanup;
444 if (attributes < 0)
445 attributes = 1;
447 if (result != ASN1_ELEMENT_NOT_FOUND)
448 for (j = 0; j < attributes; j++)
451 snprintf (root, sizeof (root), "?%u.bagAttributes.?%u", i + 1,
452 j + 1);
454 result =
455 _gnutls_x509_decode_and_read_attribute (c2, root, oid,
456 sizeof (oid), &attr_val,
457 1, 0);
459 if (result < 0)
461 gnutls_assert ();
462 continue; /* continue in case we find some known attributes */
465 if (strcmp (oid, KEY_ID_OID) == 0)
467 size = attr_val.size;
469 result =
470 _gnutls_x509_decode_octet_string (NULL, attr_val.data, size,
471 attr_val.data, &size);
472 attr_val.size = size;
473 if (result < 0)
475 _gnutls_free_datum (&attr_val);
476 gnutls_assert ();
477 _gnutls_debug_log
478 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
479 continue;
481 bag->element[i].local_key_id = attr_val;
483 else if (strcmp (oid, FRIENDLY_NAME_OID) == 0)
485 size = attr_val.size;
486 result =
487 _gnutls_x509_decode_octet_string ("BMPString",
488 attr_val.data, size,
489 attr_val.data, &size);
490 attr_val.size = size;
491 if (result < 0)
493 _gnutls_free_datum (&attr_val);
494 gnutls_assert ();
495 _gnutls_debug_log
496 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
497 continue;
499 bag->element[i].friendly_name =
500 ucs2_to_ascii ((char*)attr_val.data, attr_val.size);
502 else
504 _gnutls_free_datum (&attr_val);
505 _gnutls_debug_log
506 ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid);
511 bag->element[i].type = bag_type;
515 asn1_delete_structure (&c2);
518 return 0;
520 cleanup:
521 if (c2)
522 asn1_delete_structure (&c2);
523 return result;
528 static int
529 _parse_safe_contents (ASN1_TYPE sc, const char *sc_name,
530 gnutls_pkcs12_bag_t bag)
532 gnutls_datum_t content = { NULL, 0 };
533 int result;
535 /* Step 1. Extract the content.
538 result = _gnutls_x509_read_value (sc, sc_name, &content, 1);
539 if (result < 0)
541 gnutls_assert ();
542 goto cleanup;
545 result = _pkcs12_decode_safe_contents (&content, bag);
546 if (result < 0)
548 gnutls_assert ();
549 goto cleanup;
552 _gnutls_free_datum (&content);
554 return 0;
556 cleanup:
557 _gnutls_free_datum (&content);
558 return result;
563 * gnutls_pkcs12_get_bag:
564 * @pkcs12: should contain a gnutls_pkcs12_t structure
565 * @indx: contains the index of the bag to extract
566 * @bag: An initialized bag, where the contents of the bag will be copied
568 * This function will return a Bag from the PKCS12 structure.
570 * After the last Bag has been read
571 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
573 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
574 * negative error value.
577 gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12,
578 int indx, gnutls_pkcs12_bag_t bag)
580 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
581 int result, len;
582 char root2[ASN1_MAX_NAME_SIZE];
583 char oid[MAX_OID_SIZE];
585 if (pkcs12 == NULL)
587 gnutls_assert ();
588 return GNUTLS_E_INVALID_REQUEST;
591 /* Step 1. decode the data.
593 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
594 if (result < 0)
596 gnutls_assert ();
597 return result;
600 /* Step 2. Parse the AuthenticatedSafe
603 snprintf (root2, sizeof (root2), "?%u.contentType", indx + 1);
605 len = sizeof (oid) - 1;
606 result = asn1_read_value (c2, root2, oid, &len);
608 if (result == ASN1_ELEMENT_NOT_FOUND)
610 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
611 goto cleanup;
614 if (result != ASN1_SUCCESS)
616 gnutls_assert ();
617 result = _gnutls_asn2err (result);
618 goto cleanup;
621 /* Not encrypted Bag
624 snprintf (root2, sizeof (root2), "?%u.content", indx + 1);
626 if (strcmp (oid, DATA_OID) == 0)
628 result = _parse_safe_contents (c2, root2, bag);
629 goto cleanup;
632 /* ENC_DATA_OID needs decryption */
634 bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
635 bag->bag_elements = 1;
637 result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data, 0);
638 if (result < 0)
640 gnutls_assert ();
641 goto cleanup;
644 result = 0;
646 cleanup:
647 if (c2)
648 asn1_delete_structure (&c2);
649 return result;
652 /* Creates an empty PFX structure for the PKCS12 structure.
654 static int
655 create_empty_pfx (ASN1_TYPE pkcs12)
657 uint8_t three = 3;
658 int result;
659 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
661 /* Use version 3
663 result = asn1_write_value (pkcs12, "version", &three, 1);
664 if (result != ASN1_SUCCESS)
666 gnutls_assert ();
667 result = _gnutls_asn2err (result);
668 goto cleanup;
671 /* Write the content type of the data
673 result = asn1_write_value (pkcs12, "authSafe.contentType", DATA_OID, 1);
674 if (result != ASN1_SUCCESS)
676 gnutls_assert ();
677 result = _gnutls_asn2err (result);
678 goto cleanup;
681 /* Check if the authenticatedSafe content is empty, and encode a
682 * null one in that case.
685 if ((result = asn1_create_element
686 (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
687 &c2)) != ASN1_SUCCESS)
689 gnutls_assert ();
690 result = _gnutls_asn2err (result);
691 goto cleanup;
694 result =
695 _gnutls_x509_der_encode_and_copy (c2, "", pkcs12, "authSafe.content", 1);
696 if (result < 0)
698 gnutls_assert ();
699 goto cleanup;
701 asn1_delete_structure (&c2);
703 return 0;
705 cleanup:
706 asn1_delete_structure (&c2);
707 return result;
712 * gnutls_pkcs12_set_bag:
713 * @pkcs12: should contain a gnutls_pkcs12_t structure
714 * @bag: An initialized bag
716 * This function will insert a Bag into the PKCS12 structure.
718 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
719 * negative error value.
722 gnutls_pkcs12_set_bag (gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag)
724 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
725 ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
726 int result;
727 int enc = 0, dum = 1;
728 char null;
730 if (pkcs12 == NULL)
732 gnutls_assert ();
733 return GNUTLS_E_INVALID_REQUEST;
736 /* Step 1. Check if the pkcs12 structure is empty. In that
737 * case generate an empty PFX.
739 result = asn1_read_value (pkcs12->pkcs12, "authSafe.content", &null, &dum);
740 if (result == ASN1_VALUE_NOT_FOUND)
742 result = create_empty_pfx (pkcs12->pkcs12);
743 if (result < 0)
745 gnutls_assert ();
746 return result;
750 /* Step 2. decode the authenticatedSafe.
752 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
753 if (result < 0)
755 gnutls_assert ();
756 return result;
759 /* Step 3. Encode the bag elements into a SafeContents
760 * structure.
762 result = _pkcs12_encode_safe_contents (bag, &safe_cont, &enc);
763 if (result < 0)
765 gnutls_assert ();
766 return result;
769 /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe
770 * structure.
772 result = asn1_write_value (c2, "", "NEW", 1);
773 if (result != ASN1_SUCCESS)
775 gnutls_assert ();
776 result = _gnutls_asn2err (result);
777 goto cleanup;
780 if (enc)
781 result = asn1_write_value (c2, "?LAST.contentType", ENC_DATA_OID, 1);
782 else
783 result = asn1_write_value (c2, "?LAST.contentType", DATA_OID, 1);
784 if (result != ASN1_SUCCESS)
786 gnutls_assert ();
787 result = _gnutls_asn2err (result);
788 goto cleanup;
791 if (enc)
793 /* Encrypted packets are written directly.
795 result =
796 asn1_write_value (c2, "?LAST.content",
797 bag->element[0].data.data,
798 bag->element[0].data.size);
799 if (result != ASN1_SUCCESS)
801 gnutls_assert ();
802 result = _gnutls_asn2err (result);
803 goto cleanup;
806 else
808 result =
809 _gnutls_x509_der_encode_and_copy (safe_cont, "", c2,
810 "?LAST.content", 1);
811 if (result < 0)
813 gnutls_assert ();
814 goto cleanup;
818 asn1_delete_structure (&safe_cont);
821 /* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12
822 * structure.
824 result =
825 _gnutls_x509_der_encode_and_copy (c2, "", pkcs12->pkcs12,
826 "authSafe.content", 1);
827 if (result < 0)
829 gnutls_assert ();
830 goto cleanup;
833 asn1_delete_structure (&c2);
835 return 0;
837 cleanup:
838 asn1_delete_structure (&c2);
839 asn1_delete_structure (&safe_cont);
840 return result;
844 * gnutls_pkcs12_generate_mac:
845 * @pkcs12: should contain a gnutls_pkcs12_t structure
846 * @pass: The password for the MAC
848 * This function will generate a MAC for the PKCS12 structure.
850 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
851 * negative error value.
854 gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const char *pass)
856 uint8_t salt[8], key[20];
857 int result;
858 const int iter = 1;
859 digest_hd_st td1;
860 gnutls_datum_t tmp = { NULL, 0 };
861 uint8_t sha_mac[20];
863 if (pkcs12 == NULL)
865 gnutls_assert ();
866 return GNUTLS_E_INVALID_REQUEST;
869 /* Generate the salt.
871 result = _gnutls_rnd (GNUTLS_RND_NONCE, salt, sizeof (salt));
872 if (result < 0)
874 gnutls_assert ();
875 return result;
878 /* Write the salt into the structure.
880 result =
881 asn1_write_value (pkcs12->pkcs12, "macData.macSalt", salt, sizeof (salt));
882 if (result != ASN1_SUCCESS)
884 gnutls_assert ();
885 result = _gnutls_asn2err (result);
886 goto cleanup;
889 /* write the iterations
892 if (iter > 1)
894 result =
895 _gnutls_x509_write_uint32 (pkcs12->pkcs12, "macData.iterations",
896 iter);
897 if (result < 0)
899 gnutls_assert ();
900 goto cleanup;
904 /* Generate the key.
906 result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt),
907 iter, pass, sizeof (key), key);
908 if (result < 0)
910 gnutls_assert ();
911 goto cleanup;
914 /* Get the data to be MACed
916 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
917 if (result < 0)
919 gnutls_assert ();
920 goto cleanup;
923 /* MAC the data
925 result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
926 if (result < 0)
928 gnutls_assert ();
929 goto cleanup;
932 _gnutls_hmac (&td1, tmp.data, tmp.size);
933 _gnutls_free_datum (&tmp);
935 _gnutls_hmac_deinit (&td1, sha_mac);
938 result =
939 asn1_write_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac,
940 sizeof (sha_mac));
941 if (result != ASN1_SUCCESS)
943 gnutls_assert ();
944 result = _gnutls_asn2err (result);
945 goto cleanup;
948 result =
949 asn1_write_value (pkcs12->pkcs12,
950 "macData.mac.digestAlgorithm.parameters", NULL, 0);
951 if (result != ASN1_SUCCESS)
953 gnutls_assert ();
954 result = _gnutls_asn2err (result);
955 goto cleanup;
958 result =
959 asn1_write_value (pkcs12->pkcs12,
960 "macData.mac.digestAlgorithm.algorithm", HASH_OID_SHA1,
962 if (result != ASN1_SUCCESS)
964 gnutls_assert ();
965 result = _gnutls_asn2err (result);
966 goto cleanup;
969 return 0;
971 cleanup:
972 _gnutls_free_datum (&tmp);
973 return result;
977 * gnutls_pkcs12_verify_mac:
978 * @pkcs12: should contain a gnutls_pkcs12_t structure
979 * @pass: The password for the MAC
981 * This function will verify the MAC for the PKCS12 structure.
983 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
984 * negative error value.
987 gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass)
989 uint8_t key[20];
990 int result;
991 unsigned int iter;
992 int len;
993 digest_hd_st td1;
994 gnutls_datum_t tmp = { NULL, 0 }, salt =
996 NULL, 0};
997 uint8_t sha_mac[20];
998 uint8_t sha_mac_orig[20];
1000 if (pkcs12 == NULL)
1002 gnutls_assert ();
1003 return GNUTLS_E_INVALID_REQUEST;
1006 /* read the iterations
1009 result =
1010 _gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter);
1011 if (result < 0)
1013 iter = 1; /* the default */
1017 /* Read the salt from the structure.
1019 result =
1020 _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0);
1021 if (result != ASN1_SUCCESS)
1023 gnutls_assert ();
1024 result = _gnutls_asn2err (result);
1025 goto cleanup;
1028 /* Generate the key.
1030 result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size,
1031 iter, pass, sizeof (key), key);
1032 if (result < 0)
1034 gnutls_assert ();
1035 goto cleanup;
1038 _gnutls_free_datum (&salt);
1040 /* Get the data to be MACed
1042 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
1043 if (result < 0)
1045 gnutls_assert ();
1046 goto cleanup;
1049 /* MAC the data
1051 result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
1052 if (result < 0)
1054 gnutls_assert ();
1055 goto cleanup;
1058 _gnutls_hmac (&td1, tmp.data, tmp.size);
1059 _gnutls_free_datum (&tmp);
1061 _gnutls_hmac_deinit (&td1, sha_mac);
1063 len = sizeof (sha_mac_orig);
1064 result =
1065 asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig,
1066 &len);
1067 if (result != ASN1_SUCCESS)
1069 gnutls_assert ();
1070 result = _gnutls_asn2err (result);
1071 goto cleanup;
1074 if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0)
1076 gnutls_assert ();
1077 return GNUTLS_E_MAC_VERIFY_FAILED;
1080 return 0;
1082 cleanup:
1083 _gnutls_free_datum (&tmp);
1084 _gnutls_free_datum (&salt);
1085 return result;
1089 static int
1090 write_attributes (gnutls_pkcs12_bag_t bag, int elem,
1091 ASN1_TYPE c2, const char *where)
1093 int result;
1094 char root[128];
1096 /* If the bag attributes are empty, then write
1097 * nothing to the attribute field.
1099 if (bag->element[elem].friendly_name == NULL &&
1100 bag->element[elem].local_key_id.data == NULL)
1102 /* no attributes
1104 result = asn1_write_value (c2, where, NULL, 0);
1105 if (result != ASN1_SUCCESS)
1107 gnutls_assert ();
1108 return _gnutls_asn2err (result);
1111 return 0;
1114 if (bag->element[elem].local_key_id.data != NULL)
1117 /* Add a new Attribute
1119 result = asn1_write_value (c2, where, "NEW", 1);
1120 if (result != ASN1_SUCCESS)
1122 gnutls_assert ();
1123 return _gnutls_asn2err (result);
1126 _gnutls_str_cpy (root, sizeof (root), where);
1127 _gnutls_str_cat (root, sizeof (root), ".?LAST");
1129 result =
1130 _gnutls_x509_encode_and_write_attribute (KEY_ID_OID, c2, root,
1131 bag->
1132 element[elem].local_key_id.
1133 data,
1134 bag->
1135 element[elem].local_key_id.
1136 size, 1);
1137 if (result < 0)
1139 gnutls_assert ();
1140 return result;
1144 if (bag->element[elem].friendly_name != NULL)
1146 uint8_t *name;
1147 int size, i;
1148 const char *p;
1150 /* Add a new Attribute
1152 result = asn1_write_value (c2, where, "NEW", 1);
1153 if (result != ASN1_SUCCESS)
1155 gnutls_assert ();
1156 return _gnutls_asn2err (result);
1159 /* convert name to BMPString
1161 size = strlen (bag->element[elem].friendly_name) * 2;
1162 name = gnutls_malloc (size);
1164 if (name == NULL)
1166 gnutls_assert ();
1167 return GNUTLS_E_MEMORY_ERROR;
1170 p = bag->element[elem].friendly_name;
1171 for (i = 0; i < size; i += 2)
1173 name[i] = 0;
1174 name[i + 1] = *p;
1175 p++;
1178 _gnutls_str_cpy (root, sizeof (root), where);
1179 _gnutls_str_cat (root, sizeof (root), ".?LAST");
1181 result =
1182 _gnutls_x509_encode_and_write_attribute (FRIENDLY_NAME_OID, c2,
1183 root, name, size, 1);
1185 gnutls_free (name);
1187 if (result < 0)
1189 gnutls_assert ();
1190 return result;
1194 return 0;
1198 /* Encodes the bag into a SafeContents structure, and puts the output in
1199 * the given datum. Enc is set to non (0) if the data are encrypted;
1202 _pkcs12_encode_safe_contents (gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents,
1203 int *enc)
1205 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1206 int result;
1207 int i;
1208 const char *oid;
1210 if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc)
1212 *enc = 1;
1213 return 0; /* ENCRYPTED BAG, do nothing. */
1215 else if (enc)
1216 *enc = 0;
1218 /* Step 1. Create the SEQUENCE.
1221 if ((result = asn1_create_element
1222 (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
1223 &c2)) != ASN1_SUCCESS)
1225 gnutls_assert ();
1226 result = _gnutls_asn2err (result);
1227 goto cleanup;
1230 for (i = 0; i < bag->bag_elements; i++)
1233 oid = bag_to_oid (bag->element[i].type);
1234 if (oid == NULL)
1236 gnutls_assert ();
1237 continue;
1240 result = asn1_write_value (c2, "", "NEW", 1);
1241 if (result != ASN1_SUCCESS)
1243 gnutls_assert ();
1244 result = _gnutls_asn2err (result);
1245 goto cleanup;
1248 /* Copy the bag type.
1250 result = asn1_write_value (c2, "?LAST.bagId", oid, 1);
1251 if (result != ASN1_SUCCESS)
1253 gnutls_assert ();
1254 result = _gnutls_asn2err (result);
1255 goto cleanup;
1258 /* Set empty attributes
1260 result = write_attributes (bag, i, c2, "?LAST.bagAttributes");
1261 if (result < 0)
1263 gnutls_assert ();
1264 goto cleanup;
1268 /* Copy the Bag Value
1271 if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE ||
1272 bag->element[i].type == GNUTLS_BAG_SECRET ||
1273 bag->element[i].type == GNUTLS_BAG_CRL)
1275 gnutls_datum_t tmp;
1277 /* in that case encode it to a CertBag or
1278 * a CrlBag.
1281 result =
1282 _pkcs12_encode_crt_bag (bag->element[i].type,
1283 &bag->element[i].data, &tmp);
1285 if (result < 0)
1287 gnutls_assert ();
1288 goto cleanup;
1291 result = _gnutls_x509_write_value (c2, "?LAST.bagValue", &tmp, 0);
1293 _gnutls_free_datum (&tmp);
1296 else
1299 result = _gnutls_x509_write_value (c2, "?LAST.bagValue",
1300 &bag->element[i].data, 0);
1303 if (result < 0)
1305 gnutls_assert ();
1306 goto cleanup;
1311 /* Encode the data and copy them into the datum
1313 *contents = c2;
1315 return 0;
1317 cleanup:
1318 if (c2)
1319 asn1_delete_structure (&c2);
1320 return result;
1324 /* Checks if the extra_certs contain certificates that may form a chain
1325 * with the first certificate in chain (it is expected that chain_len==1)
1326 * and appends those in the chain.
1328 static int make_chain(gnutls_x509_crt_t **chain, unsigned int *chain_len,
1329 gnutls_x509_crt_t **extra_certs, unsigned int *extra_certs_len,
1330 unsigned int flags)
1332 unsigned int i;
1334 if (*chain_len != 1)
1335 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1337 i = 0;
1338 while(i<*extra_certs_len)
1340 /* if it is an issuer but not a self-signed one */
1341 if (gnutls_x509_crt_check_issuer((*chain)[*chain_len - 1], (*extra_certs)[i]) != 0)
1343 if (!(flags & GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED) &&
1344 gnutls_x509_crt_check_issuer((*extra_certs)[i], (*extra_certs)[i]) != 0)
1345 goto skip;
1347 *chain = gnutls_realloc (*chain, sizeof((*chain)[0]) *
1348 ++(*chain_len));
1349 if (*chain == NULL)
1351 gnutls_assert();
1352 return GNUTLS_E_MEMORY_ERROR;
1354 (*chain)[*chain_len - 1] = (*extra_certs)[i];
1356 (*extra_certs)[i] = (*extra_certs)[*extra_certs_len-1];
1357 (*extra_certs_len)--;
1359 i=0;
1360 continue;
1363 skip:
1364 i++;
1366 return 0;
1370 * gnutls_pkcs12_simple_parse:
1371 * @p12: the PKCS#12 blob.
1372 * @password: optional password used to decrypt PKCS#12 blob, bags and keys.
1373 * @key: a structure to store the parsed private key.
1374 * @chain: the corresponding to key certificate chain
1375 * @chain_len: will be updated with the number of additional
1376 * @extra_certs: optional pointer to receive an array of additional
1377 * certificates found in the PKCS#12 blob.
1378 * @extra_certs_len: will be updated with the number of additional
1379 * certs.
1380 * @crl: an optional structure to store the parsed CRL.
1381 * @flags: should be zero or one of GNUTLS_PKCS12_SP_*
1383 * This function parses a PKCS#12 blob in @p12blob and extracts the
1384 * private key, the corresponding certificate chain, and any additional
1385 * certificates and a CRL.
1387 * The @extra_certs_ret and @extra_certs_ret_len parameters are optional
1388 * and both may be set to %NULL. If either is non-%NULL, then both must
1389 * be.
1391 * MAC:ed PKCS#12 files are supported. Encrypted PKCS#12 bags are
1392 * supported. Encrypted PKCS#8 private keys are supported. However,
1393 * only password based security, and the same password for all
1394 * operations, are supported.
1396 * PKCS#12 file may contain many keys and/or certificates, and there
1397 * is no way to identify which key/certificate pair you want. You
1398 * should make sure the PKCS#12 file only contain one key/certificate
1399 * pair and/or one CRL.
1401 * It is believed that the limitations of this function is acceptable
1402 * for most usage, and that any more flexibility would introduce
1403 * complexity that would make it harder to use this functionality at
1404 * all.
1406 * If the provided structure has encrypted fields but no password
1407 * is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED.
1409 * Note that normally the chain constructed does not include self signed
1410 * certificates, to comply with TLS' requirements. If, however, the flag
1411 * %GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED is specified then
1412 * self signed certificates will be included in the chain.
1414 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1415 * negative error value.
1417 * Since: 3.1
1420 gnutls_pkcs12_simple_parse (gnutls_pkcs12_t p12,
1421 const char *password,
1422 gnutls_x509_privkey_t * key,
1423 gnutls_x509_crt_t ** chain,
1424 unsigned int * chain_len,
1425 gnutls_x509_crt_t ** extra_certs,
1426 unsigned int * extra_certs_len,
1427 gnutls_x509_crl_t * crl,
1428 unsigned int flags)
1430 gnutls_pkcs12_bag_t bag = NULL;
1431 gnutls_x509_crt_t *_extra_certs = NULL;
1432 unsigned int _extra_certs_len = 0;
1433 gnutls_x509_crt_t *_chain = NULL;
1434 unsigned int _chain_len = 0;
1435 int idx = 0;
1436 int ret;
1437 size_t cert_id_size = 0;
1438 size_t key_id_size = 0;
1439 uint8_t cert_id[20];
1440 uint8_t key_id[20];
1441 int privkey_ok = 0;
1442 unsigned int i;
1444 *key = NULL;
1446 if (crl)
1447 *crl = NULL;
1449 /* find the first private key */
1450 for (;;)
1452 int elements_in_bag;
1453 int i;
1455 ret = gnutls_pkcs12_bag_init (&bag);
1456 if (ret < 0)
1458 bag = NULL;
1459 gnutls_assert ();
1460 goto done;
1463 ret = gnutls_pkcs12_get_bag (p12, idx, bag);
1464 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1465 break;
1466 if (ret < 0)
1468 gnutls_assert ();
1469 goto done;
1472 ret = gnutls_pkcs12_bag_get_type (bag, 0);
1473 if (ret < 0)
1475 gnutls_assert ();
1476 goto done;
1479 if (ret == GNUTLS_BAG_ENCRYPTED)
1481 if (password == NULL)
1483 ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
1484 goto done;
1487 ret = gnutls_pkcs12_bag_decrypt (bag, password);
1488 if (ret < 0)
1490 gnutls_assert ();
1491 goto done;
1495 elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
1496 if (elements_in_bag < 0)
1498 gnutls_assert ();
1499 goto done;
1502 for (i = 0; i < elements_in_bag; i++)
1504 int type;
1505 gnutls_datum_t data;
1507 type = gnutls_pkcs12_bag_get_type (bag, i);
1508 if (type < 0)
1510 gnutls_assert ();
1511 goto done;
1514 ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
1515 if (ret < 0)
1517 gnutls_assert ();
1518 goto done;
1521 switch (type)
1523 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
1524 if (password == NULL)
1526 ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
1527 goto done;
1530 case GNUTLS_BAG_PKCS8_KEY:
1531 if (*key != NULL) /* too simple to continue */
1533 gnutls_assert ();
1534 break;
1537 ret = gnutls_x509_privkey_init (key);
1538 if (ret < 0)
1540 gnutls_assert ();
1541 goto done;
1544 ret = gnutls_x509_privkey_import_pkcs8
1545 (*key, &data, GNUTLS_X509_FMT_DER, password,
1546 type == GNUTLS_BAG_PKCS8_KEY ? GNUTLS_PKCS_PLAIN : 0);
1547 if (ret < 0)
1549 gnutls_assert ();
1550 gnutls_x509_privkey_deinit (*key);
1551 goto done;
1554 key_id_size = sizeof (key_id);
1555 ret =
1556 gnutls_x509_privkey_get_key_id (*key, 0, key_id,
1557 &key_id_size);
1558 if (ret < 0)
1560 gnutls_assert ();
1561 gnutls_x509_privkey_deinit (*key);
1562 goto done;
1565 privkey_ok = 1; /* break */
1566 break;
1567 default:
1568 break;
1572 idx++;
1573 gnutls_pkcs12_bag_deinit (bag);
1575 if (privkey_ok != 0) /* private key was found */
1576 break;
1579 if (privkey_ok == 0) /* no private key */
1581 gnutls_assert ();
1582 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1585 /* now find the corresponding certificate
1587 idx = 0;
1588 bag = NULL;
1589 for (;;)
1591 int elements_in_bag;
1592 int i;
1594 ret = gnutls_pkcs12_bag_init (&bag);
1595 if (ret < 0)
1597 bag = NULL;
1598 gnutls_assert ();
1599 goto done;
1602 ret = gnutls_pkcs12_get_bag (p12, idx, bag);
1603 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1604 break;
1605 if (ret < 0)
1607 gnutls_assert ();
1608 goto done;
1611 ret = gnutls_pkcs12_bag_get_type (bag, 0);
1612 if (ret < 0)
1614 gnutls_assert ();
1615 goto done;
1618 if (ret == GNUTLS_BAG_ENCRYPTED)
1620 ret = gnutls_pkcs12_bag_decrypt (bag, password);
1621 if (ret < 0)
1623 gnutls_assert ();
1624 goto done;
1628 elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
1629 if (elements_in_bag < 0)
1631 gnutls_assert ();
1632 goto done;
1635 for (i = 0; i < elements_in_bag; i++)
1637 int type;
1638 gnutls_datum_t data;
1639 gnutls_x509_crt_t this_cert;
1641 type = gnutls_pkcs12_bag_get_type (bag, i);
1642 if (type < 0)
1644 gnutls_assert ();
1645 goto done;
1648 ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
1649 if (ret < 0)
1651 gnutls_assert ();
1652 goto done;
1655 switch (type)
1657 case GNUTLS_BAG_CERTIFICATE:
1658 ret = gnutls_x509_crt_init (&this_cert);
1659 if (ret < 0)
1661 gnutls_assert ();
1662 goto done;
1665 ret =
1666 gnutls_x509_crt_import (this_cert, &data, GNUTLS_X509_FMT_DER);
1667 if (ret < 0)
1669 gnutls_assert ();
1670 gnutls_x509_crt_deinit (this_cert);
1671 goto done;
1674 /* check if the key id match */
1675 cert_id_size = sizeof (cert_id);
1676 ret =
1677 gnutls_x509_crt_get_key_id (this_cert, 0, cert_id, &cert_id_size);
1678 if (ret < 0)
1680 gnutls_assert ();
1681 gnutls_x509_crt_deinit (this_cert);
1682 goto done;
1685 if (memcmp (cert_id, key_id, cert_id_size) != 0)
1686 { /* they don't match - skip the certificate */
1687 if (extra_certs)
1689 _extra_certs = gnutls_realloc (_extra_certs,
1690 sizeof(_extra_certs[0]) *
1691 ++_extra_certs_len);
1692 if (!_extra_certs)
1694 gnutls_assert ();
1695 ret = GNUTLS_E_MEMORY_ERROR;
1696 goto done;
1698 _extra_certs[_extra_certs_len - 1] = this_cert;
1699 this_cert = NULL;
1701 else
1703 gnutls_x509_crt_deinit (this_cert);
1706 else
1708 if (_chain_len == 0)
1710 _chain = gnutls_malloc (sizeof(_chain[0]) * (++_chain_len));
1711 if (!_chain)
1713 gnutls_assert ();
1714 ret = GNUTLS_E_MEMORY_ERROR;
1715 goto done;
1717 _chain[_chain_len - 1] = this_cert;
1718 this_cert = NULL;
1720 else
1722 gnutls_x509_crt_deinit (this_cert);
1725 break;
1727 case GNUTLS_BAG_CRL:
1728 if (crl == NULL || *crl != NULL)
1730 gnutls_assert ();
1731 break;
1734 ret = gnutls_x509_crl_init (crl);
1735 if (ret < 0)
1737 gnutls_assert ();
1738 goto done;
1741 ret = gnutls_x509_crl_import (*crl, &data, GNUTLS_X509_FMT_DER);
1742 if (ret < 0)
1744 gnutls_assert ();
1745 gnutls_x509_crl_deinit (*crl);
1746 goto done;
1748 break;
1750 case GNUTLS_BAG_ENCRYPTED:
1751 /* XXX Bother to recurse one level down? Unlikely to
1752 use the same password anyway. */
1753 case GNUTLS_BAG_EMPTY:
1754 default:
1755 break;
1759 idx++;
1760 gnutls_pkcs12_bag_deinit (bag);
1763 if (_chain_len != 1)
1765 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1766 goto done;
1769 ret = make_chain(&_chain, &_chain_len, &_extra_certs, &_extra_certs_len, flags);
1770 if (ret < 0)
1772 gnutls_assert();
1773 goto done;
1776 ret = 0;
1778 done:
1779 if (bag)
1780 gnutls_pkcs12_bag_deinit (bag);
1782 if (ret < 0)
1784 if (*key)
1785 gnutls_x509_privkey_deinit(*key);
1786 if (_extra_certs_len && _extra_certs != NULL)
1788 for (i = 0; i < _extra_certs_len; i++)
1789 gnutls_x509_crt_deinit(_extra_certs[i]);
1790 gnutls_free(_extra_certs);
1792 if (_chain_len && chain != NULL)
1794 for (i = 0; i < _chain_len; i++)
1795 gnutls_x509_crt_deinit(_chain[i]);
1796 gnutls_free(_chain);
1799 return ret;
1802 if (extra_certs && _extra_certs_len > 0)
1804 *extra_certs = _extra_certs;
1805 *extra_certs_len = _extra_certs_len;
1807 else
1809 if (extra_certs)
1811 *extra_certs = NULL;
1812 *extra_certs_len = 0;
1814 for (i = 0; i < _extra_certs_len; i++)
1815 gnutls_x509_crt_deinit(_extra_certs[i]);
1816 gnutls_free(_extra_certs);
1819 *chain = _chain;
1820 *chain_len = _chain_len;
1822 return ret;