doc update
[gnutls.git] / lib / x509 / pkcs12.c
blobedd06820210c66b38ca58f98d5e2e6b14a3bde03
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_string (pkcs12, "authSafe.content", &auth_safe, RV_OCTET_STRING);
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);
280 * gnutls_pkcs12_export2:
281 * @pkcs12: Holds the pkcs12 structure
282 * @format: the format of output params. One of PEM or DER.
283 * @out: will contain a structure PEM or DER encoded
285 * This function will export the pkcs12 structure to DER or PEM format.
287 * The output buffer is allocated using gnutls_malloc().
289 * If the structure is PEM encoded, it will have a header
290 * of "BEGIN PKCS12".
292 * Returns: In case of failure a negative error code will be
293 * returned, and 0 on success.
295 * Since: 3.1
298 gnutls_pkcs12_export2 (gnutls_pkcs12_t pkcs12,
299 gnutls_x509_crt_fmt_t format, gnutls_datum_t *out)
301 if (pkcs12 == NULL)
303 gnutls_assert ();
304 return GNUTLS_E_INVALID_REQUEST;
307 return _gnutls_x509_export_int2 (pkcs12->pkcs12, format, PEM_PKCS12, out);
310 static int
311 oid2bag (const char *oid)
313 if (strcmp (oid, BAG_PKCS8_KEY) == 0)
314 return GNUTLS_BAG_PKCS8_KEY;
315 if (strcmp (oid, BAG_PKCS8_ENCRYPTED_KEY) == 0)
316 return GNUTLS_BAG_PKCS8_ENCRYPTED_KEY;
317 if (strcmp (oid, BAG_CERTIFICATE) == 0)
318 return GNUTLS_BAG_CERTIFICATE;
319 if (strcmp (oid, BAG_CRL) == 0)
320 return GNUTLS_BAG_CRL;
321 if (strcmp (oid, BAG_SECRET) == 0)
322 return GNUTLS_BAG_SECRET;
324 return GNUTLS_BAG_UNKNOWN;
327 static const char *
328 bag_to_oid (int bag)
330 switch (bag)
332 case GNUTLS_BAG_PKCS8_KEY:
333 return BAG_PKCS8_KEY;
334 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
335 return BAG_PKCS8_ENCRYPTED_KEY;
336 case GNUTLS_BAG_CERTIFICATE:
337 return BAG_CERTIFICATE;
338 case GNUTLS_BAG_CRL:
339 return BAG_CRL;
340 case GNUTLS_BAG_SECRET:
341 return BAG_SECRET;
343 return NULL;
346 static inline char *
347 ucs2_to_ascii (char *data, int size)
349 int i, j;
351 for (i = 0; i < size / 2; i++)
353 j = 2 * i + 1;
354 if (isascii (data[j]))
355 data[i] = data[i * 2 + 1];
356 else
357 data[i] = '?';
359 data[i] = 0;
361 return data;
364 /* Decodes the SafeContents, and puts the output in
365 * the given bag.
368 _pkcs12_decode_safe_contents (const gnutls_datum_t * content,
369 gnutls_pkcs12_bag_t bag)
371 char oid[MAX_OID_SIZE], root[ASN1_MAX_NAME_SIZE];
372 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
373 int len, result;
374 int bag_type;
375 gnutls_datum_t attr_val;
376 gnutls_datum_t t;
377 int count = 0, i, attributes, j;
379 /* Step 1. Extract the SEQUENCE.
382 if ((result = asn1_create_element
383 (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
384 &c2)) != ASN1_SUCCESS)
386 gnutls_assert ();
387 result = _gnutls_asn2err (result);
388 goto cleanup;
391 result = asn1_der_decoding (&c2, content->data, content->size, NULL);
392 if (result != ASN1_SUCCESS)
394 gnutls_assert ();
395 result = _gnutls_asn2err (result);
396 goto cleanup;
399 /* Count the number of bags
401 result = asn1_number_of_elements (c2, "", &count);
402 if (result != ASN1_SUCCESS)
404 gnutls_assert ();
405 result = _gnutls_asn2err (result);
406 goto cleanup;
409 bag->bag_elements = MIN (MAX_BAG_ELEMENTS, count);
411 for (i = 0; i < bag->bag_elements; i++)
414 snprintf (root, sizeof (root), "?%u.bagId", i + 1);
416 len = sizeof (oid);
417 result = asn1_read_value (c2, root, oid, &len);
418 if (result != ASN1_SUCCESS)
420 gnutls_assert ();
421 result = _gnutls_asn2err (result);
422 goto cleanup;
425 /* Read the Bag type
427 bag_type = oid2bag (oid);
429 if (bag_type < 0)
431 gnutls_assert ();
432 goto cleanup;
435 /* Read the Bag Value
438 snprintf (root, sizeof (root), "?%u.bagValue", i + 1);
440 result = _gnutls_x509_read_value (c2, root, &bag->element[i].data);
441 if (result < 0)
443 gnutls_assert ();
444 goto cleanup;
447 if (bag_type == GNUTLS_BAG_CERTIFICATE || bag_type == GNUTLS_BAG_CRL
448 || bag_type == GNUTLS_BAG_SECRET)
450 gnutls_datum_t tmp = bag->element[i].data;
452 result =
453 _pkcs12_decode_crt_bag (bag_type, &tmp, &bag->element[i].data);
454 if (result < 0)
456 gnutls_assert ();
457 goto cleanup;
460 _gnutls_free_datum (&tmp);
463 /* read the bag attributes
465 snprintf (root, sizeof (root), "?%u.bagAttributes", i + 1);
467 result = asn1_number_of_elements (c2, root, &attributes);
468 if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND)
470 gnutls_assert ();
471 result = _gnutls_asn2err (result);
472 goto cleanup;
475 if (attributes < 0)
476 attributes = 1;
478 if (result != ASN1_ELEMENT_NOT_FOUND)
479 for (j = 0; j < attributes; j++)
482 snprintf (root, sizeof (root), "?%u.bagAttributes.?%u", i + 1,
483 j + 1);
485 result =
486 _gnutls_x509_decode_and_read_attribute (c2, root, oid,
487 sizeof (oid), &attr_val,
488 1, 0);
490 if (result < 0)
492 gnutls_assert ();
493 continue; /* continue in case we find some known attributes */
496 if (strcmp (oid, KEY_ID_OID) == 0)
498 result =
499 _gnutls_x509_decode_string (NULL, attr_val.data, attr_val.size, &t);
500 _gnutls_free_datum (&attr_val);
501 if (result < 0)
503 gnutls_assert ();
504 _gnutls_debug_log
505 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
506 continue;
509 attr_val.data = t.data;
510 attr_val.size = t.size;
512 bag->element[i].local_key_id = attr_val;
514 else if (strcmp (oid, FRIENDLY_NAME_OID) == 0)
516 result =
517 _gnutls_x509_decode_string ("BMPString",
518 attr_val.data, attr_val.size, &t);
519 _gnutls_free_datum (&attr_val);
520 if (result < 0)
522 gnutls_assert ();
523 _gnutls_debug_log
524 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
525 continue;
528 attr_val.data = t.data;
529 attr_val.size = t.size;
531 bag->element[i].friendly_name =
532 ucs2_to_ascii ((char*)attr_val.data, attr_val.size);
534 else
536 _gnutls_free_datum (&attr_val);
537 _gnutls_debug_log
538 ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid);
543 bag->element[i].type = bag_type;
547 asn1_delete_structure (&c2);
550 return 0;
552 cleanup:
553 if (c2)
554 asn1_delete_structure (&c2);
555 return result;
560 static int
561 _parse_safe_contents (ASN1_TYPE sc, const char *sc_name,
562 gnutls_pkcs12_bag_t bag)
564 gnutls_datum_t content = { NULL, 0 };
565 int result;
567 /* Step 1. Extract the content.
570 result = _gnutls_x509_read_string (sc, sc_name, &content, RV_OCTET_STRING);
571 if (result < 0)
573 gnutls_assert ();
574 goto cleanup;
577 result = _pkcs12_decode_safe_contents (&content, bag);
578 if (result < 0)
580 gnutls_assert ();
581 goto cleanup;
584 _gnutls_free_datum (&content);
586 return 0;
588 cleanup:
589 _gnutls_free_datum (&content);
590 return result;
595 * gnutls_pkcs12_get_bag:
596 * @pkcs12: should contain a gnutls_pkcs12_t structure
597 * @indx: contains the index of the bag to extract
598 * @bag: An initialized bag, where the contents of the bag will be copied
600 * This function will return a Bag from the PKCS12 structure.
602 * After the last Bag has been read
603 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
605 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
606 * negative error value.
609 gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12,
610 int indx, gnutls_pkcs12_bag_t bag)
612 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
613 int result, len;
614 char root2[ASN1_MAX_NAME_SIZE];
615 char oid[MAX_OID_SIZE];
617 if (pkcs12 == NULL)
619 gnutls_assert ();
620 return GNUTLS_E_INVALID_REQUEST;
623 /* Step 1. decode the data.
625 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
626 if (result < 0)
628 gnutls_assert ();
629 return result;
632 /* Step 2. Parse the AuthenticatedSafe
635 snprintf (root2, sizeof (root2), "?%u.contentType", indx + 1);
637 len = sizeof (oid) - 1;
638 result = asn1_read_value (c2, root2, oid, &len);
640 if (result == ASN1_ELEMENT_NOT_FOUND)
642 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
643 goto cleanup;
646 if (result != ASN1_SUCCESS)
648 gnutls_assert ();
649 result = _gnutls_asn2err (result);
650 goto cleanup;
653 /* Not encrypted Bag
656 snprintf (root2, sizeof (root2), "?%u.content", indx + 1);
658 if (strcmp (oid, DATA_OID) == 0)
660 result = _parse_safe_contents (c2, root2, bag);
661 goto cleanup;
664 /* ENC_DATA_OID needs decryption */
666 bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
667 bag->bag_elements = 1;
669 result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data);
670 if (result < 0)
672 gnutls_assert ();
673 goto cleanup;
676 result = 0;
678 cleanup:
679 if (c2)
680 asn1_delete_structure (&c2);
681 return result;
684 /* Creates an empty PFX structure for the PKCS12 structure.
686 static int
687 create_empty_pfx (ASN1_TYPE pkcs12)
689 uint8_t three = 3;
690 int result;
691 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
693 /* Use version 3
695 result = asn1_write_value (pkcs12, "version", &three, 1);
696 if (result != ASN1_SUCCESS)
698 gnutls_assert ();
699 result = _gnutls_asn2err (result);
700 goto cleanup;
703 /* Write the content type of the data
705 result = asn1_write_value (pkcs12, "authSafe.contentType", DATA_OID, 1);
706 if (result != ASN1_SUCCESS)
708 gnutls_assert ();
709 result = _gnutls_asn2err (result);
710 goto cleanup;
713 /* Check if the authenticatedSafe content is empty, and encode a
714 * null one in that case.
717 if ((result = asn1_create_element
718 (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
719 &c2)) != ASN1_SUCCESS)
721 gnutls_assert ();
722 result = _gnutls_asn2err (result);
723 goto cleanup;
726 result =
727 _gnutls_x509_der_encode_and_copy (c2, "", pkcs12, "authSafe.content", 1);
728 if (result < 0)
730 gnutls_assert ();
731 goto cleanup;
733 asn1_delete_structure (&c2);
735 return 0;
737 cleanup:
738 asn1_delete_structure (&c2);
739 return result;
744 * gnutls_pkcs12_set_bag:
745 * @pkcs12: should contain a gnutls_pkcs12_t structure
746 * @bag: An initialized bag
748 * This function will insert a Bag into the PKCS12 structure.
750 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
751 * negative error value.
754 gnutls_pkcs12_set_bag (gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag)
756 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
757 ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
758 int result;
759 int enc = 0, dum = 1;
760 char null;
762 if (pkcs12 == NULL)
764 gnutls_assert ();
765 return GNUTLS_E_INVALID_REQUEST;
768 /* Step 1. Check if the pkcs12 structure is empty. In that
769 * case generate an empty PFX.
771 result = asn1_read_value (pkcs12->pkcs12, "authSafe.content", &null, &dum);
772 if (result == ASN1_VALUE_NOT_FOUND)
774 result = create_empty_pfx (pkcs12->pkcs12);
775 if (result < 0)
777 gnutls_assert ();
778 return result;
782 /* Step 2. decode the authenticatedSafe.
784 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
785 if (result < 0)
787 gnutls_assert ();
788 return result;
791 /* Step 3. Encode the bag elements into a SafeContents
792 * structure.
794 result = _pkcs12_encode_safe_contents (bag, &safe_cont, &enc);
795 if (result < 0)
797 gnutls_assert ();
798 return result;
801 /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe
802 * structure.
804 result = asn1_write_value (c2, "", "NEW", 1);
805 if (result != ASN1_SUCCESS)
807 gnutls_assert ();
808 result = _gnutls_asn2err (result);
809 goto cleanup;
812 if (enc)
813 result = asn1_write_value (c2, "?LAST.contentType", ENC_DATA_OID, 1);
814 else
815 result = asn1_write_value (c2, "?LAST.contentType", DATA_OID, 1);
816 if (result != ASN1_SUCCESS)
818 gnutls_assert ();
819 result = _gnutls_asn2err (result);
820 goto cleanup;
823 if (enc)
825 /* Encrypted packets are written directly.
827 result =
828 asn1_write_value (c2, "?LAST.content",
829 bag->element[0].data.data,
830 bag->element[0].data.size);
831 if (result != ASN1_SUCCESS)
833 gnutls_assert ();
834 result = _gnutls_asn2err (result);
835 goto cleanup;
838 else
840 result =
841 _gnutls_x509_der_encode_and_copy (safe_cont, "", c2,
842 "?LAST.content", 1);
843 if (result < 0)
845 gnutls_assert ();
846 goto cleanup;
850 asn1_delete_structure (&safe_cont);
853 /* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12
854 * structure.
856 result =
857 _gnutls_x509_der_encode_and_copy (c2, "", pkcs12->pkcs12,
858 "authSafe.content", 1);
859 if (result < 0)
861 gnutls_assert ();
862 goto cleanup;
865 asn1_delete_structure (&c2);
867 return 0;
869 cleanup:
870 asn1_delete_structure (&c2);
871 asn1_delete_structure (&safe_cont);
872 return result;
876 * gnutls_pkcs12_generate_mac:
877 * @pkcs12: should contain a gnutls_pkcs12_t structure
878 * @pass: The password for the MAC
880 * This function will generate a MAC for the PKCS12 structure.
882 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
883 * negative error value.
886 gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const char *pass)
888 uint8_t salt[8], key[20];
889 int result;
890 const int iter = 1;
891 digest_hd_st td1;
892 gnutls_datum_t tmp = { NULL, 0 };
893 uint8_t sha_mac[20];
895 if (pkcs12 == NULL)
897 gnutls_assert ();
898 return GNUTLS_E_INVALID_REQUEST;
901 /* Generate the salt.
903 result = _gnutls_rnd (GNUTLS_RND_NONCE, salt, sizeof (salt));
904 if (result < 0)
906 gnutls_assert ();
907 return result;
910 /* Write the salt into the structure.
912 result =
913 asn1_write_value (pkcs12->pkcs12, "macData.macSalt", salt, sizeof (salt));
914 if (result != ASN1_SUCCESS)
916 gnutls_assert ();
917 result = _gnutls_asn2err (result);
918 goto cleanup;
921 /* write the iterations
924 if (iter > 1)
926 result =
927 _gnutls_x509_write_uint32 (pkcs12->pkcs12, "macData.iterations",
928 iter);
929 if (result < 0)
931 gnutls_assert ();
932 goto cleanup;
936 /* Generate the key.
938 result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt),
939 iter, pass, sizeof (key), key);
940 if (result < 0)
942 gnutls_assert ();
943 goto cleanup;
946 /* Get the data to be MACed
948 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
949 if (result < 0)
951 gnutls_assert ();
952 goto cleanup;
955 /* MAC the data
957 result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
958 if (result < 0)
960 gnutls_assert ();
961 goto cleanup;
964 _gnutls_hmac (&td1, tmp.data, tmp.size);
965 _gnutls_free_datum (&tmp);
967 _gnutls_hmac_deinit (&td1, sha_mac);
970 result =
971 asn1_write_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac,
972 sizeof (sha_mac));
973 if (result != ASN1_SUCCESS)
975 gnutls_assert ();
976 result = _gnutls_asn2err (result);
977 goto cleanup;
980 result =
981 asn1_write_value (pkcs12->pkcs12,
982 "macData.mac.digestAlgorithm.parameters", NULL, 0);
983 if (result != ASN1_SUCCESS)
985 gnutls_assert ();
986 result = _gnutls_asn2err (result);
987 goto cleanup;
990 result =
991 asn1_write_value (pkcs12->pkcs12,
992 "macData.mac.digestAlgorithm.algorithm", HASH_OID_SHA1,
994 if (result != ASN1_SUCCESS)
996 gnutls_assert ();
997 result = _gnutls_asn2err (result);
998 goto cleanup;
1001 return 0;
1003 cleanup:
1004 _gnutls_free_datum (&tmp);
1005 return result;
1009 * gnutls_pkcs12_verify_mac:
1010 * @pkcs12: should contain a gnutls_pkcs12_t structure
1011 * @pass: The password for the MAC
1013 * This function will verify the MAC for the PKCS12 structure.
1015 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1016 * negative error value.
1019 gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass)
1021 uint8_t key[20];
1022 int result;
1023 unsigned int iter;
1024 int len;
1025 digest_hd_st td1;
1026 gnutls_datum_t tmp = { NULL, 0 }, salt =
1028 NULL, 0};
1029 uint8_t sha_mac[20];
1030 uint8_t sha_mac_orig[20];
1032 if (pkcs12 == NULL)
1034 gnutls_assert ();
1035 return GNUTLS_E_INVALID_REQUEST;
1038 /* read the iterations
1041 result =
1042 _gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter);
1043 if (result < 0)
1045 iter = 1; /* the default */
1049 /* Read the salt from the structure.
1051 result =
1052 _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt);
1053 if (result != ASN1_SUCCESS)
1055 gnutls_assert ();
1056 result = _gnutls_asn2err (result);
1057 goto cleanup;
1060 /* Generate the key.
1062 result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size,
1063 iter, pass, sizeof (key), key);
1064 if (result < 0)
1066 gnutls_assert ();
1067 goto cleanup;
1070 _gnutls_free_datum (&salt);
1072 /* Get the data to be MACed
1074 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
1075 if (result < 0)
1077 gnutls_assert ();
1078 goto cleanup;
1081 /* MAC the data
1083 result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
1084 if (result < 0)
1086 gnutls_assert ();
1087 goto cleanup;
1090 _gnutls_hmac (&td1, tmp.data, tmp.size);
1091 _gnutls_free_datum (&tmp);
1093 _gnutls_hmac_deinit (&td1, sha_mac);
1095 len = sizeof (sha_mac_orig);
1096 result =
1097 asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig,
1098 &len);
1099 if (result != ASN1_SUCCESS)
1101 gnutls_assert ();
1102 result = _gnutls_asn2err (result);
1103 goto cleanup;
1106 if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0)
1108 gnutls_assert ();
1109 return GNUTLS_E_MAC_VERIFY_FAILED;
1112 return 0;
1114 cleanup:
1115 _gnutls_free_datum (&tmp);
1116 _gnutls_free_datum (&salt);
1117 return result;
1121 static int
1122 write_attributes (gnutls_pkcs12_bag_t bag, int elem,
1123 ASN1_TYPE c2, const char *where)
1125 int result;
1126 char root[128];
1128 /* If the bag attributes are empty, then write
1129 * nothing to the attribute field.
1131 if (bag->element[elem].friendly_name == NULL &&
1132 bag->element[elem].local_key_id.data == NULL)
1134 /* no attributes
1136 result = asn1_write_value (c2, where, NULL, 0);
1137 if (result != ASN1_SUCCESS)
1139 gnutls_assert ();
1140 return _gnutls_asn2err (result);
1143 return 0;
1146 if (bag->element[elem].local_key_id.data != NULL)
1149 /* Add a new Attribute
1151 result = asn1_write_value (c2, where, "NEW", 1);
1152 if (result != ASN1_SUCCESS)
1154 gnutls_assert ();
1155 return _gnutls_asn2err (result);
1158 _gnutls_str_cpy (root, sizeof (root), where);
1159 _gnutls_str_cat (root, sizeof (root), ".?LAST");
1161 result =
1162 _gnutls_x509_encode_and_write_attribute (KEY_ID_OID, c2, root,
1163 bag->
1164 element[elem].local_key_id.
1165 data,
1166 bag->
1167 element[elem].local_key_id.
1168 size, 1);
1169 if (result < 0)
1171 gnutls_assert ();
1172 return result;
1176 if (bag->element[elem].friendly_name != NULL)
1178 uint8_t *name;
1179 int size, i;
1180 const char *p;
1182 /* Add a new Attribute
1184 result = asn1_write_value (c2, where, "NEW", 1);
1185 if (result != ASN1_SUCCESS)
1187 gnutls_assert ();
1188 return _gnutls_asn2err (result);
1191 /* convert name to BMPString
1193 size = strlen (bag->element[elem].friendly_name) * 2;
1194 name = gnutls_malloc (size);
1196 if (name == NULL)
1198 gnutls_assert ();
1199 return GNUTLS_E_MEMORY_ERROR;
1202 p = bag->element[elem].friendly_name;
1203 for (i = 0; i < size; i += 2)
1205 name[i] = 0;
1206 name[i + 1] = *p;
1207 p++;
1210 _gnutls_str_cpy (root, sizeof (root), where);
1211 _gnutls_str_cat (root, sizeof (root), ".?LAST");
1213 result =
1214 _gnutls_x509_encode_and_write_attribute (FRIENDLY_NAME_OID, c2,
1215 root, name, size, 1);
1217 gnutls_free (name);
1219 if (result < 0)
1221 gnutls_assert ();
1222 return result;
1226 return 0;
1230 /* Encodes the bag into a SafeContents structure, and puts the output in
1231 * the given datum. Enc is set to non-zero if the data are encrypted;
1234 _pkcs12_encode_safe_contents (gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents,
1235 int *enc)
1237 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1238 int result;
1239 int i;
1240 const char *oid;
1242 if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc)
1244 *enc = 1;
1245 return 0; /* ENCRYPTED BAG, do nothing. */
1247 else if (enc)
1248 *enc = 0;
1250 /* Step 1. Create the SEQUENCE.
1253 if ((result = asn1_create_element
1254 (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
1255 &c2)) != ASN1_SUCCESS)
1257 gnutls_assert ();
1258 result = _gnutls_asn2err (result);
1259 goto cleanup;
1262 for (i = 0; i < bag->bag_elements; i++)
1265 oid = bag_to_oid (bag->element[i].type);
1266 if (oid == NULL)
1268 gnutls_assert ();
1269 continue;
1272 result = asn1_write_value (c2, "", "NEW", 1);
1273 if (result != ASN1_SUCCESS)
1275 gnutls_assert ();
1276 result = _gnutls_asn2err (result);
1277 goto cleanup;
1280 /* Copy the bag type.
1282 result = asn1_write_value (c2, "?LAST.bagId", oid, 1);
1283 if (result != ASN1_SUCCESS)
1285 gnutls_assert ();
1286 result = _gnutls_asn2err (result);
1287 goto cleanup;
1290 /* Set empty attributes
1292 result = write_attributes (bag, i, c2, "?LAST.bagAttributes");
1293 if (result < 0)
1295 gnutls_assert ();
1296 goto cleanup;
1300 /* Copy the Bag Value
1303 if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE ||
1304 bag->element[i].type == GNUTLS_BAG_SECRET ||
1305 bag->element[i].type == GNUTLS_BAG_CRL)
1307 gnutls_datum_t tmp;
1309 /* in that case encode it to a CertBag or
1310 * a CrlBag.
1313 result =
1314 _pkcs12_encode_crt_bag (bag->element[i].type,
1315 &bag->element[i].data, &tmp);
1317 if (result < 0)
1319 gnutls_assert ();
1320 goto cleanup;
1323 result = _gnutls_x509_write_value (c2, "?LAST.bagValue", &tmp, 0);
1325 _gnutls_free_datum (&tmp);
1328 else
1331 result = _gnutls_x509_write_value (c2, "?LAST.bagValue",
1332 &bag->element[i].data, 0);
1335 if (result < 0)
1337 gnutls_assert ();
1338 goto cleanup;
1343 /* Encode the data and copy them into the datum
1345 *contents = c2;
1347 return 0;
1349 cleanup:
1350 if (c2)
1351 asn1_delete_structure (&c2);
1352 return result;
1356 /* Checks if the extra_certs contain certificates that may form a chain
1357 * with the first certificate in chain (it is expected that chain_len==1)
1358 * and appends those in the chain.
1360 static int make_chain(gnutls_x509_crt_t **chain, unsigned int *chain_len,
1361 gnutls_x509_crt_t **extra_certs, unsigned int *extra_certs_len,
1362 unsigned int flags)
1364 unsigned int i;
1366 if (*chain_len != 1)
1367 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1369 i = 0;
1370 while(i<*extra_certs_len)
1372 /* if it is an issuer but not a self-signed one */
1373 if (gnutls_x509_crt_check_issuer((*chain)[*chain_len - 1], (*extra_certs)[i]) != 0)
1375 if (!(flags & GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED) &&
1376 gnutls_x509_crt_check_issuer((*extra_certs)[i], (*extra_certs)[i]) != 0)
1377 goto skip;
1379 *chain = gnutls_realloc (*chain, sizeof((*chain)[0]) *
1380 ++(*chain_len));
1381 if (*chain == NULL)
1383 gnutls_assert();
1384 return GNUTLS_E_MEMORY_ERROR;
1386 (*chain)[*chain_len - 1] = (*extra_certs)[i];
1388 (*extra_certs)[i] = (*extra_certs)[*extra_certs_len-1];
1389 (*extra_certs_len)--;
1391 i=0;
1392 continue;
1395 skip:
1396 i++;
1398 return 0;
1402 * gnutls_pkcs12_simple_parse:
1403 * @p12: the PKCS#12 blob.
1404 * @password: optional password used to decrypt PKCS#12 blob, bags and keys.
1405 * @key: a structure to store the parsed private key.
1406 * @chain: the corresponding to key certificate chain
1407 * @chain_len: will be updated with the number of additional
1408 * @extra_certs: optional pointer to receive an array of additional
1409 * certificates found in the PKCS#12 blob.
1410 * @extra_certs_len: will be updated with the number of additional
1411 * certs.
1412 * @crl: an optional structure to store the parsed CRL.
1413 * @flags: should be zero or one of GNUTLS_PKCS12_SP_*
1415 * This function parses a PKCS#12 blob in @p12blob and extracts the
1416 * private key, the corresponding certificate chain, and any additional
1417 * certificates and a CRL.
1419 * The @extra_certs_ret and @extra_certs_ret_len parameters are optional
1420 * and both may be set to %NULL. If either is non-%NULL, then both must
1421 * be.
1423 * Encrypted PKCS#12 bags and PKCS#8 private keys are supported. However,
1424 * only password based security, and the same password for all
1425 * operations, are supported.
1427 * PKCS#12 file may contain many keys and/or certificates, and there
1428 * is no way to identify which key/certificate pair you want. You
1429 * should make sure the PKCS#12 file only contain one key/certificate
1430 * pair and/or one CRL.
1432 * It is believed that the limitations of this function is acceptable
1433 * for most usage, and that any more flexibility would introduce
1434 * complexity that would make it harder to use this functionality at
1435 * all.
1437 * If the provided structure has encrypted fields but no password
1438 * is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED.
1440 * Note that normally the chain constructed does not include self signed
1441 * certificates, to comply with TLS' requirements. If, however, the flag
1442 * %GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED is specified then
1443 * self signed certificates will be included in the chain.
1445 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1446 * negative error value.
1448 * Since: 3.1
1451 gnutls_pkcs12_simple_parse (gnutls_pkcs12_t p12,
1452 const char *password,
1453 gnutls_x509_privkey_t * key,
1454 gnutls_x509_crt_t ** chain,
1455 unsigned int * chain_len,
1456 gnutls_x509_crt_t ** extra_certs,
1457 unsigned int * extra_certs_len,
1458 gnutls_x509_crl_t * crl,
1459 unsigned int flags)
1461 gnutls_pkcs12_bag_t bag = NULL;
1462 gnutls_x509_crt_t *_extra_certs = NULL;
1463 unsigned int _extra_certs_len = 0;
1464 gnutls_x509_crt_t *_chain = NULL;
1465 unsigned int _chain_len = 0;
1466 int idx = 0;
1467 int ret;
1468 size_t cert_id_size = 0;
1469 size_t key_id_size = 0;
1470 uint8_t cert_id[20];
1471 uint8_t key_id[20];
1472 int privkey_ok = 0;
1473 unsigned int i;
1475 *key = NULL;
1477 if (crl)
1478 *crl = NULL;
1480 /* find the first private key */
1481 for (;;)
1483 int elements_in_bag;
1484 int i;
1486 ret = gnutls_pkcs12_bag_init (&bag);
1487 if (ret < 0)
1489 bag = NULL;
1490 gnutls_assert ();
1491 goto done;
1494 ret = gnutls_pkcs12_get_bag (p12, idx, bag);
1495 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1496 break;
1497 if (ret < 0)
1499 gnutls_assert ();
1500 goto done;
1503 ret = gnutls_pkcs12_bag_get_type (bag, 0);
1504 if (ret < 0)
1506 gnutls_assert ();
1507 goto done;
1510 if (ret == GNUTLS_BAG_ENCRYPTED)
1512 if (password == NULL)
1514 ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
1515 goto done;
1518 ret = gnutls_pkcs12_bag_decrypt (bag, password);
1519 if (ret < 0)
1521 gnutls_assert ();
1522 goto done;
1526 elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
1527 if (elements_in_bag < 0)
1529 gnutls_assert ();
1530 goto done;
1533 for (i = 0; i < elements_in_bag; i++)
1535 int type;
1536 gnutls_datum_t data;
1538 type = gnutls_pkcs12_bag_get_type (bag, i);
1539 if (type < 0)
1541 gnutls_assert ();
1542 goto done;
1545 ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
1546 if (ret < 0)
1548 gnutls_assert ();
1549 goto done;
1552 switch (type)
1554 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
1555 if (password == NULL)
1557 ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
1558 goto done;
1561 case GNUTLS_BAG_PKCS8_KEY:
1562 if (*key != NULL) /* too simple to continue */
1564 gnutls_assert ();
1565 break;
1568 ret = gnutls_x509_privkey_init (key);
1569 if (ret < 0)
1571 gnutls_assert ();
1572 goto done;
1575 ret = gnutls_x509_privkey_import_pkcs8
1576 (*key, &data, GNUTLS_X509_FMT_DER, password,
1577 type == GNUTLS_BAG_PKCS8_KEY ? GNUTLS_PKCS_PLAIN : 0);
1578 if (ret < 0)
1580 gnutls_assert ();
1581 gnutls_x509_privkey_deinit (*key);
1582 goto done;
1585 key_id_size = sizeof (key_id);
1586 ret =
1587 gnutls_x509_privkey_get_key_id (*key, 0, key_id,
1588 &key_id_size);
1589 if (ret < 0)
1591 gnutls_assert ();
1592 gnutls_x509_privkey_deinit (*key);
1593 goto done;
1596 privkey_ok = 1; /* break */
1597 break;
1598 default:
1599 break;
1603 idx++;
1604 gnutls_pkcs12_bag_deinit (bag);
1606 if (privkey_ok != 0) /* private key was found */
1607 break;
1610 if (privkey_ok == 0) /* no private key */
1612 gnutls_assert ();
1613 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1616 /* now find the corresponding certificate
1618 idx = 0;
1619 bag = NULL;
1620 for (;;)
1622 int elements_in_bag;
1623 int i;
1625 ret = gnutls_pkcs12_bag_init (&bag);
1626 if (ret < 0)
1628 bag = NULL;
1629 gnutls_assert ();
1630 goto done;
1633 ret = gnutls_pkcs12_get_bag (p12, idx, bag);
1634 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1635 break;
1636 if (ret < 0)
1638 gnutls_assert ();
1639 goto done;
1642 ret = gnutls_pkcs12_bag_get_type (bag, 0);
1643 if (ret < 0)
1645 gnutls_assert ();
1646 goto done;
1649 if (ret == GNUTLS_BAG_ENCRYPTED)
1651 ret = gnutls_pkcs12_bag_decrypt (bag, password);
1652 if (ret < 0)
1654 gnutls_assert ();
1655 goto done;
1659 elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
1660 if (elements_in_bag < 0)
1662 gnutls_assert ();
1663 goto done;
1666 for (i = 0; i < elements_in_bag; i++)
1668 int type;
1669 gnutls_datum_t data;
1670 gnutls_x509_crt_t this_cert;
1672 type = gnutls_pkcs12_bag_get_type (bag, i);
1673 if (type < 0)
1675 gnutls_assert ();
1676 goto done;
1679 ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
1680 if (ret < 0)
1682 gnutls_assert ();
1683 goto done;
1686 switch (type)
1688 case GNUTLS_BAG_CERTIFICATE:
1689 ret = gnutls_x509_crt_init (&this_cert);
1690 if (ret < 0)
1692 gnutls_assert ();
1693 goto done;
1696 ret =
1697 gnutls_x509_crt_import (this_cert, &data, GNUTLS_X509_FMT_DER);
1698 if (ret < 0)
1700 gnutls_assert ();
1701 gnutls_x509_crt_deinit (this_cert);
1702 goto done;
1705 /* check if the key id match */
1706 cert_id_size = sizeof (cert_id);
1707 ret =
1708 gnutls_x509_crt_get_key_id (this_cert, 0, cert_id, &cert_id_size);
1709 if (ret < 0)
1711 gnutls_assert ();
1712 gnutls_x509_crt_deinit (this_cert);
1713 goto done;
1716 if (memcmp (cert_id, key_id, cert_id_size) != 0)
1717 { /* they don't match - skip the certificate */
1718 if (extra_certs)
1720 _extra_certs = gnutls_realloc (_extra_certs,
1721 sizeof(_extra_certs[0]) *
1722 ++_extra_certs_len);
1723 if (!_extra_certs)
1725 gnutls_assert ();
1726 ret = GNUTLS_E_MEMORY_ERROR;
1727 goto done;
1729 _extra_certs[_extra_certs_len - 1] = this_cert;
1730 this_cert = NULL;
1732 else
1734 gnutls_x509_crt_deinit (this_cert);
1737 else
1739 if (_chain_len == 0)
1741 _chain = gnutls_malloc (sizeof(_chain[0]) * (++_chain_len));
1742 if (!_chain)
1744 gnutls_assert ();
1745 ret = GNUTLS_E_MEMORY_ERROR;
1746 goto done;
1748 _chain[_chain_len - 1] = this_cert;
1749 this_cert = NULL;
1751 else
1753 gnutls_x509_crt_deinit (this_cert);
1756 break;
1758 case GNUTLS_BAG_CRL:
1759 if (crl == NULL || *crl != NULL)
1761 gnutls_assert ();
1762 break;
1765 ret = gnutls_x509_crl_init (crl);
1766 if (ret < 0)
1768 gnutls_assert ();
1769 goto done;
1772 ret = gnutls_x509_crl_import (*crl, &data, GNUTLS_X509_FMT_DER);
1773 if (ret < 0)
1775 gnutls_assert ();
1776 gnutls_x509_crl_deinit (*crl);
1777 goto done;
1779 break;
1781 case GNUTLS_BAG_ENCRYPTED:
1782 /* XXX Bother to recurse one level down? Unlikely to
1783 use the same password anyway. */
1784 case GNUTLS_BAG_EMPTY:
1785 default:
1786 break;
1790 idx++;
1791 gnutls_pkcs12_bag_deinit (bag);
1794 if (_chain_len != 1)
1796 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1797 goto done;
1800 ret = make_chain(&_chain, &_chain_len, &_extra_certs, &_extra_certs_len, flags);
1801 if (ret < 0)
1803 gnutls_assert();
1804 goto done;
1807 ret = 0;
1809 done:
1810 if (bag)
1811 gnutls_pkcs12_bag_deinit (bag);
1813 if (ret < 0)
1815 if (*key)
1816 gnutls_x509_privkey_deinit(*key);
1817 if (_extra_certs_len && _extra_certs != NULL)
1819 for (i = 0; i < _extra_certs_len; i++)
1820 gnutls_x509_crt_deinit(_extra_certs[i]);
1821 gnutls_free(_extra_certs);
1823 if (_chain_len && _chain != NULL)
1825 for (i = 0; i < _chain_len; i++)
1826 gnutls_x509_crt_deinit(_chain[i]);
1827 gnutls_free(_chain);
1830 return ret;
1833 if (extra_certs && _extra_certs_len > 0)
1835 *extra_certs = _extra_certs;
1836 *extra_certs_len = _extra_certs_len;
1838 else
1840 if (extra_certs)
1842 *extra_certs = NULL;
1843 *extra_certs_len = 0;
1845 for (i = 0; i < _extra_certs_len; i++)
1846 gnutls_x509_crt_deinit(_extra_certs[i]);
1847 gnutls_free(_extra_certs);
1850 *chain = _chain;
1851 *chain_len = _chain_len;
1853 return ret;