Added functions to export structures in an allocated buffer.
[gnutls.git] / lib / x509 / pkcs7.c
blob5149f5c3fed2380890941a229a7a1b5054d8c45f
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 result = _gnutls_fbase64_decode (PEM_PKCS7, data->data, data->size,
219 &_data);
221 if (result <= 0)
223 gnutls_assert ();
224 return result;
227 need_free = 1;
231 result = asn1_der_decoding (&pkcs7->pkcs7, _data.data, _data.size, NULL);
232 if (result != ASN1_SUCCESS)
234 result = _gnutls_asn2err (result);
235 gnutls_assert ();
236 goto cleanup;
239 if (need_free)
240 _gnutls_free_datum (&_data);
242 return 0;
244 cleanup:
245 if (need_free)
246 _gnutls_free_datum (&_data);
247 return result;
251 * gnutls_pkcs7_get_crt_raw:
252 * @pkcs7: should contain a gnutls_pkcs7_t structure
253 * @indx: contains the index of the certificate to extract
254 * @certificate: the contents of the certificate will be copied
255 * there (may be null)
256 * @certificate_size: should hold the size of the certificate
258 * This function will return a certificate of the PKCS7 or RFC2630
259 * certificate set.
261 * After the last certificate has been read
262 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
264 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
265 * negative error value. If the provided buffer is not long enough,
266 * then @certificate_size is updated and
267 * %GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
270 gnutls_pkcs7_get_crt_raw (gnutls_pkcs7_t pkcs7,
271 int indx, void *certificate,
272 size_t * certificate_size)
274 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
275 int result, len;
276 char root2[ASN1_MAX_NAME_SIZE];
277 char oid[MAX_OID_SIZE];
278 gnutls_datum_t tmp = { NULL, 0 };
280 if (certificate_size == NULL || pkcs7 == NULL)
281 return GNUTLS_E_INVALID_REQUEST;
283 /* Step 1. decode the signed data.
285 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, &tmp);
286 if (result < 0)
288 gnutls_assert ();
289 return result;
292 /* Step 2. Parse the CertificateSet
295 snprintf (root2, sizeof (root2), "certificates.?%u", indx + 1);
297 len = sizeof (oid) - 1;
299 result = asn1_read_value (c2, root2, oid, &len);
301 if (result == ASN1_VALUE_NOT_FOUND)
303 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
304 goto cleanup;
307 if (result != ASN1_SUCCESS)
309 gnutls_assert ();
310 result = _gnutls_asn2err (result);
311 goto cleanup;
314 /* if 'Certificate' is the choice found:
316 if (strcmp (oid, "certificate") == 0)
318 int start, end;
320 result = asn1_der_decoding_startEnd (c2, tmp.data, tmp.size,
321 root2, &start, &end);
323 if (result != ASN1_SUCCESS)
325 gnutls_assert ();
326 result = _gnutls_asn2err (result);
327 goto cleanup;
330 end = end - start + 1;
332 if ((unsigned) end > *certificate_size)
334 *certificate_size = end;
335 result = GNUTLS_E_SHORT_MEMORY_BUFFER;
336 goto cleanup;
339 if (certificate)
340 memcpy (certificate, &tmp.data[start], end);
342 *certificate_size = end;
344 result = 0;
347 else
349 result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
352 cleanup:
353 _gnutls_free_datum (&tmp);
354 if (c2)
355 asn1_delete_structure (&c2);
356 return result;
360 * gnutls_pkcs7_get_crt_count:
361 * @pkcs7: should contain a #gnutls_pkcs7_t structure
363 * This function will return the number of certifcates in the PKCS7
364 * or RFC2630 certificate set.
366 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
367 * negative error value.
370 gnutls_pkcs7_get_crt_count (gnutls_pkcs7_t pkcs7)
372 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
373 int result, count;
375 if (pkcs7 == NULL)
376 return GNUTLS_E_INVALID_REQUEST;
378 /* Step 1. decode the signed data.
380 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
381 if (result < 0)
383 gnutls_assert ();
384 return result;
387 /* Step 2. Count the CertificateSet */
389 result = asn1_number_of_elements (c2, "certificates", &count);
391 asn1_delete_structure (&c2);
393 if (result != ASN1_SUCCESS)
395 gnutls_assert ();
396 return 0; /* no certificates */
399 return count;
404 * gnutls_pkcs7_export:
405 * @pkcs7: Holds the pkcs7 structure
406 * @format: the format of output params. One of PEM or DER.
407 * @output_data: will contain a structure PEM or DER encoded
408 * @output_data_size: holds the size of output_data (and will be
409 * replaced by the actual size of parameters)
411 * This function will export the pkcs7 structure to DER or PEM format.
413 * If the buffer provided is not long enough to hold the output, then
414 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
415 * will be returned.
417 * If the structure is PEM encoded, it will have a header
418 * of "BEGIN PKCS7".
420 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
421 * negative error value.
424 gnutls_pkcs7_export (gnutls_pkcs7_t pkcs7,
425 gnutls_x509_crt_fmt_t format, void *output_data,
426 size_t * output_data_size)
428 if (pkcs7 == NULL)
429 return GNUTLS_E_INVALID_REQUEST;
431 return _gnutls_x509_export_int (pkcs7->pkcs7, format, PEM_PKCS7,
432 output_data, output_data_size);
436 * gnutls_pkcs7_export2:
437 * @pkcs7: Holds the pkcs7 structure
438 * @format: the format of output params. One of PEM or DER.
439 * @out: will contain a structure PEM or DER encoded
441 * This function will export the pkcs7 structure to DER or PEM format.
443 * The output buffer is allocated using gnutls_malloc().
445 * If the structure is PEM encoded, it will have a header
446 * of "BEGIN PKCS7".
448 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
449 * negative error value.
452 gnutls_pkcs7_export2 (gnutls_pkcs7_t pkcs7,
453 gnutls_x509_crt_fmt_t format, gnutls_datum_t *out)
455 if (pkcs7 == NULL)
456 return GNUTLS_E_INVALID_REQUEST;
458 return _gnutls_x509_export_int2 (pkcs7->pkcs7, format, PEM_PKCS7, out);
461 /* Creates an empty signed data structure in the pkcs7
462 * structure and returns a handle to the signed data.
464 static int
465 create_empty_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata)
467 uint8_t one = 1;
468 int result;
470 *sdata = ASN1_TYPE_EMPTY;
472 if ((result = asn1_create_element
473 (_gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData",
474 sdata)) != ASN1_SUCCESS)
476 gnutls_assert ();
477 result = _gnutls_asn2err (result);
478 goto cleanup;
481 /* Use version 1
483 result = asn1_write_value (*sdata, "version", &one, 1);
484 if (result != ASN1_SUCCESS)
486 gnutls_assert ();
487 result = _gnutls_asn2err (result);
488 goto cleanup;
491 /* Use no digest algorithms
494 /* id-data */
495 result =
496 asn1_write_value (*sdata, "encapContentInfo.eContentType",
497 "1.2.840.113549.1.7.5", 1);
498 if (result != ASN1_SUCCESS)
500 gnutls_assert ();
501 result = _gnutls_asn2err (result);
502 goto cleanup;
505 result = asn1_write_value (*sdata, "encapContentInfo.eContent", NULL, 0);
506 if (result != ASN1_SUCCESS)
508 gnutls_assert ();
509 result = _gnutls_asn2err (result);
510 goto cleanup;
513 /* Add no certificates.
516 /* Add no crls.
519 /* Add no signerInfos.
522 /* Write the content type of the signed data
524 result = asn1_write_value (pkcs7, "contentType", SIGNED_DATA_OID, 1);
525 if (result != ASN1_SUCCESS)
527 gnutls_assert ();
528 result = _gnutls_asn2err (result);
529 goto cleanup;
532 return 0;
534 cleanup:
535 asn1_delete_structure (sdata);
536 return result;
541 * gnutls_pkcs7_set_crt_raw:
542 * @pkcs7: should contain a #gnutls_pkcs7_t structure
543 * @crt: the DER encoded certificate to be added
545 * This function will add a certificate to the PKCS7 or RFC2630
546 * certificate set.
548 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
549 * negative error value.
552 gnutls_pkcs7_set_crt_raw (gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crt)
554 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
555 int result;
557 if (pkcs7 == NULL)
558 return GNUTLS_E_INVALID_REQUEST;
560 /* Step 1. decode the signed data.
562 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
563 if (result < 0 && result != GNUTLS_E_ASN1_VALUE_NOT_FOUND)
565 gnutls_assert ();
566 return result;
569 /* If the signed data are uninitialized
570 * then create them.
572 if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
574 /* The pkcs7 structure is new, so create the
575 * signedData.
577 result = create_empty_signed_data (pkcs7->pkcs7, &c2);
578 if (result < 0)
580 gnutls_assert ();
581 return result;
585 /* Step 2. Append the new certificate.
588 result = asn1_write_value (c2, "certificates", "NEW", 1);
589 if (result != ASN1_SUCCESS)
591 gnutls_assert ();
592 result = _gnutls_asn2err (result);
593 goto cleanup;
596 result = asn1_write_value (c2, "certificates.?LAST", "certificate", 1);
597 if (result != ASN1_SUCCESS)
599 gnutls_assert ();
600 result = _gnutls_asn2err (result);
601 goto cleanup;
604 result =
605 asn1_write_value (c2, "certificates.?LAST.certificate", crt->data,
606 crt->size);
607 if (result != ASN1_SUCCESS)
609 gnutls_assert ();
610 result = _gnutls_asn2err (result);
611 goto cleanup;
614 /* Step 3. Replace the old content with the new
616 result =
617 _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
618 if (result < 0)
620 gnutls_assert ();
621 goto cleanup;
624 asn1_delete_structure (&c2);
626 return 0;
628 cleanup:
629 if (c2)
630 asn1_delete_structure (&c2);
631 return result;
635 * gnutls_pkcs7_set_crt:
636 * @pkcs7: should contain a #gnutls_pkcs7_t structure
637 * @crt: the certificate to be copied.
639 * This function will add a parsed certificate to the PKCS7 or
640 * RFC2630 certificate set. This is a wrapper function over
641 * gnutls_pkcs7_set_crt_raw() .
643 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
644 * negative error value.
647 gnutls_pkcs7_set_crt (gnutls_pkcs7_t pkcs7, gnutls_x509_crt_t crt)
649 int ret;
650 gnutls_datum_t data;
652 if (pkcs7 == NULL)
653 return GNUTLS_E_INVALID_REQUEST;
655 ret = _gnutls_x509_der_encode (crt->cert, "", &data, 0);
656 if (ret < 0)
658 gnutls_assert ();
659 return ret;
662 ret = gnutls_pkcs7_set_crt_raw (pkcs7, &data);
664 _gnutls_free_datum (&data);
666 if (ret < 0)
668 gnutls_assert ();
669 return ret;
672 return 0;
677 * gnutls_pkcs7_delete_crt:
678 * @pkcs7: should contain a gnutls_pkcs7_t structure
679 * @indx: the index of the certificate to delete
681 * This function will delete a certificate from a PKCS7 or RFC2630
682 * certificate set. Index starts from 0. Returns 0 on success.
684 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
685 * negative error value.
688 gnutls_pkcs7_delete_crt (gnutls_pkcs7_t pkcs7, int indx)
690 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
691 int result;
692 char root2[ASN1_MAX_NAME_SIZE];
694 if (pkcs7 == NULL)
695 return GNUTLS_E_INVALID_REQUEST;
697 /* Step 1. Decode the signed data.
699 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
700 if (result < 0)
702 gnutls_assert ();
703 return result;
706 /* Step 2. Delete the certificate.
709 snprintf (root2, sizeof (root2), "certificates.?%u", indx + 1);
711 result = asn1_write_value (c2, root2, NULL, 0);
712 if (result != ASN1_SUCCESS)
714 gnutls_assert ();
715 result = _gnutls_asn2err (result);
716 goto cleanup;
719 /* Step 3. Replace the old content with the new
721 result =
722 _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
723 if (result < 0)
725 gnutls_assert ();
726 goto cleanup;
729 asn1_delete_structure (&c2);
731 return 0;
733 cleanup:
734 if (c2)
735 asn1_delete_structure (&c2);
736 return result;
739 /* Read and write CRLs
743 * gnutls_pkcs7_get_crl_raw:
744 * @pkcs7: should contain a #gnutls_pkcs7_t structure
745 * @indx: contains the index of the crl to extract
746 * @crl: the contents of the crl will be copied there (may be null)
747 * @crl_size: should hold the size of the crl
749 * This function will return a crl of the PKCS7 or RFC2630 crl set.
751 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
752 * negative error value. If the provided buffer is not long enough,
753 * then @crl_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER is
754 * returned. After the last crl has been read
755 * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned.
758 gnutls_pkcs7_get_crl_raw (gnutls_pkcs7_t pkcs7,
759 int indx, void *crl, size_t * crl_size)
761 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
762 int result;
763 char root2[ASN1_MAX_NAME_SIZE];
764 gnutls_datum_t tmp = { NULL, 0 };
765 int start, end;
767 if (pkcs7 == NULL || crl_size == NULL)
768 return GNUTLS_E_INVALID_REQUEST;
770 /* Step 1. decode the signed data.
772 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, &tmp);
773 if (result < 0)
775 gnutls_assert ();
776 return result;
779 /* Step 2. Parse the CertificateSet
782 snprintf (root2, sizeof (root2), "crls.?%u", indx + 1);
784 /* Get the raw CRL
786 result = asn1_der_decoding_startEnd (c2, tmp.data, tmp.size,
787 root2, &start, &end);
789 if (result != ASN1_SUCCESS)
791 gnutls_assert ();
792 result = _gnutls_asn2err (result);
793 goto cleanup;
796 end = end - start + 1;
798 if ((unsigned) end > *crl_size)
800 *crl_size = end;
801 result = GNUTLS_E_SHORT_MEMORY_BUFFER;
802 goto cleanup;
805 if (crl)
806 memcpy (crl, &tmp.data[start], end);
808 *crl_size = end;
810 result = 0;
812 cleanup:
813 _gnutls_free_datum (&tmp);
814 if (c2)
815 asn1_delete_structure (&c2);
816 return result;
820 * gnutls_pkcs7_get_crl_count:
821 * @pkcs7: should contain a gnutls_pkcs7_t structure
823 * This function will return the number of certifcates in the PKCS7
824 * or RFC2630 crl set.
826 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
827 * negative error value.
830 gnutls_pkcs7_get_crl_count (gnutls_pkcs7_t pkcs7)
832 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
833 int result, count;
835 if (pkcs7 == NULL)
836 return GNUTLS_E_INVALID_REQUEST;
838 /* Step 1. decode the signed data.
840 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
841 if (result < 0)
843 gnutls_assert ();
844 return result;
847 /* Step 2. Count the CertificateSet */
849 result = asn1_number_of_elements (c2, "crls", &count);
851 asn1_delete_structure (&c2);
853 if (result != ASN1_SUCCESS)
855 gnutls_assert ();
856 return 0; /* no crls */
859 return count;
864 * gnutls_pkcs7_set_crl_raw:
865 * @pkcs7: should contain a #gnutls_pkcs7_t structure
866 * @crl: the DER encoded crl to be added
868 * This function will add a crl to the PKCS7 or RFC2630 crl set.
870 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
871 * negative error value.
874 gnutls_pkcs7_set_crl_raw (gnutls_pkcs7_t pkcs7, const gnutls_datum_t * crl)
876 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
877 int result;
879 if (pkcs7 == NULL)
880 return GNUTLS_E_INVALID_REQUEST;
882 /* Step 1. decode the signed data.
884 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
885 if (result < 0 && result != GNUTLS_E_ASN1_VALUE_NOT_FOUND)
887 gnutls_assert ();
888 return result;
891 /* If the signed data are uninitialized
892 * then create them.
894 if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
896 /* The pkcs7 structure is new, so create the
897 * signedData.
899 result = create_empty_signed_data (pkcs7->pkcs7, &c2);
900 if (result < 0)
902 gnutls_assert ();
903 return result;
907 /* Step 2. Append the new crl.
910 result = asn1_write_value (c2, "crls", "NEW", 1);
911 if (result != ASN1_SUCCESS)
913 gnutls_assert ();
914 result = _gnutls_asn2err (result);
915 goto cleanup;
918 result = asn1_write_value (c2, "crls.?LAST", crl->data, crl->size);
919 if (result != ASN1_SUCCESS)
921 gnutls_assert ();
922 result = _gnutls_asn2err (result);
923 goto cleanup;
926 /* Step 3. Replace the old content with the new
928 result =
929 _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
930 if (result < 0)
932 gnutls_assert ();
933 goto cleanup;
936 asn1_delete_structure (&c2);
938 return 0;
940 cleanup:
941 if (c2)
942 asn1_delete_structure (&c2);
943 return result;
947 * gnutls_pkcs7_set_crl:
948 * @pkcs7: should contain a #gnutls_pkcs7_t structure
949 * @crl: the DER encoded crl to be added
951 * This function will add a parsed CRL to the PKCS7 or RFC2630 crl
952 * set.
954 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
955 * negative error value.
958 gnutls_pkcs7_set_crl (gnutls_pkcs7_t pkcs7, gnutls_x509_crl_t crl)
960 int ret;
961 gnutls_datum_t data;
963 if (pkcs7 == NULL)
964 return GNUTLS_E_INVALID_REQUEST;
966 ret = _gnutls_x509_der_encode (crl->crl, "", &data, 0);
967 if (ret < 0)
969 gnutls_assert ();
970 return ret;
973 ret = gnutls_pkcs7_set_crl_raw (pkcs7, &data);
975 _gnutls_free_datum (&data);
977 if (ret < 0)
979 gnutls_assert ();
980 return ret;
983 return 0;
987 * gnutls_pkcs7_delete_crl:
988 * @pkcs7: should contain a #gnutls_pkcs7_t structure
989 * @indx: the index of the crl to delete
991 * This function will delete a crl from a PKCS7 or RFC2630 crl set.
992 * Index starts from 0. Returns 0 on success.
994 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
995 * negative error value.
998 gnutls_pkcs7_delete_crl (gnutls_pkcs7_t pkcs7, int indx)
1000 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
1001 int result;
1002 char root2[ASN1_MAX_NAME_SIZE];
1004 if (pkcs7 == NULL)
1005 return GNUTLS_E_INVALID_REQUEST;
1007 /* Step 1. Decode the signed data.
1009 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
1010 if (result < 0)
1012 gnutls_assert ();
1013 return result;
1016 /* Step 2. Delete the crl.
1019 snprintf (root2, sizeof (root2), "crls.?%u", indx + 1);
1021 result = asn1_write_value (c2, root2, NULL, 0);
1022 if (result != ASN1_SUCCESS)
1024 gnutls_assert ();
1025 result = _gnutls_asn2err (result);
1026 goto cleanup;
1029 /* Step 3. Replace the old content with the new
1031 result =
1032 _gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
1033 if (result < 0)
1035 gnutls_assert ();
1036 goto cleanup;
1039 asn1_delete_structure (&c2);
1041 return 0;
1043 cleanup:
1044 if (c2)
1045 asn1_delete_structure (&c2);
1046 return result;