diff options
-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); } |