1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 * GIO - GLib Input, Output and Streaming Library
5 * Copyright 2010 Collabora, Ltd
6 * Copyright 2018 Igalia S.L.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but 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
19 * Public License along with this library; if not, see
20 * <http://www.gnu.org/licenses/>.
22 * In addition, when the library is used with OpenSSL, a special
23 * exception applies. Refer to the LICENSE_EXCEPTION file for details.
25 * Author: Stef Walter <stefw@collabora.co.uk>
30 #include "gtlsdatabase-gnutls.h"
33 #include <glib/gi18n-lib.h>
34 #include <gnutls/x509.h>
36 #include "gtlscertificate-gnutls.h"
38 #include "gtlsgnutls-version.h"
43 * This class is protected by mutex because the default GTlsDatabase
44 * is a global singleton, accessible via the default GTlsBackend.
48 /* Read-only after construct, but still has to be protected by the mutex. */
49 gnutls_x509_trust_list_t trust_list;
52 * These are hash tables of GBytes -> GPtrArray<GBytes>. The values of
53 * the ptr array are full DER encoded certificate values. The keys are byte
54 * arrays containing either subject DNs, issuer DNs, or full DER encoded certs
60 * This is a table of GBytes -> GBytes. The values and keys are
61 * DER encoded certificate values.
66 * This is a table of gchar * -> GPtrArray<GBytes>. The values of
67 * the ptr array are full DER encoded certificate values. The keys are the
68 * string handles. This array is populated on demand.
71 } GTlsDatabaseGnutlsPrivate;
73 static void g_tls_database_gnutls_initable_interface_init (GInitableIface *iface);
75 G_DEFINE_TYPE_WITH_CODE (GTlsDatabaseGnutls, g_tls_database_gnutls, G_TYPE_TLS_DATABASE,
76 G_ADD_PRIVATE (GTlsDatabaseGnutls);
77 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
78 g_tls_database_gnutls_initable_interface_init);
82 bytes_multi_table_new (void)
84 return g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
85 (GDestroyNotify)g_bytes_unref,
86 (GDestroyNotify)g_ptr_array_unref);
90 bytes_multi_table_insert (GHashTable *table,
96 multi = g_hash_table_lookup (table, key);
99 multi = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref);
100 g_hash_table_insert (table, g_bytes_ref (key), multi);
102 g_ptr_array_add (multi, g_bytes_ref (value));
106 bytes_multi_table_lookup_ref_one (GHashTable *table,
111 multi = g_hash_table_lookup (table, key);
115 g_assert (multi->len > 0);
116 return g_bytes_ref (multi->pdata[0]);
120 bytes_multi_table_lookup_ref_all (GHashTable *table,
127 multi = g_hash_table_lookup (table, key);
131 for (i = 0; i < multi->len; i++)
132 list = g_list_prepend (list, g_bytes_ref (multi->pdata[i]));
134 return g_list_reverse (list);
138 create_handles_array_unlocked (GTlsDatabaseGnutls *self,
139 GHashTable *complete)
146 handles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
147 (GDestroyNotify)g_bytes_unref);
149 g_hash_table_iter_init (&iter, complete);
150 while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&der))
152 g_assert (G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate);
153 handle = G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate (self, der);
155 g_hash_table_insert (handles, handle, g_bytes_ref (der));
162 initialize_tables (gnutls_x509_trust_list_t trust_list,
163 GHashTable *subjects,
165 GHashTable *complete)
167 gnutls_x509_trust_list_iter_t iter = NULL;
168 gnutls_x509_crt_t cert = NULL;
171 GBytes *subject = NULL;
172 GBytes *issuer = NULL;
175 while (gnutls_x509_trust_list_iter_get_ca (trust_list, &iter, &cert) == 0)
177 gerr = gnutls_x509_crt_get_raw_dn (cert, &dn);
180 g_warning ("failed to get subject of anchor certificate: %s",
181 gnutls_strerror (gerr));
184 subject = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
186 gerr = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn);
189 g_warning ("failed to get issuer of anchor certificate: %s",
190 gnutls_strerror (gerr));
193 issuer = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
195 gerr = gnutls_x509_crt_export2 (cert, GNUTLS_X509_FMT_DER, &dn);
198 g_warning ("failed to get certificate DER: %s",
199 gnutls_strerror (gerr));
202 der = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
204 /* Three different ways of looking up same certificate */
205 bytes_multi_table_insert (subjects, subject, der);
206 bytes_multi_table_insert (issuers, issuer, der);
208 g_hash_table_insert (complete, g_bytes_ref (der),
212 g_clear_pointer (&der, g_bytes_unref);
213 g_clear_pointer (&subject, g_bytes_unref);
214 g_clear_pointer (&issuer, g_bytes_unref);
215 g_clear_pointer (&cert, gnutls_x509_crt_deinit);
220 g_tls_database_gnutls_finalize (GObject *object)
222 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (object);
223 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
225 g_clear_pointer (&priv->subjects, g_hash_table_destroy);
226 g_clear_pointer (&priv->issuers, g_hash_table_destroy);
227 g_clear_pointer (&priv->complete, g_hash_table_destroy);
228 g_clear_pointer (&priv->handles, g_hash_table_destroy);
230 gnutls_x509_trust_list_deinit (priv->trust_list, 1);
232 g_mutex_clear (&priv->mutex);
234 G_OBJECT_CLASS (g_tls_database_gnutls_parent_class)->finalize (object);
238 g_tls_database_gnutls_init (GTlsDatabaseGnutls *self)
240 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
242 g_mutex_init (&priv->mutex);
246 g_tls_database_gnutls_create_certificate_handle (GTlsDatabase *database,
247 GTlsCertificate *certificate)
249 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
250 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
253 gchar *handle = NULL;
255 der = g_tls_certificate_gnutls_get_bytes (G_TLS_CERTIFICATE_GNUTLS (certificate));
256 g_return_val_if_fail (der, FALSE);
258 g_mutex_lock (&priv->mutex);
260 /* At the same time look up whether this certificate is in list */
261 contains = g_hash_table_lookup (priv->complete, der) ? TRUE : FALSE;
263 g_mutex_unlock (&priv->mutex);
265 /* Certificate is in the database */
268 g_assert (G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate);
269 handle = G_TLS_DATABASE_GNUTLS_GET_CLASS (self)->create_handle_for_certificate (self, der);
276 static GTlsCertificate *
277 g_tls_database_gnutls_lookup_certificate_for_handle (GTlsDatabase *database,
279 GTlsInteraction *interaction,
280 GTlsDatabaseLookupFlags flags,
281 GCancellable *cancellable,
284 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
285 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
286 GTlsCertificate *cert;
288 gnutls_datum_t datum;
291 if (g_cancellable_set_error_if_cancelled (cancellable, error))
297 g_mutex_lock (&priv->mutex);
299 /* Create the handles table if not already done */
301 priv->handles = create_handles_array_unlocked (self, priv->complete);
303 der = g_hash_table_lookup (priv->handles, handle);
307 g_mutex_unlock (&priv->mutex);
312 datum.data = (unsigned char *)g_bytes_get_data (der, &length);
315 if (g_cancellable_set_error_if_cancelled (cancellable, error))
318 cert = g_tls_certificate_gnutls_new (&datum, NULL);
324 static GTlsCertificate *
325 g_tls_database_gnutls_lookup_certificate_issuer (GTlsDatabase *database,
326 GTlsCertificate *certificate,
327 GTlsInteraction *interaction,
328 GTlsDatabaseLookupFlags flags,
329 GCancellable *cancellable,
332 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
333 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
334 gnutls_datum_t dn = { NULL, 0 };
335 GBytes *subject, *der;
336 gnutls_datum_t datum;
337 GTlsCertificate *issuer = NULL;
338 gnutls_x509_crt_t cert;
342 g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (certificate), NULL);
344 if (g_cancellable_set_error_if_cancelled (cancellable, error))
347 if (flags & G_TLS_DATABASE_LOOKUP_KEYPAIR)
350 /* Dig out the issuer of this certificate */
351 cert = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (certificate));
352 gerr = gnutls_x509_crt_get_raw_issuer_dn (cert, &dn);
355 g_warning ("failed to get issuer of certificate: %s", gnutls_strerror (gerr));
359 subject = g_bytes_new_with_free_func (dn.data, dn.size, gnutls_free, dn.data);
361 /* Find the full DER value of the certificate */
362 g_mutex_lock (&priv->mutex);
363 der = bytes_multi_table_lookup_ref_one (priv->subjects, subject);
364 g_mutex_unlock (&priv->mutex);
366 g_bytes_unref (subject);
368 if (g_cancellable_set_error_if_cancelled (cancellable, error))
374 datum.data = (unsigned char *)g_bytes_get_data (der, &length);
376 issuer = g_tls_certificate_gnutls_new (&datum, NULL);
385 g_tls_database_gnutls_lookup_certificates_issued_by (GTlsDatabase *database,
386 GByteArray *issuer_raw_dn,
387 GTlsInteraction *interaction,
388 GTlsDatabaseLookupFlags flags,
389 GCancellable *cancellable,
392 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
393 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
395 gnutls_datum_t datum;
396 GList *issued = NULL;
401 if (g_cancellable_set_error_if_cancelled (cancellable, error))
404 /* We don't have any private keys here */
405 if (flags & G_TLS_DATABASE_LOOKUP_KEYPAIR)
408 issuer = g_bytes_new_static (issuer_raw_dn->data, issuer_raw_dn->len);
410 /* Find the full DER value of the certificate */
411 g_mutex_lock (&priv->mutex);
412 ders = bytes_multi_table_lookup_ref_all (priv->issuers, issuer);
413 g_mutex_unlock (&priv->mutex);
415 g_bytes_unref (issuer);
417 for (l = ders; l; l = g_list_next (l))
419 if (g_cancellable_set_error_if_cancelled (cancellable, error))
421 g_list_free_full (issued, g_object_unref);
426 datum.data = (unsigned char *)g_bytes_get_data (l->data, &length);
428 issued = g_list_prepend (issued, g_tls_certificate_gnutls_new (&datum, NULL));
431 g_list_free_full (ders, (GDestroyNotify)g_bytes_unref);
436 gnutls_x509_crt_t *chain;
440 static CertificateChain *
441 certificate_chain_new (void)
443 return g_new0 (CertificateChain, 1);
447 certificate_chain_free (CertificateChain *chain)
449 g_free (chain->chain);
453 static CertificateChain *
454 convert_certificate_chain_to_gnutls (GTlsCertificateGnutls *chain)
456 GTlsCertificate *cert;
457 CertificateChain *gnutls_chain;
460 gnutls_chain = certificate_chain_new ();
462 for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert))
463 gnutls_chain->length++;
465 gnutls_chain->chain = g_new (gnutls_x509_crt_t, gnutls_chain->length);
467 for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert), i++)
468 gnutls_chain->chain[i] = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (cert));
470 g_assert (i == gnutls_chain->length);
475 static GTlsCertificateFlags
476 g_tls_database_gnutls_verify_chain (GTlsDatabase *database,
477 GTlsCertificate *chain,
478 const gchar *purpose,
479 GSocketConnectable *identity,
480 GTlsInteraction *interaction,
481 GTlsDatabaseVerifyFlags flags,
482 GCancellable *cancellable,
485 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (database);
486 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
487 GTlsCertificateFlags result;
489 CertificateChain *gnutls_chain;
492 g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS (chain),
493 G_TLS_CERTIFICATE_GENERIC_ERROR);
496 if (g_cancellable_set_error_if_cancelled (cancellable, error))
497 return G_TLS_CERTIFICATE_GENERIC_ERROR;
499 g_mutex_lock (&priv->mutex);
500 gnutls_chain = convert_certificate_chain_to_gnutls (G_TLS_CERTIFICATE_GNUTLS (chain));
501 gerr = gnutls_x509_trust_list_verify_crt (priv->trust_list,
502 gnutls_chain->chain, gnutls_chain->length,
503 0, &gnutls_result, NULL);
504 g_mutex_unlock (&priv->mutex);
506 if (gerr != 0 || g_cancellable_set_error_if_cancelled (cancellable, error))
508 certificate_chain_free (gnutls_chain);
509 return G_TLS_CERTIFICATE_GENERIC_ERROR;
512 result = g_tls_certificate_gnutls_convert_flags (gnutls_result);
515 result |= g_tls_certificate_gnutls_verify_identity (G_TLS_CERTIFICATE_GNUTLS (chain),
519 certificate_chain_free (gnutls_chain);
524 g_tls_database_gnutls_create_handle_for_certificate (GTlsDatabaseGnutls *self,
531 * Here we create a URI that looks like
532 * system-trust:#11b2641821252596420e468c275771f5e51022c121a17bd7a89a2f37b6336c8f.
534 * system-trust is a meaningless URI scheme, and the handle does not
535 * even need to be a URI; this is just a nice stable way to uniquely
536 * identify a certificate.
539 bookmark = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, der);
540 uri = g_strconcat ("system-trust:#", bookmark, NULL);
548 g_tls_database_gnutls_populate_trust_list (GTlsDatabaseGnutls *self,
549 gnutls_x509_trust_list_t trust_list,
552 int gerr = gnutls_x509_trust_list_add_system_trust (trust_list, 0, 0);
553 if (gerr == GNUTLS_E_UNIMPLEMENTED_FEATURE)
555 g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
556 _("Failed to load system trust store: GnuTLS was not configured with a system trust"));
560 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC,
561 _("Failed to load system trust store: %s"),
562 gnutls_strerror (gerr));
567 static gnutls_x509_trust_list_t
568 create_trust_list (GTlsDatabaseGnutls *self,
571 GTlsDatabaseGnutlsClass *database_class = G_TLS_DATABASE_GNUTLS_GET_CLASS (self);
572 gnutls_x509_trust_list_t trust_list;
575 ret = gnutls_x509_trust_list_init (&trust_list, 0);
578 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC, "Failed to initialize trust list: %s", gnutls_strerror (ret));
582 g_assert (database_class->populate_trust_list);
583 if (!database_class->populate_trust_list (self, trust_list, error))
585 gnutls_x509_trust_list_deinit (trust_list, TRUE);
592 gnutls_certificate_credentials_t
593 g_tls_database_gnutls_get_credentials (GTlsDatabaseGnutls *self,
596 gnutls_certificate_credentials_t credentials;
597 gnutls_x509_trust_list_t trust_list = NULL;
600 ret = gnutls_certificate_allocate_credentials (&credentials);
603 g_set_error (error, G_TLS_ERROR, G_TLS_ERROR_MISC, "Failed to allocate credentials: %s", gnutls_strerror (ret));
607 trust_list = create_trust_list (self, error);
610 gnutls_certificate_free_credentials (credentials);
614 gnutls_certificate_set_trust_list (credentials, trust_list, 0);
619 g_tls_database_gnutls_class_init (GTlsDatabaseGnutlsClass *klass)
621 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
622 GTlsDatabaseClass *database_class = G_TLS_DATABASE_CLASS (klass);
624 gobject_class->finalize = g_tls_database_gnutls_finalize;
626 database_class->create_certificate_handle = g_tls_database_gnutls_create_certificate_handle;
627 database_class->lookup_certificate_for_handle = g_tls_database_gnutls_lookup_certificate_for_handle;
628 database_class->lookup_certificate_issuer = g_tls_database_gnutls_lookup_certificate_issuer;
629 database_class->lookup_certificates_issued_by = g_tls_database_gnutls_lookup_certificates_issued_by;
630 database_class->verify_chain = g_tls_database_gnutls_verify_chain;
632 klass->create_handle_for_certificate = g_tls_database_gnutls_create_handle_for_certificate;
633 klass->populate_trust_list = g_tls_database_gnutls_populate_trust_list;
637 g_tls_database_gnutls_initable_init (GInitable *initable,
638 GCancellable *cancellable,
641 GTlsDatabaseGnutls *self = G_TLS_DATABASE_GNUTLS (initable);
642 GTlsDatabaseGnutlsPrivate *priv = g_tls_database_gnutls_get_instance_private (self);
643 gnutls_x509_trust_list_t trust_list = NULL;
644 GHashTable *subjects = NULL;
645 GHashTable *issuers = NULL;
646 GHashTable *complete = NULL;
647 gboolean result = TRUE;
649 if (g_cancellable_set_error_if_cancelled (cancellable, error))
652 trust_list = create_trust_list (self, error);
656 subjects = bytes_multi_table_new ();
657 issuers = bytes_multi_table_new ();
659 complete = g_hash_table_new_full (g_bytes_hash, g_bytes_equal,
660 (GDestroyNotify)g_bytes_unref,
661 (GDestroyNotify)g_bytes_unref);
663 initialize_tables (trust_list, subjects, issuers, complete);
665 if (g_cancellable_set_error_if_cancelled (cancellable, error))
670 g_mutex_lock (&priv->mutex);
671 if (!priv->trust_list)
673 priv->trust_list = trust_list;
678 priv->subjects = subjects;
683 priv->issuers = issuers;
688 priv->complete = complete;
691 g_mutex_unlock (&priv->mutex);
695 gnutls_x509_trust_list_deinit (trust_list, 1);
697 g_hash_table_unref (subjects);
699 g_hash_table_unref (issuers);
701 g_hash_table_unref (complete);
706 g_tls_database_gnutls_initable_interface_init (GInitableIface *iface)
708 iface->init = g_tls_database_gnutls_initable_init;
712 g_tls_database_gnutls_new (GError **error)
714 g_return_val_if_fail (!error || !*error, NULL);
716 return g_initable_new (G_TYPE_TLS_DATABASE_GNUTLS, NULL, error, NULL);