aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/https/x509/pkcs7.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/https/x509/pkcs7.c')
-rw-r--r--src/daemon/https/x509/pkcs7.c1029
1 files changed, 0 insertions, 1029 deletions
diff --git a/src/daemon/https/x509/pkcs7.c b/src/daemon/https/x509/pkcs7.c
deleted file mode 100644
index 45f2b03c..00000000
--- a/src/daemon/https/x509/pkcs7.c
+++ /dev/null
@@ -1,1029 +0,0 @@
1/*
2 * Copyright (C) 2003, 2004, 2005 Free Software Foundation
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GNUTLS.
7 *
8 * The GNUTLS library 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 2.1 of
11 * the License, or (at your option) any later version.
12 *
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.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
22 *
23 */
24
25/* Functions that relate on PKCS7 certificate lists parsing.
26 */
27
28#include <gnutls_int.h>
29#include <libtasn1.h>
30
31#ifdef ENABLE_PKI
32
33#include <gnutls_datum.h>
34#include <gnutls_global.h>
35#include <gnutls_errors.h>
36#include <common.h>
37#include <x509_b64.h>
38#include <pkcs7.h>
39#include <dn.h>
40
41#define SIGNED_DATA_OID "1.2.840.113549.1.7.2"
42
43/* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE,
44 * which holds them. If raw is non null then the raw decoded
45 * data are copied (they are locally allocated) there.
46 */
47static int
48_decode_pkcs7_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata,
49 MHD_gnutls_datum_t * raw)
50{
51 char oid[128];
52 ASN1_TYPE c2;
53 opaque *tmp = NULL;
54 int tmp_size, len, result;
55
56 len = sizeof (oid) - 1;
57 result = MHD__asn1_read_value (pkcs7, "contentType", oid, &len);
58 if (result != ASN1_SUCCESS)
59 {
60 MHD_gnutls_assert ();
61 return MHD_gtls_asn2err (result);
62 }
63
64 if (strcmp (oid, SIGNED_DATA_OID) != 0)
65 {
66 MHD_gnutls_assert ();
67 MHD__gnutls_x509_log ("Unknown PKCS7 Content OID '%s'\n", oid);
68 return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
69 }
70
71 if ((result = MHD__asn1_create_element
72 (MHD__gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData",
73 &c2)) != ASN1_SUCCESS)
74 {
75 MHD_gnutls_assert ();
76 return MHD_gtls_asn2err (result);
77 }
78
79 /* the Signed-data has been created, so
80 * decode them.
81 */
82 tmp_size = 0;
83 result = MHD__asn1_read_value (pkcs7, "content", NULL, &tmp_size);
84 if (result != ASN1_MEM_ERROR)
85 {
86 MHD_gnutls_assert ();
87 result = MHD_gtls_asn2err (result);
88 goto cleanup;
89 }
90
91 tmp = MHD_gnutls_malloc (tmp_size);
92 if (tmp == NULL)
93 {
94 MHD_gnutls_assert ();
95 result = GNUTLS_E_MEMORY_ERROR;
96 goto cleanup;
97 }
98
99 result = MHD__asn1_read_value (pkcs7, "content", tmp, &tmp_size);
100 if (result != ASN1_SUCCESS)
101 {
102 MHD_gnutls_assert ();
103 result = MHD_gtls_asn2err (result);
104 goto cleanup;
105 }
106
107 /* tmp, tmp_size hold the data and the size of the CertificateSet structure
108 * actually the ANY stuff.
109 */
110
111 /* Step 1. In case of a signed structure extract certificate set.
112 */
113
114 result = MHD__asn1_der_decoding (&c2, tmp, tmp_size, NULL);
115 if (result != ASN1_SUCCESS)
116 {
117 MHD_gnutls_assert ();
118 result = MHD_gtls_asn2err (result);
119 goto cleanup;
120 }
121
122 if (raw == NULL)
123 {
124 MHD_gnutls_free (tmp);
125 }
126 else
127 {
128 raw->data = tmp;
129 raw->size = tmp_size;
130 }
131
132 *sdata = c2;
133
134 return 0;
135
136cleanup:
137 if (c2)
138 MHD__asn1_delete_structure (&c2);
139 MHD_gnutls_free (tmp);
140 return result;
141}
142
143/**
144 * MHD_gnutls_pkcs7_init - This function initializes a MHD_gnutls_pkcs7_t structure
145 * @pkcs7: The structure to be initialized
146 *
147 * This function will initialize a PKCS7 structure. PKCS7 structures
148 * usually contain lists of X.509 Certificates and X.509 Certificate
149 * revocation lists.
150 *
151 * Returns 0 on success.
152 *
153 **/
154int
155MHD_gnutls_pkcs7_init (MHD_gnutls_pkcs7_t * pkcs7)
156{
157 *pkcs7 = MHD_gnutls_calloc (1, sizeof (MHD_gnutls_pkcs7_int));
158
159 if (*pkcs7)
160 {
161 int result = MHD__asn1_create_element (MHD__gnutls_get_pkix (),
162 "PKIX1.pkcs-7-ContentInfo",
163 &(*pkcs7)->pkcs7);
164 if (result != ASN1_SUCCESS)
165 {
166 MHD_gnutls_assert ();
167 MHD_gnutls_free (*pkcs7);
168 return MHD_gtls_asn2err (result);
169 }
170 return 0; /* success */
171 }
172 return GNUTLS_E_MEMORY_ERROR;
173}
174
175/**
176 * MHD_gnutls_pkcs7_deinit - This function deinitializes memory used by a MHD_gnutls_pkcs7_t structure
177 * @pkcs7: The structure to be initialized
178 *
179 * This function will deinitialize a PKCS7 structure.
180 *
181 **/
182void
183MHD_gnutls_pkcs7_deinit (MHD_gnutls_pkcs7_t pkcs7)
184{
185 if (!pkcs7)
186 return;
187
188 if (pkcs7->pkcs7)
189 MHD__asn1_delete_structure (&pkcs7->pkcs7);
190
191 MHD_gnutls_free (pkcs7);
192}
193
194/**
195 * MHD_gnutls_pkcs7_import - This function will import a DER or PEM encoded PKCS7
196 * @pkcs7: The structure to store the parsed PKCS7.
197 * @data: The DER or PEM encoded PKCS7.
198 * @format: One of DER or PEM
199 *
200 * This function will convert the given DER or PEM encoded PKCS7
201 * to the native MHD_gnutls_pkcs7_t format. The output will be stored in 'pkcs7'.
202 *
203 * If the PKCS7 is PEM encoded it should have a header of "PKCS7".
204 *
205 * Returns 0 on success.
206 *
207 **/
208int
209MHD_gnutls_pkcs7_import (MHD_gnutls_pkcs7_t pkcs7,
210 const MHD_gnutls_datum_t * data,
211 MHD_gnutls_x509_crt_fmt_t format)
212{
213 int result = 0, need_free = 0;
214 MHD_gnutls_datum_t _data;
215
216 if (pkcs7 == NULL)
217 return GNUTLS_E_INVALID_REQUEST;
218
219 _data.data = data->data;
220 _data.size = data->size;
221
222 /* If the PKCS7 is in PEM format then decode it
223 */
224 if (format == GNUTLS_X509_FMT_PEM)
225 {
226 opaque *out;
227
228 result = MHD__gnutls_fbase64_decode (PEM_PKCS7, data->data, data->size,
229 &out);
230
231 if (result <= 0)
232 {
233 if (result == 0)
234 result = GNUTLS_E_INTERNAL_ERROR;
235 MHD_gnutls_assert ();
236 return result;
237 }
238
239 _data.data = out;
240 _data.size = result;
241
242 need_free = 1;
243 }
244
245
246 result =
247 MHD__asn1_der_decoding (&pkcs7->pkcs7, _data.data, _data.size, NULL);
248 if (result != ASN1_SUCCESS)
249 {
250 result = MHD_gtls_asn2err (result);
251 MHD_gnutls_assert ();
252 goto cleanup;
253 }
254
255 if (need_free)
256 MHD__gnutls_free_datum (&_data);
257
258 return 0;
259
260cleanup:
261 if (need_free)
262 MHD__gnutls_free_datum (&_data);
263 return result;
264}
265
266/**
267 * MHD_gnutls_pkcs7_get_crt_raw - This function returns a certificate in a PKCS7 certificate set
268 * @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
269 * @indx: contains the index of the certificate to extract
270 * @certificate: the contents of the certificate will be copied there (may be null)
271 * @certificate_size: should hold the size of the certificate
272 *
273 * This function will return a certificate of the PKCS7 or RFC2630 certificate set.
274 * Returns 0 on success. If the provided buffer is not long enough,
275 * then @certificate_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
276 *
277 * After the last certificate has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
278 * will be returned.
279 *
280 **/
281int
282MHD_gnutls_pkcs7_get_crt_raw (MHD_gnutls_pkcs7_t pkcs7,
283 int indx, void *certificate,
284 size_t * certificate_size)
285{
286 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
287 int result, len;
288 char root2[MAX_NAME_SIZE];
289 char oid[128];
290 MHD_gnutls_datum_t tmp = { NULL, 0 };
291
292 if (certificate_size == NULL || pkcs7 == NULL)
293 return GNUTLS_E_INVALID_REQUEST;
294
295 /* Step 1. decode the signed data.
296 */
297 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, &tmp);
298 if (result < 0)
299 {
300 MHD_gnutls_assert ();
301 return result;
302 }
303
304 /* Step 2. Parse the CertificateSet
305 */
306
307 snprintf (root2, sizeof (root2), "certificates.?%u", indx + 1);
308
309 len = sizeof (oid) - 1;
310
311 result = MHD__asn1_read_value (c2, root2, oid, &len);
312
313 if (result == ASN1_VALUE_NOT_FOUND)
314 {
315 result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
316 goto cleanup;
317 }
318
319 if (result != ASN1_SUCCESS)
320 {
321 MHD_gnutls_assert ();
322 result = MHD_gtls_asn2err (result);
323 goto cleanup;
324 }
325
326 /* if 'Certificate' is the choice found:
327 */
328 if (strcmp (oid, "certificate") == 0)
329 {
330 int start, end;
331
332 result = MHD__asn1_der_decoding_startEnd (c2, tmp.data, tmp.size,
333 root2, &start, &end);
334
335 if (result != ASN1_SUCCESS)
336 {
337 MHD_gnutls_assert ();
338 result = MHD_gtls_asn2err (result);
339 goto cleanup;
340 }
341
342 end = end - start + 1;
343
344 if ((unsigned) end > *certificate_size)
345 {
346 *certificate_size = end;
347 result = GNUTLS_E_SHORT_MEMORY_BUFFER;
348 goto cleanup;
349 }
350
351 if (certificate)
352 memcpy (certificate, &tmp.data[start], end);
353
354 *certificate_size = end;
355
356 result = 0;
357
358 }
359 else
360 {
361 result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
362 }
363
364cleanup:
365 MHD__gnutls_free_datum (&tmp);
366 if (c2)
367 MHD__asn1_delete_structure (&c2);
368 return result;
369}
370
371/**
372 * MHD_gnutls_pkcs7_get_crt_count - This function returns the number of certificates in a PKCS7 certificate set
373 * @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
374 *
375 * This function will return the number of certifcates in the PKCS7 or
376 * RFC2630 certificate set.
377 *
378 * Returns a negative value on failure.
379 *
380 **/
381int
382MHD_gnutls_pkcs7_get_crt_count (MHD_gnutls_pkcs7_t pkcs7)
383{
384 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
385 int result, count;
386
387 if (pkcs7 == NULL)
388 return GNUTLS_E_INVALID_REQUEST;
389
390 /* Step 1. decode the signed data.
391 */
392 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
393 if (result < 0)
394 {
395 MHD_gnutls_assert ();
396 return result;
397 }
398
399 /* Step 2. Count the CertificateSet */
400
401 result = MHD__asn1_number_of_elements (c2, "certificates", &count);
402
403 MHD__asn1_delete_structure (&c2);
404
405 if (result != ASN1_SUCCESS)
406 {
407 MHD_gnutls_assert ();
408 return 0; /* no certificates */
409 }
410
411 return count;
412
413}
414
415/**
416 * MHD_gnutls_pkcs7_export - This function will export the pkcs7 structure
417 * @pkcs7: Holds the pkcs7 structure
418 * @format: the format of output params. One of PEM or DER.
419 * @output_data: will contain a structure PEM or DER encoded
420 * @output_data_size: holds the size of output_data (and will be
421 * replaced by the actual size of parameters)
422 *
423 * This function will export the pkcs7 structure to DER or PEM format.
424 *
425 * If the buffer provided is not long enough to hold the output, then
426 * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
427 * be returned.
428 *
429 * If the structure is PEM encoded, it will have a header
430 * of "BEGIN PKCS7".
431 *
432 * Return value: In case of failure a negative value will be
433 * returned, and 0 on success.
434 *
435 **/
436int
437MHD_gnutls_pkcs7_export (MHD_gnutls_pkcs7_t pkcs7,
438 MHD_gnutls_x509_crt_fmt_t format, void *output_data,
439 size_t * output_data_size)
440{
441 if (pkcs7 == NULL)
442 return GNUTLS_E_INVALID_REQUEST;
443
444 return MHD__gnutls_x509_export_int (pkcs7->pkcs7, format, PEM_PKCS7,
445 output_data, output_data_size);
446}
447
448/* Creates an empty signed data structure in the pkcs7
449 * structure and returns a handle to the signed data.
450 */
451static int
452create_empty_signed_data (ASN1_TYPE pkcs7, ASN1_TYPE * sdata)
453{
454 uint8_t one = 1;
455 int result;
456
457 *sdata = ASN1_TYPE_EMPTY;
458
459 if ((result = MHD__asn1_create_element
460 (MHD__gnutls_get_pkix (), "PKIX1.pkcs-7-SignedData",
461 sdata)) != ASN1_SUCCESS)
462 {
463 MHD_gnutls_assert ();
464 result = MHD_gtls_asn2err (result);
465 goto cleanup;
466 }
467
468 /* Use version 1
469 */
470 result = MHD__asn1_write_value (*sdata, "version", &one, 1);
471 if (result != ASN1_SUCCESS)
472 {
473 MHD_gnutls_assert ();
474 result = MHD_gtls_asn2err (result);
475 goto cleanup;
476 }
477
478 /* Use no digest algorithms
479 */
480
481 /* id-data */
482 result =
483 MHD__asn1_write_value (*sdata, "encapContentInfo.eContentType",
484 "1.2.840.113549.1.7.5", 1);
485 if (result != ASN1_SUCCESS)
486 {
487 MHD_gnutls_assert ();
488 result = MHD_gtls_asn2err (result);
489 goto cleanup;
490 }
491
492 result =
493 MHD__asn1_write_value (*sdata, "encapContentInfo.eContent", NULL, 0);
494 if (result != ASN1_SUCCESS)
495 {
496 MHD_gnutls_assert ();
497 result = MHD_gtls_asn2err (result);
498 goto cleanup;
499 }
500
501 /* Add no certificates.
502 */
503
504 /* Add no crls.
505 */
506
507 /* Add no signerInfos.
508 */
509
510 /* Write the content type of the signed data
511 */
512 result = MHD__asn1_write_value (pkcs7, "contentType", SIGNED_DATA_OID, 1);
513 if (result != ASN1_SUCCESS)
514 {
515 MHD_gnutls_assert ();
516 result = MHD_gtls_asn2err (result);
517 goto cleanup;
518 }
519
520 return 0;
521
522cleanup:
523 MHD__asn1_delete_structure (sdata);
524 return result;
525
526}
527
528/**
529 * MHD_gnutls_pkcs7_set_crt_raw - This function adds a certificate in a PKCS7 certificate set
530 * @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
531 * @crt: the DER encoded certificate to be added
532 *
533 * This function will add a certificate to the PKCS7 or RFC2630 certificate set.
534 * Returns 0 on success.
535 *
536 **/
537int
538MHD_gnutls_pkcs7_set_crt_raw (MHD_gnutls_pkcs7_t pkcs7,
539 const MHD_gnutls_datum_t * crt)
540{
541 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
542 int result;
543
544 if (pkcs7 == NULL)
545 return GNUTLS_E_INVALID_REQUEST;
546
547 /* Step 1. decode the signed data.
548 */
549 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
550 if (result < 0 && result != GNUTLS_E_ASN1_VALUE_NOT_FOUND)
551 {
552 MHD_gnutls_assert ();
553 return result;
554 }
555
556 /* If the signed data are uninitialized
557 * then create them.
558 */
559 if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
560 {
561 /* The pkcs7 structure is new, so create the
562 * signedData.
563 */
564 result = create_empty_signed_data (pkcs7->pkcs7, &c2);
565 if (result < 0)
566 {
567 MHD_gnutls_assert ();
568 return result;
569 }
570 }
571
572 /* Step 2. Append the new certificate.
573 */
574
575 result = MHD__asn1_write_value (c2, "certificates", "NEW", 1);
576 if (result != ASN1_SUCCESS)
577 {
578 MHD_gnutls_assert ();
579 result = MHD_gtls_asn2err (result);
580 goto cleanup;
581 }
582
583 result = MHD__asn1_write_value (c2, "certificates.?LAST", "certificate", 1);
584 if (result != ASN1_SUCCESS)
585 {
586 MHD_gnutls_assert ();
587 result = MHD_gtls_asn2err (result);
588 goto cleanup;
589 }
590
591 result =
592 MHD__asn1_write_value (c2, "certificates.?LAST.certificate", crt->data,
593 crt->size);
594 if (result != ASN1_SUCCESS)
595 {
596 MHD_gnutls_assert ();
597 result = MHD_gtls_asn2err (result);
598 goto cleanup;
599 }
600
601 /* Step 3. Replace the old content with the new
602 */
603 result =
604 MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
605 if (result < 0)
606 {
607 MHD_gnutls_assert ();
608 goto cleanup;
609 }
610
611 MHD__asn1_delete_structure (&c2);
612
613 return 0;
614
615cleanup:
616 if (c2)
617 MHD__asn1_delete_structure (&c2);
618 return result;
619}
620
621/**
622 * MHD_gnutls_pkcs7_set_crt - This function adds a parsed certificate in a PKCS7 certificate set
623 * @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
624 * @crt: the certificate to be copied.
625 *
626 * This function will add a parsed certificate to the PKCS7 or RFC2630 certificate set.
627 * This is a wrapper function over MHD_gnutls_pkcs7_set_crt_raw() .
628 *
629 * Returns 0 on success.
630 *
631 **/
632int
633MHD_gnutls_pkcs7_set_crt (MHD_gnutls_pkcs7_t pkcs7, MHD_gnutls_x509_crt_t crt)
634{
635 int ret;
636 MHD_gnutls_datum_t data;
637
638 if (pkcs7 == NULL)
639 return GNUTLS_E_INVALID_REQUEST;
640
641 ret = MHD__gnutls_x509_der_encode (crt->cert, "", &data, 0);
642 if (ret < 0)
643 {
644 MHD_gnutls_assert ();
645 return ret;
646 }
647
648 ret = MHD_gnutls_pkcs7_set_crt_raw (pkcs7, &data);
649
650 MHD__gnutls_free_datum (&data);
651
652 if (ret < 0)
653 {
654 MHD_gnutls_assert ();
655 return ret;
656 }
657
658 return 0;
659}
660
661
662/**
663 * MHD_gnutls_pkcs7_delete_crt - This function deletes a certificate from a PKCS7 certificate set
664 * @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
665 * @indx: the index of the certificate to delete
666 *
667 * This function will delete a certificate from a PKCS7 or RFC2630 certificate set.
668 * Index starts from 0. Returns 0 on success.
669 *
670 **/
671int
672MHD_gnutls_pkcs7_delete_crt (MHD_gnutls_pkcs7_t pkcs7, int indx)
673{
674 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
675 int result;
676 char root2[MAX_NAME_SIZE];
677
678 if (pkcs7 == NULL)
679 return GNUTLS_E_INVALID_REQUEST;
680
681 /* Step 1. Decode the signed data.
682 */
683 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
684 if (result < 0)
685 {
686 MHD_gnutls_assert ();
687 return result;
688 }
689
690 /* Step 2. Delete the certificate.
691 */
692
693 snprintf (root2, sizeof (root2), "certificates.?%u", indx + 1);
694
695 result = MHD__asn1_write_value (c2, root2, NULL, 0);
696 if (result != ASN1_SUCCESS)
697 {
698 MHD_gnutls_assert ();
699 result = MHD_gtls_asn2err (result);
700 goto cleanup;
701 }
702
703 /* Step 3. Replace the old content with the new
704 */
705 result =
706 MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
707 if (result < 0)
708 {
709 MHD_gnutls_assert ();
710 goto cleanup;
711 }
712
713 MHD__asn1_delete_structure (&c2);
714
715 return 0;
716
717cleanup:
718 if (c2)
719 MHD__asn1_delete_structure (&c2);
720 return result;
721}
722
723/* Read and write CRLs
724 */
725
726/**
727 * MHD_gnutls_pkcs7_get_crl_raw - This function returns a crl in a PKCS7 crl set
728 * @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
729 * @indx: contains the index of the crl to extract
730 * @crl: the contents of the crl will be copied there (may be null)
731 * @crl_size: should hold the size of the crl
732 *
733 * This function will return a crl of the PKCS7 or RFC2630 crl set.
734 * Returns 0 on success. If the provided buffer is not long enough,
735 * then @crl_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
736 *
737 * After the last crl has been read GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
738 * will be returned.
739 *
740 **/
741int
742MHD_gnutls_pkcs7_get_crl_raw (MHD_gnutls_pkcs7_t pkcs7,
743 int indx, void *crl, size_t * crl_size)
744{
745 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
746 int result;
747 char root2[MAX_NAME_SIZE];
748 MHD_gnutls_datum_t tmp = { NULL, 0 };
749 int start, end;
750
751 if (pkcs7 == NULL || crl_size == NULL)
752 return GNUTLS_E_INVALID_REQUEST;
753
754 /* Step 1. decode the signed data.
755 */
756 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, &tmp);
757 if (result < 0)
758 {
759 MHD_gnutls_assert ();
760 return result;
761 }
762
763 /* Step 2. Parse the CertificateSet
764 */
765
766 snprintf (root2, sizeof (root2), "crls.?%u", indx + 1);
767
768 /* Get the raw CRL
769 */
770 result = MHD__asn1_der_decoding_startEnd (c2, tmp.data, tmp.size,
771 root2, &start, &end);
772
773 if (result != ASN1_SUCCESS)
774 {
775 MHD_gnutls_assert ();
776 result = MHD_gtls_asn2err (result);
777 goto cleanup;
778 }
779
780 end = end - start + 1;
781
782 if ((unsigned) end > *crl_size)
783 {
784 *crl_size = end;
785 result = GNUTLS_E_SHORT_MEMORY_BUFFER;
786 goto cleanup;
787 }
788
789 if (crl)
790 memcpy (crl, &tmp.data[start], end);
791
792 *crl_size = end;
793
794 result = 0;
795
796cleanup:
797 MHD__gnutls_free_datum (&tmp);
798 if (c2)
799 MHD__asn1_delete_structure (&c2);
800 return result;
801}
802
803/**
804 * MHD_gnutls_pkcs7_get_crl_count - This function returns the number of crls in a PKCS7 crl set
805 * @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
806 *
807 * This function will return the number of certifcates in the PKCS7 or
808 * RFC2630 crl set.
809 *
810 * Returns a negative value on failure.
811 *
812 **/
813int
814MHD_gnutls_pkcs7_get_crl_count (MHD_gnutls_pkcs7_t pkcs7)
815{
816 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
817 int result, count;
818
819 if (pkcs7 == NULL)
820 return GNUTLS_E_INVALID_REQUEST;
821
822 /* Step 1. decode the signed data.
823 */
824 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
825 if (result < 0)
826 {
827 MHD_gnutls_assert ();
828 return result;
829 }
830
831 /* Step 2. Count the CertificateSet */
832
833 result = MHD__asn1_number_of_elements (c2, "crls", &count);
834
835 MHD__asn1_delete_structure (&c2);
836
837 if (result != ASN1_SUCCESS)
838 {
839 MHD_gnutls_assert ();
840 return 0; /* no crls */
841 }
842
843 return count;
844
845}
846
847/**
848 * MHD_gnutls_pkcs7_set_crl_raw - This function adds a crl in a PKCS7 crl set
849 * @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
850 * @crl: the DER encoded crl to be added
851 *
852 * This function will add a crl to the PKCS7 or RFC2630 crl set.
853 * Returns 0 on success.
854 *
855 **/
856int
857MHD_gnutls_pkcs7_set_crl_raw (MHD_gnutls_pkcs7_t pkcs7,
858 const MHD_gnutls_datum_t * crl)
859{
860 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
861 int result;
862
863 if (pkcs7 == NULL)
864 return GNUTLS_E_INVALID_REQUEST;
865
866 /* Step 1. decode the signed data.
867 */
868 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
869 if (result < 0 && result != GNUTLS_E_ASN1_VALUE_NOT_FOUND)
870 {
871 MHD_gnutls_assert ();
872 return result;
873 }
874
875 /* If the signed data are uninitialized
876 * then create them.
877 */
878 if (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND)
879 {
880 /* The pkcs7 structure is new, so create the
881 * signedData.
882 */
883 result = create_empty_signed_data (pkcs7->pkcs7, &c2);
884 if (result < 0)
885 {
886 MHD_gnutls_assert ();
887 return result;
888 }
889 }
890
891 /* Step 2. Append the new crl.
892 */
893
894 result = MHD__asn1_write_value (c2, "crls", "NEW", 1);
895 if (result != ASN1_SUCCESS)
896 {
897 MHD_gnutls_assert ();
898 result = MHD_gtls_asn2err (result);
899 goto cleanup;
900 }
901
902 result = MHD__asn1_write_value (c2, "crls.?LAST", crl->data, crl->size);
903 if (result != ASN1_SUCCESS)
904 {
905 MHD_gnutls_assert ();
906 result = MHD_gtls_asn2err (result);
907 goto cleanup;
908 }
909
910 /* Step 3. Replace the old content with the new
911 */
912 result =
913 MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
914 if (result < 0)
915 {
916 MHD_gnutls_assert ();
917 goto cleanup;
918 }
919
920 MHD__asn1_delete_structure (&c2);
921
922 return 0;
923
924cleanup:
925 if (c2)
926 MHD__asn1_delete_structure (&c2);
927 return result;
928}
929
930/**
931 * MHD_gnutls_pkcs7_set_crl - This function adds a parsed crl in a PKCS7 crl set
932 * @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
933 * @crl: the DER encoded crl to be added
934 *
935 * This function will add a parsed crl to the PKCS7 or RFC2630 crl set.
936 * Returns 0 on success.
937 *
938 **/
939int
940MHD_gnutls_pkcs7_set_crl (MHD_gnutls_pkcs7_t pkcs7, MHD_gnutls_x509_crl_t crl)
941{
942 int ret;
943 MHD_gnutls_datum_t data;
944
945 if (pkcs7 == NULL)
946 return GNUTLS_E_INVALID_REQUEST;
947
948 ret = MHD__gnutls_x509_der_encode (crl->crl, "", &data, 0);
949 if (ret < 0)
950 {
951 MHD_gnutls_assert ();
952 return ret;
953 }
954
955 ret = MHD_gnutls_pkcs7_set_crl_raw (pkcs7, &data);
956
957 MHD__gnutls_free_datum (&data);
958
959 if (ret < 0)
960 {
961 MHD_gnutls_assert ();
962 return ret;
963 }
964
965 return 0;
966}
967
968/**
969 * MHD_gnutls_pkcs7_delete_crl - This function deletes a crl from a PKCS7 crl set
970 * @pkcs7_struct: should contain a MHD_gnutls_pkcs7_t structure
971 * @indx: the index of the crl to delete
972 *
973 * This function will delete a crl from a PKCS7 or RFC2630 crl set.
974 * Index starts from 0. Returns 0 on success.
975 *
976 **/
977int
978MHD_gnutls_pkcs7_delete_crl (MHD_gnutls_pkcs7_t pkcs7, int indx)
979{
980 ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
981 int result;
982 char root2[MAX_NAME_SIZE];
983
984 if (pkcs7 == NULL)
985 return GNUTLS_E_INVALID_REQUEST;
986
987 /* Step 1. Decode the signed data.
988 */
989 result = _decode_pkcs7_signed_data (pkcs7->pkcs7, &c2, NULL);
990 if (result < 0)
991 {
992 MHD_gnutls_assert ();
993 return result;
994 }
995
996 /* Step 2. Delete the crl.
997 */
998
999 snprintf (root2, sizeof (root2), "crls.?%u", indx + 1);
1000
1001 result = MHD__asn1_write_value (c2, root2, NULL, 0);
1002 if (result != ASN1_SUCCESS)
1003 {
1004 MHD_gnutls_assert ();
1005 result = MHD_gtls_asn2err (result);
1006 goto cleanup;
1007 }
1008
1009 /* Step 3. Replace the old content with the new
1010 */
1011 result =
1012 MHD__gnutls_x509_der_encode_and_copy (c2, "", pkcs7->pkcs7, "content", 0);
1013 if (result < 0)
1014 {
1015 MHD_gnutls_assert ();
1016 goto cleanup;
1017 }
1018
1019 MHD__asn1_delete_structure (&c2);
1020
1021 return 0;
1022
1023cleanup:
1024 if (c2)
1025 MHD__asn1_delete_structure (&c2);
1026 return result;
1027}
1028
1029#endif /* ENABLE_PKI */