diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/constate.c | 24 | ||||
-rw-r--r-- | lib/ext/pre_shared_key.c | 12 | ||||
-rw-r--r-- | lib/gnutls_int.h | 2 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 43 | ||||
-rw-r--r-- | lib/libgnutls.map | 6 | ||||
-rw-r--r-- | lib/quic-api.c | 63 | ||||
-rw-r--r-- | lib/quic.h | 38 |
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 */ |