[glib-networking/pgriffis/ocsp-openssl: 4/5] openssl: Implement OCSP MustStaple




commit 825446ccdfb3e08870822a9a78f993e7bd3ebaef
Author: Patrick Griffis <pgriffis igalia com>
Date:   Sat Jul 31 18:42:01 2021 -0500

    openssl: Implement OCSP MustStaple

 tls/base/gtlsconnection-base.c             |  1 -
 tls/openssl/gtlsclientconnection-openssl.c | 21 +++-----
 tls/openssl/gtlsdatabase-openssl.c         | 85 ++++++++++++++++++++++++++----
 tls/tests/certificate.c                    |  2 +-
 tls/tests/connection.c                     |  5 --
 5 files changed, 82 insertions(+), 32 deletions(-)
---
diff --git a/tls/base/gtlsconnection-base.c b/tls/base/gtlsconnection-base.c
index 716f1631..632008b4 100644
--- a/tls/base/gtlsconnection-base.c
+++ b/tls/base/gtlsconnection-base.c
@@ -1259,7 +1259,6 @@ verify_peer_certificate (GTlsConnectionBase *tls,
 {
   GTlsConnectionBaseClass *tls_class = G_TLS_CONNECTION_BASE_GET_CLASS (tls);
   GSocketConnectable *peer_identity = NULL;
-  GTlsConnectionBaseClass *tls_class = G_TLS_CONNECTION_BASE_GET_CLASS (tls);
   GTlsDatabase *database;
   GTlsCertificateFlags errors = 0;
   gboolean is_client;
diff --git a/tls/openssl/gtlsclientconnection-openssl.c b/tls/openssl/gtlsclientconnection-openssl.c
index 7573adb1..ba2e943a 100644
--- a/tls/openssl/gtlsclientconnection-openssl.c
+++ b/tls/openssl/gtlsclientconnection-openssl.c
@@ -222,14 +222,12 @@ verify_ocsp_response (GTlsClientConnectionOpenssl *openssl,
 
   ssl = g_tls_connection_openssl_get_ssl (G_TLS_CONNECTION_OPENSSL (openssl));
   len = SSL_get_tlsext_status_ocsp_resp (ssl, &p);
-  /* Soft fail in case of no response is the best we can do
-   * FIXME: this makes it security theater, why bother with OCSP at all? */
-  if (!p)
-    return 0;
-
-  resp = d2i_OCSP_RESPONSE (NULL, (const unsigned char **)&p, len);
-  if (!resp)
-    return G_TLS_CERTIFICATE_GENERIC_ERROR;
+  if (p)
+    {
+      resp = d2i_OCSP_RESPONSE (NULL, (const unsigned char **)&p, len);
+      if (!resp)
+        return G_TLS_CERTIFICATE_GENERIC_ERROR;
+    }
 
   database = g_tls_connection_get_database (G_TLS_CONNECTION (openssl));
 
@@ -432,12 +430,6 @@ set_curve_list (GTlsClientConnectionOpenssl *client)
 }
 #endif
 
-static gboolean
-use_ocsp (void)
-{
-  return g_getenv ("G_TLS_OPENSSL_OCSP_ENABLED") != NULL;
-}
-
 static gboolean
 g_tls_client_connection_openssl_initable_init (GInitable       *initable,
                                                GCancellable    *cancellable,
@@ -531,7 +523,6 @@ g_tls_client_connection_openssl_initable_init (GInitable       *initable,
 
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
     !defined(OPENSSL_NO_OCSP)
-  if (use_ocsp())
     SSL_set_tlsext_status_type (client->ssl, TLSEXT_STATUSTYPE_ocsp);
 #endif
 
diff --git a/tls/openssl/gtlsdatabase-openssl.c b/tls/openssl/gtlsdatabase-openssl.c
index 65b5ff42..9b65d36e 100644
--- a/tls/openssl/gtlsdatabase-openssl.c
+++ b/tls/openssl/gtlsdatabase-openssl.c
@@ -313,6 +313,39 @@ g_tls_database_openssl_new (GError **error)
   return g_initable_new (G_TYPE_TLS_DATABASE_OPENSSL, NULL, error, NULL);
 }
 
+static gboolean
+check_chain_for_ocsp_must_staple (const STACK_OF(X509) *chain)
+{
+  for (guint i_cert = 0; i_cert < sk_X509_num (chain); i_cert++)
+    {
+      X509 *cert = sk_X509_value (chain, i_cert);
+      int idx = -1; /* We ignore the return of this as we only expect 1 extension */
+      STACK_OF(ASN1_INTEGER) *features = X509_get_ext_d2i (cert, NID_tlsfeature, NULL, &idx);
+
+      if (!features)
+        {
+          X509_free (cert);
+          continue;
+        }
+
+      for (guint i_feature = 0; i_feature < sk_ASN1_INTEGER_num (features); i_feature++)
+        {
+          const long feature_id = ASN1_INTEGER_get (sk_ASN1_INTEGER_value (features, i_feature));
+          if (feature_id == 5 || feature_id == 17) /* status_request, status_request_v2 */
+            {
+              sk_ASN1_INTEGER_free (features);
+              X509_free (cert);
+              return TRUE;
+            }
+        }
+
+      sk_ASN1_INTEGER_free (features);
+      X509_free (cert);
+    }
+
+  return FALSE;
+}
+
 GTlsCertificateFlags
 g_tls_database_openssl_verify_ocsp_response (GTlsDatabaseOpenssl *self,
                                              GTlsCertificate     *chain,
@@ -322,35 +355,64 @@ g_tls_database_openssl_verify_ocsp_response (GTlsDatabaseOpenssl *self,
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
   !defined(OPENSSL_NO_OCSP)
   GTlsDatabaseOpensslPrivate *priv;
-  STACK_OF(X509) *chain_openssl = NULL;
+  STACK_OF(X509) *peer_chain = NULL;
   OCSP_BASICRESP *basic_resp = NULL;
   int ocsp_status = 0;
   int i;
 
-  ocsp_status = OCSP_response_status (resp);
-  if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL)
+  peer_chain = convert_certificate_chain_to_openssl (G_TLS_CERTIFICATE_OPENSSL (chain));
+
+  priv = g_tls_database_openssl_get_instance_private (self);
+  if ((peer_chain == NULL) ||
+      (priv->store == NULL))
     {
       errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
       goto end;
     }
 
-  basic_resp = OCSP_response_get1_basic (resp);
-  if (basic_resp == NULL)
+  /* If we are missing a response we check if the chain requires a response ("Must-Staple") */
+  if (resp == NULL)
+    {
+      GTlsCertificate *issuer;
+
+      issuer = g_tls_database_lookup_certificate_issuer (G_TLS_DATABASE (self),
+                                                         chain,
+                                                         NULL,
+                                                         G_TLS_DATABASE_LOOKUP_NONE,
+                                                         NULL,
+                                                         NULL);
+
+      if (issuer)
+        {
+          STACK_OF(X509) *issuer_chain = convert_certificate_chain_to_openssl (G_TLS_CERTIFICATE_OPENSSL 
(issuer));
+
+          if (check_chain_for_ocsp_must_staple (peer_chain) ||
+              check_chain_for_ocsp_must_staple (issuer_chain))
+                  errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
+
+          sk_X509_free (issuer_chain);
+          g_object_unref (issuer);
+        }
+
+      /* Either we errored because of MustStaple or continue on ignoring OCSP */
+      goto end;
+    }
+
+  ocsp_status = OCSP_response_status (resp);
+  if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL)
     {
       errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
       goto end;
     }
 
-  chain_openssl = convert_certificate_chain_to_openssl (G_TLS_CERTIFICATE_OPENSSL (chain));
-  priv = g_tls_database_openssl_get_instance_private (self);
-  if ((chain_openssl == NULL) ||
-      (priv->store == NULL))
+  basic_resp = OCSP_response_get1_basic (resp);
+  if (basic_resp == NULL)
     {
       errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
       goto end;
     }
 
-  if (OCSP_basic_verify (basic_resp, chain_openssl, priv->store, 0) <= 0)
+  if (OCSP_basic_verify (basic_resp, peer_chain, priv->store, 0) <= 0)
     {
       errors = G_TLS_CERTIFICATE_GENERIC_ERROR;
       goto end;
@@ -396,6 +458,9 @@ g_tls_database_openssl_verify_ocsp_response (GTlsDatabaseOpenssl *self,
     }
 
 end:
+  if (peer_chain)
+    sk_X509_free (peer_chain);
+
   if (basic_resp)
     OCSP_BASICRESP_free (basic_resp);
 
diff --git a/tls/tests/certificate.c b/tls/tests/certificate.c
index c0100d30..db3eeaa6 100644
--- a/tls/tests/certificate.c
+++ b/tls/tests/certificate.c
@@ -405,7 +405,7 @@ test_create_list (void)
 
   list = g_tls_certificate_list_new_from_file (tls_test_file_path ("ca-roots.pem"), &error);
   g_assert_no_error (error);
-  g_assert_cmpint (g_list_length (list), ==, 8);
+  g_assert_cmpint (g_list_length (list), ==, 10);
 
   g_list_free_full (list, g_object_unref);
 }
diff --git a/tls/tests/connection.c b/tls/tests/connection.c
index 2127cbfe..d3aca0e3 100644
--- a/tls/tests/connection.c
+++ b/tls/tests/connection.c
@@ -2979,11 +2979,6 @@ test_connection_oscp_must_staple (TestConnection *test,
   GIOStream *connection;
   GError *error = NULL;
 
-#ifdef BACKEND_IS_OPENSSL
-  g_test_skip ("OCSP Must-Staple is not supported with the openssl backend");
-  return;
-#endif
-
   test->database = g_tls_file_database_new (tls_test_file_path ("ca-ocsp.pem"), &error);
   g_assert_no_error (error);
   g_assert_nonnull (test->database);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]