[glib-networking] Add unit tests for TLS channel binding, all types and backends
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking] Add unit tests for TLS channel binding, all types and backends
- Date: Tue, 1 Sep 2020 16:08:46 +0000 (UTC)
commit 883be9c5d6dc494d8d49d3c4d70769885037d0a4
Author: Ruslan N. Marchenko <me ruff mobi>
Date: Wed Jun 3 23:58:58 2020 +0200
Add unit tests for TLS channel binding, all types and backends
* Test units verify if both client and server binding data matches.
* Test units require Glib-2.0 version 2.65.1 hence bump the dependency
meson.build | 2 +-
tls/tests/connection.c | 224 ++++++++++++++++++++++++++++++++++++++++
tls/tests/files/create-files.sh | 4 +
3 files changed, 229 insertions(+), 1 deletion(-)
---
diff --git a/meson.build b/meson.build
index 317be9a..5f5f6ab 100644
--- a/meson.build
+++ b/meson.build
@@ -48,7 +48,7 @@ if host_system.contains('linux')
endif
# *** Check GLib GIO ***
-glib_dep = dependency('glib-2.0', version: '>= 2.63.0',
+glib_dep = dependency('glib-2.0', version: '>= 2.65.1',
fallback: ['glib', 'libglib_dep'])
gio_dep = dependency('gio-2.0',
fallback: ['glib', 'libgio_dep'])
diff --git a/tls/tests/connection.c b/tls/tests/connection.c
index ccae1cd..0044176 100644
--- a/tls/tests/connection.c
+++ b/tls/tests/connection.c
@@ -2412,6 +2412,224 @@ test_socket_timeout (TestConnection *test,
#endif
}
+static void
+test_connection_binding_match_tls_unique (TestConnection *test,
+ gconstpointer data)
+{
+ GSocketClient *client;
+ GIOStream *connection;
+ GByteArray *client_cb, *server_cb;
+ gchar *client_b64, *server_b64;
+ GError *error = NULL;
+
+ test->database = g_tls_file_database_new (tls_test_file_path ("ca-roots.pem"), &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (test->database);
+
+ start_async_server_service (test, G_TLS_AUTHENTICATION_NONE, WRITE_THEN_WAIT);
+
+ client = g_socket_client_new ();
+ connection = G_IO_STREAM (g_socket_client_connect (client, G_SOCKET_CONNECTABLE (test->address),
+ NULL, &error));
+ g_assert_no_error (error);
+ g_object_unref (client);
+
+ test->client_connection = g_tls_client_connection_new (connection, test->identity, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (test->client_connection);
+ g_object_unref (connection);
+
+ g_tls_connection_set_database (G_TLS_CONNECTION (test->client_connection), test->database);
+
+ /* All validation in this test */
+ g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (test->client_connection),
+ G_TLS_CERTIFICATE_VALIDATE_ALL);
+
+ read_test_data_async (test);
+ g_main_loop_run (test->loop);
+
+ /* Smoke test: ensure both sides support tls-unique */
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->client_connection),
+ G_TLS_CHANNEL_BINDING_TLS_UNIQUE, NULL, NULL));
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->server_connection),
+ G_TLS_CHANNEL_BINDING_TLS_UNIQUE, NULL, NULL));
+
+ /* Real test: retrieve bindings and compare */
+ client_cb = g_byte_array_new ();
+ server_cb = g_byte_array_new ();
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->client_connection),
+ G_TLS_CHANNEL_BINDING_TLS_UNIQUE, client_cb, NULL));
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->server_connection),
+ G_TLS_CHANNEL_BINDING_TLS_UNIQUE, server_cb, NULL));
+
+#ifdef BACKEND_IS_OPENSSL
+ g_assert_cmpint (client_cb->len, >, 0);
+ g_assert_cmpint (server_cb->len, >, 0);
+#else
+ /* GnuTLS returns empty binding for TLS1.3, let's pretend it didn't happen
+ * see https://gitlab.com/gnutls/gnutls/-/issues/1041 */
+ if (client_cb->len == 0 && server_cb->len == 0)
+ g_test_skip ("GnuTLS missing support for tls-unique over TLS1.3");
+#endif
+
+ client_b64 = g_base64_encode (client_cb->data, client_cb->len);
+ server_b64 = g_base64_encode (server_cb->data, server_cb->len);
+ g_assert_cmpstr (client_b64, ==, server_b64);
+
+ g_free (client_b64);
+ g_free (server_b64);
+ g_byte_array_unref (client_cb);
+ g_byte_array_unref (server_cb);
+
+ /* drop the mic */
+ close_server_connection (test);
+ wait_until_server_finished (test);
+
+ g_assert_no_error (test->read_error);
+ g_assert_no_error (test->server_error);
+}
+
+/* create_files.sh should update this digest but if anything goes wrong
+ * please make sure the string below matches the output of
+ * openssl x509 -outform der -in files/server.pem | openssl sha256 -binary | base64
+ **/
+#define SERVER_CERT_DIGEST_B64 "jd+Lgj78hyCQXLgZhEKeBPDypjTaLfsPPExqs+6R/n0="
+static void
+test_connection_binding_match_tls_server_end_point (TestConnection *test,
+ gconstpointer data)
+{
+ GSocketClient *client;
+ GIOStream *connection;
+ GByteArray *client_cb, *server_cb;
+ gchar *client_b64, *server_b64;
+ GError *error = NULL;
+
+ test->database = g_tls_file_database_new (tls_test_file_path ("ca-roots.pem"), &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (test->database);
+
+ start_async_server_service (test, G_TLS_AUTHENTICATION_NONE, WRITE_THEN_WAIT);
+
+ client = g_socket_client_new ();
+ connection = G_IO_STREAM (g_socket_client_connect (client, G_SOCKET_CONNECTABLE (test->address),
+ NULL, &error));
+ g_assert_no_error (error);
+ g_object_unref (client);
+
+ test->client_connection = g_tls_client_connection_new (connection, test->identity, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (test->client_connection);
+ g_object_unref (connection);
+
+ g_tls_connection_set_database (G_TLS_CONNECTION (test->client_connection), test->database);
+
+ /* All validation in this test */
+ g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (test->client_connection),
+ G_TLS_CERTIFICATE_VALIDATE_ALL);
+
+ read_test_data_async (test);
+ g_main_loop_run (test->loop);
+
+ /* Smoke test: ensure both sides support tls-server-end-point */
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->client_connection),
+ G_TLS_CHANNEL_BINDING_TLS_SERVER_END_POINT, NULL, NULL));
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->server_connection),
+ G_TLS_CHANNEL_BINDING_TLS_SERVER_END_POINT, NULL, NULL));
+
+ /* Real test: retrieve bindings and compare */
+ client_cb = g_byte_array_new ();
+ server_cb = g_byte_array_new ();
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->client_connection),
+ G_TLS_CHANNEL_BINDING_TLS_SERVER_END_POINT, client_cb, NULL));
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->server_connection),
+ G_TLS_CHANNEL_BINDING_TLS_SERVER_END_POINT, server_cb, NULL));
+
+ client_b64 = g_base64_encode (client_cb->data, client_cb->len);
+ server_b64 = g_base64_encode (server_cb->data, server_cb->len);
+ g_assert_cmpstr (client_b64, ==, server_b64);
+ g_assert_cmpstr (client_b64, ==, SERVER_CERT_DIGEST_B64);
+ g_assert_cmpstr (server_b64, ==, SERVER_CERT_DIGEST_B64);
+
+ g_free (client_b64);
+ g_free (server_b64);
+ g_byte_array_unref (client_cb);
+ g_byte_array_unref (server_cb);
+
+ /* drop the mic */
+ close_server_connection (test);
+ wait_until_server_finished (test);
+
+ g_assert_no_error (test->read_error);
+ g_assert_no_error (test->server_error);
+}
+
+static void
+test_connection_binding_match_tls_exporter (TestConnection *test,
+ gconstpointer data)
+{
+ GSocketClient *client;
+ GIOStream *connection;
+ GByteArray *client_cb, *server_cb;
+ gchar *client_b64, *server_b64;
+ GError *error = NULL;
+
+ test->database = g_tls_file_database_new (tls_test_file_path ("ca-roots.pem"), &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (test->database);
+
+ start_async_server_service (test, G_TLS_AUTHENTICATION_NONE, WRITE_THEN_WAIT);
+
+ client = g_socket_client_new ();
+ connection = G_IO_STREAM (g_socket_client_connect (client, G_SOCKET_CONNECTABLE (test->address),
+ NULL, &error));
+ g_assert_no_error (error);
+ g_object_unref (client);
+
+ test->client_connection = g_tls_client_connection_new (connection, test->identity, &error);
+ g_assert_no_error (error);
+ g_assert_nonnull (test->client_connection);
+ g_object_unref (connection);
+
+ g_tls_connection_set_database (G_TLS_CONNECTION (test->client_connection), test->database);
+
+ /* All validation in this test */
+ g_tls_client_connection_set_validation_flags (G_TLS_CLIENT_CONNECTION (test->client_connection),
+ G_TLS_CERTIFICATE_VALIDATE_ALL);
+
+ read_test_data_async (test);
+ g_main_loop_run (test->loop);
+
+ /* Smoke test: ensure both sides support tls-exporter */
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->client_connection),
+ (GTlsChannelBindingType)100500, NULL, NULL));
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->server_connection),
+ (GTlsChannelBindingType)100500, NULL, NULL));
+
+ /* Real test: retrieve bindings and compare */
+ client_cb = g_byte_array_new ();
+ server_cb = g_byte_array_new ();
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->client_connection),
+ (GTlsChannelBindingType)100500, client_cb, NULL));
+ g_assert_true (g_tls_connection_get_channel_binding_data (G_TLS_CONNECTION (test->server_connection),
+ (GTlsChannelBindingType)100500, server_cb, NULL));
+
+ client_b64 = g_base64_encode (client_cb->data, client_cb->len);
+ server_b64 = g_base64_encode (server_cb->data, server_cb->len);
+ g_assert_cmpstr (client_b64, ==, server_b64);
+
+ g_free (client_b64);
+ g_free (server_b64);
+ g_byte_array_unref (client_cb);
+ g_byte_array_unref (server_cb);
+
+ /* drop the mic */
+ close_server_connection (test);
+ wait_until_server_finished (test);
+
+ g_assert_no_error (test->read_error);
+ g_assert_no_error (test->server_error);
+}
+
static void
test_connection_missing_server_identity (TestConnection *test,
gconstpointer data)
@@ -2658,6 +2876,12 @@ main (int argc,
setup_connection, test_connection_missing_server_identity, teardown_connection);
g_test_add ("/tls/" BACKEND "/connection/peer-certificate-notify", TestConnection, NULL,
setup_connection, test_peer_certificate_notify, teardown_connection);
+ g_test_add ("/tls/" BACKEND "/connection/binding/match-tls-unique", TestConnection, NULL,
+ setup_connection, test_connection_binding_match_tls_unique, teardown_connection);
+ g_test_add ("/tls/" BACKEND "/connection/binding/match-tls-server-end-point", TestConnection, NULL,
+ setup_connection, test_connection_binding_match_tls_server_end_point, teardown_connection);
+ g_test_add ("/tls/" BACKEND "/connection/binding/match-tls-exporter", TestConnection, NULL,
+ setup_connection, test_connection_binding_match_tls_exporter, teardown_connection);
ret = g_test_run ();
diff --git a/tls/tests/files/create-files.sh b/tls/tests/files/create-files.sh
index 8fda797..07df725 100755
--- a/tls/tests/files/create-files.sh
+++ b/tls/tests/files/create-files.sh
@@ -80,6 +80,10 @@ msg "Concatenating server certificate and private key into a single file"
cat server.pem > server-and-key.pem
cat server-key.pem >> server-and-key.pem
+msg "Updating digest of the new certificate in connections.c"
+DIGEST=$( openssl x509 -outform der -in server.pem | openssl sha256 -binary | base64 | sed 's/\//\\\//g' )
+sed -i "/define SERVER_CERT_DIGEST_B64/s/\"\([^\"]\+\)\"/\"$DIGEST\"/" ../connection.c
+
msg "Converting server certificate from PEM to DER"
openssl x509 -in server.pem -outform DER -out server.der
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]