2 * Copyright (C) 2003, 2004, 2005, 2008, 2010 Free Software Foundation,
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* Functions that relate on PKCS12 packet parsing.
29 #include <gnutls_int.h>
34 #include <gnutls_datum.h>
35 #include <gnutls_global.h>
36 #include <gnutls_errors.h>
37 #include <gnutls_num.h>
44 /* Decodes the PKCS #12 auth_safe, and returns the allocated raw data,
45 * which holds them. Returns an ASN1_TYPE of authenticatedSafe.
48 _decode_pkcs12_auth_safe (ASN1_TYPE pkcs12, ASN1_TYPE * authen_safe,
51 char oid[MAX_OID_SIZE];
52 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
53 gnutls_datum_t auth_safe = { NULL, 0 };
55 char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
57 len = sizeof (oid) - 1;
58 result = asn1_read_value (pkcs12, "authSafe.contentType", oid, &len);
59 if (result != ASN1_SUCCESS)
62 return _gnutls_asn2err (result);
65 if (strcmp (oid, DATA_OID) != 0)
68 _gnutls_x509_log ("Unknown PKCS12 Content OID '%s'\n", oid);
69 return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
72 /* Step 1. Read the content data
76 _gnutls_x509_read_value (pkcs12, "authSafe.content", &auth_safe, 1);
83 /* Step 2. Extract the authenticatedSafe.
86 if ((result = asn1_create_element
87 (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
88 &c2)) != ASN1_SUCCESS)
91 result = _gnutls_asn2err (result);
95 result = asn1_der_decoding (&c2, auth_safe.data, auth_safe.size, error_str);
96 if (result != ASN1_SUCCESS)
99 _gnutls_x509_log ("DER error: %s\n", error_str);
100 result = _gnutls_asn2err (result);
106 _gnutls_free_datum (&auth_safe);
110 raw->data = auth_safe.data;
111 raw->size = auth_safe.size;
117 asn1_delete_structure (&c2);
123 asn1_delete_structure (&c2);
124 _gnutls_free_datum (&auth_safe);
129 * gnutls_pkcs12_init:
130 * @pkcs12: The structure to be initialized
132 * This function will initialize a PKCS12 structure. PKCS12 structures
133 * usually contain lists of X.509 Certificates and X.509 Certificate
136 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
137 * negative error value.
140 gnutls_pkcs12_init (gnutls_pkcs12_t * pkcs12)
142 *pkcs12 = gnutls_calloc (1, sizeof (gnutls_pkcs12_int));
146 int result = asn1_create_element (_gnutls_get_pkix (),
149 if (result != ASN1_SUCCESS)
152 gnutls_free (*pkcs12);
153 return _gnutls_asn2err (result);
155 return 0; /* success */
157 return GNUTLS_E_MEMORY_ERROR;
161 * gnutls_pkcs12_deinit:
162 * @pkcs12: The structure to be initialized
164 * This function will deinitialize a PKCS12 structure.
167 gnutls_pkcs12_deinit (gnutls_pkcs12_t pkcs12)
173 asn1_delete_structure (&pkcs12->pkcs12);
175 gnutls_free (pkcs12);
179 * gnutls_pkcs12_import:
180 * @pkcs12: The structure to store the parsed PKCS12.
181 * @data: The DER or PEM encoded PKCS12.
182 * @format: One of DER or PEM
183 * @flags: an ORed sequence of gnutls_privkey_pkcs8_flags
185 * This function will convert the given DER or PEM encoded PKCS12
186 * to the native gnutls_pkcs12_t format. The output will be stored in 'pkcs12'.
188 * If the PKCS12 is PEM encoded it should have a header of "PKCS12".
190 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
191 * negative error value.
194 gnutls_pkcs12_import (gnutls_pkcs12_t pkcs12,
195 const gnutls_datum_t * data,
196 gnutls_x509_crt_fmt_t format, unsigned int flags)
198 int result = 0, need_free = 0;
199 gnutls_datum_t _data;
200 char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
202 _data.data = data->data;
203 _data.size = data->size;
208 return GNUTLS_E_INVALID_REQUEST;
211 /* If the PKCS12 is in PEM format then decode it
213 if (format == GNUTLS_X509_FMT_PEM)
217 result = _gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size,
223 result = GNUTLS_E_INTERNAL_ERROR;
235 asn1_der_decoding (&pkcs12->pkcs12, _data.data, _data.size, error_str);
236 if (result != ASN1_SUCCESS)
238 result = _gnutls_asn2err (result);
239 _gnutls_x509_log ("DER error: %s\n", error_str);
245 _gnutls_free_datum (&_data);
251 _gnutls_free_datum (&_data);
257 * gnutls_pkcs12_export:
258 * @pkcs12: Holds the pkcs12 structure
259 * @format: the format of output params. One of PEM or DER.
260 * @output_data: will contain a structure PEM or DER encoded
261 * @output_data_size: holds the size of output_data (and will be
262 * replaced by the actual size of parameters)
264 * This function will export the pkcs12 structure to DER or PEM format.
266 * If the buffer provided is not long enough to hold the output, then
267 * *output_data_size will be updated and GNUTLS_E_SHORT_MEMORY_BUFFER
270 * If the structure is PEM encoded, it will have a header
273 * Return value: In case of failure a negative value will be
274 * returned, and 0 on success.
277 gnutls_pkcs12_export (gnutls_pkcs12_t pkcs12,
278 gnutls_x509_crt_fmt_t format, void *output_data,
279 size_t * output_data_size)
284 return GNUTLS_E_INVALID_REQUEST;
287 return _gnutls_x509_export_int (pkcs12->pkcs12, format, PEM_PKCS12,
288 output_data, output_data_size);
292 oid2bag (const char *oid)
294 if (strcmp (oid, BAG_PKCS8_KEY) == 0)
295 return GNUTLS_BAG_PKCS8_KEY;
296 if (strcmp (oid, BAG_PKCS8_ENCRYPTED_KEY) == 0)
297 return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY;
298 if (strcmp (oid, BAG_CERTIFICATE) == 0)
299 return GNUTLS_BAG_CERTIFICATE;
300 if (strcmp (oid, BAG_CRL) == 0)
301 return GNUTLS_BAG_CRL;
302 if (strcmp (oid, BAG_SECRET) == 0)
303 return GNUTLS_BAG_SECRET;
305 return GNUTLS_BAG_UNKNOWN;
313 case GNUTLS_BAG_PKCS8_KEY:
314 return BAG_PKCS8_KEY;
315 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
316 return BAG_PKCS8_ENCRYPTED_KEY;
317 case GNUTLS_BAG_CERTIFICATE:
318 return BAG_CERTIFICATE;
321 case GNUTLS_BAG_SECRET:
328 ucs2_to_ascii (char *data, int size)
332 for (i = 0; i < size / 2; i++)
335 if (isascii (data[j]))
336 data[i] = data[i * 2 + 1];
345 /* Decodes the SafeContents, and puts the output in
349 _pkcs12_decode_safe_contents (const gnutls_datum_t * content,
350 gnutls_pkcs12_bag_t bag)
352 char oid[MAX_OID_SIZE], root[ASN1_MAX_NAME_SIZE];
353 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
356 gnutls_datum_t attr_val;
357 int count = 0, i, attributes, j;
360 /* Step 1. Extract the SEQUENCE.
363 if ((result = asn1_create_element
364 (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
365 &c2)) != ASN1_SUCCESS)
368 result = _gnutls_asn2err (result);
372 result = asn1_der_decoding (&c2, content->data, content->size, NULL);
373 if (result != ASN1_SUCCESS)
376 result = _gnutls_asn2err (result);
380 /* Count the number of bags
382 result = asn1_number_of_elements (c2, "", &count);
383 if (result != ASN1_SUCCESS)
386 result = _gnutls_asn2err (result);
390 bag->bag_elements = MIN (MAX_BAG_ELEMENTS, count);
392 for (i = 0; i < bag->bag_elements; i++)
395 snprintf (root, sizeof (root), "?%u.bagId", i + 1);
398 result = asn1_read_value (c2, root, oid, &len);
399 if (result != ASN1_SUCCESS)
402 result = _gnutls_asn2err (result);
408 bag_type = oid2bag (oid);
416 /* Read the Bag Value
419 snprintf (root, sizeof (root), "?%u.bagValue", i + 1);
421 result = _gnutls_x509_read_value (c2, root, &bag->element[i].data, 0);
428 if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL
429 || bag_type == GNUTLS_BAG_SECRET)
431 gnutls_datum_t tmp = bag->element[i].data;
434 _pkcs12_decode_crt_bag (bag_type, &tmp, &bag->element[i].data);
441 _gnutls_free_datum (&tmp);
444 /* read the bag attributes
446 snprintf (root, sizeof (root), "?%u.bagAttributes", i + 1);
448 result = asn1_number_of_elements (c2, root, &attributes);
449 if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND)
452 result = _gnutls_asn2err (result);
459 if (result != ASN1_ELEMENT_NOT_FOUND)
460 for (j = 0; j < attributes; j++)
463 snprintf (root, sizeof (root), "?%u.bagAttributes.?%u", i + 1,
467 _gnutls_x509_decode_and_read_attribute (c2, root, oid,
468 sizeof (oid), &attr_val,
474 continue; /* continue in case we find some known attributes */
477 if (strcmp (oid, KEY_ID_OID) == 0)
479 size = attr_val.size;
482 _gnutls_x509_decode_octet_string (NULL, attr_val.data, size,
483 attr_val.data, &size);
484 attr_val.size = size;
487 _gnutls_free_datum (&attr_val);
490 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
493 bag->element[i].local_key_id = attr_val;
495 else if (strcmp (oid, FRIENDLY_NAME_OID) == 0)
497 size = attr_val.size;
499 _gnutls_x509_decode_octet_string ("BMPString",
501 attr_val.data, &size);
502 attr_val.size = size;
505 _gnutls_free_datum (&attr_val);
508 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
511 bag->element[i].friendly_name =
512 ucs2_to_ascii (attr_val.data, attr_val.size);
516 _gnutls_free_datum (&attr_val);
518 ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid);
523 bag->element[i].type = bag_type;
527 asn1_delete_structure (&c2);
534 asn1_delete_structure (&c2);
541 _parse_safe_contents (ASN1_TYPE sc, const char *sc_name,
542 gnutls_pkcs12_bag_t bag)
544 gnutls_datum_t content = { NULL, 0 };
547 /* Step 1. Extract the content.
550 result = _gnutls_x509_read_value (sc, sc_name, &content, 1);
557 result = _pkcs12_decode_safe_contents (&content, bag);
564 _gnutls_free_datum (&content);
569 _gnutls_free_datum (&content);
575 * gnutls_pkcs12_get_bag:
576 * @pkcs12: should contain a gnutls_pkcs12_t structure
577 * @indx: contains the index of the bag to extract
578 * @bag: An initialized bag, where the contents of the bag will be copied
580 * This function will return a Bag from the PKCS12 structure.
582 * After the last Bag has been read
583 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
585 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
586 * negative error value.
589 gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12,
590 int indx, gnutls_pkcs12_bag_t bag)
592 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
594 char root2[ASN1_MAX_NAME_SIZE];
595 char oid[MAX_OID_SIZE];
600 return GNUTLS_E_INVALID_REQUEST;
603 /* Step 1. decode the data.
605 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
612 /* Step 2. Parse the AuthenticatedSafe
615 snprintf (root2, sizeof (root2), "?%u.contentType", indx + 1);
617 len = sizeof (oid) - 1;
618 result = asn1_read_value (c2, root2, oid, &len);
620 if (result == ASN1_ELEMENT_NOT_FOUND)
622 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
626 if (result != ASN1_SUCCESS)
629 result = _gnutls_asn2err (result);
636 snprintf (root2, sizeof (root2), "?%u.content", indx + 1);
638 if (strcmp (oid, DATA_OID) == 0)
640 result = _parse_safe_contents (c2, root2, bag);
644 /* ENC_DATA_OID needs decryption */
646 bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
647 bag->bag_elements = 1;
649 result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data, 0);
660 asn1_delete_structure (&c2);
664 /* Creates an empty PFX structure for the PKCS12 structure.
667 create_empty_pfx (ASN1_TYPE pkcs12)
671 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
675 result = asn1_write_value (pkcs12, "version", &three, 1);
676 if (result != ASN1_SUCCESS)
679 result = _gnutls_asn2err (result);
683 /* Write the content type of the data
685 result = asn1_write_value (pkcs12, "authSafe.contentType", DATA_OID, 1);
686 if (result != ASN1_SUCCESS)
689 result = _gnutls_asn2err (result);
693 /* Check if the authenticatedSafe content is empty, and encode a
694 * null one in that case.
697 if ((result = asn1_create_element
698 (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
699 &c2)) != ASN1_SUCCESS)
702 result = _gnutls_asn2err (result);
707 _gnutls_x509_der_encode_and_copy (c2, "", pkcs12, "authSafe.content", 1);
713 asn1_delete_structure (&c2);
718 asn1_delete_structure (&c2);
724 * gnutls_pkcs12_set_bag:
725 * @pkcs12: should contain a gnutls_pkcs12_t structure
726 * @bag: An initialized bag
728 * This function will insert a Bag into the PKCS12 structure.
730 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
731 * negative error value.
734 gnutls_pkcs12_set_bag (gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag)
736 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
737 ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
739 int enc = 0, dum = 1;
745 return GNUTLS_E_INVALID_REQUEST;
748 /* Step 1. Check if the pkcs12 structure is empty. In that
749 * case generate an empty PFX.
751 result = asn1_read_value (pkcs12->pkcs12, "authSafe.content", &null, &dum);
752 if (result == ASN1_VALUE_NOT_FOUND)
754 result = create_empty_pfx (pkcs12->pkcs12);
762 /* Step 2. decode the authenticatedSafe.
764 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
771 /* Step 3. Encode the bag elements into a SafeContents
774 result = _pkcs12_encode_safe_contents (bag, &safe_cont, &enc);
781 /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe
784 result = asn1_write_value (c2, "", "NEW", 1);
785 if (result != ASN1_SUCCESS)
788 result = _gnutls_asn2err (result);
793 result = asn1_write_value (c2, "?LAST.contentType", ENC_DATA_OID, 1);
795 result = asn1_write_value (c2, "?LAST.contentType", DATA_OID, 1);
796 if (result != ASN1_SUCCESS)
799 result = _gnutls_asn2err (result);
805 /* Encrypted packets are written directly.
808 asn1_write_value (c2, "?LAST.content",
809 bag->element[0].data.data,
810 bag->element[0].data.size);
811 if (result != ASN1_SUCCESS)
814 result = _gnutls_asn2err (result);
821 _gnutls_x509_der_encode_and_copy (safe_cont, "", c2,
830 asn1_delete_structure (&safe_cont);
833 /* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12
837 _gnutls_x509_der_encode_and_copy (c2, "", pkcs12->pkcs12,
838 "authSafe.content", 1);
845 asn1_delete_structure (&c2);
850 asn1_delete_structure (&c2);
851 asn1_delete_structure (&safe_cont);
856 * gnutls_pkcs12_generate_mac:
857 * @pkcs12: should contain a gnutls_pkcs12_t structure
858 * @pass: The password for the MAC
860 * This function will generate a MAC for the PKCS12 structure.
862 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
863 * negative error value.
866 gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const char *pass)
868 opaque salt[8], key[20];
872 gnutls_datum_t tmp = { NULL, 0 };
878 return GNUTLS_E_INVALID_REQUEST;
881 /* Generate the salt.
883 result = _gnutls_rnd (GNUTLS_RND_NONCE, salt, sizeof (salt));
890 /* Write the salt into the structure.
893 asn1_write_value (pkcs12->pkcs12, "macData.macSalt", salt, sizeof (salt));
894 if (result != ASN1_SUCCESS)
897 result = _gnutls_asn2err (result);
901 /* write the iterations
907 _gnutls_x509_write_uint32 (pkcs12->pkcs12, "macData.iterations",
918 result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt),
919 iter, pass, sizeof (key), key);
926 /* Get the data to be MACed
928 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
937 result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
944 _gnutls_hmac (&td1, tmp.data, tmp.size);
945 _gnutls_free_datum (&tmp);
947 _gnutls_hmac_deinit (&td1, sha_mac);
951 asn1_write_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac,
953 if (result != ASN1_SUCCESS)
956 result = _gnutls_asn2err (result);
961 asn1_write_value (pkcs12->pkcs12,
962 "macData.mac.digestAlgorithm.parameters", NULL, 0);
963 if (result != ASN1_SUCCESS)
966 result = _gnutls_asn2err (result);
971 asn1_write_value (pkcs12->pkcs12,
972 "macData.mac.digestAlgorithm.algorithm", HASH_OID_SHA1,
974 if (result != ASN1_SUCCESS)
977 result = _gnutls_asn2err (result);
984 _gnutls_free_datum (&tmp);
989 * gnutls_pkcs12_verify_mac:
990 * @pkcs12: should contain a gnutls_pkcs12_t structure
991 * @pass: The password for the MAC
993 * This function will verify the MAC for the PKCS12 structure.
995 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
996 * negative error value.
999 gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass)
1006 gnutls_datum_t tmp = { NULL, 0 }, salt =
1010 opaque sha_mac_orig[20];
1015 return GNUTLS_E_INVALID_REQUEST;
1018 /* read the iterations
1022 _gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter);
1025 iter = 1; /* the default */
1029 /* Read the salt from the structure.
1032 _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0);
1033 if (result != ASN1_SUCCESS)
1036 result = _gnutls_asn2err (result);
1040 /* Generate the key.
1042 result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size,
1043 iter, pass, sizeof (key), key);
1050 _gnutls_free_datum (&salt);
1052 /* Get the data to be MACed
1054 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
1063 result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
1070 _gnutls_hmac (&td1, tmp.data, tmp.size);
1071 _gnutls_free_datum (&tmp);
1073 _gnutls_hmac_deinit (&td1, sha_mac);
1075 len = sizeof (sha_mac_orig);
1077 asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig,
1079 if (result != ASN1_SUCCESS)
1082 result = _gnutls_asn2err (result);
1086 if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0)
1089 return GNUTLS_E_MAC_VERIFY_FAILED;
1095 _gnutls_free_datum (&tmp);
1096 _gnutls_free_datum (&salt);
1102 write_attributes (gnutls_pkcs12_bag_t bag, int elem,
1103 ASN1_TYPE c2, const char *where)
1108 /* If the bag attributes are empty, then write
1109 * nothing to the attribute field.
1111 if (bag->element[elem].friendly_name == NULL &&
1112 bag->element[elem].local_key_id.data == NULL)
1116 result = asn1_write_value (c2, where, NULL, 0);
1117 if (result != ASN1_SUCCESS)
1120 return _gnutls_asn2err (result);
1126 if (bag->element[elem].local_key_id.data != NULL)
1129 /* Add a new Attribute
1131 result = asn1_write_value (c2, where, "NEW", 1);
1132 if (result != ASN1_SUCCESS)
1135 return _gnutls_asn2err (result);
1138 _gnutls_str_cpy (root, sizeof (root), where);
1139 _gnutls_str_cat (root, sizeof (root), ".?LAST");
1142 _gnutls_x509_encode_and_write_attribute (KEY_ID_OID, c2, root,
1144 element[elem].local_key_id.
1147 element[elem].local_key_id.
1156 if (bag->element[elem].friendly_name != NULL)
1162 /* Add a new Attribute
1164 result = asn1_write_value (c2, where, "NEW", 1);
1165 if (result != ASN1_SUCCESS)
1168 return _gnutls_asn2err (result);
1171 /* convert name to BMPString
1173 size = strlen (bag->element[elem].friendly_name) * 2;
1174 name = gnutls_malloc (size);
1179 return GNUTLS_E_MEMORY_ERROR;
1182 p = bag->element[elem].friendly_name;
1183 for (i = 0; i < size; i += 2)
1190 _gnutls_str_cpy (root, sizeof (root), where);
1191 _gnutls_str_cat (root, sizeof (root), ".?LAST");
1194 _gnutls_x509_encode_and_write_attribute (FRIENDLY_NAME_OID, c2,
1195 root, name, size, 1);
1210 /* Encodes the bag into a SafeContents structure, and puts the output in
1211 * the given datum. Enc is set to non zero if the data are encrypted;
1214 _pkcs12_encode_safe_contents (gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents,
1217 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1222 if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc)
1225 return 0; /* ENCRYPTED BAG, do nothing. */
1230 /* Step 1. Create the SEQUENCE.
1233 if ((result = asn1_create_element
1234 (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
1235 &c2)) != ASN1_SUCCESS)
1238 result = _gnutls_asn2err (result);
1242 for (i = 0; i < bag->bag_elements; i++)
1245 oid = bag_to_oid (bag->element[i].type);
1252 result = asn1_write_value (c2, "", "NEW", 1);
1253 if (result != ASN1_SUCCESS)
1256 result = _gnutls_asn2err (result);
1260 /* Copy the bag type.
1262 result = asn1_write_value (c2, "?LAST.bagId", oid, 1);
1263 if (result != ASN1_SUCCESS)
1266 result = _gnutls_asn2err (result);
1270 /* Set empty attributes
1272 result = write_attributes (bag, i, c2, "?LAST.bagAttributes");
1280 /* Copy the Bag Value
1283 if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE ||
1284 bag->element[i].type == GNUTLS_BAG_SECRET ||
1285 bag->element[i].type == GNUTLS_BAG_CRL)
1289 /* in that case encode it to a CertBag or
1294 _pkcs12_encode_crt_bag (bag->element[i].type,
1295 &bag->element[i].data, &tmp);
1303 result = _gnutls_x509_write_value (c2, "?LAST.bagValue", &tmp, 0);
1305 _gnutls_free_datum (&tmp);
1311 result = _gnutls_x509_write_value (c2, "?LAST.bagValue",
1312 &bag->element[i].data, 0);
1323 /* Encode the data and copy them into the datum
1331 asn1_delete_structure (&c2);
1337 #endif /* ENABLE_PKI */