summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2017-11-29 11:18:40 +0100
committerDaiki Ueno <dueno@redhat.com>2017-11-30 15:52:58 +0100
commit15e907c69ef2fa1bc476ec268bc1411eef157c2f (patch)
tree12a5849b47e70a5638e4530a98252db34b96b676
parentec19d4c148fba67b1e19c62191863bc2e54285e9 (diff)
downloadgnutls-tmp-draft-ietf-tls-tls13-21-dueno-sslkeylogfile.tar.gz
keylogfile: write TLS 1.3 secretstmp-draft-ietf-tls-tls13-21-dueno-sslkeylogfile
Signed-off-by: Daiki Ueno <dueno@redhat.com>
-rw-r--r--lib/constate.c13
-rw-r--r--lib/handshake-tls13.c4
-rw-r--r--tests/keylog-env.c72
3 files changed, 71 insertions, 18 deletions
diff --git a/lib/constate.c b/lib/constate.c
index 9635e4b008..fee9361d36 100644
--- a/lib/constate.c
+++ b/lib/constate.c
@@ -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);
diff --git a/lib/handshake-tls13.c b/lib/handshake-tls13.c
index 02889dc90d..9a36bacc40 100644
--- a/lib/handshake-tls13.c
+++ b/lib/handshake-tls13.c
@@ -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)
diff --git a/tests/keylog-env.c b/tests/keylog-env.c
index 2b0d166982..5f5f74e176 100644
--- a/tests/keylog-env.c
+++ b/tests/keylog-env.c
@@ -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);
}