summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2019-02-25 14:35:16 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2019-03-02 21:15:26 +0100
commit2db896b7fd3258851898652e9ddef7335f23e450 (patch)
treeb71baa9067348e4c11c37d3db3b2605a33b6a34f
parente53bd8ed2010cc061a9d36cfc36cf8d076894ee1 (diff)
downloadgnutls-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.c25
-rw-r--r--lib/gnutls_int.h4
-rw-r--r--lib/state.c15
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);
}