Use the new asn1_read_node_value()
[gnutls.git] / lib / x509 / pkcs12.c
blobf26fd4fa3516ac235ef886fc707db45d08e03668
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 uint8_t *out;
212 result = _gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size,
213 &out);
215 if (result <= 0)
217 if (result == 0)
218 result = GNUTLS_E_INTERNAL_ERROR;
219 gnutls_assert ();
220 return result;
223 _data.data = out;
224 _data.size = result;
226 need_free = 1;
229 result =
230 asn1_der_decoding (&pkcs12->pkcs12, _data.data, _data.size, error_str);
231 if (result != ASN1_SUCCESS)
233 result = _gnutls_asn2err (result);
234 _gnutls_debug_log ("DER error: %s\n", error_str);
235 gnutls_assert ();
236 goto cleanup;
239 if (need_free)
240 _gnutls_free_datum (&_data);
242 return 0;
244 cleanup:
245 if (need_free)
246 _gnutls_free_datum (&_data);
247 return result;
252 * gnutls_pkcs12_export:
253 * @pkcs12: Holds the pkcs12 structure
254 * @format: the format of output params. One of PEM or DER.
255 * @output_data: will contain a structure PEM or DER encoded
256 * @output_data_size: holds the size of output_data (and will be
257 * replaced by the actual size of parameters)
259 * This function will export the pkcs12 structure to DER or PEM format.
261 * If the buffer provided is not long enough to hold the output, then
262 * *output_data_size will be updated and GNUTLS_E_SHORT_MEMORY_BUFFER
263 * will be returned.
265 * If the structure is PEM encoded, it will have a header
266 * of "BEGIN PKCS12".
268 * Returns: In case of failure a negative error code will be
269 * returned, and 0 on success.
272 gnutls_pkcs12_export (gnutls_pkcs12_t pkcs12,
273 gnutls_x509_crt_fmt_t format, void *output_data,
274 size_t * output_data_size)
276 if (pkcs12 == NULL)
278 gnutls_assert ();
279 return GNUTLS_E_INVALID_REQUEST;
282 return _gnutls_x509_export_int (pkcs12->pkcs12, format, PEM_PKCS12,
283 output_data, output_data_size);
286 static int
287 oid2bag (const char *oid)
289 if (strcmp (oid, BAG_PKCS8_KEY) == 0)
290 return GNUTLS_BAG_PKCS8_KEY;
291 if (strcmp (oid, BAG_PKCS8_ENCRYPTED_KEY) == 0)
292 return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY;
293 if (strcmp (oid, BAG_CERTIFICATE) == 0)
294 return GNUTLS_BAG_CERTIFICATE;
295 if (strcmp (oid, BAG_CRL) == 0)
296 return GNUTLS_BAG_CRL;
297 if (strcmp (oid, BAG_SECRET) == 0)
298 return GNUTLS_BAG_SECRET;
300 return GNUTLS_BAG_UNKNOWN;
303 static const char *
304 bag_to_oid (int bag)
306 switch (bag)
308 case GNUTLS_BAG_PKCS8_KEY:
309 return BAG_PKCS8_KEY;
310 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
311 return BAG_PKCS8_ENCRYPTED_KEY;
312 case GNUTLS_BAG_CERTIFICATE:
313 return BAG_CERTIFICATE;
314 case GNUTLS_BAG_CRL:
315 return BAG_CRL;
316 case GNUTLS_BAG_SECRET:
317 return BAG_SECRET;
319 return NULL;
322 static inline char *
323 ucs2_to_ascii (char *data, int size)
325 int i, j;
327 for (i = 0; i < size / 2; i++)
329 j = 2 * i + 1;
330 if (isascii (data[j]))
331 data[i] = data[i * 2 + 1];
332 else
333 data[i] = '?';
335 data[i] = 0;
337 return data;
340 /* Decodes the SafeContents, and puts the output in
341 * the given bag.
344 _pkcs12_decode_safe_contents (const gnutls_datum_t * content,
345 gnutls_pkcs12_bag_t bag)
347 char oid[MAX_OID_SIZE], root[ASN1_MAX_NAME_SIZE];
348 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
349 int len, result;
350 int bag_type;
351 gnutls_datum_t attr_val;
352 int count = 0, i, attributes, j;
353 size_t size;
355 /* Step 1. Extract the SEQUENCE.
358 if ((result = asn1_create_element
359 (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
360 &c2)) != ASN1_SUCCESS)
362 gnutls_assert ();
363 result = _gnutls_asn2err (result);
364 goto cleanup;
367 result = asn1_der_decoding (&c2, content->data, content->size, NULL);
368 if (result != ASN1_SUCCESS)
370 gnutls_assert ();
371 result = _gnutls_asn2err (result);
372 goto cleanup;
375 /* Count the number of bags
377 result = asn1_number_of_elements (c2, "", &count);
378 if (result != ASN1_SUCCESS)
380 gnutls_assert ();
381 result = _gnutls_asn2err (result);
382 goto cleanup;
385 bag->bag_elements = MIN (MAX_BAG_ELEMENTS, count);
387 for (i = 0; i < bag->bag_elements; i++)
390 snprintf (root, sizeof (root), "?%u.bagId", i + 1);
392 len = sizeof (oid);
393 result = asn1_read_value (c2, root, oid, &len);
394 if (result != ASN1_SUCCESS)
396 gnutls_assert ();
397 result = _gnutls_asn2err (result);
398 goto cleanup;
401 /* Read the Bag type
403 bag_type = oid2bag (oid);
405 if (bag_type < 0)
407 gnutls_assert ();
408 goto cleanup;
411 /* Read the Bag Value
414 snprintf (root, sizeof (root), "?%u.bagValue", i + 1);
416 result = _gnutls_x509_read_value (c2, root, &bag->element[i].data, 0);
417 if (result < 0)
419 gnutls_assert ();
420 goto cleanup;
423 if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL
424 || bag_type == GNUTLS_BAG_SECRET)
426 gnutls_datum_t tmp = bag->element[i].data;
428 result =
429 _pkcs12_decode_crt_bag (bag_type, &tmp, &bag->element[i].data);
430 if (result < 0)
432 gnutls_assert ();
433 goto cleanup;
436 _gnutls_free_datum (&tmp);
439 /* read the bag attributes
441 snprintf (root, sizeof (root), "?%u.bagAttributes", i + 1);
443 result = asn1_number_of_elements (c2, root, &attributes);
444 if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND)
446 gnutls_assert ();
447 result = _gnutls_asn2err (result);
448 goto cleanup;
451 if (attributes < 0)
452 attributes = 1;
454 if (result != ASN1_ELEMENT_NOT_FOUND)
455 for (j = 0; j < attributes; j++)
458 snprintf (root, sizeof (root), "?%u.bagAttributes.?%u", i + 1,
459 j + 1);
461 result =
462 _gnutls_x509_decode_and_read_attribute (c2, root, oid,
463 sizeof (oid), &attr_val,
464 1, 0);
466 if (result < 0)
468 gnutls_assert ();
469 continue; /* continue in case we find some known attributes */
472 if (strcmp (oid, KEY_ID_OID) == 0)
474 size = attr_val.size;
476 result =
477 _gnutls_x509_decode_octet_string (NULL, attr_val.data, size,
478 attr_val.data, &size);
479 attr_val.size = size;
480 if (result < 0)
482 _gnutls_free_datum (&attr_val);
483 gnutls_assert ();
484 _gnutls_debug_log
485 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
486 continue;
488 bag->element[i].local_key_id = attr_val;
490 else if (strcmp (oid, FRIENDLY_NAME_OID) == 0)
492 size = attr_val.size;
493 result =
494 _gnutls_x509_decode_octet_string ("BMPString",
495 attr_val.data, size,
496 attr_val.data, &size);
497 attr_val.size = size;
498 if (result < 0)
500 _gnutls_free_datum (&attr_val);
501 gnutls_assert ();
502 _gnutls_debug_log
503 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
504 continue;
506 bag->element[i].friendly_name =
507 ucs2_to_ascii ((char*)attr_val.data, attr_val.size);
509 else
511 _gnutls_free_datum (&attr_val);
512 _gnutls_debug_log
513 ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid);
518 bag->element[i].type = bag_type;
522 asn1_delete_structure (&c2);
525 return 0;
527 cleanup:
528 if (c2)
529 asn1_delete_structure (&c2);
530 return result;
535 static int
536 _parse_safe_contents (ASN1_TYPE sc, const char *sc_name,
537 gnutls_pkcs12_bag_t bag)
539 gnutls_datum_t content = { NULL, 0 };
540 int result;
542 /* Step 1. Extract the content.
545 result = _gnutls_x509_read_value (sc, sc_name, &content, 1);
546 if (result < 0)
548 gnutls_assert ();
549 goto cleanup;
552 result = _pkcs12_decode_safe_contents (&content, bag);
553 if (result < 0)
555 gnutls_assert ();
556 goto cleanup;
559 _gnutls_free_datum (&content);
561 return 0;
563 cleanup:
564 _gnutls_free_datum (&content);
565 return result;
570 * gnutls_pkcs12_get_bag:
571 * @pkcs12: should contain a gnutls_pkcs12_t structure
572 * @indx: contains the index of the bag to extract
573 * @bag: An initialized bag, where the contents of the bag will be copied
575 * This function will return a Bag from the PKCS12 structure.
577 * After the last Bag has been read
578 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
580 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
581 * negative error value.
584 gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12,
585 int indx, gnutls_pkcs12_bag_t bag)
587 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
588 int result, len;
589 char root2[ASN1_MAX_NAME_SIZE];
590 char oid[MAX_OID_SIZE];
592 if (pkcs12 == NULL)
594 gnutls_assert ();
595 return GNUTLS_E_INVALID_REQUEST;
598 /* Step 1. decode the data.
600 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
601 if (result < 0)
603 gnutls_assert ();
604 return result;
607 /* Step 2. Parse the AuthenticatedSafe
610 snprintf (root2, sizeof (root2), "?%u.contentType", indx + 1);
612 len = sizeof (oid) - 1;
613 result = asn1_read_value (c2, root2, oid, &len);
615 if (result == ASN1_ELEMENT_NOT_FOUND)
617 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
618 goto cleanup;
621 if (result != ASN1_SUCCESS)
623 gnutls_assert ();
624 result = _gnutls_asn2err (result);
625 goto cleanup;
628 /* Not encrypted Bag
631 snprintf (root2, sizeof (root2), "?%u.content", indx + 1);
633 if (strcmp (oid, DATA_OID) == 0)
635 result = _parse_safe_contents (c2, root2, bag);
636 goto cleanup;
639 /* ENC_DATA_OID needs decryption */
641 bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
642 bag->bag_elements = 1;
644 result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data, 0);
645 if (result < 0)
647 gnutls_assert ();
648 goto cleanup;
651 result = 0;
653 cleanup:
654 if (c2)
655 asn1_delete_structure (&c2);
656 return result;
659 /* Creates an empty PFX structure for the PKCS12 structure.
661 static int
662 create_empty_pfx (ASN1_TYPE pkcs12)
664 uint8_t three = 3;
665 int result;
666 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
668 /* Use version 3
670 result = asn1_write_value (pkcs12, "version", &three, 1);
671 if (result != ASN1_SUCCESS)
673 gnutls_assert ();
674 result = _gnutls_asn2err (result);
675 goto cleanup;
678 /* Write the content type of the data
680 result = asn1_write_value (pkcs12, "authSafe.contentType", DATA_OID, 1);
681 if (result != ASN1_SUCCESS)
683 gnutls_assert ();
684 result = _gnutls_asn2err (result);
685 goto cleanup;
688 /* Check if the authenticatedSafe content is empty, and encode a
689 * null one in that case.
692 if ((result = asn1_create_element
693 (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
694 &c2)) != ASN1_SUCCESS)
696 gnutls_assert ();
697 result = _gnutls_asn2err (result);
698 goto cleanup;
701 result =
702 _gnutls_x509_der_encode_and_copy (c2, "", pkcs12, "authSafe.content", 1);
703 if (result < 0)
705 gnutls_assert ();
706 goto cleanup;
708 asn1_delete_structure (&c2);
710 return 0;
712 cleanup:
713 asn1_delete_structure (&c2);
714 return result;
719 * gnutls_pkcs12_set_bag:
720 * @pkcs12: should contain a gnutls_pkcs12_t structure
721 * @bag: An initialized bag
723 * This function will insert a Bag into the PKCS12 structure.
725 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
726 * negative error value.
729 gnutls_pkcs12_set_bag (gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag)
731 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
732 ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
733 int result;
734 int enc = 0, dum = 1;
735 char null;
737 if (pkcs12 == NULL)
739 gnutls_assert ();
740 return GNUTLS_E_INVALID_REQUEST;
743 /* Step 1. Check if the pkcs12 structure is empty. In that
744 * case generate an empty PFX.
746 result = asn1_read_value (pkcs12->pkcs12, "authSafe.content", &null, &dum);
747 if (result == ASN1_VALUE_NOT_FOUND)
749 result = create_empty_pfx (pkcs12->pkcs12);
750 if (result < 0)
752 gnutls_assert ();
753 return result;
757 /* Step 2. decode the authenticatedSafe.
759 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
760 if (result < 0)
762 gnutls_assert ();
763 return result;
766 /* Step 3. Encode the bag elements into a SafeContents
767 * structure.
769 result = _pkcs12_encode_safe_contents (bag, &safe_cont, &enc);
770 if (result < 0)
772 gnutls_assert ();
773 return result;
776 /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe
777 * structure.
779 result = asn1_write_value (c2, "", "NEW", 1);
780 if (result != ASN1_SUCCESS)
782 gnutls_assert ();
783 result = _gnutls_asn2err (result);
784 goto cleanup;
787 if (enc)
788 result = asn1_write_value (c2, "?LAST.contentType", ENC_DATA_OID, 1);
789 else
790 result = asn1_write_value (c2, "?LAST.contentType", DATA_OID, 1);
791 if (result != ASN1_SUCCESS)
793 gnutls_assert ();
794 result = _gnutls_asn2err (result);
795 goto cleanup;
798 if (enc)
800 /* Encrypted packets are written directly.
802 result =
803 asn1_write_value (c2, "?LAST.content",
804 bag->element[0].data.data,
805 bag->element[0].data.size);
806 if (result != ASN1_SUCCESS)
808 gnutls_assert ();
809 result = _gnutls_asn2err (result);
810 goto cleanup;
813 else
815 result =
816 _gnutls_x509_der_encode_and_copy (safe_cont, "", c2,
817 "?LAST.content", 1);
818 if (result < 0)
820 gnutls_assert ();
821 goto cleanup;
825 asn1_delete_structure (&safe_cont);
828 /* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12
829 * structure.
831 result =
832 _gnutls_x509_der_encode_and_copy (c2, "", pkcs12->pkcs12,
833 "authSafe.content", 1);
834 if (result < 0)
836 gnutls_assert ();
837 goto cleanup;
840 asn1_delete_structure (&c2);
842 return 0;
844 cleanup:
845 asn1_delete_structure (&c2);
846 asn1_delete_structure (&safe_cont);
847 return result;
851 * gnutls_pkcs12_generate_mac:
852 * @pkcs12: should contain a gnutls_pkcs12_t structure
853 * @pass: The password for the MAC
855 * This function will generate a MAC for the PKCS12 structure.
857 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
858 * negative error value.
861 gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const char *pass)
863 uint8_t salt[8], key[20];
864 int result;
865 const int iter = 1;
866 digest_hd_st td1;
867 gnutls_datum_t tmp = { NULL, 0 };
868 uint8_t sha_mac[20];
870 if (pkcs12 == NULL)
872 gnutls_assert ();
873 return GNUTLS_E_INVALID_REQUEST;
876 /* Generate the salt.
878 result = _gnutls_rnd (GNUTLS_RND_NONCE, salt, sizeof (salt));
879 if (result < 0)
881 gnutls_assert ();
882 return result;
885 /* Write the salt into the structure.
887 result =
888 asn1_write_value (pkcs12->pkcs12, "macData.macSalt", salt, sizeof (salt));
889 if (result != ASN1_SUCCESS)
891 gnutls_assert ();
892 result = _gnutls_asn2err (result);
893 goto cleanup;
896 /* write the iterations
899 if (iter > 1)
901 result =
902 _gnutls_x509_write_uint32 (pkcs12->pkcs12, "macData.iterations",
903 iter);
904 if (result < 0)
906 gnutls_assert ();
907 goto cleanup;
911 /* Generate the key.
913 result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt),
914 iter, pass, sizeof (key), key);
915 if (result < 0)
917 gnutls_assert ();
918 goto cleanup;
921 /* Get the data to be MACed
923 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
924 if (result < 0)
926 gnutls_assert ();
927 goto cleanup;
930 /* MAC the data
932 result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
933 if (result < 0)
935 gnutls_assert ();
936 goto cleanup;
939 _gnutls_hmac (&td1, tmp.data, tmp.size);
940 _gnutls_free_datum (&tmp);
942 _gnutls_hmac_deinit (&td1, sha_mac);
945 result =
946 asn1_write_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac,
947 sizeof (sha_mac));
948 if (result != ASN1_SUCCESS)
950 gnutls_assert ();
951 result = _gnutls_asn2err (result);
952 goto cleanup;
955 result =
956 asn1_write_value (pkcs12->pkcs12,
957 "macData.mac.digestAlgorithm.parameters", NULL, 0);
958 if (result != ASN1_SUCCESS)
960 gnutls_assert ();
961 result = _gnutls_asn2err (result);
962 goto cleanup;
965 result =
966 asn1_write_value (pkcs12->pkcs12,
967 "macData.mac.digestAlgorithm.algorithm", HASH_OID_SHA1,
969 if (result != ASN1_SUCCESS)
971 gnutls_assert ();
972 result = _gnutls_asn2err (result);
973 goto cleanup;
976 return 0;
978 cleanup:
979 _gnutls_free_datum (&tmp);
980 return result;
984 * gnutls_pkcs12_verify_mac:
985 * @pkcs12: should contain a gnutls_pkcs12_t structure
986 * @pass: The password for the MAC
988 * This function will verify the MAC for the PKCS12 structure.
990 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
991 * negative error value.
994 gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass)
996 uint8_t key[20];
997 int result;
998 unsigned int iter;
999 int len;
1000 digest_hd_st td1;
1001 gnutls_datum_t tmp = { NULL, 0 }, salt =
1003 NULL, 0};
1004 uint8_t sha_mac[20];
1005 uint8_t sha_mac_orig[20];
1007 if (pkcs12 == NULL)
1009 gnutls_assert ();
1010 return GNUTLS_E_INVALID_REQUEST;
1013 /* read the iterations
1016 result =
1017 _gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter);
1018 if (result < 0)
1020 iter = 1; /* the default */
1024 /* Read the salt from the structure.
1026 result =
1027 _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0);
1028 if (result != ASN1_SUCCESS)
1030 gnutls_assert ();
1031 result = _gnutls_asn2err (result);
1032 goto cleanup;
1035 /* Generate the key.
1037 result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size,
1038 iter, pass, sizeof (key), key);
1039 if (result < 0)
1041 gnutls_assert ();
1042 goto cleanup;
1045 _gnutls_free_datum (&salt);
1047 /* Get the data to be MACed
1049 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
1050 if (result < 0)
1052 gnutls_assert ();
1053 goto cleanup;
1056 /* MAC the data
1058 result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
1059 if (result < 0)
1061 gnutls_assert ();
1062 goto cleanup;
1065 _gnutls_hmac (&td1, tmp.data, tmp.size);
1066 _gnutls_free_datum (&tmp);
1068 _gnutls_hmac_deinit (&td1, sha_mac);
1070 len = sizeof (sha_mac_orig);
1071 result =
1072 asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig,
1073 &len);
1074 if (result != ASN1_SUCCESS)
1076 gnutls_assert ();
1077 result = _gnutls_asn2err (result);
1078 goto cleanup;
1081 if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0)
1083 gnutls_assert ();
1084 return GNUTLS_E_MAC_VERIFY_FAILED;
1087 return 0;
1089 cleanup:
1090 _gnutls_free_datum (&tmp);
1091 _gnutls_free_datum (&salt);
1092 return result;
1096 static int
1097 write_attributes (gnutls_pkcs12_bag_t bag, int elem,
1098 ASN1_TYPE c2, const char *where)
1100 int result;
1101 char root[128];
1103 /* If the bag attributes are empty, then write
1104 * nothing to the attribute field.
1106 if (bag->element[elem].friendly_name == NULL &&
1107 bag->element[elem].local_key_id.data == NULL)
1109 /* no attributes
1111 result = asn1_write_value (c2, where, NULL, 0);
1112 if (result != ASN1_SUCCESS)
1114 gnutls_assert ();
1115 return _gnutls_asn2err (result);
1118 return 0;
1121 if (bag->element[elem].local_key_id.data != NULL)
1124 /* Add a new Attribute
1126 result = asn1_write_value (c2, where, "NEW", 1);
1127 if (result != ASN1_SUCCESS)
1129 gnutls_assert ();
1130 return _gnutls_asn2err (result);
1133 _gnutls_str_cpy (root, sizeof (root), where);
1134 _gnutls_str_cat (root, sizeof (root), ".?LAST");
1136 result =
1137 _gnutls_x509_encode_and_write_attribute (KEY_ID_OID, c2, root,
1138 bag->
1139 element[elem].local_key_id.
1140 data,
1141 bag->
1142 element[elem].local_key_id.
1143 size, 1);
1144 if (result < 0)
1146 gnutls_assert ();
1147 return result;
1151 if (bag->element[elem].friendly_name != NULL)
1153 uint8_t *name;
1154 int size, i;
1155 const char *p;
1157 /* Add a new Attribute
1159 result = asn1_write_value (c2, where, "NEW", 1);
1160 if (result != ASN1_SUCCESS)
1162 gnutls_assert ();
1163 return _gnutls_asn2err (result);
1166 /* convert name to BMPString
1168 size = strlen (bag->element[elem].friendly_name) * 2;
1169 name = gnutls_malloc (size);
1171 if (name == NULL)
1173 gnutls_assert ();
1174 return GNUTLS_E_MEMORY_ERROR;
1177 p = bag->element[elem].friendly_name;
1178 for (i = 0; i < size; i += 2)
1180 name[i] = 0;
1181 name[i + 1] = *p;
1182 p++;
1185 _gnutls_str_cpy (root, sizeof (root), where);
1186 _gnutls_str_cat (root, sizeof (root), ".?LAST");
1188 result =
1189 _gnutls_x509_encode_and_write_attribute (FRIENDLY_NAME_OID, c2,
1190 root, name, size, 1);
1192 gnutls_free (name);
1194 if (result < 0)
1196 gnutls_assert ();
1197 return result;
1201 return 0;
1205 /* Encodes the bag into a SafeContents structure, and puts the output in
1206 * the given datum. Enc is set to non (0) if the data are encrypted;
1209 _pkcs12_encode_safe_contents (gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents,
1210 int *enc)
1212 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1213 int result;
1214 int i;
1215 const char *oid;
1217 if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc)
1219 *enc = 1;
1220 return 0; /* ENCRYPTED BAG, do nothing. */
1222 else if (enc)
1223 *enc = 0;
1225 /* Step 1. Create the SEQUENCE.
1228 if ((result = asn1_create_element
1229 (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
1230 &c2)) != ASN1_SUCCESS)
1232 gnutls_assert ();
1233 result = _gnutls_asn2err (result);
1234 goto cleanup;
1237 for (i = 0; i < bag->bag_elements; i++)
1240 oid = bag_to_oid (bag->element[i].type);
1241 if (oid == NULL)
1243 gnutls_assert ();
1244 continue;
1247 result = asn1_write_value (c2, "", "NEW", 1);
1248 if (result != ASN1_SUCCESS)
1250 gnutls_assert ();
1251 result = _gnutls_asn2err (result);
1252 goto cleanup;
1255 /* Copy the bag type.
1257 result = asn1_write_value (c2, "?LAST.bagId", oid, 1);
1258 if (result != ASN1_SUCCESS)
1260 gnutls_assert ();
1261 result = _gnutls_asn2err (result);
1262 goto cleanup;
1265 /* Set empty attributes
1267 result = write_attributes (bag, i, c2, "?LAST.bagAttributes");
1268 if (result < 0)
1270 gnutls_assert ();
1271 goto cleanup;
1275 /* Copy the Bag Value
1278 if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE ||
1279 bag->element[i].type == GNUTLS_BAG_SECRET ||
1280 bag->element[i].type == GNUTLS_BAG_CRL)
1282 gnutls_datum_t tmp;
1284 /* in that case encode it to a CertBag or
1285 * a CrlBag.
1288 result =
1289 _pkcs12_encode_crt_bag (bag->element[i].type,
1290 &bag->element[i].data, &tmp);
1292 if (result < 0)
1294 gnutls_assert ();
1295 goto cleanup;
1298 result = _gnutls_x509_write_value (c2, "?LAST.bagValue", &tmp, 0);
1300 _gnutls_free_datum (&tmp);
1303 else
1306 result = _gnutls_x509_write_value (c2, "?LAST.bagValue",
1307 &bag->element[i].data, 0);
1310 if (result < 0)
1312 gnutls_assert ();
1313 goto cleanup;
1318 /* Encode the data and copy them into the datum
1320 *contents = c2;
1322 return 0;
1324 cleanup:
1325 if (c2)
1326 asn1_delete_structure (&c2);
1327 return result;