Tizen 2.0 Release
[external/libgnutls26.git] / lib / x509 / crl.c
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010 Free Software
3  * Foundation, Inc.
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS.
8  *
9  * The GnuTLS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA
23  *
24  */
25
26 #include <gnutls_int.h>
27 #include <libtasn1.h>
28
29 #ifdef ENABLE_PKI
30
31 #include <gnutls_datum.h>
32 #include <gnutls_global.h>
33 #include <gnutls_errors.h>
34 #include <common.h>
35 #include <x509_b64.h>
36 #include <x509_int.h>
37
38 /**
39  * gnutls_x509_crl_init:
40  * @crl: The structure to be initialized
41  *
42  * This function will initialize a CRL structure. CRL stands for
43  * Certificate Revocation List. A revocation list usually contains
44  * lists of certificate serial numbers that have been revoked by an
45  * Authority. The revocation lists are always signed with the
46  * authority's private key.
47  *
48  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
49  *   negative error value.
50  **/
51 int
52 gnutls_x509_crl_init (gnutls_x509_crl_t * crl)
53 {
54   *crl = gnutls_calloc (1, sizeof (gnutls_x509_crl_int));
55
56   if (*crl)
57     {
58       int result = asn1_create_element (_gnutls_get_pkix (),
59                                         "PKIX1.CertificateList",
60                                         &(*crl)->crl);
61       if (result != ASN1_SUCCESS)
62         {
63           gnutls_assert ();
64           gnutls_free (*crl);
65           return _gnutls_asn2err (result);
66         }
67       return 0;                 /* success */
68     }
69   return GNUTLS_E_MEMORY_ERROR;
70 }
71
72 /**
73  * gnutls_x509_crl_deinit:
74  * @crl: The structure to be initialized
75  *
76  * This function will deinitialize a CRL structure.
77  **/
78 void
79 gnutls_x509_crl_deinit (gnutls_x509_crl_t crl)
80 {
81   if (!crl)
82     return;
83
84   if (crl->crl)
85     asn1_delete_structure (&crl->crl);
86
87   gnutls_free (crl);
88 }
89
90 /**
91  * gnutls_x509_crl_import:
92  * @crl: The structure to store the parsed CRL.
93  * @data: The DER or PEM encoded CRL.
94  * @format: One of DER or PEM
95  *
96  * This function will convert the given DER or PEM encoded CRL
97  * to the native #gnutls_x509_crl_t format. The output will be stored in 'crl'.
98  *
99  * If the CRL is PEM encoded it should have a header of "X509 CRL".
100  *
101  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
102  *   negative error value.
103  **/
104 int
105 gnutls_x509_crl_import (gnutls_x509_crl_t crl,
106                         const gnutls_datum_t * data,
107                         gnutls_x509_crt_fmt_t format)
108 {
109   int result = 0, need_free = 0;
110   gnutls_datum_t _data;
111
112   _data.data = data->data;
113   _data.size = data->size;
114
115   if (crl == NULL)
116     {
117       gnutls_assert ();
118       return GNUTLS_E_INVALID_REQUEST;
119     }
120
121   /* If the CRL is in PEM format then decode it
122    */
123   if (format == GNUTLS_X509_FMT_PEM)
124     {
125       opaque *out;
126
127       result = _gnutls_fbase64_decode (PEM_CRL, data->data, data->size, &out);
128
129       if (result <= 0)
130         {
131           if (result == 0)
132             result = GNUTLS_E_INTERNAL_ERROR;
133           gnutls_assert ();
134           return result;
135         }
136
137       _data.data = out;
138       _data.size = result;
139
140       need_free = 1;
141     }
142
143
144   result = asn1_der_decoding (&crl->crl, _data.data, _data.size, NULL);
145   if (result != ASN1_SUCCESS)
146     {
147       result = _gnutls_asn2err (result);
148       gnutls_assert ();
149       goto cleanup;
150     }
151
152   if (need_free)
153     _gnutls_free_datum (&_data);
154
155   return 0;
156
157 cleanup:
158   if (need_free)
159     _gnutls_free_datum (&_data);
160   return result;
161 }
162
163
164 /**
165  * gnutls_x509_crl_get_issuer_dn:
166  * @crl: should contain a gnutls_x509_crl_t structure
167  * @buf: a pointer to a structure to hold the peer's name (may be null)
168  * @sizeof_buf: initially holds the size of @buf
169  *
170  * This function will copy the name of the CRL issuer in the provided
171  * buffer. The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
172  * described in RFC2253. The output string will be ASCII or UTF-8
173  * encoded, depending on the certificate data.
174  *
175  * If buf is %NULL then only the size will be filled.
176  *
177  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
178  * not long enough, and in that case the sizeof_buf will be updated
179  * with the required size, and 0 on success.
180  *
181  **/
182 int
183 gnutls_x509_crl_get_issuer_dn (const gnutls_x509_crl_t crl, char *buf,
184                                size_t * sizeof_buf)
185 {
186   if (crl == NULL)
187     {
188       gnutls_assert ();
189       return GNUTLS_E_INVALID_REQUEST;
190     }
191
192   return _gnutls_x509_parse_dn (crl->crl,
193                                 "tbsCertList.issuer.rdnSequence",
194                                 buf, sizeof_buf);
195 }
196
197 /**
198  * gnutls_x509_crl_get_issuer_dn_by_oid:
199  * @crl: should contain a gnutls_x509_crl_t structure
200  * @oid: holds an Object Identified in null terminated string
201  * @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one.
202  * @raw_flag: If non zero returns the raw DER data of the DN part.
203  * @buf: a pointer to a structure to hold the peer's name (may be null)
204  * @sizeof_buf: initially holds the size of @buf
205  *
206  * This function will extract the part of the name of the CRL issuer
207  * specified by the given OID. The output will be encoded as described
208  * in RFC2253. The output string will be ASCII or UTF-8 encoded,
209  * depending on the certificate data.
210  *
211  * Some helper macros with popular OIDs can be found in gnutls/x509.h
212  * If raw flag is zero, this function will only return known OIDs as
213  * text. Other OIDs will be DER encoded, as described in RFC2253 -- in
214  * hex format with a '\#' prefix.  You can check about known OIDs
215  * using gnutls_x509_dn_oid_known().
216  *
217  * If buf is null then only the size will be filled.
218  *
219  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
220  * not long enough, and in that case the sizeof_buf will be updated
221  * with the required size, and 0 on success.
222  **/
223 int
224 gnutls_x509_crl_get_issuer_dn_by_oid (gnutls_x509_crl_t crl,
225                                       const char *oid, int indx,
226                                       unsigned int raw_flag, void *buf,
227                                       size_t * sizeof_buf)
228 {
229   if (crl == NULL)
230     {
231       gnutls_assert ();
232       return GNUTLS_E_INVALID_REQUEST;
233     }
234
235   return _gnutls_x509_parse_dn_oid (crl->crl,
236                                     "tbsCertList.issuer.rdnSequence",
237                                     oid, indx, raw_flag, buf, sizeof_buf);
238 }
239
240 /**
241  * gnutls_x509_crl_get_dn_oid:
242  * @crl: should contain a gnutls_x509_crl_t structure
243  * @indx: Specifies which DN OID to send. Use zero to get the first one.
244  * @oid: a pointer to a structure to hold the name (may be null)
245  * @sizeof_oid: initially holds the size of 'oid'
246  *
247  * This function will extract the requested OID of the name of the CRL
248  * issuer, specified by the given index.
249  *
250  * If oid is null then only the size will be filled.
251  *
252  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is
253  * not long enough, and in that case the sizeof_oid will be updated
254  * with the required size.  On success 0 is returned.
255  **/
256 int
257 gnutls_x509_crl_get_dn_oid (gnutls_x509_crl_t crl,
258                             int indx, void *oid, size_t * sizeof_oid)
259 {
260   if (crl == NULL)
261     {
262       gnutls_assert ();
263       return GNUTLS_E_INVALID_REQUEST;
264     }
265
266   return _gnutls_x509_get_dn_oid (crl->crl,
267                                   "tbsCertList.issuer.rdnSequence", indx,
268                                   oid, sizeof_oid);
269 }
270
271
272 /**
273  * gnutls_x509_crl_get_signature_algorithm:
274  * @crl: should contain a #gnutls_x509_crl_t structure
275  *
276  * This function will return a value of the #gnutls_sign_algorithm_t
277  * enumeration that is the signature algorithm.
278  *
279  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
280  *   negative error value.
281  **/
282 int
283 gnutls_x509_crl_get_signature_algorithm (gnutls_x509_crl_t crl)
284 {
285   int result;
286   gnutls_datum_t sa;
287
288   if (crl == NULL)
289     {
290       gnutls_assert ();
291       return GNUTLS_E_INVALID_REQUEST;
292     }
293
294   /* Read the signature algorithm. Note that parameters are not
295    * read. They will be read from the issuer's certificate if needed.
296    */
297
298   result =
299     _gnutls_x509_read_value (crl->crl, "signatureAlgorithm.algorithm",
300                              &sa, 0);
301
302   if (result < 0)
303     {
304       gnutls_assert ();
305       return result;
306     }
307
308   result = _gnutls_x509_oid2sign_algorithm ((const char *) sa.data);
309
310   _gnutls_free_datum (&sa);
311
312   return result;
313 }
314
315 /**
316  * gnutls_x509_crl_get_signature:
317  * @crl: should contain a gnutls_x509_crl_t structure
318  * @sig: a pointer where the signature part will be copied (may be null).
319  * @sizeof_sig: initially holds the size of @sig
320  *
321  * This function will extract the signature field of a CRL.
322  *
323  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
324  *   negative error value. and a negative value on error.
325  **/
326 int
327 gnutls_x509_crl_get_signature (gnutls_x509_crl_t crl,
328                                char *sig, size_t * sizeof_sig)
329 {
330   int result;
331   int bits;
332   unsigned int len;
333
334   if (crl == NULL)
335     {
336       gnutls_assert ();
337       return GNUTLS_E_INVALID_REQUEST;
338     }
339
340   bits = 0;
341   result = asn1_read_value (crl->crl, "signature", NULL, &bits);
342   if (result != ASN1_MEM_ERROR)
343     {
344       gnutls_assert ();
345       return _gnutls_asn2err (result);
346     }
347
348   if (bits % 8 != 0)
349     {
350       gnutls_assert ();
351       return GNUTLS_E_CERTIFICATE_ERROR;
352     }
353
354   len = bits / 8;
355
356   if (*sizeof_sig < len)
357     {
358       *sizeof_sig = bits / 8;
359       return GNUTLS_E_SHORT_MEMORY_BUFFER;
360     }
361
362   result = asn1_read_value (crl->crl, "signature", sig, &len);
363   if (result != ASN1_SUCCESS)
364     {
365       gnutls_assert ();
366       return _gnutls_asn2err (result);
367     }
368
369   return 0;
370 }
371
372 /**
373  * gnutls_x509_crl_get_version:
374  * @crl: should contain a #gnutls_x509_crl_t structure
375  *
376  * This function will return the version of the specified CRL.
377  *
378  * Returns: The version number, or a negative value on error.
379  **/
380 int
381 gnutls_x509_crl_get_version (gnutls_x509_crl_t crl)
382 {
383   opaque version[8];
384   int len, result;
385
386   if (crl == NULL)
387     {
388       gnutls_assert ();
389       return GNUTLS_E_INVALID_REQUEST;
390     }
391
392   len = sizeof (version);
393   if ((result =
394        asn1_read_value (crl->crl, "tbsCertList.version", version,
395                         &len)) != ASN1_SUCCESS)
396     {
397       gnutls_assert ();
398       return _gnutls_asn2err (result);
399     }
400
401   return (int) version[0] + 1;
402 }
403
404 /**
405  * gnutls_x509_crl_get_this_update:
406  * @crl: should contain a #gnutls_x509_crl_t structure
407  *
408  * This function will return the time this CRL was issued.
409  *
410  * Returns: when the CRL was issued, or (time_t)-1 on error.
411  **/
412 time_t
413 gnutls_x509_crl_get_this_update (gnutls_x509_crl_t crl)
414 {
415   if (crl == NULL)
416     {
417       gnutls_assert ();
418       return (time_t) - 1;
419     }
420
421   return _gnutls_x509_get_time (crl->crl, "tbsCertList.thisUpdate");
422 }
423
424 /**
425  * gnutls_x509_crl_get_next_update:
426  * @crl: should contain a #gnutls_x509_crl_t structure
427  *
428  * This function will return the time the next CRL will be issued.
429  * This field is optional in a CRL so it might be normal to get an
430  * error instead.
431  *
432  * Returns: when the next CRL will be issued, or (time_t)-1 on error.
433  **/
434 time_t
435 gnutls_x509_crl_get_next_update (gnutls_x509_crl_t crl)
436 {
437   if (crl == NULL)
438     {
439       gnutls_assert ();
440       return (time_t) - 1;
441     }
442
443   return _gnutls_x509_get_time (crl->crl, "tbsCertList.nextUpdate");
444 }
445
446 /**
447  * gnutls_x509_crl_get_crt_count:
448  * @crl: should contain a #gnutls_x509_crl_t structure
449  *
450  * This function will return the number of revoked certificates in the
451  * given CRL.
452  *
453  * Returns: number of certificates, a negative value on failure.
454  **/
455 int
456 gnutls_x509_crl_get_crt_count (gnutls_x509_crl_t crl)
457 {
458
459   int count, result;
460
461   if (crl == NULL)
462     {
463       gnutls_assert ();
464       return GNUTLS_E_INVALID_REQUEST;
465     }
466
467   result =
468     asn1_number_of_elements (crl->crl,
469                              "tbsCertList.revokedCertificates", &count);
470
471   if (result != ASN1_SUCCESS)
472     {
473       gnutls_assert ();
474       return 0;                 /* no certificates */
475     }
476
477   return count;
478 }
479
480 /**
481  * gnutls_x509_crl_get_crt_serial:
482  * @crl: should contain a #gnutls_x509_crl_t structure
483  * @indx: the index of the certificate to extract (starting from 0)
484  * @serial: where the serial number will be copied
485  * @serial_size: initially holds the size of serial
486  * @t: if non null, will hold the time this certificate was revoked
487  *
488  * This function will retrieve the serial number of the specified, by
489  * the index, revoked certificate.
490  *
491  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
492  *   negative error value. and a negative value on error.
493  **/
494 int
495 gnutls_x509_crl_get_crt_serial (gnutls_x509_crl_t crl, int indx,
496                                 unsigned char *serial,
497                                 size_t * serial_size, time_t * t)
498 {
499
500   int result, _serial_size;
501   char serial_name[ASN1_MAX_NAME_SIZE];
502   char date_name[ASN1_MAX_NAME_SIZE];
503
504   if (crl == NULL)
505     {
506       gnutls_assert ();
507       return GNUTLS_E_INVALID_REQUEST;
508     }
509
510   snprintf (serial_name, sizeof (serial_name),
511             "tbsCertList.revokedCertificates.?%u.userCertificate", indx + 1);
512   snprintf (date_name, sizeof (date_name),
513             "tbsCertList.revokedCertificates.?%u.revocationDate", indx + 1);
514
515   _serial_size = *serial_size;
516   result = asn1_read_value (crl->crl, serial_name, serial, &_serial_size);
517
518   *serial_size = _serial_size;
519   if (result != ASN1_SUCCESS)
520     {
521       gnutls_assert ();
522       if (result == ASN1_ELEMENT_NOT_FOUND)
523         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
524       return _gnutls_asn2err (result);
525     }
526
527   if (t)
528     {
529       *t = _gnutls_x509_get_time (crl->crl, date_name);
530     }
531
532   return 0;
533 }
534
535 /**
536  * gnutls_x509_crl_get_raw_issuer_dn:
537  * @crl: should contain a gnutls_x509_crl_t structure
538  * @dn: will hold the starting point of the DN
539  *
540  * This function will return a pointer to the DER encoded DN structure
541  * and the length.
542  *
543  * Returns: a negative value on error, and zero on success.
544  *
545  * Since: 2.12.0
546  **/
547 int
548 gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl,
549                                    gnutls_datum_t * dn)
550 {
551   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
552   int result, len1;
553   int start1, end1;
554   gnutls_datum_t crl_signed_data;
555
556   if (crl == NULL)
557     {
558       gnutls_assert ();
559       return GNUTLS_E_INVALID_REQUEST;
560     }
561
562   /* get the issuer of 'crl'
563    */
564   if ((result =
565        asn1_create_element (_gnutls_get_pkix (), "PKIX1.TBSCertList",
566                             &c2)) != ASN1_SUCCESS)
567     {
568       gnutls_assert ();
569       return _gnutls_asn2err (result);
570     }
571
572   result =
573     _gnutls_x509_get_signed_data (crl->crl, "tbsCertList", &crl_signed_data);
574   if (result < 0)
575     {
576       gnutls_assert ();
577       goto cleanup;
578     }
579
580   result =
581     asn1_der_decoding (&c2, crl_signed_data.data, crl_signed_data.size, NULL);
582   if (result != ASN1_SUCCESS)
583     {
584       /* couldn't decode DER */
585       gnutls_assert ();
586       asn1_delete_structure (&c2);
587       result = _gnutls_asn2err (result);
588       goto cleanup;
589     }
590
591   result =
592     asn1_der_decoding_startEnd (c2, crl_signed_data.data,
593                                 crl_signed_data.size, "issuer",
594                                 &start1, &end1);
595
596   if (result != ASN1_SUCCESS)
597     {
598       gnutls_assert ();
599       result = _gnutls_asn2err (result);
600       goto cleanup;
601     }
602
603   len1 = end1 - start1 + 1;
604
605   _gnutls_set_datum (dn, &crl_signed_data.data[start1], len1);
606
607   result = 0;
608
609 cleanup:
610   asn1_delete_structure (&c2);
611   _gnutls_free_datum (&crl_signed_data);
612   return result;
613 }
614
615 /**
616  * gnutls_x509_crl_export:
617  * @crl: Holds the revocation list
618  * @format: the format of output params. One of PEM or DER.
619  * @output_data: will contain a private key PEM or DER encoded
620  * @output_data_size: holds the size of output_data (and will
621  *   be replaced by the actual size of parameters)
622  *
623  * This function will export the revocation list to DER or PEM format.
624  *
625  * If the buffer provided is not long enough to hold the output, then
626  * %GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
627  *
628  * If the structure is PEM encoded, it will have a header
629  * of "BEGIN X509 CRL".
630  *
631  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
632  *   negative error value. and a negative value on failure.
633  **/
634 int
635 gnutls_x509_crl_export (gnutls_x509_crl_t crl,
636                         gnutls_x509_crt_fmt_t format, void *output_data,
637                         size_t * output_data_size)
638 {
639   if (crl == NULL)
640     {
641       gnutls_assert ();
642       return GNUTLS_E_INVALID_REQUEST;
643     }
644
645   return _gnutls_x509_export_int (crl->crl, format, PEM_CRL,
646                                   output_data, output_data_size);
647 }
648
649 /*-
650  * _gnutls_x509_crl_cpy - This function copies a gnutls_x509_crl_t structure
651  * @dest: The structure where to copy
652  * @src: The structure to be copied
653  *
654  * This function will copy an X.509 certificate structure.
655  *
656  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
657  *   negative error value.
658  -*/
659 int
660 _gnutls_x509_crl_cpy (gnutls_x509_crl_t dest, gnutls_x509_crl_t src)
661 {
662   int ret;
663   size_t der_size;
664   opaque *der;
665   gnutls_datum_t tmp;
666
667   ret = gnutls_x509_crl_export (src, GNUTLS_X509_FMT_DER, NULL, &der_size);
668   if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
669     {
670       gnutls_assert ();
671       return ret;
672     }
673
674   der = gnutls_malloc (der_size);
675   if (der == NULL)
676     {
677       gnutls_assert ();
678       return GNUTLS_E_MEMORY_ERROR;
679     }
680
681   ret = gnutls_x509_crl_export (src, GNUTLS_X509_FMT_DER, der, &der_size);
682   if (ret < 0)
683     {
684       gnutls_assert ();
685       gnutls_free (der);
686       return ret;
687     }
688
689   tmp.data = der;
690   tmp.size = der_size;
691   ret = gnutls_x509_crl_import (dest, &tmp, GNUTLS_X509_FMT_DER);
692
693   gnutls_free (der);
694
695   if (ret < 0)
696     {
697       gnutls_assert ();
698       return ret;
699     }
700
701   return 0;
702
703 }
704
705 /**
706  * gnutls_x509_crl_get_authority_key_id:
707  * @crl: should contain a #gnutls_x509_crl_t structure
708  * @ret: The place where the identifier will be copied
709  * @ret_size: Holds the size of the result field.
710  * @critical: will be non zero if the extension is marked as critical
711  *   (may be null)
712  *
713  * This function will return the CRL authority's key identifier.  This
714  * is obtained by the X.509 Authority Key identifier extension field
715  * (2.5.29.35).  Note that this function only returns the
716  * keyIdentifier field of the extension.
717  *
718  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
719  *   negative value in case of an error.
720  *
721  * Since: 2.8.0
722  **/
723 int
724 gnutls_x509_crl_get_authority_key_id (gnutls_x509_crl_t crl, void *ret,
725                                       size_t * ret_size,
726                                       unsigned int *critical)
727 {
728   int result, len;
729   gnutls_datum_t id;
730   ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
731
732   if (crl == NULL)
733     {
734       gnutls_assert ();
735       return GNUTLS_E_INVALID_REQUEST;
736     }
737
738
739   if (ret)
740     memset (ret, 0, *ret_size);
741   else
742     *ret_size = 0;
743
744   if ((result =
745        _gnutls_x509_crl_get_extension (crl, "2.5.29.35", 0, &id,
746                                        critical)) < 0)
747     {
748       return result;
749     }
750
751   if (id.size == 0 || id.data == NULL)
752     {
753       gnutls_assert ();
754       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
755     }
756
757   result = asn1_create_element
758     (_gnutls_get_pkix (), "PKIX1.AuthorityKeyIdentifier", &c2);
759   if (result != ASN1_SUCCESS)
760     {
761       gnutls_assert ();
762       _gnutls_free_datum (&id);
763       return _gnutls_asn2err (result);
764     }
765
766   result = asn1_der_decoding (&c2, id.data, id.size, NULL);
767   _gnutls_free_datum (&id);
768
769   if (result != ASN1_SUCCESS)
770     {
771       gnutls_assert ();
772       asn1_delete_structure (&c2);
773       return _gnutls_asn2err (result);
774     }
775
776   len = *ret_size;
777   result = asn1_read_value (c2, "keyIdentifier", ret, &len);
778
779   *ret_size = len;
780   asn1_delete_structure (&c2);
781
782   if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND)
783     {
784       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
785     }
786
787   if (result != ASN1_SUCCESS)
788     {
789       gnutls_assert ();
790       return _gnutls_asn2err (result);
791     }
792
793   return 0;
794 }
795
796 /**
797  * gnutls_x509_crl_get_number:
798  * @crl: should contain a #gnutls_x509_crl_t structure
799  * @ret: The place where the number will be copied
800  * @ret_size: Holds the size of the result field.
801  * @critical: will be non zero if the extension is marked as critical
802  *   (may be null)
803  *
804  * This function will return the CRL number extension.  This is
805  * obtained by the CRL Number extension field (2.5.29.20).
806  *
807  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
808  *   negative value in case of an error.
809  *
810  * Since: 2.8.0
811  **/
812 int
813 gnutls_x509_crl_get_number (gnutls_x509_crl_t crl, void *ret,
814                             size_t * ret_size, unsigned int *critical)
815 {
816   int result;
817   gnutls_datum_t id;
818
819   if (crl == NULL)
820     {
821       gnutls_assert ();
822       return GNUTLS_E_INVALID_REQUEST;
823     }
824
825
826   if (ret)
827     memset (ret, 0, *ret_size);
828   else
829     *ret_size = 0;
830
831   if ((result =
832        _gnutls_x509_crl_get_extension (crl, "2.5.29.20", 0, &id,
833                                        critical)) < 0)
834     {
835       return result;
836     }
837
838   if (id.size == 0 || id.data == NULL)
839     {
840       gnutls_assert ();
841       return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
842     }
843
844   result = _gnutls_x509_ext_extract_number (ret, ret_size, id.data, id.size);
845
846   _gnutls_free_datum (&id);
847
848   if (result < 0)
849     {
850       gnutls_assert ();
851       return result;
852     }
853
854   return 0;
855 }
856
857 /**
858  * gnutls_x509_crl_get_extension_oid:
859  * @crl: should contain a #gnutls_x509_crl_t structure
860  * @indx: Specifies which extension OID to send, use zero to get the first one.
861  * @oid: a pointer to a structure to hold the OID (may be null)
862  * @sizeof_oid: initially holds the size of @oid
863  *
864  * This function will return the requested extension OID in the CRL.
865  * The extension OID will be stored as a string in the provided
866  * buffer.
867  *
868  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
869  *   negative value in case of an error.  If your have reached the
870  *   last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
871  *   will be returned.
872  *
873  * Since: 2.8.0
874  **/
875 int
876 gnutls_x509_crl_get_extension_oid (gnutls_x509_crl_t crl, int indx,
877                                    void *oid, size_t * sizeof_oid)
878 {
879   int result;
880
881   if (crl == NULL)
882     {
883       gnutls_assert ();
884       return GNUTLS_E_INVALID_REQUEST;
885     }
886
887   result = _gnutls_x509_crl_get_extension_oid (crl, indx, oid, sizeof_oid);
888   if (result < 0)
889     {
890       return result;
891     }
892
893   return 0;
894
895 }
896
897 /**
898  * gnutls_x509_crl_get_extension_info:
899  * @crl: should contain a #gnutls_x509_crl_t structure
900  * @indx: Specifies which extension OID to send, use zero to get the first one.
901  * @oid: a pointer to a structure to hold the OID
902  * @sizeof_oid: initially holds the maximum size of @oid, on return
903  *   holds actual size of @oid.
904  * @critical: output variable with critical flag, may be NULL.
905  *
906  * This function will return the requested extension OID in the CRL,
907  * and the critical flag for it.  The extension OID will be stored as
908  * a string in the provided buffer.  Use
909  * gnutls_x509_crl_get_extension_data() to extract the data.
910  *
911  * If the buffer provided is not long enough to hold the output, then
912  * *@sizeof_oid is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will be
913  * returned.
914  *
915  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
916  *   negative value in case of an error.  If your have reached the
917  *   last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
918  *   will be returned.
919  *
920  * Since: 2.8.0
921  **/
922 int
923 gnutls_x509_crl_get_extension_info (gnutls_x509_crl_t crl, int indx,
924                                     void *oid, size_t * sizeof_oid,
925                                     int *critical)
926 {
927   int result;
928   char str_critical[10];
929   char name[ASN1_MAX_NAME_SIZE];
930   int len;
931
932   if (!crl)
933     {
934       gnutls_assert ();
935       return GNUTLS_E_INVALID_REQUEST;
936     }
937
938   snprintf (name, sizeof (name), "tbsCertList.crlExtensions.?%u.extnID",
939             indx + 1);
940
941   len = *sizeof_oid;
942   result = asn1_read_value (crl->crl, name, oid, &len);
943   *sizeof_oid = len;
944
945   if (result == ASN1_ELEMENT_NOT_FOUND)
946     return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
947   else if (result != ASN1_SUCCESS)
948     {
949       gnutls_assert ();
950       return _gnutls_asn2err (result);
951     }
952
953   snprintf (name, sizeof (name), "tbsCertList.crlExtensions.?%u.critical",
954             indx + 1);
955   len = sizeof (str_critical);
956   result = asn1_read_value (crl->crl, name, str_critical, &len);
957   if (result != ASN1_SUCCESS)
958     {
959       gnutls_assert ();
960       return _gnutls_asn2err (result);
961     }
962
963   if (critical)
964     {
965       if (str_critical[0] == 'T')
966         *critical = 1;
967       else
968         *critical = 0;
969     }
970
971   return 0;
972
973 }
974
975 /**
976  * gnutls_x509_crl_get_extension_data:
977  * @crl: should contain a #gnutls_x509_crl_t structure
978  * @indx: Specifies which extension OID to send. Use zero to get the first one.
979  * @data: a pointer to a structure to hold the data (may be null)
980  * @sizeof_data: initially holds the size of @oid
981  *
982  * This function will return the requested extension data in the CRL.
983  * The extension data will be stored as a string in the provided
984  * buffer.
985  *
986  * Use gnutls_x509_crl_get_extension_info() to extract the OID and
987  * critical flag.  Use gnutls_x509_crl_get_extension_info() instead,
988  * if you want to get data indexed by the extension OID rather than
989  * sequence.
990  *
991  * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
992  *   negative value in case of an error.  If your have reached the
993  *   last extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
994  *   will be returned.
995  *
996  * Since: 2.8.0
997  **/
998 int
999 gnutls_x509_crl_get_extension_data (gnutls_x509_crl_t crl, int indx,
1000                                     void *data, size_t * sizeof_data)
1001 {
1002   int result, len;
1003   char name[ASN1_MAX_NAME_SIZE];
1004
1005   if (!crl)
1006     {
1007       gnutls_assert ();
1008       return GNUTLS_E_INVALID_REQUEST;
1009     }
1010
1011   snprintf (name, sizeof (name), "tbsCertList.crlExtensions.?%u.extnValue",
1012             indx + 1);
1013
1014   len = *sizeof_data;
1015   result = asn1_read_value (crl->crl, name, data, &len);
1016   *sizeof_data = len;
1017
1018   if (result == ASN1_ELEMENT_NOT_FOUND)
1019     return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1020   else if (result < 0)
1021     {
1022       gnutls_assert ();
1023       return _gnutls_asn2err (result);
1024     }
1025
1026   return 0;
1027 }
1028
1029 #endif