[glib-networking/pgriffis/ocsp-openssl: 4/5] openssl: Implement OCSP MustStaple
- From: Patrick Griffis <pgriffis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/pgriffis/ocsp-openssl: 4/5] openssl: Implement OCSP MustStaple
- Date: Sat, 31 Jul 2021 23:52:26 +0000 (UTC)
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]