gnutls_x509_trust_list_remove_cas() and derivatives will utilize a black list.
[gnutls:gnutls.git] / lib / x509 / verify-high.c
1 /*
2  * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
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 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 License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>
20  *
21  */
22
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <libtasn1.h>
26 #include <gnutls_global.h>
27 #include <gnutls_num.h>         /* MAX */
28 #include <gnutls_sig.h>
29 #include <gnutls_str.h>
30 #include <gnutls_datum.h>
31 #include <hash-pjw-bare.h>
32 #include "x509_int.h"
33 #include <common.h>
34 #include "verify-high.h"
35
36 struct named_cert_st {
37         gnutls_x509_crt_t cert;
38         uint8_t name[MAX_SERVER_NAME_SIZE];
39         unsigned int name_size;
40 };
41
42 struct node_st {
43         /* The trusted certificates */
44         gnutls_x509_crt_t *trusted_cas;
45         unsigned int trusted_ca_size;
46
47         struct named_cert_st *named_certs;
48         unsigned int named_cert_size;
49
50         /* The trusted CRLs */
51         gnutls_x509_crl_t *crls;
52         unsigned int crl_size;
53
54 };
55
56 struct gnutls_x509_trust_list_st {
57         unsigned int size;
58         struct node_st *node;
59
60         gnutls_x509_crt_t *blacklisted;
61         unsigned int blacklisted_size;
62 };
63
64 #define DEFAULT_SIZE 127
65
66 /**
67  * gnutls_x509_trust_list_init:
68  * @list: The structure to be initialized
69  * @size: The size of the internal hash table. Use (0) for default size.
70  *
71  * This function will initialize an X.509 trust list structure.
72  *
73  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
74  *   negative error value.
75  *
76  * Since: 3.0
77  **/
78 int
79 gnutls_x509_trust_list_init(gnutls_x509_trust_list_t * list,
80                             unsigned int size)
81 {
82         gnutls_x509_trust_list_t tmp;
83         
84         FAIL_IF_LIB_ERROR;
85         
86         tmp =
87             gnutls_calloc(1, sizeof(struct gnutls_x509_trust_list_st));
88
89         if (!tmp)
90                 return GNUTLS_E_MEMORY_ERROR;
91
92         if (size == 0)
93                 size = DEFAULT_SIZE;
94         tmp->size = size;
95
96         tmp->node = gnutls_calloc(1, tmp->size * sizeof(tmp->node[0]));
97         if (tmp->node == NULL) {
98                 gnutls_assert();
99                 gnutls_free(tmp);
100                 return GNUTLS_E_MEMORY_ERROR;
101         }
102
103         *list = tmp;
104
105         return 0;               /* success */
106 }
107
108 /**
109  * gnutls_x509_trust_list_deinit:
110  * @list: The structure to be deinitialized
111  * @all: if non-(0) it will deinitialize all the certificates and CRLs contained in the structure.
112  *
113  * This function will deinitialize a trust list.
114  *
115  * Since: 3.0
116  **/
117 void
118 gnutls_x509_trust_list_deinit(gnutls_x509_trust_list_t list,
119                               unsigned int all)
120 {
121         unsigned int i, j;
122
123         if (!list)
124                 return;
125
126         for (j = 0; j < list->blacklisted_size; j++) {
127                 gnutls_x509_crt_deinit(list->blacklisted[j]);
128         }
129         gnutls_free(list->blacklisted);
130
131         for (i = 0; i < list->size; i++) {
132                 if (all)
133                         for (j = 0; j < list->node[i].trusted_ca_size; j++) {
134                                 gnutls_x509_crt_deinit(list->node[i].
135                                                        trusted_cas[j]);
136                         }
137                 gnutls_free(list->node[i].trusted_cas);
138
139
140                 if (all)
141                         for (j = 0; j < list->node[i].crl_size; j++) {
142                                 gnutls_x509_crl_deinit(list->node[i].
143                                                        crls[j]);
144                         }
145                 gnutls_free(list->node[i].crls);
146
147                 if (all)
148                         for (j = 0; j < list->node[i].named_cert_size; j++) {
149                                 gnutls_x509_crt_deinit(list->node[i].
150                                                        named_certs[j].
151                                                        cert);
152                         }
153                 gnutls_free(list->node[i].named_certs);
154         }
155
156         gnutls_free(list->node);
157         gnutls_free(list);
158 }
159
160 /**
161  * gnutls_x509_trust_list_add_cas:
162  * @list: The structure of the list
163  * @clist: A list of CAs
164  * @clist_size: The length of the CA list
165  * @flags: should be 0.
166  *
167  * This function will add the given certificate authorities
168  * to the trusted list. The list of CAs must not be deinitialized
169  * during this structure's lifetime.
170  *
171  * Returns: The number of added elements is returned.
172  *
173  * Since: 3.0
174  **/
175 int
176 gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list,
177                                const gnutls_x509_crt_t * clist,
178                                int clist_size, unsigned int flags)
179 {
180         int i;
181         uint32_t hash;
182
183         for (i = 0; i < clist_size; i++) {
184                 hash =
185                     hash_pjw_bare(clist[i]->raw_dn.data,
186                                   clist[i]->raw_dn.size);
187                 hash %= list->size;
188
189                 list->node[hash].trusted_cas =
190                     gnutls_realloc_fast(list->node[hash].trusted_cas,
191                                         (list->node[hash].trusted_ca_size +
192                                          1) *
193                                         sizeof(list->node[hash].
194                                                trusted_cas[0]));
195                 if (list->node[hash].trusted_cas == NULL) {
196                         gnutls_assert();
197                         return i;
198                 }
199
200                 list->node[hash].trusted_cas[list->node[hash].
201                                              trusted_ca_size] = clist[i];
202                 list->node[hash].trusted_ca_size++;
203         }
204
205         return i;
206 }
207
208 static gnutls_x509_crt_t crt_cpy(gnutls_x509_crt_t src)
209 {
210 gnutls_x509_crt_t dst;
211 int ret;
212
213         ret = gnutls_x509_crt_init(&dst);
214         if (ret < 0) {
215                 gnutls_assert();
216                 return NULL;
217         }
218         
219         ret = _gnutls_x509_crt_cpy(dst, src);
220         if (ret < 0) {
221                 gnutls_assert();
222                 return NULL;
223         }
224         
225         return dst;
226 }
227
228 /**
229  * gnutls_x509_trust_list_remove_cas:
230  * @list: The structure of the list
231  * @clist: A list of CAs
232  * @clist_size: The length of the CA list
233  *
234  * This function will remove the given certificate authorities
235  * from the trusted list.
236  *
237  * Note that this function can accept certificates and authorities
238  * not yet known. In that case they will be kept in a separate
239  * black list that will be used during certificate verification.
240  * Unlike gnutls_x509_trust_list_add_cas() there is no deinitialization
241  * restriction for  certificate list provided in this function.
242  *
243  * Returns: The number of removed elements is returned.
244  *
245  * Since: 3.1.10
246  **/
247 int
248 gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list,
249                                   const gnutls_x509_crt_t * clist,
250                                   int clist_size)
251 {
252         int i, r = 0;
253         unsigned j;
254         uint32_t hash;
255
256         for (i = 0; i < clist_size; i++) {
257                 hash =
258                     hash_pjw_bare(clist[i]->raw_dn.data,
259                                   clist[i]->raw_dn.size);
260                 hash %= list->size;
261
262                 for (j = 0; j < list->node[hash].trusted_ca_size; j++) {
263                         if (_gnutls_check_if_same_cert
264                             (clist[i],
265                              list->node[hash].trusted_cas[j]) != 0) {
266
267                                 fprintf(stderr, "removing CA with hash %.4x\n", (unsigned)hash);
268                                 gnutls_x509_crt_deinit(list->node[hash].
269                                                        trusted_cas[j]);
270                                 list->node[hash].trusted_cas[j] =
271                                     list->node[hash].trusted_cas[list->
272                                                                  node
273                                                                  [hash].
274                                                                  trusted_ca_size
275                                                                  - 1];
276                                 list->node[hash].trusted_ca_size--;
277                                 r++;
278                                 break;
279                         }
280                 }
281                 
282                 /* Add the CA (or plain) certificate to the black list as well.
283                  * This will prevent a subordinate CA from being valid, and 
284                  * ensure that a server certificate will also get rejected.
285                  */
286                 list->blacklisted =
287                     gnutls_realloc_fast(list->blacklisted,
288                                 (list->blacklisted_size + 1) *
289                                 sizeof(list->blacklisted[0]));
290                 if (list->blacklisted == NULL)
291                         return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
292
293                 list->blacklisted[list->blacklisted_size] = crt_cpy(clist[i]);
294                 if (list->blacklisted[list->blacklisted_size] != NULL)
295                         list->blacklisted_size++;
296         }
297
298         return r;
299 }
300
301 /**
302  * gnutls_x509_trust_list_add_named_crt:
303  * @list: The structure of the list
304  * @cert: A certificate
305  * @name: An identifier for the certificate
306  * @name_size: The size of the identifier
307  * @flags: should be 0.
308  *
309  * This function will add the given certificate to the trusted
310  * list and associate it with a name. The certificate will not be
311  * be used for verification with gnutls_x509_trust_list_verify_crt()
312  * but only with gnutls_x509_trust_list_verify_named_crt().
313  *
314  * In principle this function can be used to set individual "server"
315  * certificates that are trusted by the user for that specific server
316  * but for no other purposes.
317  *
318  * The certificate must not be deinitialized during the lifetime
319  * of the trusted list.
320  *
321  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
322  *   negative error value.
323  *
324  * Since: 3.0
325  **/
326 int
327 gnutls_x509_trust_list_add_named_crt(gnutls_x509_trust_list_t list,
328                                      gnutls_x509_crt_t cert,
329                                      const void *name, size_t name_size,
330                                      unsigned int flags)
331 {
332         uint32_t hash;
333
334         if (name_size >= MAX_SERVER_NAME_SIZE)
335                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
336
337         hash =
338             hash_pjw_bare(cert->raw_issuer_dn.data,
339                           cert->raw_issuer_dn.size);
340         hash %= list->size;
341
342         list->node[hash].named_certs =
343             gnutls_realloc_fast(list->node[hash].named_certs,
344                                 (list->node[hash].named_cert_size +
345                                  1) *
346                                 sizeof(list->node[hash].named_certs[0]));
347         if (list->node[hash].named_certs == NULL)
348                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
349
350         list->node[hash].named_certs[list->node[hash].named_cert_size].
351             cert = cert;
352         memcpy(list->node[hash].
353                named_certs[list->node[hash].named_cert_size].name, name,
354                name_size);
355         list->node[hash].named_certs[list->node[hash].
356                                      named_cert_size].name_size =
357             name_size;
358
359         list->node[hash].named_cert_size++;
360
361         return 0;
362 }
363
364 /**
365  * gnutls_x509_trust_list_add_crls:
366  * @list: The structure of the list
367  * @crl_list: A list of CRLs
368  * @crl_size: The length of the CRL list
369  * @flags: if GNUTLS_TL_VERIFY_CRL is given the CRLs will be verified before being added.
370  * @verification_flags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL
371  *
372  * This function will add the given certificate revocation lists
373  * to the trusted list. The list of CRLs must not be deinitialized
374  * during this structure's lifetime.
375  *
376  * This function must be called after gnutls_x509_trust_list_add_cas()
377  * to allow verifying the CRLs for validity.
378  *
379  * Returns: The number of added elements is returned.
380  *
381  * Since: 3.0
382  **/
383 int
384 gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list,
385                                 const gnutls_x509_crl_t * crl_list,
386                                 int crl_size, unsigned int flags,
387                                 unsigned int verification_flags)
388 {
389         int ret, i, j = 0;
390         unsigned int vret = 0;
391         uint32_t hash;
392
393         /* Probably we can optimize things such as removing duplicates
394          * etc.
395          */
396         if (crl_size == 0 || crl_list == NULL)
397                 return 0;
398
399         for (i = 0; i < crl_size; i++) {
400                 hash =
401                     hash_pjw_bare(crl_list[i]->raw_issuer_dn.data,
402                                   crl_list[i]->raw_issuer_dn.size);
403                 hash %= list->size;
404
405                 if (flags & GNUTLS_TL_VERIFY_CRL) {
406
407                         ret =
408                             gnutls_x509_crl_verify(crl_list[i],
409                                                    list->node[hash].
410                                                    trusted_cas,
411                                                    list->node[hash].
412                                                    trusted_ca_size,
413                                                    verification_flags,
414                                                    &vret);
415                         if (ret < 0 || vret != 0)
416                                 continue;
417                 }
418
419                 list->node[hash].crls =
420                     gnutls_realloc_fast(list->node[hash].crls,
421                                         (list->node[hash].crl_size +
422                                          1) *
423                                         sizeof(list->node[hash].
424                                                trusted_cas[0]));
425                 if (list->node[hash].crls == NULL) {
426                         gnutls_assert();
427                         return i;
428                 }
429
430                 list->node[hash].crls[list->node[hash].crl_size] =
431                     crl_list[i];
432                 list->node[hash].crl_size++;
433                 j++;
434         }
435
436         return j;
437 }
438
439 /* Takes a certificate list and shortens it if there are
440  * intermedia certificates already trusted by us.
441  *
442  * FIXME: This is very similar to _gnutls_x509_verify_certificate().
443  *
444  * Returns the new size of the list or a negative number on error.
445  */
446 static int shorten_clist(gnutls_x509_trust_list_t list,
447                          gnutls_x509_crt_t * certificate_list,
448                          unsigned int clist_size)
449 {
450         unsigned int j, i;
451         uint32_t hash;
452
453         if (clist_size > 1) {
454                 /* Check if the last certificate in the path is self signed.
455                  * In that case ignore it (a certificate is trusted only if it
456                  * leads to a trusted party by us, not the server's).
457                  *
458                  * This prevents from verifying self signed certificates against
459                  * themselves. This (although not bad) caused verification
460                  * failures on some root self signed certificates that use the
461                  * MD2 algorithm.
462                  */
463                 if (gnutls_x509_crt_check_issuer
464                     (certificate_list[clist_size - 1],
465                      certificate_list[clist_size - 1]) != 0) {
466                         clist_size--;
467                 }
468         }
469
470         /* We want to shorten the chain by removing the cert that matches
471          * one of the certs we trust and all the certs after that i.e. if
472          * cert chain is A signed-by B signed-by C signed-by D (signed-by
473          * self-signed E but already removed above), and we trust B, remove
474          * B, C and D. */
475         for (i = 1; i < clist_size; i++) {
476                 hash =
477                     hash_pjw_bare(certificate_list[i]->raw_issuer_dn.data,
478                                   certificate_list[i]->raw_issuer_dn.size);
479                 hash %= list->size;
480
481                 for (j = 0; j < list->node[hash].trusted_ca_size; j++) {
482                         if (_gnutls_check_if_same_cert
483                             (certificate_list[i],
484                              list->node[hash].trusted_cas[j]) != 0) {
485                                 /* cut the list at the point of first the trusted certificate */
486                                 clist_size = i + 1;
487                                 break;
488                         }
489                 }
490                 /* clist_size may have been changed which gets out of loop */
491         }
492
493         return clist_size;
494 }
495
496 /* Takes a certificate list and orders it with subject, issuer order.
497  *
498  * *clist_size contains the size of the ordered list (which is always less or
499  * equal to the original).
500  *
501  * Returns the sorted list which may be the original clist.
502  */
503 static gnutls_x509_crt_t *sort_clist(gnutls_x509_crt_t
504                                      sorted[DEFAULT_MAX_VERIFY_DEPTH],
505                                      gnutls_x509_crt_t * clist,
506                                      unsigned int *clist_size)
507 {
508         int prev;
509         unsigned int j, i;
510         int issuer[DEFAULT_MAX_VERIFY_DEPTH];   /* contain the index of the issuers */
511
512         /* Do not bother sorting if too many certificates are given.
513          * Prevent any DoS attacks.
514          */
515         if (*clist_size > DEFAULT_MAX_VERIFY_DEPTH)
516                 return clist;
517
518         for (i = 0; i < DEFAULT_MAX_VERIFY_DEPTH; i++)
519                 issuer[i] = -1;
520
521         /* Find the issuer of each certificate and store it
522          * in issuer array.
523          */
524         for (i = 0; i < *clist_size; i++) {
525                 for (j = 1; j < *clist_size; j++) {
526                         if (i == j)
527                                 continue;
528
529                         if (gnutls_x509_crt_check_issuer(clist[i],
530                                                          clist[j]) != 0) {
531                                 issuer[i] = j;
532                                 break;
533                         }
534                 }
535         }
536
537         if (issuer[0] == -1) {
538                 *clist_size = 1;
539                 return clist;
540         }
541
542         prev = 0;
543         sorted[0] = clist[0];
544         for (i = 1; i < *clist_size; i++) {
545                 prev = issuer[prev];
546                 if (prev == -1) {       /* no issuer */
547                         *clist_size = i;
548                         break;
549                 }
550                 sorted[i] = clist[prev];
551         }
552
553         return sorted;
554 }
555
556 /**
557  * gnutls_x509_trust_list_get_issuer:
558  * @list: The structure of the list
559  * @cert: is the certificate to find issuer for
560  * @issuer: Will hold the issuer if any. Should be treated as constant.
561  * @flags: Use (0).
562  *
563  * This function will attempt to find the issuer of the
564  * given certificate.
565  *
566  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
567  *   negative error value.
568  *
569  * Since: 3.0
570  **/
571 int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t list,
572                                       gnutls_x509_crt_t cert,
573                                       gnutls_x509_crt_t * issuer,
574                                       unsigned int flags)
575 {
576         int ret;
577         unsigned int i;
578         uint32_t hash;
579
580         hash =
581             hash_pjw_bare(cert->raw_issuer_dn.data,
582                           cert->raw_issuer_dn.size);
583         hash %= list->size;
584
585         for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
586                 ret =
587                     gnutls_x509_crt_check_issuer(cert,
588                                                  list->node[hash].
589                                                  trusted_cas[i]);
590                 if (ret != 0) {
591                         *issuer = list->node[hash].trusted_cas[i];
592                         return 0;
593                 }
594         }
595
596         return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
597 }
598
599 static
600 int check_if_in_blacklist(gnutls_x509_crt_t * cert_list, unsigned int cert_list_size,
601         gnutls_x509_crt_t * blacklist, unsigned int blacklist_size)
602 {
603 unsigned i, j;
604
605         if (blacklist_size == 0)
606                 return 0;
607         
608         for (i=0;i<cert_list_size;i++) {
609                 for (j=0;j<blacklist_size;j++) {
610                         if (_gnutls_check_if_same_cert(cert_list[i], blacklist[j]) != 0) {
611                                 return 1;
612                         }
613                 }
614         }
615
616         return 0;
617 }
618
619 /**
620  * gnutls_x509_trust_list_verify_crt:
621  * @list: The structure of the list
622  * @cert_list: is the certificate list to be verified
623  * @cert_list_size: is the certificate list size
624  * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
625  * @verify: will hold the certificate verification output.
626  * @func: If non-null will be called on each chain element verification with the output.
627  *
628  * This function will try to verify the given certificate and return
629  * its status. The @verify parameter will hold an OR'ed sequence of
630  * %gnutls_certificate_status_t flags.
631  *
632  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
633  *   negative error value.
634  *
635  * Since: 3.0
636  **/
637 int
638 gnutls_x509_trust_list_verify_crt(gnutls_x509_trust_list_t list,
639                                   gnutls_x509_crt_t * cert_list,
640                                   unsigned int cert_list_size,
641                                   unsigned int flags,
642                                   unsigned int *verify,
643                                   gnutls_verify_output_function func)
644 {
645         int ret;
646         unsigned int i;
647         uint32_t hash;
648         gnutls_x509_crt_t sorted[DEFAULT_MAX_VERIFY_DEPTH];
649
650         if (cert_list == NULL || cert_list_size < 1)
651                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
652
653         if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN))
654                 cert_list = sort_clist(sorted, cert_list, &cert_list_size);
655
656         cert_list_size = shorten_clist(list, cert_list, cert_list_size);
657         if (cert_list_size <= 0)
658                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
659
660         hash =
661             hash_pjw_bare(cert_list[cert_list_size - 1]->raw_issuer_dn.
662                           data,
663                           cert_list[cert_list_size -
664                                     1]->raw_issuer_dn.size);
665         hash %= list->size;
666
667         ret = check_if_in_blacklist(cert_list, cert_list_size,
668                 list->blacklisted, list->blacklisted_size);
669         if (ret != 0) {
670                 *verify |= GNUTLS_CERT_REVOKED;
671                 *verify |= GNUTLS_CERT_INVALID;
672                 return 0;
673         }
674
675         *verify =
676             _gnutls_x509_verify_certificate(cert_list, cert_list_size,
677                                             list->node[hash].trusted_cas,
678                                             list->
679                                             node[hash].trusted_ca_size,
680                                             flags, func);
681
682         if (*verify != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS))
683                 return 0;
684
685         /* Check revocation of individual certificates.
686          * start with the last one that we already have its hash
687          */
688         ret =
689             _gnutls_x509_crt_check_revocation(cert_list
690                                               [cert_list_size - 1],
691                                               list->node[hash].crls,
692                                               list->node[hash].crl_size,
693                                               func);
694         if (ret == 1) {         /* revoked */
695                 *verify |= GNUTLS_CERT_REVOKED;
696                 *verify |= GNUTLS_CERT_INVALID;
697                 return 0;
698         }
699
700         for (i = 0; i < cert_list_size - 1; i++) {
701                 hash =
702                     hash_pjw_bare(cert_list[i]->raw_issuer_dn.data,
703                                   cert_list[i]->raw_issuer_dn.size);
704                 hash %= list->size;
705
706                 ret = _gnutls_x509_crt_check_revocation(cert_list[i],
707                                                         list->node[hash].
708                                                         crls,
709                                                         list->node[hash].
710                                                         crl_size, func);
711                 if (ret == 1) { /* revoked */
712                         *verify |= GNUTLS_CERT_REVOKED;
713                         *verify |= GNUTLS_CERT_INVALID;
714                         return 0;
715                 }
716         }
717
718         return 0;
719 }
720
721 /**
722  * gnutls_x509_trust_list_verify_named_crt:
723  * @list: The structure of the list
724  * @cert: is the certificate to be verified
725  * @name: is the certificate's name
726  * @name_size: is the certificate's name size
727  * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
728  * @verify: will hold the certificate verification output.
729  * @func: If non-null will be called on each chain element verification with the output.
730  *
731  * This function will try to find a certificate that is associated with the provided 
732  * name --see gnutls_x509_trust_list_add_named_crt(). If a match is found the certificate is considered valid. In addition to that
733  * this function will also check CRLs. The @verify parameter will hold an OR'ed sequence of
734  * %gnutls_certificate_status_t flags.
735  *
736  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
737  *   negative error value.
738  *
739  * Since: 3.0
740  **/
741 int
742 gnutls_x509_trust_list_verify_named_crt(gnutls_x509_trust_list_t list,
743                                         gnutls_x509_crt_t cert,
744                                         const void *name,
745                                         size_t name_size,
746                                         unsigned int flags,
747                                         unsigned int *verify,
748                                         gnutls_verify_output_function func)
749 {
750         int ret;
751         unsigned int i;
752         uint32_t hash;
753
754         hash =
755             hash_pjw_bare(cert->raw_issuer_dn.data,
756                           cert->raw_issuer_dn.size);
757         hash %= list->size;
758
759         *verify = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND;
760
761         for (i = 0; i < list->node[hash].named_cert_size; i++) {
762                 if (_gnutls_check_if_same_cert(cert, list->node[hash].named_certs[i].cert) != 0) {      /* check if name matches */
763                         if (list->node[hash].named_certs[i].name_size ==
764                             name_size
765                             && memcmp(list->node[hash].named_certs[i].name,
766                                       name, name_size) == 0) {
767                                 *verify = 0;
768                                 break;
769                         }
770                 }
771         }
772
773         if (*verify != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS))
774                 return 0;
775
776         /* Check revocation of individual certificates.
777          * start with the last one that we already have its hash
778          */
779         ret = _gnutls_x509_crt_check_revocation(cert,
780                                                 list->node[hash].crls,
781                                                 list->node[hash].crl_size,
782                                                 func);
783         if (ret == 1) {         /* revoked */
784                 *verify |= GNUTLS_CERT_REVOKED;
785                 *verify |= GNUTLS_CERT_INVALID;
786                 return 0;
787         }
788
789         return 0;
790 }
791
792 /* return 1 if @cert is in @list, 0 if not */
793 int
794 _gnutls_trustlist_inlist(gnutls_x509_trust_list_t list,
795                          gnutls_x509_crt_t cert)
796 {
797         int ret;
798         unsigned int i;
799         uint32_t hash;
800
801         hash = hash_pjw_bare(cert->raw_dn.data, cert->raw_dn.size);
802         hash %= list->size;
803
804         for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
805                 ret =
806                     _gnutls_check_if_same_cert(cert,
807                                                list->node[hash].
808                                                trusted_cas[i]);
809                 if (ret != 0)
810                         return 1;
811         }
812
813         return 0;
814 }