2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <gnutls_errors.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>
34 #include "verify-high.h"
36 struct named_cert_st {
37 gnutls_x509_crt_t cert;
38 uint8_t name[MAX_SERVER_NAME_SIZE];
39 unsigned int name_size;
43 /* The trusted certificates */
44 gnutls_x509_crt_t *trusted_cas;
45 unsigned int trusted_ca_size;
47 struct named_cert_st *named_certs;
48 unsigned int named_cert_size;
50 /* The trusted CRLs */
51 gnutls_x509_crl_t *crls;
52 unsigned int crl_size;
56 struct gnutls_x509_trust_list_st {
60 gnutls_x509_crt_t *blacklisted;
61 unsigned int blacklisted_size;
64 #define DEFAULT_SIZE 127
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.
71 * This function will initialize an X.509 trust list structure.
73 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
74 * negative error value.
79 gnutls_x509_trust_list_init(gnutls_x509_trust_list_t * list,
82 gnutls_x509_trust_list_t tmp;
87 gnutls_calloc(1, sizeof(struct gnutls_x509_trust_list_st));
90 return GNUTLS_E_MEMORY_ERROR;
96 tmp->node = gnutls_calloc(1, tmp->size * sizeof(tmp->node[0]));
97 if (tmp->node == NULL) {
100 return GNUTLS_E_MEMORY_ERROR;
105 return 0; /* success */
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.
113 * This function will deinitialize a trust list.
118 gnutls_x509_trust_list_deinit(gnutls_x509_trust_list_t list,
126 for (j = 0; j < list->blacklisted_size; j++) {
127 gnutls_x509_crt_deinit(list->blacklisted[j]);
129 gnutls_free(list->blacklisted);
131 for (i = 0; i < list->size; i++) {
133 for (j = 0; j < list->node[i].trusted_ca_size; j++) {
134 gnutls_x509_crt_deinit(list->node[i].
137 gnutls_free(list->node[i].trusted_cas);
141 for (j = 0; j < list->node[i].crl_size; j++) {
142 gnutls_x509_crl_deinit(list->node[i].
145 gnutls_free(list->node[i].crls);
148 for (j = 0; j < list->node[i].named_cert_size; j++) {
149 gnutls_x509_crt_deinit(list->node[i].
153 gnutls_free(list->node[i].named_certs);
156 gnutls_free(list->node);
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.
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.
171 * Returns: The number of added elements is returned.
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)
183 for (i = 0; i < clist_size; i++) {
185 hash_pjw_bare(clist[i]->raw_dn.data,
186 clist[i]->raw_dn.size);
189 list->node[hash].trusted_cas =
190 gnutls_realloc_fast(list->node[hash].trusted_cas,
191 (list->node[hash].trusted_ca_size +
193 sizeof(list->node[hash].
195 if (list->node[hash].trusted_cas == NULL) {
200 list->node[hash].trusted_cas[list->node[hash].
201 trusted_ca_size] = clist[i];
202 list->node[hash].trusted_ca_size++;
208 static gnutls_x509_crt_t crt_cpy(gnutls_x509_crt_t src)
210 gnutls_x509_crt_t dst;
213 ret = gnutls_x509_crt_init(&dst);
219 ret = _gnutls_x509_crt_cpy(dst, src);
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
234 * This function will remove the given certificate authorities
235 * from the trusted list.
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.
243 * Returns: The number of removed elements is returned.
248 gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list,
249 const gnutls_x509_crt_t * clist,
256 for (i = 0; i < clist_size; i++) {
258 hash_pjw_bare(clist[i]->raw_dn.data,
259 clist[i]->raw_dn.size);
262 for (j = 0; j < list->node[hash].trusted_ca_size; j++) {
263 if (_gnutls_check_if_same_cert
265 list->node[hash].trusted_cas[j]) != 0) {
267 fprintf(stderr, "removing CA with hash %.4x\n", (unsigned)hash);
268 gnutls_x509_crt_deinit(list->node[hash].
270 list->node[hash].trusted_cas[j] =
271 list->node[hash].trusted_cas[list->
276 list->node[hash].trusted_ca_size--;
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.
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);
293 list->blacklisted[list->blacklisted_size] = crt_cpy(clist[i]);
294 if (list->blacklisted[list->blacklisted_size] != NULL)
295 list->blacklisted_size++;
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.
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().
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.
318 * The certificate must not be deinitialized during the lifetime
319 * of the trusted list.
321 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
322 * negative error value.
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,
334 if (name_size >= MAX_SERVER_NAME_SIZE)
335 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
338 hash_pjw_bare(cert->raw_issuer_dn.data,
339 cert->raw_issuer_dn.size);
342 list->node[hash].named_certs =
343 gnutls_realloc_fast(list->node[hash].named_certs,
344 (list->node[hash].named_cert_size +
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);
350 list->node[hash].named_certs[list->node[hash].named_cert_size].
352 memcpy(list->node[hash].
353 named_certs[list->node[hash].named_cert_size].name, name,
355 list->node[hash].named_certs[list->node[hash].
356 named_cert_size].name_size =
359 list->node[hash].named_cert_size++;
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
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.
376 * This function must be called after gnutls_x509_trust_list_add_cas()
377 * to allow verifying the CRLs for validity.
379 * Returns: The number of added elements is returned.
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)
390 unsigned int vret = 0;
393 /* Probably we can optimize things such as removing duplicates
396 if (crl_size == 0 || crl_list == NULL)
399 for (i = 0; i < crl_size; i++) {
401 hash_pjw_bare(crl_list[i]->raw_issuer_dn.data,
402 crl_list[i]->raw_issuer_dn.size);
405 if (flags & GNUTLS_TL_VERIFY_CRL) {
408 gnutls_x509_crl_verify(crl_list[i],
415 if (ret < 0 || vret != 0)
419 list->node[hash].crls =
420 gnutls_realloc_fast(list->node[hash].crls,
421 (list->node[hash].crl_size +
423 sizeof(list->node[hash].
425 if (list->node[hash].crls == NULL) {
430 list->node[hash].crls[list->node[hash].crl_size] =
432 list->node[hash].crl_size++;
439 /* Takes a certificate list and shortens it if there are
440 * intermedia certificates already trusted by us.
442 * FIXME: This is very similar to _gnutls_x509_verify_certificate().
444 * Returns the new size of the list or a negative number on error.
446 static int shorten_clist(gnutls_x509_trust_list_t list,
447 gnutls_x509_crt_t * certificate_list,
448 unsigned int clist_size)
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).
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
463 if (gnutls_x509_crt_check_issuer
464 (certificate_list[clist_size - 1],
465 certificate_list[clist_size - 1]) != 0) {
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
475 for (i = 1; i < clist_size; i++) {
477 hash_pjw_bare(certificate_list[i]->raw_issuer_dn.data,
478 certificate_list[i]->raw_issuer_dn.size);
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 */
490 /* clist_size may have been changed which gets out of loop */
496 /* Takes a certificate list and orders it with subject, issuer order.
498 * *clist_size contains the size of the ordered list (which is always less or
499 * equal to the original).
501 * Returns the sorted list which may be the original clist.
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)
510 int issuer[DEFAULT_MAX_VERIFY_DEPTH]; /* contain the index of the issuers */
512 /* Do not bother sorting if too many certificates are given.
513 * Prevent any DoS attacks.
515 if (*clist_size > DEFAULT_MAX_VERIFY_DEPTH)
518 for (i = 0; i < DEFAULT_MAX_VERIFY_DEPTH; i++)
521 /* Find the issuer of each certificate and store it
524 for (i = 0; i < *clist_size; i++) {
525 for (j = 1; j < *clist_size; j++) {
529 if (gnutls_x509_crt_check_issuer(clist[i],
537 if (issuer[0] == -1) {
543 sorted[0] = clist[0];
544 for (i = 1; i < *clist_size; i++) {
546 if (prev == -1) { /* no issuer */
550 sorted[i] = clist[prev];
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.
563 * This function will attempt to find the issuer of the
566 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
567 * negative error value.
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,
581 hash_pjw_bare(cert->raw_issuer_dn.data,
582 cert->raw_issuer_dn.size);
585 for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
587 gnutls_x509_crt_check_issuer(cert,
591 *issuer = list->node[hash].trusted_cas[i];
596 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
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)
605 if (blacklist_size == 0)
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) {
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.
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.
632 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
633 * negative error value.
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,
642 unsigned int *verify,
643 gnutls_verify_output_function func)
648 gnutls_x509_crt_t sorted[DEFAULT_MAX_VERIFY_DEPTH];
650 if (cert_list == NULL || cert_list_size < 1)
651 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
653 if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN))
654 cert_list = sort_clist(sorted, cert_list, &cert_list_size);
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);
661 hash_pjw_bare(cert_list[cert_list_size - 1]->raw_issuer_dn.
663 cert_list[cert_list_size -
664 1]->raw_issuer_dn.size);
667 ret = check_if_in_blacklist(cert_list, cert_list_size,
668 list->blacklisted, list->blacklisted_size);
670 *verify |= GNUTLS_CERT_REVOKED;
671 *verify |= GNUTLS_CERT_INVALID;
676 _gnutls_x509_verify_certificate(cert_list, cert_list_size,
677 list->node[hash].trusted_cas,
679 node[hash].trusted_ca_size,
682 if (*verify != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS))
685 /* Check revocation of individual certificates.
686 * start with the last one that we already have its hash
689 _gnutls_x509_crt_check_revocation(cert_list
690 [cert_list_size - 1],
691 list->node[hash].crls,
692 list->node[hash].crl_size,
694 if (ret == 1) { /* revoked */
695 *verify |= GNUTLS_CERT_REVOKED;
696 *verify |= GNUTLS_CERT_INVALID;
700 for (i = 0; i < cert_list_size - 1; i++) {
702 hash_pjw_bare(cert_list[i]->raw_issuer_dn.data,
703 cert_list[i]->raw_issuer_dn.size);
706 ret = _gnutls_x509_crt_check_revocation(cert_list[i],
711 if (ret == 1) { /* revoked */
712 *verify |= GNUTLS_CERT_REVOKED;
713 *verify |= GNUTLS_CERT_INVALID;
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.
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.
736 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
737 * negative error value.
742 gnutls_x509_trust_list_verify_named_crt(gnutls_x509_trust_list_t list,
743 gnutls_x509_crt_t cert,
747 unsigned int *verify,
748 gnutls_verify_output_function func)
755 hash_pjw_bare(cert->raw_issuer_dn.data,
756 cert->raw_issuer_dn.size);
759 *verify = GNUTLS_CERT_INVALID | GNUTLS_CERT_SIGNER_NOT_FOUND;
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 ==
765 && memcmp(list->node[hash].named_certs[i].name,
766 name, name_size) == 0) {
773 if (*verify != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS))
776 /* Check revocation of individual certificates.
777 * start with the last one that we already have its hash
779 ret = _gnutls_x509_crt_check_revocation(cert,
780 list->node[hash].crls,
781 list->node[hash].crl_size,
783 if (ret == 1) { /* revoked */
784 *verify |= GNUTLS_CERT_REVOKED;
785 *verify |= GNUTLS_CERT_INVALID;
792 /* return 1 if @cert is in @list, 0 if not */
794 _gnutls_trustlist_inlist(gnutls_x509_trust_list_t list,
795 gnutls_x509_crt_t cert)
801 hash = hash_pjw_bare(cert->raw_dn.data, cert->raw_dn.size);
804 for (i = 0; i < list->node[hash].trusted_ca_size; i++) {
806 _gnutls_check_if_same_cert(cert,