/* A handshake process has been completed */
bool initial_negotiation_completed;
+ void *post_negotiation_lock; /* protects access to the variable above
+ * in the cases where negotiation is incomplete
+ * after gnutls_handshake() - early/false start */
/* The type of transport protocol; stream or datagram */
transport_t transport;
#include "tls13/finished.h"
#include "tls13/key_update.h"
#include "ext/pre_shared_key.h"
+#include "locks.h"
static int generate_rms_keys(gnutls_session_t session);
static int generate_hs_traffic_keys(gnutls_session_t session);
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
}
-
- /* explicitly reset any false start flags */
+ /* no lock of post_negotiation_lock is required here as this is not run
+ * after handshake */
session->internals.recv_state = RECV_STATE_0;
session->internals.initial_negotiation_completed = 1;
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
}
- /* explicitly reset any false start flags */
+ /* explicitly reset any early start flags */
+ gnutls_mutex_lock(&session->internals.post_negotiation_lock);
session->internals.recv_state = RECV_STATE_0;
session->internals.initial_negotiation_completed = 1;
+ gnutls_mutex_unlock(&session->internals.post_negotiation_lock);
SAVE_TRANSCRIPT;
#include <dtls.h>
#include "secrets.h"
#include "tls13/session_ticket.h"
+#include "locks.h"
#define TRUE 1
#define FALSE 0
}
- session->internals.initial_negotiation_completed = 1;
-
cleanup:
_gnutls_buffer_clear(&buf);
}
/* explicitly reset any false start flags */
+ gnutls_mutex_lock(&session->internals.post_negotiation_lock);
+ session->internals.initial_negotiation_completed = 1;
session->internals.recv_state = RECV_STATE_0;
+ gnutls_mutex_unlock(&session->internals.post_negotiation_lock);
return 0;
}
break;
}
-
return 0;
}
break;
}
+ /* no lock of post_negotiation_lock is required here as this is not run
+ * after handshake */
+ session->internals.initial_negotiation_completed = 1;
+
return _gnutls_check_id_for_change(session);
}
#include <dh.h>
#include <random.h>
#include <xsize.h>
+#include "locks.h"
struct tls_record_st {
uint16_t header_size;
if (unlikely(!session->internals.initial_negotiation_completed)) {
/* this is to protect buggy applications from sending unencrypted
- * data. We allow sending however, if we are in false start handshake
- * state. */
- if (session->internals.recv_state != RECV_STATE_FALSE_START &&
+ * data. We allow sending however, if we are in false or early start
+ * handshake state. */
+ gnutls_mutex_lock(&session->internals.post_negotiation_lock);
+
+ /* we intentionally re-check the initial_negotation_completed variable
+ * to avoid locking during normal operation of gnutls_record_send2() */
+ if (!session->internals.initial_negotiation_completed &&
+ session->internals.recv_state != RECV_STATE_FALSE_START &&
session->internals.recv_state != RECV_STATE_FALSE_START_HANDLING &&
session->internals.recv_state != RECV_STATE_EARLY_START &&
session->internals.recv_state != RECV_STATE_EARLY_START_HANDLING &&
- !(session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT))
+ !(session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT)) {
+
+ gnutls_mutex_unlock(&session->internals.post_negotiation_lock);
return gnutls_assert_val(GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE);
+ }
+ gnutls_mutex_unlock(&session->internals.post_negotiation_lock);
}
if (unlikely(!vers))
#include "dtls.h"
#include "tls13/session_ticket.h"
#include "ext/cert_types.h"
+#include "locks.h"
/* to be used by supplemental data support to disable TLS1.3
* when supplemental data have been globally registered */
if (*session == NULL)
return GNUTLS_E_MEMORY_ERROR;
+ ret = gnutls_mutex_init(&(*session)->internals.post_negotiation_lock);
+ if (ret < 0) {
+ gnutls_assert();
+ gnutls_free(*session);
+ return ret;
+ }
+
ret = _gnutls_epoch_setup_next(*session, 1, NULL);
if (ret < 0) {
gnutls_free(*session);
if (session == NULL)
return;
+ gnutls_mutex_deinit(&session->internals.post_negotiation_lock);
+
/* remove auth info firstly */
_gnutls_free_auth_info(session);