]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Protected _gnutls_epoch_get from _gnutls_epoch_gc on false start
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Mon, 25 Feb 2019 13:35:16 +0000 (14:35 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 2 Mar 2019 20:15:26 +0000 (21:15 +0100)
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
lib/constate.c
lib/gnutls_int.h
lib/state.c

index e6ed8a35328ba2b3ff3c2e5f914df8ecf06718b8..f2c9b839c1a9af1e9d348088049f3b3891cbde58 100644 (file)
@@ -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);
 }
 
index a340d3747d523dcf0ea49a42e0a2d03f8ad7e33c..4547ead0a4b3d20b4df2d043558fd3aeef0de7bf 100644 (file)
@@ -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;
index a00bd34ed9115935e05917d4e0c5af18137c5827..a8ff0d81f088757ddc98a596c34854892302dc83 100644 (file)
@@ -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);
 }