]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
handshake: add callback to get notified with traffic secret change
authorDaiki Ueno <ueno@gnu.org>
Fri, 21 Feb 2020 16:48:37 +0000 (17:48 +0100)
committerDaiki Ueno <ueno@gnu.org>
Thu, 19 Nov 2020 17:18:38 +0000 (18:18 +0100)
For the use with QUIC, the change of traffic secrets must be notified
_after_ a new epoch is set up for reading or writing, and we can't
simply reuse the keylog mechanism.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
devel/libgnutls-latest-x86_64.abi
devel/symbols.last
doc/Makefile.am
doc/manpages/Makefile.am
lib/constate.c
lib/gnutls_int.h
lib/includes/gnutls/gnutls.h.in
lib/libgnutls.map

index 18ae9ff9450b1ae564fdb4fbf86dd9e64f35d0dc..8dbbe794b2767bef4f156b374ea14daa473fbd89 100644 (file)
     <elf-symbol name='gnutls_handshake_set_private_extensions' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='gnutls_handshake_set_random' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='gnutls_handshake_set_read_function' version='GNUTLS_3_7_0' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='gnutls_handshake_set_secret_function' version='GNUTLS_3_7_0' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='gnutls_handshake_set_timeout' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='gnutls_handshake_write' version='GNUTLS_3_7_0' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='gnutls_hash' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
index 5c0a8e34cce51e15ccc2d8d99a7a15df81e50b42..3a9be1bc5e693c48ada4e0411178b5f9d2c02207 100644 (file)
@@ -271,6 +271,7 @@ gnutls_handshake_set_post_client_hello_function@GNUTLS_3_4
 gnutls_handshake_set_private_extensions@GNUTLS_3_4
 gnutls_handshake_set_random@GNUTLS_3_4
 gnutls_handshake_set_read_function@GNUTLS_3_7_0
+gnutls_handshake_set_secret_function@GNUTLS_3_7_0
 gnutls_handshake_set_timeout@GNUTLS_3_4
 gnutls_handshake_write@GNUTLS_3_7_0
 gnutls_hash@GNUTLS_3_4
index 0dd9b9e32fa86b1e35ec752c6ca9c8d600267776..fd495a83a35dbb0470f2ac05f0ce3d97954cea1f 100644 (file)
@@ -1088,6 +1088,8 @@ FUNCS += functions/gnutls_handshake_set_random
 FUNCS += functions/gnutls_handshake_set_random.short
 FUNCS += functions/gnutls_handshake_set_read_function
 FUNCS += functions/gnutls_handshake_set_read_function.short
+FUNCS += functions/gnutls_handshake_set_secret_function
+FUNCS += functions/gnutls_handshake_set_secret_function.short
 FUNCS += functions/gnutls_handshake_set_timeout
 FUNCS += functions/gnutls_handshake_set_timeout.short
 FUNCS += functions/gnutls_handshake_write
index 2ecd7389b90e9d5d2d36b6b13d26bfc0d7225fc6..66fb70ab565e3c427325ac6f17ba9c58ebd9e7bf 100644 (file)
@@ -345,6 +345,7 @@ APIMANS += gnutls_handshake_set_post_client_hello_function.3
 APIMANS += gnutls_handshake_set_private_extensions.3
 APIMANS += gnutls_handshake_set_random.3
 APIMANS += gnutls_handshake_set_read_function.3
+APIMANS += gnutls_handshake_set_secret_function.3
 APIMANS += gnutls_handshake_set_timeout.3
 APIMANS += gnutls_handshake_write.3
 APIMANS += gnutls_hash.3
index af6a13598d617e3458868bb99ffa6eae35538a6e..3717522d3808f4e22f2a0fc744f31abee59f363f 100644 (file)
@@ -1109,6 +1109,67 @@ _gnutls_epoch_free(gnutls_session_t session, record_parameters_st * params)
        gnutls_free(params);
 }
 
+static int
+_gnutls_call_secret_func(gnutls_session_t session,
+                        hs_stage_t stage,
+                        bool for_read, bool for_write)
+{
+       const mac_entry_st *prf = NULL;
+       gnutls_record_encryption_level_t level;
+       void *secret_read = NULL, *secret_write = NULL;
+
+       if (session->internals.h_secret_func == NULL)
+               return 0;
+
+       switch (stage) {
+       case STAGE_EARLY:
+               prf = session->key.binders[0].prf;
+               level = GNUTLS_ENCRYPTION_LEVEL_EARLY;
+               if (for_read) {
+                       if (unlikely(session->security_parameters.entity == GNUTLS_CLIENT))
+                               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+                       secret_read = session->key.proto.tls13.e_ckey;
+               }
+               break;
+       case STAGE_HS:
+               prf = session->security_parameters.prf;
+               level = GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE;
+               if (for_read)
+                       secret_read = session->security_parameters.
+                               entity == GNUTLS_CLIENT ?
+                               session->key.proto.tls13.hs_skey :
+                               session->key.proto.tls13.hs_ckey;
+               if (for_write)
+                       secret_write = session->security_parameters.
+                               entity == GNUTLS_CLIENT ?
+                               session->key.proto.tls13.hs_ckey :
+                               session->key.proto.tls13.hs_skey;
+               break;
+       case STAGE_APP:
+       case STAGE_UPD_OURS:
+       case STAGE_UPD_PEERS:
+               prf = session->security_parameters.prf;
+               level = GNUTLS_ENCRYPTION_LEVEL_APPLICATION;
+               if (for_read)
+                       secret_read = session->security_parameters.
+                               entity == GNUTLS_CLIENT ?
+                               session->key.proto.tls13.ap_skey :
+                               session->key.proto.tls13.ap_ckey;
+               if (for_write)
+                       secret_write = session->security_parameters.
+                               entity == GNUTLS_CLIENT ?
+                               session->key.proto.tls13.ap_ckey :
+                               session->key.proto.tls13.ap_skey;
+               break;
+       default:
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+       }
+
+       return session->internals.h_secret_func(session, level,
+                                               secret_read, secret_write,
+                                               prf->output_size);
+}
+
 int _tls13_connection_state_init(gnutls_session_t session, hs_stage_t stage)
 {
        const uint16_t epoch_next =
@@ -1126,6 +1187,10 @@ int _tls13_connection_state_init(gnutls_session_t session, hs_stage_t stage)
        session->security_parameters.epoch_read = epoch_next;
        session->security_parameters.epoch_write = epoch_next;
 
+       ret = _gnutls_call_secret_func(session, stage, 1, 1);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
        return 0;
 }
 
@@ -1145,6 +1210,10 @@ int _tls13_read_connection_state_init(gnutls_session_t session, hs_stage_t stage
 
        session->security_parameters.epoch_read = epoch_next;
 
+       ret = _gnutls_call_secret_func(session, stage, 1, 0);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
        return 0;
 }
 
@@ -1164,6 +1233,10 @@ int _tls13_write_connection_state_init(gnutls_session_t session, hs_stage_t stag
 
        session->security_parameters.epoch_write = epoch_next;
 
+       ret = _gnutls_call_secret_func(session, stage, 0, 1);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
        return 0;
 }
 
@@ -1186,3 +1259,20 @@ _tls13_init_record_state(gnutls_cipher_algorithm_t algo, record_state_st *state)
 
        return 0;
 }
+
+/**
+ * gnutls_handshake_set_secret_function:
+ * @session: is a #gnutls_session_t type.
+ * @func: the secret func
+ *
+ * This function will set a callback to be called when a new traffic
+ * secret is installed.
+ *
+ * Since: 3.7.0
+ */
+void
+gnutls_handshake_set_secret_function(gnutls_session_t session,
+                                    gnutls_handshake_secret_func func)
+{
+       session->internals.h_secret_func = func;
+}
index b1ed6178c08aa43fd7d33d78737ea1dff3205bea..182ae6f6c9af1c0325b435a463271f7104fa398a 100644 (file)
@@ -1233,6 +1233,7 @@ typedef struct {
        unsigned int h_type;    /* the hooked type */
        int16_t h_post;         /* whether post-generation/receive */
        gnutls_handshake_read_func h_read_func;
+       gnutls_handshake_secret_func h_secret_func;
 
        gnutls_keylog_func keylog_func;
 
index 31709117b05b1eaf5b9ba0e24a1017bfcb9b2ac8..0fe672fa963a29aaa08c8299bd61c3a5a8dc560e 100644 (file)
@@ -3241,6 +3241,30 @@ gnutls_handshake_write(gnutls_session_t session,
                       gnutls_record_encryption_level_t level,
                       const void *data, size_t data_size);
 
+  /**
+   * gnutls_handshake_secret_func:
+   * @session: the current session
+   * @level: the encryption level
+   * @secret_read: the secret used for reading, can be %NULL if not set
+   * @secret_write: the secret used for writing, can be %NULL if not set
+   * @secret_size: the size of the secrets
+   *
+   * Function prototype for secret hooks. It is set using
+   * gnutls_handshake_set_secret_function().
+   *
+   * Returns: Non zero on error.
+   * Since: 3.7.0
+   */
+typedef int (*gnutls_handshake_secret_func) (gnutls_session_t session,
+                                            gnutls_record_encryption_level_t level,
+                                            const void *secret_read,
+                                            const void *secret_write,
+                                            size_t secret_size);
+
+void
+gnutls_handshake_set_secret_function(gnutls_session_t session,
+                                    gnutls_handshake_secret_func func);
+
 /* FIPS140-2 related functions */
 unsigned gnutls_fips140_mode_enabled(void);
 
index 1f9f69e45b32a6b5b990fbdb2da28c6b80feb365..58db94fb78f6100d6e61c841bb1f5dcb79c083ff 100644 (file)
@@ -1335,6 +1335,7 @@ GNUTLS_3_7_0
 {
  global:
        gnutls_handshake_set_read_function;
+       gnutls_handshake_set_secret_function;
        gnutls_handshake_write;
        gnutls_x509_trust_list_set_getissuer_function;
        gnutls_x509_trust_list_get_ptr;