Improved the certificate generation stuff.
[gnutls:gnutls.git] / lib / x509 / verify.c
1 /*
2  *  Copyright (C) 2003 Nikos Mavroyanopoulos <nmav@hellug.gr>
3  *
4  *  This file is part of GNUTLS.
5  *
6  *  The GNUTLS library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public   
8  *  License as published by the Free Software Foundation; either 
9  *  version 2.1 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19  *
20  */
21
22 /* All functions which relate to X.509 certificate verification stuff are
23  * included here
24  */
25
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_cert.h>
29 #include <libtasn1.h>
30 #include <gnutls_global.h>
31 #include <gnutls_num.h>         /* GMAX */
32 #include <gnutls_sig.h>
33 #include <gnutls_str.h>
34 #include <gnutls_datum.h>
35 #include <dn.h>
36 #include <x509.h>
37 #include <mpi.h>
38 #include <common.h>
39 #include <verify.h>
40
41 static int _gnutls_verify_certificate2(gnutls_x509_crt cert,
42                                gnutls_x509_crt *trusted_cas, int tcas_size, 
43                                unsigned int flags);
44 static
45 int _gnutls_x509_verify_signature(const gnutls_datum* signed_data,
46         const gnutls_datum* signature, gnutls_x509_crt issuer);
47 static
48 int is_crl_issuer(gnutls_x509_crl crl, gnutls_x509_crt issuer_cert);
49 static int _gnutls_verify_crl2(gnutls_x509_crl crl,
50                                gnutls_x509_crt *trusted_cas, int tcas_size, 
51                                unsigned int flags);
52
53
54 /* Checks if the issuer of a certificate is a
55  * Certificate Authority, or if the certificate is the same
56  * as the issuer (and therefore it doesn't need to be a CA).
57  *
58  * Returns true or false, if the issuer is a CA,
59  * or not.
60  */
61 static int check_if_ca(gnutls_x509_crt cert, gnutls_x509_crt issuer)
62 {
63 gnutls_datum cert_signed_data = { NULL, 0 };
64 gnutls_datum issuer_signed_data = { NULL, 0 };
65 gnutls_datum cert_signature = { NULL, 0 };
66 gnutls_datum issuer_signature = { NULL, 0 };
67 int result;
68
69         /* Check if the issuer is the same with the
70          * certificate. This is added in order for trusted
71          * certificates to be able to verify themselves.
72          */
73
74         result = _gnutls_x509_get_signed_data( issuer->cert, "tbsCertificate", &issuer_signed_data);
75         if (result < 0) {
76                 gnutls_assert();
77                 goto cleanup;
78         }
79
80         result = _gnutls_x509_get_signed_data( cert->cert, "tbsCertificate", &cert_signed_data);
81         if (result < 0) {
82                 gnutls_assert();
83                 goto cleanup;
84         }
85
86         result = _gnutls_x509_get_signature( issuer->cert, "signature", &issuer_signature);
87         if (result < 0) {
88                 gnutls_assert();
89                 goto cleanup;
90         }
91
92         result = _gnutls_x509_get_signature( cert->cert, "signature", &cert_signature);
93         if (result < 0) {
94                 gnutls_assert();
95                 goto cleanup;
96         }
97
98         if (cert_signed_data.size == issuer_signed_data.size) {
99                 if (
100                     (memcmp(cert_signed_data.data, issuer_signed_data.data,
101                         cert_signed_data.size) == 0) &&
102                     (cert_signature.size == issuer_signature.size) &&
103                     (memcmp(cert_signature.data, issuer_signature.data,
104                         cert_signature.size) == 0))
105
106                         result = 1;
107                         goto cleanup;
108         }
109
110         if (gnutls_x509_crt_get_ca_status(issuer, NULL) == 1) {
111                 result = 1;
112                 goto cleanup;
113         } else
114                 gnutls_assert();
115
116         result = 0;
117
118 cleanup:
119         _gnutls_free_datum( &cert_signed_data);
120         _gnutls_free_datum( &issuer_signed_data);
121         _gnutls_free_datum( &cert_signature);
122         _gnutls_free_datum( &issuer_signature);
123         return result;
124 }
125
126
127 /* This function checks if 'certs' issuer is 'issuer_cert'.
128  * This does a straight (DER) compare of the issuer/subject fields in
129  * the given certificates.
130  *
131  * Returns 1 if the match and zero if they don't match. Otherwise
132  * a negative value is returned to indicate error.
133  */
134 static
135 int is_issuer(gnutls_x509_crt cert, gnutls_x509_crt issuer_cert)
136 {
137         gnutls_datum dn1 = {NULL, 0}, dn2 = { NULL, 0 };
138         int ret;
139
140         ret = _gnutls_x509_crt_get_raw_issuer_dn( cert, &dn1);
141         if (ret < 0) {
142                 gnutls_assert();
143                 goto cleanup;
144         }
145
146         ret = _gnutls_x509_crt_get_raw_dn( issuer_cert, &dn2);
147         if (ret < 0) {
148                 gnutls_assert();
149                 goto cleanup;
150         }
151
152         ret = _gnutls_x509_compare_raw_dn( &dn1, &dn2);
153         
154 cleanup:
155         _gnutls_free_datum(&dn1);
156         _gnutls_free_datum(&dn2);       
157         return ret;
158
159 }
160
161
162 static inline
163 gnutls_x509_crt find_issuer(gnutls_x509_crt cert,
164                                 gnutls_x509_crt * trusted_cas, int tcas_size)
165 {
166         int i;
167
168         /* this is serial search. 
169          */
170
171         for (i = 0; i < tcas_size; i++) {
172                 if (is_issuer(cert, trusted_cas[i]) == 1)
173                         return trusted_cas[i];
174         }
175
176         gnutls_assert();
177         return NULL;
178 }
179
180
181
182 /* 
183  * Returns only 0 or 1. If 1 it means that the certificate 
184  * was successfuly verified.
185  *
186  * 'flags': an OR of the gnutls_certificate_verify_flags enumeration.
187  */
188 static int _gnutls_verify_certificate2(gnutls_x509_crt cert,
189                                gnutls_x509_crt *trusted_cas, int tcas_size, 
190                                unsigned int flags)
191 {
192 gnutls_datum cert_signed_data = { NULL, 0 };
193 gnutls_datum cert_signature = { NULL, 0 };
194 gnutls_x509_crt issuer;
195 int ret, issuer_version, result;
196
197         if (tcas_size >= 1)
198                 issuer = find_issuer(cert, trusted_cas, tcas_size);
199         else {
200                 gnutls_assert();
201                 return 0;
202         }
203
204         /* issuer is not in trusted certificate
205          * authorities.
206          */
207         if (issuer == NULL) {
208                 gnutls_assert();
209                 return 0;
210         }
211
212         issuer_version = gnutls_x509_crt_get_version( issuer);
213         if (issuer_version < 0) {
214                 gnutls_assert();
215                 return issuer_version;
216         }
217
218         if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) &&
219                 !((flags & GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT) && issuer_version == 1)) {
220                 if (check_if_ca(cert, issuer)==0) {
221                         gnutls_assert();
222                         return 0;
223                 }
224         }
225
226
227         result = _gnutls_x509_get_signed_data( cert->cert, "tbsCertificate", &cert_signed_data);
228         if (result < 0) {
229                 gnutls_assert();
230                 goto cleanup;
231         }
232
233         result = _gnutls_x509_get_signature( cert->cert, "signature", &cert_signature);
234         if (result < 0) {
235                 gnutls_assert();
236                 goto cleanup;
237         }
238
239         ret = _gnutls_x509_verify_signature(&cert_signed_data, &cert_signature, issuer);
240         if (ret < 0) {
241                 gnutls_assert();
242                 /* error. ignore it */
243                 ret = 0;
244         }
245
246         result = ret;
247         
248 cleanup:
249         _gnutls_free_datum( &cert_signed_data);
250         _gnutls_free_datum( &cert_signature);
251         
252         return result;
253 }
254
255
256 /* The algorithm used is:
257  * 1. Check the certificate chain given by the peer, if it is ok.
258  * 2. If any certificate in the chain are revoked, not
259  *    valid, or they are not CAs then the certificate is invalid.
260  * 3. If 1 is ok, then find a certificate in the trusted CAs file
261  *    that has the DN of the issuer field in the last certificate
262  *    in the peer's certificate chain.
263  * 4. If it does exist then verify it. If verification is ok then
264  *    it is trusted. Otherwise it is just valid (but not trusted).
265  */
266 /* This function verifies a X.509 certificate list. The certificate list should
267  * lead to a trusted CA in order to be trusted.
268  */
269 static
270 unsigned int _gnutls_x509_verify_certificate(gnutls_x509_crt * certificate_list,
271                                     int clist_size,
272                                     gnutls_x509_crt * trusted_cas,
273                                     int tcas_size, gnutls_x509_crl *CRLs,
274                                     int crls_size, unsigned int flags)
275 {
276         int i = 0, ret;
277         unsigned int status = 0;
278
279         /* Check for revoked certificates in the chain
280          */
281 #ifdef ENABLE_PKI
282         for (i = 0; i < clist_size; i++) {
283                 ret = gnutls_x509_crt_check_revocation( certificate_list[i],
284                         CRLs, crls_size);
285                 if (ret == 1) { /* revoked */
286                         status |= GNUTLS_CERT_REVOKED;
287                 }
288         }
289 #endif
290
291         /* Verify the certificate path 
292          */
293         for (i = 0; i < clist_size; i++) {
294                 if (i + 1 >= clist_size)
295                         break;
296
297                 if ((ret =
298                      _gnutls_verify_certificate2(certificate_list[i],
299                                                  &certificate_list[i + 1], 1, flags)) != 1) 
300                 {
301                         status |= GNUTLS_CERT_INVALID;
302                 }
303         }
304
305         if (status != 0) {
306                   /* If there is any problem in the
307                    * certificate chain then mark as not trusted
308                    * and return immediately.
309                    */
310                 gnutls_assert();
311                 return (status | GNUTLS_CERT_NOT_TRUSTED);
312         }
313         
314         /* Now verify the last certificate in the certificate path
315          * against the trusted CA certificate list.
316          *
317          * If no CAs are present returns NOT_TRUSTED. Thus works
318          * in self signed etc certificates.
319          */
320         ret =
321             _gnutls_verify_certificate2(certificate_list[i], trusted_cas,
322                                        tcas_size, flags);
323
324         if (ret == 0) {
325                 /* if the last certificate in the certificate
326                  * list is invalid, then the certificate is not
327                  * trusted.
328                  */
329                 gnutls_assert();
330                 status |= GNUTLS_CERT_NOT_TRUSTED;
331         }
332
333         return status;
334 }
335
336
337 /* Reads the digest information.
338  * we use DER here, although we should use BER. It works fine
339  * anyway.
340  */
341 static int decode_ber_digest_info( const gnutls_datum *info, gnutls_mac_algorithm *hash, 
342         opaque* digest, int *digest_size) 
343 {
344 ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
345 int result;
346 opaque str[1024];
347 int len;
348
349         if ((result=asn1_create_element( _gnutls_get_gnutls_asn(), 
350                 "GNUTLS.DigestInfo", &dinfo))!=ASN1_SUCCESS) {
351                 gnutls_assert();
352                 return _gnutls_asn2err(result);
353         }
354
355         result = asn1_der_decoding( &dinfo, info->data, info->size, NULL);
356         if (result != ASN1_SUCCESS) {
357                 gnutls_assert();
358                 asn1_delete_structure(&dinfo);
359                 return _gnutls_asn2err(result);
360         }
361         
362         len = sizeof(str)-1;
363         result =
364             asn1_read_value( dinfo, "digestAlgorithm.algorithm", str, &len);
365         if (result != ASN1_SUCCESS) {
366                 gnutls_assert();
367                 asn1_delete_structure(&dinfo);
368                 return _gnutls_asn2err(result);
369         }
370
371         *hash = _gnutls_x509_oid2mac_algorithm( str);
372
373         if (*hash==GNUTLS_MAC_UNKNOWN) {
374
375                 _gnutls_x509_log( "verify.c: HASH OID: %s\n", str);
376
377                 gnutls_assert();
378                 asn1_delete_structure(&dinfo);
379                 return GNUTLS_E_UNKNOWN_HASH_ALGORITHM;
380         }
381         
382         result =
383             asn1_read_value( dinfo, "digest", digest, digest_size);
384         if (result != ASN1_SUCCESS) {
385                 gnutls_assert();
386                 asn1_delete_structure(&dinfo);
387                 return _gnutls_asn2err(result);
388         }
389
390         asn1_delete_structure(&dinfo);
391                 
392         return 0;
393 }
394
395 /* if hash==MD5 then we do RSA-MD5
396  * if hash==SHA then we do RSA-SHA
397  * params[0] is modulus
398  * params[1] is public key
399  */
400 static int
401 _pkcs1_rsa_verify_sig( const gnutls_datum* text, const gnutls_datum* signature, 
402         GNUTLS_MPI *params, int params_len)
403 {
404         gnutls_mac_algorithm hash;
405         int ret;
406         opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE];
407         int digest_size; 
408         GNUTLS_HASH_HANDLE hd;
409         gnutls_datum decrypted;
410
411         if ( (ret=_gnutls_pkcs1_rsa_decrypt( &decrypted, *signature, params, params_len, 1)) < 0) {
412                 gnutls_assert();
413                 return ret;
414         }
415
416         /* decrypted is a BER encoded data of type DigestInfo
417          */
418
419         digest_size = sizeof(digest);   
420         if ( (ret = decode_ber_digest_info( &decrypted, &hash, digest, &digest_size)) != 0) {
421                 gnutls_assert();
422                 _gnutls_free_datum( &decrypted);
423                 return ret;
424         }
425
426         _gnutls_free_datum( &decrypted);
427
428         if (digest_size != _gnutls_hash_get_algo_len(hash)) {
429                 gnutls_assert();
430                 return GNUTLS_E_ASN1_GENERIC_ERROR;
431         }
432
433         hd = _gnutls_hash_init( hash);
434         if (hd == NULL) {
435                 gnutls_assert();
436                 return GNUTLS_E_HASH_FAILED;
437         }
438
439         _gnutls_hash( hd, text->data, text->size);
440         _gnutls_hash_deinit( hd, md);
441
442         if (memcmp( md, digest, digest_size)!=0) {
443                 gnutls_assert();
444                 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
445         }
446
447         return 0;               
448 }
449
450 /* verifies if the certificate is properly signed.
451  * returns 0 on failure and 1 on success.
452  * 
453  * 'tbs' is the signed data
454  * 'signature' is the signature!
455  */
456 static
457 int _gnutls_x509_verify_signature( const gnutls_datum* tbs,
458         const gnutls_datum* signature, gnutls_x509_crt issuer) 
459 {
460 GNUTLS_MPI issuer_params[MAX_PUBLIC_PARAMS_SIZE];
461 int ret, issuer_params_size, i;
462
463         /* Read the MPI parameters from the issuer's certificate.
464          */
465         issuer_params_size = MAX_PUBLIC_PARAMS_SIZE;
466         ret = _gnutls_x509_crt_get_mpis(issuer, issuer_params, &issuer_params_size);
467
468         if ( ret < 0) {
469                 gnutls_assert();
470                 return ret;
471         }
472
473         switch( gnutls_x509_crt_get_pk_algorithm(issuer, NULL)) 
474         {
475                 case GNUTLS_PK_RSA:
476
477                         if (_pkcs1_rsa_verify_sig( tbs, signature, issuer_params, issuer_params_size)!=0) {
478                                 gnutls_assert();
479                                 ret = 0;
480                                 goto finish;
481                         }
482
483                         ret = 1;
484                         goto finish;
485                         break;
486
487                 case GNUTLS_PK_DSA:
488                         if (_gnutls_dsa_verify( tbs, signature, issuer_params, issuer_params_size)!=0) {
489                                 gnutls_assert();
490                                 ret = 0;
491                                 goto finish;
492                         }
493
494                         ret = 1;
495                         goto finish;
496                         break;
497                 default:
498                         gnutls_assert();
499                         ret = GNUTLS_E_INTERNAL_ERROR;
500                         goto finish;
501
502         }
503
504         finish:
505
506         /* release all allocated MPIs
507          */
508         for (i = 0; i < issuer_params_size; i++) {
509                 _gnutls_mpi_release( &issuer_params[i]);
510         }
511         return ret;
512 }
513
514 /**
515   * gnutls_x509_crt_list_verify - This function verifies the given certificate list
516   * @cert_list: is the certificate list to be verified
517   * @cert_list_length: holds the number of certificate in cert_list
518   * @CA_list: is the CA list which will be used in verification
519   * @CA_list_length: holds the number of CA certificate in CA_list
520   * @CRL_list: holds a list of CRLs.
521   * @CRL_list_length: the length of CRL list.
522   * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
523   * @verify: will hold the certificate verification output.
524   *
525   * This function will try to verify the given certificate list and return its status (TRUSTED, REVOKED etc.). 
526   * The return value (status) should be one or more of the gnutls_certificate_status 
527   * enumerated elements bitwise or'd. Note that expiration and activation dates are not checked 
528   * by this function, you should check them using the appropriate functions.
529   *
530   * If no flags are specified (0), this function will use the 
531   * basicConstraints (2.5.29.19) PKIX extension. This means that only a certificate 
532   * authority is allowed to sign a certificate.
533   *
534   * However you must also check the peer's name in order to check if the verified 
535   * certificate belongs to the actual peer. 
536   *
537   *
538   * The certificate verification output will be put in 'verify' and will be
539   * one or more of the gnutls_certificate_status enumerated elements bitwise or'd.
540   *
541   * GNUTLS_CERT_NOT_TRUSTED\: the peer's certificate is not trusted.
542   *
543   * GNUTLS_CERT_INVALID\: the certificate chain is broken.
544   *
545   * GNUTLS_CERT_REVOKED\: the certificate has been revoked.
546   *
547   * GNUTLS_CERT_CORRUPTED\: the certificate is corrupted.
548   *
549   * Returns 0 on success and a negative value in case of an error.
550   *
551   **/
552 int gnutls_x509_crt_list_verify( gnutls_x509_crt* cert_list, int cert_list_length, 
553         gnutls_x509_crt * CA_list, int CA_list_length, 
554         gnutls_x509_crl* CRL_list, int CRL_list_length, 
555         unsigned int flags, unsigned int *verify)
556 {
557         if (cert_list == NULL || cert_list_length == 0)
558                 return GNUTLS_E_NO_CERTIFICATE_FOUND;
559
560         /* Verify certificate 
561          */
562         *verify =
563             _gnutls_x509_verify_certificate( cert_list, cert_list_length,
564                 CA_list, CA_list_length, CRL_list, CRL_list_length, flags);
565
566         return 0;
567 }
568
569 /**
570   * gnutls_x509_crt_verify - This function verifies the given certificate against a given trusted one
571   * @cert: is the certificate to be verified
572   * @CA_list: is one certificate that is considered to be trusted one
573   * @CA_list_length: holds the number of CA certificate in CA_list
574   * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
575   * @verify: will hold the certificate verification output.
576   *
577   * This function will try to verify the given certificate and return its status. 
578   * See gnutls_x509_crt_list_verify() for a detailed description of
579   * return values.
580   *
581   * Returns 0 on success and a negative value in case of an error.
582   *
583   **/
584 int gnutls_x509_crt_verify( gnutls_x509_crt cert,
585         gnutls_x509_crt *CA_list, int CA_list_length,
586         unsigned int flags, unsigned int *verify)
587 {
588         /* Verify certificate 
589          */
590         *verify =
591             _gnutls_verify_certificate2( cert, CA_list, CA_list_length, flags);
592
593         return 0;
594 }
595
596 /**
597   * gnutls_x509_crt_check_issuer - This function checks if the certificate given has the given issuer
598   * @cert: is the certificate to be checked
599   * @issuer: is the certificate of a possible issuer
600   *
601   * This function will check if the given certificate was issued by the
602   * given issuer. It will return true (1) if the given certificate is issued
603   * by the given issuer, and false (0) if not.
604   *
605   * A negative value is returned in case of an error.
606   *
607   **/
608 int gnutls_x509_crt_check_issuer( gnutls_x509_crt cert,
609         gnutls_x509_crt issuer)
610 {
611         return is_issuer(cert, issuer);
612 }
613
614
615 #ifdef ENABLE_PKI
616
617 /**
618   * gnutls_x509_crl_check_issuer - This function checks if the CRL given has the given issuer
619   * @crl: is the CRL to be checked
620   * @issuer: is the certificate of a possible issuer
621   *
622   * This function will check if the given CRL was issued by the
623   * given issuer certificate. It will return true (1) if the given CRL was issued
624   * by the given issuer, and false (0) if not.
625   *
626   * A negative value is returned in case of an error.
627   *
628   **/
629 int gnutls_x509_crl_check_issuer( gnutls_x509_crl cert,
630         gnutls_x509_crt issuer)
631 {
632         return is_crl_issuer(cert, issuer);
633 }
634
635 /**
636   * gnutls_x509_crl_verify - This function verifies the given crl against a given trusted one
637   * @crl: is the crl to be verified
638   * @CA_list: is a certificate list that is considered to be trusted one
639   * @CA_list_length: holds the number of CA certificates in CA_list
640   * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
641   * @verify: will hold the crl verification output.
642   *
643   * This function will try to verify the given crl and return its status.
644   * See gnutls_x509_crt_list_verify() for a detailed description of
645   * return values.
646   *
647   * Returns 0 on success and a negative value in case of an error.
648   *
649   **/
650 int gnutls_x509_crl_verify( gnutls_x509_crl crl,
651         gnutls_x509_crt *CA_list, int CA_list_length,
652         unsigned int flags, unsigned int *verify)
653 {
654         /* Verify crl 
655          */
656         *verify =
657             _gnutls_verify_crl2( crl, CA_list, CA_list_length, flags);
658
659         return 0;
660 }
661
662
663 /* The same as above, but here we've got a CRL.
664  */
665 static
666 int is_crl_issuer(gnutls_x509_crl crl, gnutls_x509_crt issuer_cert)
667 {
668         gnutls_datum dn1 = {NULL, 0}, dn2 = {NULL, 0};
669         int ret;
670
671         ret = _gnutls_x509_crl_get_raw_issuer_dn( crl, &dn1);
672         if (ret < 0) {
673                 gnutls_assert();
674                 goto cleanup;
675         }
676
677         ret = _gnutls_x509_crt_get_raw_dn( issuer_cert, &dn2);
678         if (ret < 0) {
679                 gnutls_assert();
680                 return ret;
681         }
682
683         ret = _gnutls_x509_compare_raw_dn( &dn1, &dn2);
684         
685 cleanup:
686         _gnutls_free_datum( &dn1);
687         _gnutls_free_datum( &dn2);
688         
689         return ret;
690 }
691
692 static inline
693 gnutls_x509_crt find_crl_issuer(gnutls_x509_crl crl,
694                                 gnutls_x509_crt * trusted_cas, int tcas_size)
695 {
696         int i;
697
698         /* this is serial search. 
699          */
700
701         for (i = 0; i < tcas_size; i++) {
702                 if (is_crl_issuer(crl, trusted_cas[i]) == 1)
703                         return trusted_cas[i];
704         }
705
706         gnutls_assert();
707         return NULL;
708 }
709
710 /* 
711  * Returns only 0 or 1. If 1 it means that the CRL
712  * was successfuly verified.
713  *
714  * 'flags': an OR of the gnutls_certificate_verify_flags enumeration.
715  */
716 static int _gnutls_verify_crl2(gnutls_x509_crl crl,
717                                gnutls_x509_crt *trusted_cas, int tcas_size, 
718                                unsigned int flags)
719 {
720 /* CRL is ignored for now */
721 gnutls_datum crl_signed_data = { NULL, 0 };
722 gnutls_datum crl_signature = { NULL, 0 };
723 gnutls_x509_crt issuer;
724 int ret, result;
725
726         if (tcas_size >= 1)
727                 issuer = find_crl_issuer(crl, trusted_cas, tcas_size);
728         else {
729                 gnutls_assert();
730                 return 0;
731         }
732
733         /* issuer is not in trusted certificate
734          * authorities.
735          */
736         if (issuer == NULL) {
737                 gnutls_assert();
738                 return 0;
739         }
740
741         if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN)) {
742                 if (gnutls_x509_crt_get_ca_status(issuer, NULL) != 1) 
743                 {
744                         gnutls_assert();
745                         return 0;
746                 }
747         }
748
749         result = _gnutls_x509_get_signed_data( crl->crl, "tbsCertList", &crl_signed_data);
750         if (result < 0) {
751                 gnutls_assert();
752                 goto cleanup;
753         }
754
755         result = _gnutls_x509_get_signature( crl->crl, "signature", &crl_signature);
756         if (result < 0) {
757                 gnutls_assert();
758                 goto cleanup;
759         }
760
761
762         ret = _gnutls_x509_verify_signature(&crl_signed_data, &crl_signature, issuer);
763         if (ret < 0) {
764                 gnutls_assert();
765                 /* error. ignore it */
766                 ret = 0;
767         }
768
769         result = ret;
770         
771 cleanup:
772         _gnutls_free_datum( &crl_signed_data);
773         _gnutls_free_datum( &crl_signature);
774         
775         return result;
776 }
777
778 #endif