]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
keylogfile: write TLS 1.3 secrets
authorDaiki Ueno <dueno@redhat.com>
Wed, 29 Nov 2017 10:18:40 +0000 (11:18 +0100)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 19 Feb 2018 14:29:36 +0000 (15:29 +0100)
Signed-off-by: Daiki Ueno <dueno@redhat.com>
lib/constate.c
lib/handshake-tls13.c
tests/keylog-env.c

index c0967f7f0a257a7d0d1f5325688c846d05a4ba4a..fcc8c0bd4c12d7f5f1488a4e9a6cad2e08ef9f39 100644 (file)
@@ -211,16 +211,19 @@ _tls13_set_keys(gnutls_session_t session, hs_stage_t stage, record_parameters_st
        record_state_st *client_write, *server_write;
        const char *label;
        unsigned label_size, hsk_len;
+       const char *keylog_label;
        int ret;
 
        if (stage == STAGE_HS) {
                label = HANDSHAKE_CLIENT_TRAFFIC_LABEL;
                label_size = sizeof(HANDSHAKE_CLIENT_TRAFFIC_LABEL)-1;
                hsk_len = session->internals.handshake_hash_buffer.length;
+               keylog_label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
        } else {
                label = APPLICATION_CLIENT_TRAFFIC_LABEL;
                label_size = sizeof(APPLICATION_CLIENT_TRAFFIC_LABEL)-1;
                hsk_len = session->internals.handshake_hash_buffer_server_finished_len;
+               keylog_label = "CLIENT_TRAFFIC_SECRET_0";
        }
 
        ret = _tls13_derive_secret(session, label, label_size,
@@ -231,6 +234,10 @@ _tls13_set_keys(gnutls_session_t session, hs_stage_t stage, record_parameters_st
        if (ret < 0)
                return gnutls_assert_val(ret);
 
+       _gnutls_nss_keylog_write(session, keylog_label,
+                                session->key.hs_ckey,
+                                session->security_parameters.prf->output_size);
+
        /* client keys */
        ret = _tls13_expand_secret(session, "key", 3, NULL, 0, session->key.hs_ckey, key_size, ckey_block);
        if (ret < 0)
@@ -244,9 +251,11 @@ _tls13_set_keys(gnutls_session_t session, hs_stage_t stage, record_parameters_st
        if (stage == STAGE_HS) {
                label = HANDSHAKE_SERVER_TRAFFIC_LABEL;
                label_size = sizeof(HANDSHAKE_SERVER_TRAFFIC_LABEL)-1;
+               keylog_label = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
        } else {
                label = APPLICATION_SERVER_TRAFFIC_LABEL;
                label_size = sizeof(APPLICATION_SERVER_TRAFFIC_LABEL)-1;
+               keylog_label = "SERVER_TRAFFIC_SECRET_0";
        }
 
        ret = _tls13_derive_secret(session, label, label_size,
@@ -258,6 +267,10 @@ _tls13_set_keys(gnutls_session_t session, hs_stage_t stage, record_parameters_st
        if (ret < 0)
                return gnutls_assert_val(ret);
 
+       _gnutls_nss_keylog_write(session, keylog_label,
+                                session->key.hs_skey,
+                                session->security_parameters.prf->output_size);
+
        ret = _tls13_expand_secret(session, "key", 3, NULL, 0, session->key.hs_skey, key_size, skey_block);
        if (ret < 0)
                return gnutls_assert_val(ret);
index 02889dc90d293a6435995b6b350f86be7a49d070..9a36bacc406c95ddc89bed9b5033c00a3a58a22e 100644 (file)
@@ -162,6 +162,10 @@ static int generate_ap_traffic_keys(gnutls_session_t session)
        if (ret < 0)
                return gnutls_assert_val(ret);
 
+       _gnutls_nss_keylog_write(session, "EXPORTER_SECRET",
+                                session->key.ap_expkey,
+                                session->security_parameters.prf->output_size);
+
        _gnutls_epoch_bump(session);
        ret = _gnutls_epoch_dup(session);
        if (ret < 0)
index 2b0d166982c53ffce0e9b2f3650216c24861ce35..5f5f74e176024b37b12ebbcf4caf88297bf272b7 100644 (file)
@@ -24,6 +24,7 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -43,7 +44,7 @@
 #include "utils.h"
 #include "cert-common.h"
 
-/* Test for GNUTLS_KEYLOGFILE being functional.
+/* Test for SSLKEYLOGFILE being functional.
  *
  */
 
@@ -52,8 +53,23 @@ static void tls_log_func(int level, const char *str)
        fprintf(stderr, "<%d>| %s", level, str);
 }
 
-#define LSTR "CLIENT_RANDOM "
-static void search_for_str(const char *filename)
+/* In TLS 1.2, we only expect CLIENT_RANDOM.  */
+static const char *tls12_included_labels[] = { "CLIENT_RANDOM", NULL };
+static const char *tls12_excluded_labels[] = { NULL };
+
+/* In TLS 1.3, we expect secrets derived in handshake phases, but not
+ * CLIENT_RANDOM.  */
+static const char *tls13_included_labels[] = {
+       "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
+       "SERVER_HANDSHAKE_TRAFFIC_SECRET",
+       "CLIENT_TRAFFIC_SECRET_0",
+       "SERVER_TRAFFIC_SECRET_0",
+       "EXPORTER_SECRET",
+       NULL
+};
+static const char *tls13_excluded_labels[] = { "CLIENT_RANDOM", NULL };
+
+static void search_for_str(const char *filename, const char *label, bool excluded)
 {
        char line[512];
        FILE *fp = fopen(filename, "r");
@@ -61,35 +77,37 @@ static void search_for_str(const char *filename)
 
        while( (p = fgets(line, sizeof(line), fp)) != NULL) {
                success("%s", line);
-               if (strncmp(line, LSTR, sizeof(LSTR)-1) == 0) {
+               if (strncmp(line, label, strlen(label)) == 0 &&
+                   line[strlen(label)] == ' ') {
                        fclose(fp);
+                       if (excluded)
+                               fail("file should not contain %s\n", label);
                        return;
                }
        }
        fclose(fp);
-       fail("file did not contain CLIENT_RANDOM\n");
+       if (!excluded)
+               fail("file should contain %s\n", label);
 }
 
-static void run(const char *env, const char *filename)
+static void run(const char *filename, const char *prio,
+               const char **included, const char **excluded)
 {
        gnutls_certificate_credentials_t x509_cred;
        gnutls_certificate_credentials_t clicred;
+       const char **p;
        int ret;
 
-       remove(filename);
-
 #ifdef _WIN32
        {
                char buf[512];
-               snprintf(buf, sizeof(buf), "%s=%s", env, filename);
+               snprintf(buf, sizeof(buf), "SSLKEYLOGFILE=%s", filename);
                _putenv(buf);
        }
 #else
-       setenv(env, filename, 1);
+       setenv("SSLKEYLOGFILE", filename, 1);
 #endif
 
-       global_init();
-
        if (debug) {
                gnutls_global_set_log_level(6);
                gnutls_global_set_log_function(tls_log_func);
@@ -112,21 +130,21 @@ static void run(const char *env, const char *filename)
                fail("set_x509_trust_file failed: %s\n", gnutls_strerror(ret));
 
 
-       test_cli_serv(x509_cred, clicred, "NORMAL", "localhost", NULL, NULL, NULL);
+       test_cli_serv(x509_cred, clicred, prio, "localhost", NULL, NULL, NULL);
 
        if (access(filename, R_OK) != 0) {
                fail("keylog file was not created\n");
                exit(1);
        }
 
-       search_for_str(filename);
+       for (p = included; *p; p++)
+               search_for_str(filename, *p, false);
+       for (p = excluded; *p; p++)
+               search_for_str(filename, *p, true);
 
        gnutls_certificate_free_credentials(x509_cred);
        gnutls_certificate_free_credentials(clicred);
 
-       gnutls_global_deinit();
-       remove(filename);
-
        if (debug)
                success("success");
 }
@@ -137,5 +155,23 @@ void doit(void)
 
        assert(get_tmpname(filename)!=NULL);
 
-       run("SSLKEYLOGFILE", filename);
+       remove(filename);
+       global_init();
+
+       run(filename,
+           "NONE:+VERS-TLS1.2:+AES-128-CBC:+SHA1:+SIGN-ALL:+COMP-NULL:+RSA",
+           tls12_included_labels, tls12_excluded_labels);
+
+       /* This is needed because the SSLKEYLOGFILE envvar is checked
+        * only once and the file is never closed until the library is
+        * unloaded.  Truncate the file to zero length, so we can
+        * reuse the same file for multiple tests.  */
+       truncate(filename, 0);
+
+       run(filename,
+           "NONE:+VERS-TLS1.3:+AES-256-GCM:+AEAD:+SIGN-ALL:+GROUP-ALL",
+           tls13_included_labels, tls13_excluded_labels);
+
+       gnutls_global_deinit();
+       remove(filename);
 }