diff options
Diffstat (limited to 'lib/constate.c')
-rw-r--r-- | lib/constate.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/lib/constate.c b/lib/constate.c index af6a13598d..3717522d38 100644 --- a/lib/constate.c +++ b/lib/constate.c @@ -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; +} |