diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2019-02-25 14:35:16 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2019-03-02 21:15:26 +0100 |
commit | 2db896b7fd3258851898652e9ddef7335f23e450 (patch) | |
tree | b71baa9067348e4c11c37d3db3b2605a33b6a34f | |
parent | e53bd8ed2010cc061a9d36cfc36cf8d076894ee1 (diff) | |
download | gnutls-2db896b7fd3258851898652e9ddef7335f23e450.tar.gz |
Protected _gnutls_epoch_get from _gnutls_epoch_gc on false start
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r-- | lib/constate.c | 25 | ||||
-rw-r--r-- | lib/gnutls_int.h | 4 | ||||
-rw-r--r-- | lib/state.c | 15 |
3 files changed, 37 insertions, 7 deletions
diff --git a/lib/constate.c b/lib/constate.c index e6ed8a3532..f2c9b839c1 100644 --- a/lib/constate.c +++ b/lib/constate.c @@ -39,6 +39,7 @@ #include "secrets.h" #include "handshake.h" #include "crypto-api.h" +#include "locks.h" static const char keyexp[] = "key expansion"; static const int keyexp_length = sizeof(keyexp) - 1; @@ -906,18 +907,28 @@ _gnutls_epoch_get(gnutls_session_t session, unsigned int epoch_rel, record_parameters_st **params; int ret; + gnutls_mutex_lock(&session->internals.epoch_lock); + ret = epoch_resolve(session, epoch_rel, &epoch); - if (ret < 0) - return gnutls_assert_val(ret); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } params = epoch_get_slot(session, epoch); - if (params == NULL || *params == NULL) - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + if (params == NULL || *params == NULL) { + ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + goto cleanup; + } if (params_out) *params_out = *params; - return 0; + ret = 0; + +cleanup: + gnutls_mutex_unlock(&session->internals.epoch_lock); + return ret; } /* Ensures that the next epoch is setup. When an epoch will null ciphers @@ -1008,6 +1019,8 @@ void _gnutls_epoch_gc(gnutls_session_t session) _gnutls_record_log("REC[%p]: Start of epoch cleanup\n", session); + gnutls_mutex_lock(&session->internals.epoch_lock); + /* Free all dead cipher state */ for (i = 0; i < MAX_EPOCH_INDEX; i++) { if (session->record_parameters[i] != NULL) { @@ -1050,6 +1063,8 @@ void _gnutls_epoch_gc(gnutls_session_t session) session->security_parameters.epoch_min = session->record_parameters[0]->epoch; + gnutls_mutex_unlock(&session->internals.epoch_lock); + _gnutls_record_log("REC[%p]: End of epoch cleanup\n", session); } diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index a340d3747d..4547ead0a4 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1469,6 +1469,10 @@ typedef struct { /* anti-replay measure for 0-RTT mode */ gnutls_anti_replay_t anti_replay; + /* Protects _gnutls_epoch_gc() from _gnutls_epoch_get(); these may be + * called in parallel when false start is used and false start is used. */ + void *epoch_lock; + /* If you add anything here, check _gnutls_handshake_internal_state_clear(). */ } internals_st; diff --git a/lib/state.c b/lib/state.c index a00bd34ed9..a8ff0d81f0 100644 --- a/lib/state.c +++ b/lib/state.c @@ -459,8 +459,18 @@ int gnutls_init(gnutls_session_t * session, unsigned int flags) return ret; } + ret = gnutls_mutex_init(&(*session)->internals.epoch_lock); + if (ret < 0) { + gnutls_assert(); + gnutls_mutex_deinit(&(*session)->internals.post_negotiation_lock); + gnutls_free(*session); + return ret; + } + ret = _gnutls_epoch_setup_next(*session, 1, NULL); if (ret < 0) { + gnutls_mutex_deinit(&(*session)->internals.post_negotiation_lock); + gnutls_mutex_deinit(&(*session)->internals.epoch_lock); gnutls_free(*session); return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } @@ -599,8 +609,6 @@ void gnutls_deinit(gnutls_session_t session) if (session == NULL) return; - gnutls_mutex_deinit(&session->internals.post_negotiation_lock); - /* remove auth info firstly */ _gnutls_free_auth_info(session); @@ -650,6 +658,9 @@ void gnutls_deinit(gnutls_session_t session) /* overwrite any temp TLS1.3 keys */ gnutls_memset(&session->key.proto, 0, sizeof(session->key.proto)); + gnutls_mutex_deinit(&session->internals.post_negotiation_lock); + gnutls_mutex_deinit(&session->internals.epoch_lock); + gnutls_free(session); } |