Added functions to export structures in an allocated buffer.
[gnutls.git] / lib / x509 / pkcs12.c
blob380f3fc9b01eb859dc93a5ef050165250268dff4
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);
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 int count = 0, i, attributes, j;
377 size_t size;
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, 0);
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 size = attr_val.size;
500 result =
501 _gnutls_x509_decode_octet_string (NULL, attr_val.data, size,
502 attr_val.data, &size);
503 attr_val.size = size;
504 if (result < 0)
506 _gnutls_free_datum (&attr_val);
507 gnutls_assert ();
508 _gnutls_debug_log
509 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
510 continue;
512 bag->element[i].local_key_id = attr_val;
514 else if (strcmp (oid, FRIENDLY_NAME_OID) == 0)
516 size = attr_val.size;
517 result =
518 _gnutls_x509_decode_octet_string ("BMPString",
519 attr_val.data, size,
520 attr_val.data, &size);
521 attr_val.size = size;
522 if (result < 0)
524 _gnutls_free_datum (&attr_val);
525 gnutls_assert ();
526 _gnutls_debug_log
527 ("Error decoding PKCS12 Bag Attribute OID '%s'\n", oid);
528 continue;
530 bag->element[i].friendly_name =
531 ucs2_to_ascii ((char*)attr_val.data, attr_val.size);
533 else
535 _gnutls_free_datum (&attr_val);
536 _gnutls_debug_log
537 ("Unknown PKCS12 Bag Attribute OID '%s'\n", oid);
542 bag->element[i].type = bag_type;
546 asn1_delete_structure (&c2);
549 return 0;
551 cleanup:
552 if (c2)
553 asn1_delete_structure (&c2);
554 return result;
559 static int
560 _parse_safe_contents (ASN1_TYPE sc, const char *sc_name,
561 gnutls_pkcs12_bag_t bag)
563 gnutls_datum_t content = { NULL, 0 };
564 int result;
566 /* Step 1. Extract the content.
569 result = _gnutls_x509_read_value (sc, sc_name, &content, 1);
570 if (result < 0)
572 gnutls_assert ();
573 goto cleanup;
576 result = _pkcs12_decode_safe_contents (&content, bag);
577 if (result < 0)
579 gnutls_assert ();
580 goto cleanup;
583 _gnutls_free_datum (&content);
585 return 0;
587 cleanup:
588 _gnutls_free_datum (&content);
589 return result;
594 * gnutls_pkcs12_get_bag:
595 * @pkcs12: should contain a gnutls_pkcs12_t structure
596 * @indx: contains the index of the bag to extract
597 * @bag: An initialized bag, where the contents of the bag will be copied
599 * This function will return a Bag from the PKCS12 structure.
601 * After the last Bag has been read
602 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
604 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
605 * negative error value.
608 gnutls_pkcs12_get_bag (gnutls_pkcs12_t pkcs12,
609 int indx, gnutls_pkcs12_bag_t bag)
611 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
612 int result, len;
613 char root2[ASN1_MAX_NAME_SIZE];
614 char oid[MAX_OID_SIZE];
616 if (pkcs12 == NULL)
618 gnutls_assert ();
619 return GNUTLS_E_INVALID_REQUEST;
622 /* Step 1. decode the data.
624 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
625 if (result < 0)
627 gnutls_assert ();
628 return result;
631 /* Step 2. Parse the AuthenticatedSafe
634 snprintf (root2, sizeof (root2), "?%u.contentType", indx + 1);
636 len = sizeof (oid) - 1;
637 result = asn1_read_value (c2, root2, oid, &len);
639 if (result == ASN1_ELEMENT_NOT_FOUND)
641 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
642 goto cleanup;
645 if (result != ASN1_SUCCESS)
647 gnutls_assert ();
648 result = _gnutls_asn2err (result);
649 goto cleanup;
652 /* Not encrypted Bag
655 snprintf (root2, sizeof (root2), "?%u.content", indx + 1);
657 if (strcmp (oid, DATA_OID) == 0)
659 result = _parse_safe_contents (c2, root2, bag);
660 goto cleanup;
663 /* ENC_DATA_OID needs decryption */
665 bag->element[0].type = GNUTLS_BAG_ENCRYPTED;
666 bag->bag_elements = 1;
668 result = _gnutls_x509_read_value (c2, root2, &bag->element[0].data, 0);
669 if (result < 0)
671 gnutls_assert ();
672 goto cleanup;
675 result = 0;
677 cleanup:
678 if (c2)
679 asn1_delete_structure (&c2);
680 return result;
683 /* Creates an empty PFX structure for the PKCS12 structure.
685 static int
686 create_empty_pfx (ASN1_TYPE pkcs12)
688 uint8_t three = 3;
689 int result;
690 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
692 /* Use version 3
694 result = asn1_write_value (pkcs12, "version", &three, 1);
695 if (result != ASN1_SUCCESS)
697 gnutls_assert ();
698 result = _gnutls_asn2err (result);
699 goto cleanup;
702 /* Write the content type of the data
704 result = asn1_write_value (pkcs12, "authSafe.contentType", DATA_OID, 1);
705 if (result != ASN1_SUCCESS)
707 gnutls_assert ();
708 result = _gnutls_asn2err (result);
709 goto cleanup;
712 /* Check if the authenticatedSafe content is empty, and encode a
713 * null one in that case.
716 if ((result = asn1_create_element
717 (_gnutls_get_pkix (), "PKIX1.pkcs-12-AuthenticatedSafe",
718 &c2)) != ASN1_SUCCESS)
720 gnutls_assert ();
721 result = _gnutls_asn2err (result);
722 goto cleanup;
725 result =
726 _gnutls_x509_der_encode_and_copy (c2, "", pkcs12, "authSafe.content", 1);
727 if (result < 0)
729 gnutls_assert ();
730 goto cleanup;
732 asn1_delete_structure (&c2);
734 return 0;
736 cleanup:
737 asn1_delete_structure (&c2);
738 return result;
743 * gnutls_pkcs12_set_bag:
744 * @pkcs12: should contain a gnutls_pkcs12_t structure
745 * @bag: An initialized bag
747 * This function will insert a Bag into the PKCS12 structure.
749 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
750 * negative error value.
753 gnutls_pkcs12_set_bag (gnutls_pkcs12_t pkcs12, gnutls_pkcs12_bag_t bag)
755 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
756 ASN1_TYPE safe_cont = ASN1_TYPE_EMPTY;
757 int result;
758 int enc = 0, dum = 1;
759 char null;
761 if (pkcs12 == NULL)
763 gnutls_assert ();
764 return GNUTLS_E_INVALID_REQUEST;
767 /* Step 1. Check if the pkcs12 structure is empty. In that
768 * case generate an empty PFX.
770 result = asn1_read_value (pkcs12->pkcs12, "authSafe.content", &null, &dum);
771 if (result == ASN1_VALUE_NOT_FOUND)
773 result = create_empty_pfx (pkcs12->pkcs12);
774 if (result < 0)
776 gnutls_assert ();
777 return result;
781 /* Step 2. decode the authenticatedSafe.
783 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, &c2, NULL);
784 if (result < 0)
786 gnutls_assert ();
787 return result;
790 /* Step 3. Encode the bag elements into a SafeContents
791 * structure.
793 result = _pkcs12_encode_safe_contents (bag, &safe_cont, &enc);
794 if (result < 0)
796 gnutls_assert ();
797 return result;
800 /* Step 4. Insert the encoded SafeContents into the AuthenticatedSafe
801 * structure.
803 result = asn1_write_value (c2, "", "NEW", 1);
804 if (result != ASN1_SUCCESS)
806 gnutls_assert ();
807 result = _gnutls_asn2err (result);
808 goto cleanup;
811 if (enc)
812 result = asn1_write_value (c2, "?LAST.contentType", ENC_DATA_OID, 1);
813 else
814 result = asn1_write_value (c2, "?LAST.contentType", DATA_OID, 1);
815 if (result != ASN1_SUCCESS)
817 gnutls_assert ();
818 result = _gnutls_asn2err (result);
819 goto cleanup;
822 if (enc)
824 /* Encrypted packets are written directly.
826 result =
827 asn1_write_value (c2, "?LAST.content",
828 bag->element[0].data.data,
829 bag->element[0].data.size);
830 if (result != ASN1_SUCCESS)
832 gnutls_assert ();
833 result = _gnutls_asn2err (result);
834 goto cleanup;
837 else
839 result =
840 _gnutls_x509_der_encode_and_copy (safe_cont, "", c2,
841 "?LAST.content", 1);
842 if (result < 0)
844 gnutls_assert ();
845 goto cleanup;
849 asn1_delete_structure (&safe_cont);
852 /* Step 5. Reencode and copy the AuthenticatedSafe into the pkcs12
853 * structure.
855 result =
856 _gnutls_x509_der_encode_and_copy (c2, "", pkcs12->pkcs12,
857 "authSafe.content", 1);
858 if (result < 0)
860 gnutls_assert ();
861 goto cleanup;
864 asn1_delete_structure (&c2);
866 return 0;
868 cleanup:
869 asn1_delete_structure (&c2);
870 asn1_delete_structure (&safe_cont);
871 return result;
875 * gnutls_pkcs12_generate_mac:
876 * @pkcs12: should contain a gnutls_pkcs12_t structure
877 * @pass: The password for the MAC
879 * This function will generate a MAC for the PKCS12 structure.
881 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
882 * negative error value.
885 gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const char *pass)
887 uint8_t salt[8], key[20];
888 int result;
889 const int iter = 1;
890 digest_hd_st td1;
891 gnutls_datum_t tmp = { NULL, 0 };
892 uint8_t sha_mac[20];
894 if (pkcs12 == NULL)
896 gnutls_assert ();
897 return GNUTLS_E_INVALID_REQUEST;
900 /* Generate the salt.
902 result = _gnutls_rnd (GNUTLS_RND_NONCE, salt, sizeof (salt));
903 if (result < 0)
905 gnutls_assert ();
906 return result;
909 /* Write the salt into the structure.
911 result =
912 asn1_write_value (pkcs12->pkcs12, "macData.macSalt", salt, sizeof (salt));
913 if (result != ASN1_SUCCESS)
915 gnutls_assert ();
916 result = _gnutls_asn2err (result);
917 goto cleanup;
920 /* write the iterations
923 if (iter > 1)
925 result =
926 _gnutls_x509_write_uint32 (pkcs12->pkcs12, "macData.iterations",
927 iter);
928 if (result < 0)
930 gnutls_assert ();
931 goto cleanup;
935 /* Generate the key.
937 result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt),
938 iter, pass, sizeof (key), key);
939 if (result < 0)
941 gnutls_assert ();
942 goto cleanup;
945 /* Get the data to be MACed
947 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
948 if (result < 0)
950 gnutls_assert ();
951 goto cleanup;
954 /* MAC the data
956 result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
957 if (result < 0)
959 gnutls_assert ();
960 goto cleanup;
963 _gnutls_hmac (&td1, tmp.data, tmp.size);
964 _gnutls_free_datum (&tmp);
966 _gnutls_hmac_deinit (&td1, sha_mac);
969 result =
970 asn1_write_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac,
971 sizeof (sha_mac));
972 if (result != ASN1_SUCCESS)
974 gnutls_assert ();
975 result = _gnutls_asn2err (result);
976 goto cleanup;
979 result =
980 asn1_write_value (pkcs12->pkcs12,
981 "macData.mac.digestAlgorithm.parameters", NULL, 0);
982 if (result != ASN1_SUCCESS)
984 gnutls_assert ();
985 result = _gnutls_asn2err (result);
986 goto cleanup;
989 result =
990 asn1_write_value (pkcs12->pkcs12,
991 "macData.mac.digestAlgorithm.algorithm", HASH_OID_SHA1,
993 if (result != ASN1_SUCCESS)
995 gnutls_assert ();
996 result = _gnutls_asn2err (result);
997 goto cleanup;
1000 return 0;
1002 cleanup:
1003 _gnutls_free_datum (&tmp);
1004 return result;
1008 * gnutls_pkcs12_verify_mac:
1009 * @pkcs12: should contain a gnutls_pkcs12_t structure
1010 * @pass: The password for the MAC
1012 * This function will verify the MAC for the PKCS12 structure.
1014 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1015 * negative error value.
1018 gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass)
1020 uint8_t key[20];
1021 int result;
1022 unsigned int iter;
1023 int len;
1024 digest_hd_st td1;
1025 gnutls_datum_t tmp = { NULL, 0 }, salt =
1027 NULL, 0};
1028 uint8_t sha_mac[20];
1029 uint8_t sha_mac_orig[20];
1031 if (pkcs12 == NULL)
1033 gnutls_assert ();
1034 return GNUTLS_E_INVALID_REQUEST;
1037 /* read the iterations
1040 result =
1041 _gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter);
1042 if (result < 0)
1044 iter = 1; /* the default */
1048 /* Read the salt from the structure.
1050 result =
1051 _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0);
1052 if (result != ASN1_SUCCESS)
1054 gnutls_assert ();
1055 result = _gnutls_asn2err (result);
1056 goto cleanup;
1059 /* Generate the key.
1061 result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size,
1062 iter, pass, sizeof (key), key);
1063 if (result < 0)
1065 gnutls_assert ();
1066 goto cleanup;
1069 _gnutls_free_datum (&salt);
1071 /* Get the data to be MACed
1073 result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp);
1074 if (result < 0)
1076 gnutls_assert ();
1077 goto cleanup;
1080 /* MAC the data
1082 result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key));
1083 if (result < 0)
1085 gnutls_assert ();
1086 goto cleanup;
1089 _gnutls_hmac (&td1, tmp.data, tmp.size);
1090 _gnutls_free_datum (&tmp);
1092 _gnutls_hmac_deinit (&td1, sha_mac);
1094 len = sizeof (sha_mac_orig);
1095 result =
1096 asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig,
1097 &len);
1098 if (result != ASN1_SUCCESS)
1100 gnutls_assert ();
1101 result = _gnutls_asn2err (result);
1102 goto cleanup;
1105 if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0)
1107 gnutls_assert ();
1108 return GNUTLS_E_MAC_VERIFY_FAILED;
1111 return 0;
1113 cleanup:
1114 _gnutls_free_datum (&tmp);
1115 _gnutls_free_datum (&salt);
1116 return result;
1120 static int
1121 write_attributes (gnutls_pkcs12_bag_t bag, int elem,
1122 ASN1_TYPE c2, const char *where)
1124 int result;
1125 char root[128];
1127 /* If the bag attributes are empty, then write
1128 * nothing to the attribute field.
1130 if (bag->element[elem].friendly_name == NULL &&
1131 bag->element[elem].local_key_id.data == NULL)
1133 /* no attributes
1135 result = asn1_write_value (c2, where, NULL, 0);
1136 if (result != ASN1_SUCCESS)
1138 gnutls_assert ();
1139 return _gnutls_asn2err (result);
1142 return 0;
1145 if (bag->element[elem].local_key_id.data != NULL)
1148 /* Add a new Attribute
1150 result = asn1_write_value (c2, where, "NEW", 1);
1151 if (result != ASN1_SUCCESS)
1153 gnutls_assert ();
1154 return _gnutls_asn2err (result);
1157 _gnutls_str_cpy (root, sizeof (root), where);
1158 _gnutls_str_cat (root, sizeof (root), ".?LAST");
1160 result =
1161 _gnutls_x509_encode_and_write_attribute (KEY_ID_OID, c2, root,
1162 bag->
1163 element[elem].local_key_id.
1164 data,
1165 bag->
1166 element[elem].local_key_id.
1167 size, 1);
1168 if (result < 0)
1170 gnutls_assert ();
1171 return result;
1175 if (bag->element[elem].friendly_name != NULL)
1177 uint8_t *name;
1178 int size, i;
1179 const char *p;
1181 /* Add a new Attribute
1183 result = asn1_write_value (c2, where, "NEW", 1);
1184 if (result != ASN1_SUCCESS)
1186 gnutls_assert ();
1187 return _gnutls_asn2err (result);
1190 /* convert name to BMPString
1192 size = strlen (bag->element[elem].friendly_name) * 2;
1193 name = gnutls_malloc (size);
1195 if (name == NULL)
1197 gnutls_assert ();
1198 return GNUTLS_E_MEMORY_ERROR;
1201 p = bag->element[elem].friendly_name;
1202 for (i = 0; i < size; i += 2)
1204 name[i] = 0;
1205 name[i + 1] = *p;
1206 p++;
1209 _gnutls_str_cpy (root, sizeof (root), where);
1210 _gnutls_str_cat (root, sizeof (root), ".?LAST");
1212 result =
1213 _gnutls_x509_encode_and_write_attribute (FRIENDLY_NAME_OID, c2,
1214 root, name, size, 1);
1216 gnutls_free (name);
1218 if (result < 0)
1220 gnutls_assert ();
1221 return result;
1225 return 0;
1229 /* Encodes the bag into a SafeContents structure, and puts the output in
1230 * the given datum. Enc is set to non (0) if the data are encrypted;
1233 _pkcs12_encode_safe_contents (gnutls_pkcs12_bag_t bag, ASN1_TYPE * contents,
1234 int *enc)
1236 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1237 int result;
1238 int i;
1239 const char *oid;
1241 if (bag->element[0].type == GNUTLS_BAG_ENCRYPTED && enc)
1243 *enc = 1;
1244 return 0; /* ENCRYPTED BAG, do nothing. */
1246 else if (enc)
1247 *enc = 0;
1249 /* Step 1. Create the SEQUENCE.
1252 if ((result = asn1_create_element
1253 (_gnutls_get_pkix (), "PKIX1.pkcs-12-SafeContents",
1254 &c2)) != ASN1_SUCCESS)
1256 gnutls_assert ();
1257 result = _gnutls_asn2err (result);
1258 goto cleanup;
1261 for (i = 0; i < bag->bag_elements; i++)
1264 oid = bag_to_oid (bag->element[i].type);
1265 if (oid == NULL)
1267 gnutls_assert ();
1268 continue;
1271 result = asn1_write_value (c2, "", "NEW", 1);
1272 if (result != ASN1_SUCCESS)
1274 gnutls_assert ();
1275 result = _gnutls_asn2err (result);
1276 goto cleanup;
1279 /* Copy the bag type.
1281 result = asn1_write_value (c2, "?LAST.bagId", oid, 1);
1282 if (result != ASN1_SUCCESS)
1284 gnutls_assert ();
1285 result = _gnutls_asn2err (result);
1286 goto cleanup;
1289 /* Set empty attributes
1291 result = write_attributes (bag, i, c2, "?LAST.bagAttributes");
1292 if (result < 0)
1294 gnutls_assert ();
1295 goto cleanup;
1299 /* Copy the Bag Value
1302 if (bag->element[i].type == GNUTLS_BAG_CERTIFICATE ||
1303 bag->element[i].type == GNUTLS_BAG_SECRET ||
1304 bag->element[i].type == GNUTLS_BAG_CRL)
1306 gnutls_datum_t tmp;
1308 /* in that case encode it to a CertBag or
1309 * a CrlBag.
1312 result =
1313 _pkcs12_encode_crt_bag (bag->element[i].type,
1314 &bag->element[i].data, &tmp);
1316 if (result < 0)
1318 gnutls_assert ();
1319 goto cleanup;
1322 result = _gnutls_x509_write_value (c2, "?LAST.bagValue", &tmp, 0);
1324 _gnutls_free_datum (&tmp);
1327 else
1330 result = _gnutls_x509_write_value (c2, "?LAST.bagValue",
1331 &bag->element[i].data, 0);
1334 if (result < 0)
1336 gnutls_assert ();
1337 goto cleanup;
1342 /* Encode the data and copy them into the datum
1344 *contents = c2;
1346 return 0;
1348 cleanup:
1349 if (c2)
1350 asn1_delete_structure (&c2);
1351 return result;
1355 /* Checks if the extra_certs contain certificates that may form a chain
1356 * with the first certificate in chain (it is expected that chain_len==1)
1357 * and appends those in the chain.
1359 static int make_chain(gnutls_x509_crt_t **chain, unsigned int *chain_len,
1360 gnutls_x509_crt_t **extra_certs, unsigned int *extra_certs_len,
1361 unsigned int flags)
1363 unsigned int i;
1365 if (*chain_len != 1)
1366 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1368 i = 0;
1369 while(i<*extra_certs_len)
1371 /* if it is an issuer but not a self-signed one */
1372 if (gnutls_x509_crt_check_issuer((*chain)[*chain_len - 1], (*extra_certs)[i]) != 0)
1374 if (!(flags & GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED) &&
1375 gnutls_x509_crt_check_issuer((*extra_certs)[i], (*extra_certs)[i]) != 0)
1376 goto skip;
1378 *chain = gnutls_realloc (*chain, sizeof((*chain)[0]) *
1379 ++(*chain_len));
1380 if (*chain == NULL)
1382 gnutls_assert();
1383 return GNUTLS_E_MEMORY_ERROR;
1385 (*chain)[*chain_len - 1] = (*extra_certs)[i];
1387 (*extra_certs)[i] = (*extra_certs)[*extra_certs_len-1];
1388 (*extra_certs_len)--;
1390 i=0;
1391 continue;
1394 skip:
1395 i++;
1397 return 0;
1401 * gnutls_pkcs12_simple_parse:
1402 * @p12: the PKCS#12 blob.
1403 * @password: optional password used to decrypt PKCS#12 blob, bags and keys.
1404 * @key: a structure to store the parsed private key.
1405 * @chain: the corresponding to key certificate chain
1406 * @chain_len: will be updated with the number of additional
1407 * @extra_certs: optional pointer to receive an array of additional
1408 * certificates found in the PKCS#12 blob.
1409 * @extra_certs_len: will be updated with the number of additional
1410 * certs.
1411 * @crl: an optional structure to store the parsed CRL.
1412 * @flags: should be zero or one of GNUTLS_PKCS12_SP_*
1414 * This function parses a PKCS#12 blob in @p12blob and extracts the
1415 * private key, the corresponding certificate chain, and any additional
1416 * certificates and a CRL.
1418 * The @extra_certs_ret and @extra_certs_ret_len parameters are optional
1419 * and both may be set to %NULL. If either is non-%NULL, then both must
1420 * be.
1422 * Encrypted PKCS#12 bags and PKCS#8 private keys are supported. However,
1423 * only password based security, and the same password for all
1424 * operations, are supported.
1426 * PKCS#12 file may contain many keys and/or certificates, and there
1427 * is no way to identify which key/certificate pair you want. You
1428 * should make sure the PKCS#12 file only contain one key/certificate
1429 * pair and/or one CRL.
1431 * It is believed that the limitations of this function is acceptable
1432 * for most usage, and that any more flexibility would introduce
1433 * complexity that would make it harder to use this functionality at
1434 * all.
1436 * If the provided structure has encrypted fields but no password
1437 * is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED.
1439 * Note that normally the chain constructed does not include self signed
1440 * certificates, to comply with TLS' requirements. If, however, the flag
1441 * %GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED is specified then
1442 * self signed certificates will be included in the chain.
1444 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1445 * negative error value.
1447 * Since: 3.1
1450 gnutls_pkcs12_simple_parse (gnutls_pkcs12_t p12,
1451 const char *password,
1452 gnutls_x509_privkey_t * key,
1453 gnutls_x509_crt_t ** chain,
1454 unsigned int * chain_len,
1455 gnutls_x509_crt_t ** extra_certs,
1456 unsigned int * extra_certs_len,
1457 gnutls_x509_crl_t * crl,
1458 unsigned int flags)
1460 gnutls_pkcs12_bag_t bag = NULL;
1461 gnutls_x509_crt_t *_extra_certs = NULL;
1462 unsigned int _extra_certs_len = 0;
1463 gnutls_x509_crt_t *_chain = NULL;
1464 unsigned int _chain_len = 0;
1465 int idx = 0;
1466 int ret;
1467 size_t cert_id_size = 0;
1468 size_t key_id_size = 0;
1469 uint8_t cert_id[20];
1470 uint8_t key_id[20];
1471 int privkey_ok = 0;
1472 unsigned int i;
1474 *key = NULL;
1476 if (crl)
1477 *crl = NULL;
1479 /* find the first private key */
1480 for (;;)
1482 int elements_in_bag;
1483 int i;
1485 ret = gnutls_pkcs12_bag_init (&bag);
1486 if (ret < 0)
1488 bag = NULL;
1489 gnutls_assert ();
1490 goto done;
1493 ret = gnutls_pkcs12_get_bag (p12, idx, bag);
1494 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1495 break;
1496 if (ret < 0)
1498 gnutls_assert ();
1499 goto done;
1502 ret = gnutls_pkcs12_bag_get_type (bag, 0);
1503 if (ret < 0)
1505 gnutls_assert ();
1506 goto done;
1509 if (ret == GNUTLS_BAG_ENCRYPTED)
1511 if (password == NULL)
1513 ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
1514 goto done;
1517 ret = gnutls_pkcs12_bag_decrypt (bag, password);
1518 if (ret < 0)
1520 gnutls_assert ();
1521 goto done;
1525 elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
1526 if (elements_in_bag < 0)
1528 gnutls_assert ();
1529 goto done;
1532 for (i = 0; i < elements_in_bag; i++)
1534 int type;
1535 gnutls_datum_t data;
1537 type = gnutls_pkcs12_bag_get_type (bag, i);
1538 if (type < 0)
1540 gnutls_assert ();
1541 goto done;
1544 ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
1545 if (ret < 0)
1547 gnutls_assert ();
1548 goto done;
1551 switch (type)
1553 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
1554 if (password == NULL)
1556 ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
1557 goto done;
1560 case GNUTLS_BAG_PKCS8_KEY:
1561 if (*key != NULL) /* too simple to continue */
1563 gnutls_assert ();
1564 break;
1567 ret = gnutls_x509_privkey_init (key);
1568 if (ret < 0)
1570 gnutls_assert ();
1571 goto done;
1574 ret = gnutls_x509_privkey_import_pkcs8
1575 (*key, &data, GNUTLS_X509_FMT_DER, password,
1576 type == GNUTLS_BAG_PKCS8_KEY ? GNUTLS_PKCS_PLAIN : 0);
1577 if (ret < 0)
1579 gnutls_assert ();
1580 gnutls_x509_privkey_deinit (*key);
1581 goto done;
1584 key_id_size = sizeof (key_id);
1585 ret =
1586 gnutls_x509_privkey_get_key_id (*key, 0, key_id,
1587 &key_id_size);
1588 if (ret < 0)
1590 gnutls_assert ();
1591 gnutls_x509_privkey_deinit (*key);
1592 goto done;
1595 privkey_ok = 1; /* break */
1596 break;
1597 default:
1598 break;
1602 idx++;
1603 gnutls_pkcs12_bag_deinit (bag);
1605 if (privkey_ok != 0) /* private key was found */
1606 break;
1609 if (privkey_ok == 0) /* no private key */
1611 gnutls_assert ();
1612 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1615 /* now find the corresponding certificate
1617 idx = 0;
1618 bag = NULL;
1619 for (;;)
1621 int elements_in_bag;
1622 int i;
1624 ret = gnutls_pkcs12_bag_init (&bag);
1625 if (ret < 0)
1627 bag = NULL;
1628 gnutls_assert ();
1629 goto done;
1632 ret = gnutls_pkcs12_get_bag (p12, idx, bag);
1633 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1634 break;
1635 if (ret < 0)
1637 gnutls_assert ();
1638 goto done;
1641 ret = gnutls_pkcs12_bag_get_type (bag, 0);
1642 if (ret < 0)
1644 gnutls_assert ();
1645 goto done;
1648 if (ret == GNUTLS_BAG_ENCRYPTED)
1650 ret = gnutls_pkcs12_bag_decrypt (bag, password);
1651 if (ret < 0)
1653 gnutls_assert ();
1654 goto done;
1658 elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
1659 if (elements_in_bag < 0)
1661 gnutls_assert ();
1662 goto done;
1665 for (i = 0; i < elements_in_bag; i++)
1667 int type;
1668 gnutls_datum_t data;
1669 gnutls_x509_crt_t this_cert;
1671 type = gnutls_pkcs12_bag_get_type (bag, i);
1672 if (type < 0)
1674 gnutls_assert ();
1675 goto done;
1678 ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
1679 if (ret < 0)
1681 gnutls_assert ();
1682 goto done;
1685 switch (type)
1687 case GNUTLS_BAG_CERTIFICATE:
1688 ret = gnutls_x509_crt_init (&this_cert);
1689 if (ret < 0)
1691 gnutls_assert ();
1692 goto done;
1695 ret =
1696 gnutls_x509_crt_import (this_cert, &data, GNUTLS_X509_FMT_DER);
1697 if (ret < 0)
1699 gnutls_assert ();
1700 gnutls_x509_crt_deinit (this_cert);
1701 goto done;
1704 /* check if the key id match */
1705 cert_id_size = sizeof (cert_id);
1706 ret =
1707 gnutls_x509_crt_get_key_id (this_cert, 0, cert_id, &cert_id_size);
1708 if (ret < 0)
1710 gnutls_assert ();
1711 gnutls_x509_crt_deinit (this_cert);
1712 goto done;
1715 if (memcmp (cert_id, key_id, cert_id_size) != 0)
1716 { /* they don't match - skip the certificate */
1717 if (extra_certs)
1719 _extra_certs = gnutls_realloc (_extra_certs,
1720 sizeof(_extra_certs[0]) *
1721 ++_extra_certs_len);
1722 if (!_extra_certs)
1724 gnutls_assert ();
1725 ret = GNUTLS_E_MEMORY_ERROR;
1726 goto done;
1728 _extra_certs[_extra_certs_len - 1] = this_cert;
1729 this_cert = NULL;
1731 else
1733 gnutls_x509_crt_deinit (this_cert);
1736 else
1738 if (_chain_len == 0)
1740 _chain = gnutls_malloc (sizeof(_chain[0]) * (++_chain_len));
1741 if (!_chain)
1743 gnutls_assert ();
1744 ret = GNUTLS_E_MEMORY_ERROR;
1745 goto done;
1747 _chain[_chain_len - 1] = this_cert;
1748 this_cert = NULL;
1750 else
1752 gnutls_x509_crt_deinit (this_cert);
1755 break;
1757 case GNUTLS_BAG_CRL:
1758 if (crl == NULL || *crl != NULL)
1760 gnutls_assert ();
1761 break;
1764 ret = gnutls_x509_crl_init (crl);
1765 if (ret < 0)
1767 gnutls_assert ();
1768 goto done;
1771 ret = gnutls_x509_crl_import (*crl, &data, GNUTLS_X509_FMT_DER);
1772 if (ret < 0)
1774 gnutls_assert ();
1775 gnutls_x509_crl_deinit (*crl);
1776 goto done;
1778 break;
1780 case GNUTLS_BAG_ENCRYPTED:
1781 /* XXX Bother to recurse one level down? Unlikely to
1782 use the same password anyway. */
1783 case GNUTLS_BAG_EMPTY:
1784 default:
1785 break;
1789 idx++;
1790 gnutls_pkcs12_bag_deinit (bag);
1793 if (_chain_len != 1)
1795 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1796 goto done;
1799 ret = make_chain(&_chain, &_chain_len, &_extra_certs, &_extra_certs_len, flags);
1800 if (ret < 0)
1802 gnutls_assert();
1803 goto done;
1806 ret = 0;
1808 done:
1809 if (bag)
1810 gnutls_pkcs12_bag_deinit (bag);
1812 if (ret < 0)
1814 if (*key)
1815 gnutls_x509_privkey_deinit(*key);
1816 if (_extra_certs_len && _extra_certs != NULL)
1818 for (i = 0; i < _extra_certs_len; i++)
1819 gnutls_x509_crt_deinit(_extra_certs[i]);
1820 gnutls_free(_extra_certs);
1822 if (_chain_len && _chain != NULL)
1824 for (i = 0; i < _chain_len; i++)
1825 gnutls_x509_crt_deinit(_chain[i]);
1826 gnutls_free(_chain);
1829 return ret;
1832 if (extra_certs && _extra_certs_len > 0)
1834 *extra_certs = _extra_certs;
1835 *extra_certs_len = _extra_certs_len;
1837 else
1839 if (extra_certs)
1841 *extra_certs = NULL;
1842 *extra_certs_len = 0;
1844 for (i = 0; i < _extra_certs_len; i++)
1845 gnutls_x509_crt_deinit(_extra_certs[i]);
1846 gnutls_free(_extra_certs);
1849 *chain = _chain;
1850 *chain_len = _chain_len;
1852 return ret;