summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/constate.c24
-rw-r--r--lib/ext/pre_shared_key.c12
-rw-r--r--lib/gnutls_int.h2
-rw-r--r--lib/includes/gnutls/gnutls.h.in43
-rw-r--r--lib/libgnutls.map6
-rw-r--r--lib/quic-api.c63
-rw-r--r--lib/quic.h38
8 files changed, 189 insertions, 1 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index f1e3bb90b6..cf6d9aed88 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -81,7 +81,7 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c gthreads.h handshake-tls
cert-session.c handshake-checks.c dtls-sw.c dh-primes.c openpgp_compat.c \
crypto-selftests.c crypto-selftests-pk.c secrets.c extv.c extv.h \
hello_ext_lib.c hello_ext_lib.h ocsp-api.c stek.c cert-cred-rawpk.c \
- iov.c iov.h
+ iov.c iov.h quic-api.c quic.h
if WINDOWS
COBJECTS += system/keys-win.c
diff --git a/lib/constate.c b/lib/constate.c
index 51943ede69..c6329d7ba2 100644
--- a/lib/constate.c
+++ b/lib/constate.c
@@ -40,6 +40,7 @@
#include "handshake.h"
#include "crypto-api.h"
#include "locks.h"
+#include "quic.h"
static const char keyexp[] = "key expansion";
static const int keyexp_length = sizeof(keyexp) - 1;
@@ -274,6 +275,11 @@ _tls13_update_keys(gnutls_session_t session, hs_stage_t stage,
ret = _tls13_expand_secret(session, "iv", 2, NULL, 0, session->key.proto.tls13.ap_ckey, iv_size, iv_block);
if (ret < 0)
return gnutls_assert_val(ret);
+
+ _gnutls_call_secret_hook_func(session, GNUTLS_ENCRYPTION_LEVEL_APPLICATION,
+ GNUTLS_CLIENT,
+ session->key.proto.tls13.ap_ckey,
+ session->security_parameters.prf->output_size);
} else {
ret = _tls13_expand_secret(session, APPLICATION_TRAFFIC_UPDATE,
sizeof(APPLICATION_TRAFFIC_UPDATE)-1,
@@ -291,6 +297,11 @@ _tls13_update_keys(gnutls_session_t session, hs_stage_t stage,
ret = _tls13_expand_secret(session, "iv", 2, NULL, 0, session->key.proto.tls13.ap_skey, iv_size, iv_block);
if (ret < 0)
return gnutls_assert_val(ret);
+
+ _gnutls_call_secret_hook_func(session, GNUTLS_ENCRYPTION_LEVEL_APPLICATION,
+ GNUTLS_SERVER,
+ session->key.proto.tls13.ap_skey,
+ session->security_parameters.prf->output_size);
}
upd_state->mac_key_size = 0;
@@ -390,6 +401,7 @@ _tls13_set_keys(gnutls_session_t session, hs_stage_t stage,
unsigned label_size, hsk_len;
const char *keylog_label;
void *ckey, *skey;
+ gnutls_encryption_level_t level;
int ret;
if (stage == STAGE_UPD_OURS || stage == STAGE_UPD_PEERS)
@@ -406,12 +418,14 @@ _tls13_set_keys(gnutls_session_t session, hs_stage_t stage,
hsk_len = session->internals.handshake_hash_buffer.length;
keylog_label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
ckey = session->key.proto.tls13.hs_ckey;
+ level = GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE;
} 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";
ckey = session->key.proto.tls13.ap_ckey;
+ level = GNUTLS_ENCRYPTION_LEVEL_APPLICATION;
}
ret = _tls13_derive_secret(session, label, label_size,
@@ -426,6 +440,10 @@ _tls13_set_keys(gnutls_session_t session, hs_stage_t stage,
ckey,
session->security_parameters.prf->output_size);
+ _gnutls_call_secret_hook_func(session, level,
+ GNUTLS_CLIENT, ckey,
+ session->security_parameters.prf->output_size);
+
/* client keys */
ret = _tls13_expand_secret(session, "key", 3, NULL, 0, ckey, key_size, ckey_block);
if (ret < 0)
@@ -441,11 +459,13 @@ _tls13_set_keys(gnutls_session_t session, hs_stage_t stage,
label_size = sizeof(HANDSHAKE_SERVER_TRAFFIC_LABEL)-1;
keylog_label = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
skey = session->key.proto.tls13.hs_skey;
+ level = GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE;
} else {
label = APPLICATION_SERVER_TRAFFIC_LABEL;
label_size = sizeof(APPLICATION_SERVER_TRAFFIC_LABEL)-1;
keylog_label = "SERVER_TRAFFIC_SECRET_0";
skey = session->key.proto.tls13.ap_skey;
+ level = GNUTLS_ENCRYPTION_LEVEL_APPLICATION;
}
ret = _tls13_derive_secret(session, label, label_size,
@@ -461,6 +481,10 @@ _tls13_set_keys(gnutls_session_t session, hs_stage_t stage,
skey,
session->security_parameters.prf->output_size);
+ _gnutls_call_secret_hook_func(session, level,
+ GNUTLS_SERVER, skey,
+ session->security_parameters.prf->output_size);
+
ret = _tls13_expand_secret(session, "key", 3, NULL, 0, skey, key_size, skey_block);
if (ret < 0)
return gnutls_assert_val(ret);
diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c
index d344922910..57d36dee95 100644
--- a/lib/ext/pre_shared_key.c
+++ b/lib/ext/pre_shared_key.c
@@ -30,6 +30,7 @@
#include "tls13/psk_ext_parser.h"
#include "tls13/finished.h"
#include "tls13/session_ticket.h"
+#include "quic.h"
#include "auth/psk_passwd.h"
#include <ext/session_ticket.h>
#include <ext/pre_shared_key.h>
@@ -194,6 +195,7 @@ generate_early_secrets(gnutls_session_t session,
const mac_entry_st *prf)
{
int ret;
+ record_parameters_st *record_params;
ret = _tls13_derive_secret2(prf, EARLY_TRAFFIC_LABEL, sizeof(EARLY_TRAFFIC_LABEL)-1,
session->internals.handshake_hash_buffer.data,
@@ -207,6 +209,16 @@ generate_early_secrets(gnutls_session_t session,
session->key.proto.tls13.e_ckey,
prf->output_size);
+ ret =
+ _gnutls_epoch_get(session, EPOCH_READ_CURRENT, &record_params);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ _gnutls_call_secret_hook_func(session, GNUTLS_ENCRYPTION_LEVEL_EARLY,
+ GNUTLS_CLIENT,
+ session->key.proto.tls13.e_ckey,
+ prf->output_size);
+
ret = _tls13_derive_secret2(prf, EARLY_EXPORTER_MASTER_LABEL, sizeof(EARLY_EXPORTER_MASTER_LABEL)-1,
session->internals.handshake_hash_buffer.data,
session->internals.handshake_hash_buffer_client_hello_len,
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 3b683a1de1..617757d8e8 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -1246,6 +1246,8 @@ typedef struct {
unsigned int h_type; /* the hooked type */
int16_t h_post; /* whether post-generation/receive */
+ gnutls_secret_hook_func secret_hook;
+
/* holds the selected certificate and key.
* use _gnutls_selected_certs_deinit() and _gnutls_selected_certs_set()
* to change them.
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index f4bbbce306..6878166017 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -3087,6 +3087,49 @@ void gnutls_anti_replay_set_add_function(gnutls_anti_replay_t,
void gnutls_anti_replay_set_ptr(gnutls_anti_replay_t, void *ptr);
+/* QUIC related functions */
+
+/**
+ * gnutls_encryption_level_t:
+ * @GNUTLS_ENCRYPTION_LEVEL_INITIAL: the Initial Keys encryption level.
+ * @GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE: the Handshake Keys encryption level.
+ * @GNUTLS_ENCRYPTION_LEVEL_APPLICATION: the Application Data (1-RTT) Keys encryption level.
+ * @GNUTLS_ENCRYPTION_LEVEL_EARLY: the Early Data (0-RTT) Keys encryption level.
+ *
+ * Enumeration of encryption levels where new secrets are set. This
+ * is used by a secret hook function set with
+ * gnutls_session_set_secret_hook_function().
+ *
+ * Since: 3.6.11
+ */
+typedef enum gnutls_encryption_level {
+ GNUTLS_ENCRYPTION_LEVEL_INITIAL,
+ GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE,
+ GNUTLS_ENCRYPTION_LEVEL_APPLICATION,
+ GNUTLS_ENCRYPTION_LEVEL_EARLY
+} gnutls_encryption_level_t;
+
+/**
+ * gnutls_secret_hook_func:
+ * @session: the current session
+ * @level: the encryption level where the secret is installed
+ * @incoming: non zero if the secret is for reading an incoming message, zero otherwise
+ * @secret: the (const) data of the new traffic secret
+ *
+ * Function prototype for secret installation hooks. It is set using
+ * gnutls_session_set_secret_hook_function().
+ *
+ * Since: 3.6.11
+ */
+typedef void (*gnutls_secret_hook_func) (gnutls_session_t session,
+ gnutls_encryption_level_t level,
+ unsigned int incoming,
+ const gnutls_datum_t *secret);
+
+void gnutls_session_set_secret_hook_function(gnutls_session_t session,
+ gnutls_secret_hook_func func);
+
+
/* FIPS140-2 related functions */
unsigned gnutls_fips140_mode_enabled(void);
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 6e1da857f6..1a912acb79 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1301,6 +1301,12 @@ GNUTLS_3_6_10
gnutls_aead_cipher_decryptv2;
} GNUTLS_3_6_9;
+GNUTLS_3_6_11
+{
+ global:
+ gnutls_session_set_secret_hook_function;
+} GNUTLS_3_6_10;
+
GNUTLS_FIPS140_3_4 {
global:
gnutls_cipher_self_test;
diff --git a/lib/quic-api.c b/lib/quic-api.c
new file mode 100644
index 0000000000..31908ac507
--- /dev/null
+++ b/lib/quic-api.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 Free Software Foundation, Inc.
+ *
+ * Author: Aniketh Girish
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ *
+ */
+
+/* This file contains TLS API for QUIC protocol related types, prototypes and includes.
+ */
+
+#include "gnutls_int.h"
+#include "quic.h"
+#include <gnutls/gnutls.h>
+
+
+/**
+ * gnutls_session_set_secret_hook_function:
+ * @session: is #gnutls_session_t type
+ * @func: is the function to be called
+ *
+ * This function will set a callback to be called when a new traffic
+ * secret is installed. The callback will only be called when TLS 1.3
+ * or later is negotiated.
+ *
+ * Since: 3.6.11
+ */
+void
+gnutls_session_set_secret_hook_function(gnutls_session_t session,
+ gnutls_secret_hook_func func)
+{
+ session->internals.secret_hook = func;
+}
+
+void
+_gnutls_call_secret_hook_func(gnutls_session_t session,
+ gnutls_encryption_level_t level,
+ unsigned int sender,
+ const uint8_t *secret,
+ size_t secret_size)
+{
+ if (session->internals.secret_hook != NULL) {
+ unsigned int incoming =
+ sender != session->security_parameters.entity;
+ gnutls_datum_t data = {(void*)secret, secret_size};
+
+ session->internals.secret_hook(session, level, incoming, &data);
+ }
+}
diff --git a/lib/quic.h b/lib/quic.h
new file mode 100644
index 0000000000..9eb6eebe0d
--- /dev/null
+++ b/lib/quic.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 Free Software Foundation, Inc.
+ *
+ * Author: Aniketh Girish
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ *
+ */
+
+/* This file contains TLS API for QUIC protocol related types, prototypes and includes.
+ */
+
+
+#ifndef GNUTLS_LIB_QUIC_H
+#define GNUTLS_LIB_QUIC_H
+
+#include "gnutls_int.h"
+
+void _gnutls_call_secret_hook_func(gnutls_session_t session,
+ gnutls_encryption_level_t level,
+ unsigned int sender,
+ const uint8_t *secret,
+ size_t secret_size);
+
+#endif /* GNUTLS_LIB_QUIC_H */