Added function to sort the provided certificate chain prior to verification.
[gnutls.git] / lib / x509 / pkcs7.c
blobff6da727c877ac1539c81727c2d52e44713c1a80
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 PKCS7 certificate lists 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 <common.h>
33 #include <x509_b64.h>
35 #define SIGNED_DATA_OID "1.2.840.113549.1.7.2"
37 /* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE,
38 * which holds them. If raw is non null then the raw decoded
39 * data are copied (they are locally allocated) there.
41 static int
42 _decode_pkcs7_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata,
43 gnutls_datum_t * raw)
45 char oid[MAX_OID_SIZE];
46 ASN1_TYPE c2;
47 uint8_t *tmp = NULL;
48 int tmp_size, len, result;
50 len = sizeof (oid) - 1;
51 result = asn1_read_value (pkcs7, "contentType", oid, &len);
52 if (result != ASN1_SUCCESS)
54 gnutls_assert ();
55 return _gnutls_asn2err (result);
58 if (strcmp (oid, SIGNED_DATA_OID) != 0)
60 gnutls_assert ();
61 _gnutls_debug_log ("Unknown PKCS7 Content OID '%s'\n", oid);
62 return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
65 if ((result = asn1_create_element
66 (_gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData", &c2)) != ASN1_SUCCESS)
68 gnutls_assert ();
69 return _gnutls_asn2err (result);
72 /* the Signed-data has been created, so
73 * decode them.
75 tmp_size = 0;
76 result = asn1_read_value (pkcs7, "content", NULL, &tmp_size);
77 if (result != ASN1_MEM_ERROR)
79 gnutls_assert ();
80 result = _gnutls_asn2err (result);
81 goto cleanup;
84 tmp = gnutls_malloc (tmp_size);
85 if (tmp == NULL)
87 gnutls_assert ();
88 result = GNUTLS_E_MEMORY_ERROR;
89 goto cleanup;
92 result = asn1_read_value (pkcs7, "content", tmp, &tmp_size);
93 if (result != ASN1_SUCCESS)
95 gnutls_assert ();
96 result = _gnutls_asn2err (result);
97 goto cleanup;
100 /* tmp, tmp_size hold the data and the size of the CertificateSet structure
101 * actually the ANY stuff.
104 /* Step 1. In case of a signed structure extract certificate set.
107 result = asn1_der_decoding (&c2, tmp, tmp_size, NULL);
108 if (result != ASN1_SUCCESS)
110 gnutls_assert ();
111 result = _gnutls_asn2err (result);
112 goto cleanup;
115 if (raw == NULL)
117 gnutls_free (tmp);
119 else
121 raw->data = tmp;
122 raw->size = tmp_size;
125 *sdata = c2;
127 return 0;
129 cleanup:
130 if (c2)
131 asn1_delete_structure (&c2);
132 gnutls_free (tmp);
133 return result;
137 * gnutls_pkcs7_init:
138 * @pkcs7: The structure to be initialized
140 * This function will initialize a PKCS7 structure. PKCS7 structures
141 * usually contain lists of X.509 Certificates and X.509 Certificate
142 * revocation lists.
144 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
145 * negative error value.
148 gnutls_pkcs7_init (gnutls_pkcs7_t * pkcs7)
150 *pkcs7 = gnutls_calloc (1, sizeof (gnutls_pkcs7_int));
152 if (*pkcs7)
154 int result = asn1_create_element (_gnutls_get_pkix (),
155 "PKIX1.pkcs-7-ContentInfo",
156 &(*pkcs7)->pkcs7);
157 if (result != ASN1_SUCCESS)
159 gnutls_assert ();
160 gnutls_free (*pkcs7);
161 return _gnutls_asn2err (result);
163 return 0; /* success */
165 return GNUTLS_E_MEMORY_ERROR;
169 * gnutls_pkcs7_deinit:
170 * @pkcs7: The structure to be initialized
172 * This function will deinitialize a PKCS7 structure.
174 void
175 gnutls_pkcs7_deinit (gnutls_pkcs7_t pkcs7)
177 if (!pkcs7)
178 return;
180 if (pkcs7->pkcs7)
181 asn1_delete_structure (&pkcs7->pkcs7);
183 gnutls_free (pkcs7);
187 * gnutls_pkcs7_import:
188 * @pkcs7: The structure to store the parsed PKCS7.
189 * @data: The DER or PEM encoded PKCS7.
190 * @format: One of DER or PEM
192 * This function will convert the given DER or PEM encoded PKCS7 to
193 * the native #gnutls_pkcs7_t format. The output will be stored in
194 * @pkcs7.
196 * If the PKCS7 is PEM encoded it should have a header of "PKCS7".
198 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
199 * negative error value.
202 gnutls_pkcs7_import (gnutls_pkcs7_t pkcs7, const gnutls_datum_t * data,
203 gnutls_x509_crt_fmt_t format)
205 int result = 0, need_free = 0;
206 gnutls_datum_t _data;
208 if (pkcs7 == NULL)
209 return GNUTLS_E_INVALID_REQUEST;
211 _data.data = data->data;
212 _data.size = data->size;
214 /* If the PKCS7 is in PEM format then decode it
216 if (format == GNUTLS_X509_FMT_PEM)
218 uint8_t *out;
220 result = _gnutls_fbase64_decode (PEM_PKCS7, data->data, data->size,
221 &out);
223 if (result <= 0)
225 if (result == 0)
226 result = GNUTLS_E_INTERNAL_ERROR;
227 gnutls_assert ();
228 return result;
231 _data.data = out;
232 _data.size = result;
234 need_free = 1;
238 result = asn1_der_decoding (&pkcs7->pkcs7, _data.data, _data.size, NULL);
239 if (result != ASN1_SUCCESS)
241 result = _gnutls_asn2err (result);
242 gnutls_assert ();
243 goto cleanup;
246 if (need_free)
247 _gnutls_free_datum (&_data);
249 return 0;
251 cleanup:
252 if (need_free)
253 _gnutls_free_datum (&_data);
254 return result;
258 * gnutls_pkcs7_get_crt_raw:
259 * @pkcs7: should contain a gnutls_pkcs7_t structure
260 * @indx: contains the index of the certificate to extract
261 * @certificate: the contents of the certificate will be copied
262 * there (may be null)
263 * @certificate_size: should hold the size of the certificate
265 * This function will return a certificate of the PKCS7 or RFC2630
266 * certificate set.
268 * After the last certificate has been read
269 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
271 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
272 * negative error value. If the provided buffer is not long enough,
273 * then @certificate_size is updated and
274 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
277 gnutls_pkcs7_get_crt_raw (gnutls_pkcs7_t pkcs7,
278 int indx, void *certificate,
279 size_t * certificate_size)
281 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
282 int result, len;
283 char root2[ASN1_MAX_NAME_SIZE];
284 char oid[MAX_OID_SIZE];
285 gnutls_datum_t tmp = { NULL, 0 };
287 if (certificate_size == NULL || pkcs7 == NULL)
288 return GNUTLS_E_INVALID_REQUEST;
290 /* Step 1. decode the signed data.
292 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, &tmp);
293 if (result < 0)
295 gnutls_assert ();
296 return result;
299 /* Step 2. Parse the CertificateSet
302 snprintf (root2, sizeof (root2), "certificates.?%u", indx + 1);
304 len = sizeof (oid) - 1;
306 result = asn1_read_value (c2, root2, oid, &len);
308 if (result == ASN1_VALUE_NOT_FOUND)
310 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
311 goto cleanup;
314 if (result != ASN1_SUCCESS)
316 gnutls_assert ();
317 result = _gnutls_asn2err (result);
318 goto cleanup;
321 /* if 'Certificate' is the choice found:
323 if (strcmp (oid, "certificate") == 0)
325 int start, end;
327 result = asn1_der_decoding_startEnd (c2, tmp.data, tmp.size,
328 root2, &start, &end);
330 if (result != ASN1_SUCCESS)
332 gnutls_assert ();
333 result = _gnutls_asn2err (result);
334 goto cleanup;
337 end = end - start + 1;
339 if ((unsigned) end > *certificate_size)
341 *certificate_size = end;
342 result = GNUTLS_E_SHORT_MEMORY_BUFFER;
343 goto cleanup;
346 if (certificate)
347 memcpy (certificate, &tmp.data[start], end);
349 *certificate_size = end;
351 result = 0;
354 else
356 result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
359 cleanup:
360 _gnutls_free_datum (&tmp);
361 if (c2)
362 asn1_delete_structure (&c2);
363 return result;
367 * gnutls_pkcs7_get_crt_count:
368 * @pkcs7: should contain a #gnutls_pkcs7_t structure
370 * This function will return the number of certifcates in the PKCS7
371 * or RFC2630 certificate set.
373 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
374 * negative error value.
377 gnutls_pkcs7_get_crt_count (gnutls_pkcs7_t pkcs7)
379 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
380 int result, count;
382 if (pkcs7 == NULL)
383 return GNUTLS_E_INVALID_REQUEST;
385 /* Step 1. decode the signed data.
387 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
388 if (result < 0)
390 gnutls_assert ();
391 return result;
394 /* Step 2. Count the CertificateSet */
396 result = asn1_number_of_elements (c2, "certificates", &count);
398 asn1_delete_structure (&c2);
400 if (result != ASN1_SUCCESS)
402 gnutls_assert ();
403 return 0; /* no certificates */
406 return count;
411 * gnutls_pkcs7_export:
412 * @pkcs7: Holds the pkcs7 structure
413 * @format: the format of output params. One of PEM or DER.
414 * @output_data: will contain a structure PEM or DER encoded
415 * @output_data_size: holds the size of output_data (and will be
416 * replaced by the actual size of parameters)
418 * This function will export the pkcs7 structure to DER or PEM format.
420 * If the buffer provided is not long enough to hold the output, then
421 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
422 * will be returned.
424 * If the structure is PEM encoded, it will have a header
425 * of "BEGIN PKCS7".
427 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
428 * negative error value.
431 gnutls_pkcs7_export (gnutls_pkcs7_t pkcs7,
432 gnutls_x509_crt_fmt_t format, void *output_data,
433 size_t * output_data_size)
435 if (pkcs7 == NULL)
436 return GNUTLS_E_INVALID_REQUEST;
438 return _gnutls_x509_export_int (pkcs7->pkcs7, format, PEM_PKCS7,
439 output_data, output_data_size);
442 /* Creates an empty signed data structure in the pkcs7
443 * structure and returns a handle to the signed data.
445 static int
446 create_empty_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata)
448 uint8_t one = 1;
449 int result;
451 *sdata = ASN1_TYPE_EMPTY;
453 if ((result = asn1_create_element
454 (_gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData",
455 sdata)) != ASN1_SUCCESS)
457 gnutls_assert ();
458 result = _gnutls_asn2err (result);
459 goto cleanup;
462 /* Use version 1
464 result = asn1_write_value (*sdata, "version", &one, 1);
465 if (result != ASN1_SUCCESS)
467 gnutls_assert ();
468 result = _gnutls_asn2err (result);
469 goto cleanup;
472 /* Use no digest algorithms
475 /* id-data */
476 result =
477 asn1_write_value (*sdata, "encapContentInfo.eContentType",
478 "1.2.840.113549.1.7.5", 1);
479 if (result != ASN1_SUCCESS)
481 gnutls_assert ();
482 result = _gnutls_asn2err (result);
483 goto cleanup;
486 result = asn1_write_value (*sdata, "encapContentInfo.eContent", NULL, 0);
487 if (result != ASN1_SUCCESS)
489 gnutls_assert ();
490 result = _gnutls_asn2err (result);
491 goto cleanup;
494 /* Add no certificates.
497 /* Add no crls.
500 /* Add no signerInfos.
503 /* Write the content type of the signed data
505 result = asn1_write_value (pkcs7, "contentType", SIGNED_DATA_OID, 1);
506 if (result != ASN1_SUCCESS)
508 gnutls_assert ();
509 result = _gnutls_asn2err (result);
510 goto cleanup;
513 return 0;
515 cleanup:
516 asn1_delete_structure (sdata);
517 return result;
522 * gnutls_pkcs7_set_crt_raw:
523 * @pkcs7: should contain a #gnutls_pkcs7_t structure
524 * @crt: the DER encoded certificate to be added
526 * This function will add a certificate to the PKCS7 or RFC2630
527 * certificate set.
529 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
530 * negative error value.
533 gnutls_pkcs7_set_crt_raw (gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crt)
535 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
536 int result;
538 if (pkcs7 == NULL)
539 return GNUTLS_E_INVALID_REQUEST;
541 /* Step 1. decode the signed data.
543 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
544 if (result < 0 && result != GNUTLS_E_ASN1_VALUE_NOT_FOUND)
546 gnutls_assert ();
547 return result;
550 /* If the signed data are uninitialized
551 * then create them.
553 if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
555 /* The pkcs7 structure is new, so create the
556 * signedData.
558 result = create_empty_signed_data (pkcs7->pkcs7, &c2);
559 if (result < 0)
561 gnutls_assert ();
562 return result;
566 /* Step 2. Append the new certificate.
569 result = asn1_write_value (c2, "certificates", "NEW", 1);
570 if (result != ASN1_SUCCESS)
572 gnutls_assert ();
573 result = _gnutls_asn2err (result);
574 goto cleanup;
577 result = asn1_write_value (c2, "certificates.?LAST", "certificate", 1);
578 if (result != ASN1_SUCCESS)
580 gnutls_assert ();
581 result = _gnutls_asn2err (result);
582 goto cleanup;
585 result =
586 asn1_write_value (c2, "certificates.?LAST.certificate", crt->data,
587 crt->size);
588 if (result != ASN1_SUCCESS)
590 gnutls_assert ();
591 result = _gnutls_asn2err (result);
592 goto cleanup;
595 /* Step 3. Replace the old content with the new
597 result =
598 _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
599 if (result < 0)
601 gnutls_assert ();
602 goto cleanup;
605 asn1_delete_structure (&c2);
607 return 0;
609 cleanup:
610 if (c2)
611 asn1_delete_structure (&c2);
612 return result;
616 * gnutls_pkcs7_set_crt:
617 * @pkcs7: should contain a #gnutls_pkcs7_t structure
618 * @crt: the certificate to be copied.
620 * This function will add a parsed certificate to the PKCS7 or
621 * RFC2630 certificate set. This is a wrapper function over
622 * gnutls_pkcs7_set_crt_raw() .
624 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
625 * negative error value.
628 gnutls_pkcs7_set_crt (gnutls_pkcs7_t pkcs7, gnutls_x509_crt_t crt)
630 int ret;
631 gnutls_datum_t data;
633 if (pkcs7 == NULL)
634 return GNUTLS_E_INVALID_REQUEST;
636 ret = _gnutls_x509_der_encode (crt->cert, "", &data, 0);
637 if (ret < 0)
639 gnutls_assert ();
640 return ret;
643 ret = gnutls_pkcs7_set_crt_raw (pkcs7, &data);
645 _gnutls_free_datum (&data);
647 if (ret < 0)
649 gnutls_assert ();
650 return ret;
653 return 0;
658 * gnutls_pkcs7_delete_crt:
659 * @pkcs7: should contain a gnutls_pkcs7_t structure
660 * @indx: the index of the certificate to delete
662 * This function will delete a certificate from a PKCS7 or RFC2630
663 * certificate set. Index starts from 0. Returns 0 on success.
665 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
666 * negative error value.
669 gnutls_pkcs7_delete_crt (gnutls_pkcs7_t pkcs7, int indx)
671 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
672 int result;
673 char root2[ASN1_MAX_NAME_SIZE];
675 if (pkcs7 == NULL)
676 return GNUTLS_E_INVALID_REQUEST;
678 /* Step 1. Decode the signed data.
680 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
681 if (result < 0)
683 gnutls_assert ();
684 return result;
687 /* Step 2. Delete the certificate.
690 snprintf (root2, sizeof (root2), "certificates.?%u", indx + 1);
692 result = asn1_write_value (c2, root2, NULL, 0);
693 if (result != ASN1_SUCCESS)
695 gnutls_assert ();
696 result = _gnutls_asn2err (result);
697 goto cleanup;
700 /* Step 3. Replace the old content with the new
702 result =
703 _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
704 if (result < 0)
706 gnutls_assert ();
707 goto cleanup;
710 asn1_delete_structure (&c2);
712 return 0;
714 cleanup:
715 if (c2)
716 asn1_delete_structure (&c2);
717 return result;
720 /* Read and write CRLs
724 * gnutls_pkcs7_get_crl_raw:
725 * @pkcs7: should contain a #gnutls_pkcs7_t structure
726 * @indx: contains the index of the crl to extract
727 * @crl: the contents of the crl will be copied there (may be null)
728 * @crl_size: should hold the size of the crl
730 * This function will return a crl of the PKCS7 or RFC2630 crl set.
732 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
733 * negative error value. If the provided buffer is not long enough,
734 * then @crl_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER is
735 * returned. After the last crl has been read
736 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
739 gnutls_pkcs7_get_crl_raw (gnutls_pkcs7_t pkcs7,
740 int indx, void *crl, size_t * crl_size)
742 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
743 int result;
744 char root2[ASN1_MAX_NAME_SIZE];
745 gnutls_datum_t tmp = { NULL, 0 };
746 int start, end;
748 if (pkcs7 == NULL || crl_size == NULL)
749 return GNUTLS_E_INVALID_REQUEST;
751 /* Step 1. decode the signed data.
753 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, &tmp);
754 if (result < 0)
756 gnutls_assert ();
757 return result;
760 /* Step 2. Parse the CertificateSet
763 snprintf (root2, sizeof (root2), "crls.?%u", indx + 1);
765 /* Get the raw CRL
767 result = asn1_der_decoding_startEnd (c2, tmp.data, tmp.size,
768 root2, &start, &end);
770 if (result != ASN1_SUCCESS)
772 gnutls_assert ();
773 result = _gnutls_asn2err (result);
774 goto cleanup;
777 end = end - start + 1;
779 if ((unsigned) end > *crl_size)
781 *crl_size = end;
782 result = GNUTLS_E_SHORT_MEMORY_BUFFER;
783 goto cleanup;
786 if (crl)
787 memcpy (crl, &tmp.data[start], end);
789 *crl_size = end;
791 result = 0;
793 cleanup:
794 _gnutls_free_datum (&tmp);
795 if (c2)
796 asn1_delete_structure (&c2);
797 return result;
801 * gnutls_pkcs7_get_crl_count:
802 * @pkcs7: should contain a gnutls_pkcs7_t structure
804 * This function will return the number of certifcates in the PKCS7
805 * or RFC2630 crl set.
807 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
808 * negative error value.
811 gnutls_pkcs7_get_crl_count (gnutls_pkcs7_t pkcs7)
813 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
814 int result, count;
816 if (pkcs7 == NULL)
817 return GNUTLS_E_INVALID_REQUEST;
819 /* Step 1. decode the signed data.
821 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
822 if (result < 0)
824 gnutls_assert ();
825 return result;
828 /* Step 2. Count the CertificateSet */
830 result = asn1_number_of_elements (c2, "crls", &count);
832 asn1_delete_structure (&c2);
834 if (result != ASN1_SUCCESS)
836 gnutls_assert ();
837 return 0; /* no crls */
840 return count;
845 * gnutls_pkcs7_set_crl_raw:
846 * @pkcs7: should contain a #gnutls_pkcs7_t structure
847 * @crl: the DER encoded crl to be added
849 * This function will add a crl to the PKCS7 or RFC2630 crl set.
851 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
852 * negative error value.
855 gnutls_pkcs7_set_crl_raw (gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crl)
857 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
858 int result;
860 if (pkcs7 == NULL)
861 return GNUTLS_E_INVALID_REQUEST;
863 /* Step 1. decode the signed data.
865 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
866 if (result < 0 && result != GNUTLS_E_ASN1_VALUE_NOT_FOUND)
868 gnutls_assert ();
869 return result;
872 /* If the signed data are uninitialized
873 * then create them.
875 if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
877 /* The pkcs7 structure is new, so create the
878 * signedData.
880 result = create_empty_signed_data (pkcs7->pkcs7, &c2);
881 if (result < 0)
883 gnutls_assert ();
884 return result;
888 /* Step 2. Append the new crl.
891 result = asn1_write_value (c2, "crls", "NEW", 1);
892 if (result != ASN1_SUCCESS)
894 gnutls_assert ();
895 result = _gnutls_asn2err (result);
896 goto cleanup;
899 result = asn1_write_value (c2, "crls.?LAST", crl->data, crl->size);
900 if (result != ASN1_SUCCESS)
902 gnutls_assert ();
903 result = _gnutls_asn2err (result);
904 goto cleanup;
907 /* Step 3. Replace the old content with the new
909 result =
910 _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
911 if (result < 0)
913 gnutls_assert ();
914 goto cleanup;
917 asn1_delete_structure (&c2);
919 return 0;
921 cleanup:
922 if (c2)
923 asn1_delete_structure (&c2);
924 return result;
928 * gnutls_pkcs7_set_crl:
929 * @pkcs7: should contain a #gnutls_pkcs7_t structure
930 * @crl: the DER encoded crl to be added
932 * This function will add a parsed CRL to the PKCS7 or RFC2630 crl
933 * set.
935 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
936 * negative error value.
939 gnutls_pkcs7_set_crl (gnutls_pkcs7_t pkcs7, gnutls_x509_crl_t crl)
941 int ret;
942 gnutls_datum_t data;
944 if (pkcs7 == NULL)
945 return GNUTLS_E_INVALID_REQUEST;
947 ret = _gnutls_x509_der_encode (crl->crl, "", &data, 0);
948 if (ret < 0)
950 gnutls_assert ();
951 return ret;
954 ret = gnutls_pkcs7_set_crl_raw (pkcs7, &data);
956 _gnutls_free_datum (&data);
958 if (ret < 0)
960 gnutls_assert ();
961 return ret;
964 return 0;
968 * gnutls_pkcs7_delete_crl:
969 * @pkcs7: should contain a #gnutls_pkcs7_t structure
970 * @indx: the index of the crl to delete
972 * This function will delete a crl from a PKCS7 or RFC2630 crl set.
973 * Index starts from 0. Returns 0 on success.
975 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
976 * negative error value.
979 gnutls_pkcs7_delete_crl (gnutls_pkcs7_t pkcs7, int indx)
981 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
982 int result;
983 char root2[ASN1_MAX_NAME_SIZE];
985 if (pkcs7 == NULL)
986 return GNUTLS_E_INVALID_REQUEST;
988 /* Step 1. Decode the signed data.
990 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
991 if (result < 0)
993 gnutls_assert ();
994 return result;
997 /* Step 2. Delete the crl.
1000 snprintf (root2, sizeof (root2), "crls.?%u", indx + 1);
1002 result = asn1_write_value (c2, root2, NULL, 0);
1003 if (result != ASN1_SUCCESS)
1005 gnutls_assert ();
1006 result = _gnutls_asn2err (result);
1007 goto cleanup;
1010 /* Step 3. Replace the old content with the new
1012 result =
1013 _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
1014 if (result < 0)
1016 gnutls_assert ();
1017 goto cleanup;
1020 asn1_delete_structure (&c2);
1022 return 0;
1024 cleanup:
1025 if (c2)
1026 asn1_delete_structure (&c2);
1027 return result;