summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2018-04-17 10:59:25 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2018-04-18 16:17:44 +0200
commit2bc0a7f5cc4c203d3ad11e0b73c77986ffa5bf28 (patch)
treebe8121c87b8e6e5a98751a9a4b1f837d377ffb18
parentdfc40f1250228278ec4c0d1d5bc29d396605b535 (diff)
downloadgnutls-tmp-constate-fix.tar.gz
_gnutls_epoch_new: allow re-allocation epoch next epochtmp-constate-fix
On certain cases when re-handshake is interrupted by application data, _gnutls_epoch_new() will be called twice. Make sure that this does not lead to an error. We also rename the function to clarify its purpose _gnutls_epoch_setup_next(). Resolves #426 Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r--lib/constate.c26
-rw-r--r--lib/constate.h2
-rw-r--r--lib/handshake.c2
-rw-r--r--lib/state.c2
4 files changed, 22 insertions, 10 deletions
diff --git a/lib/constate.c b/lib/constate.c
index bdafe91b5f..62a1239718 100644
--- a/lib/constate.c
+++ b/lib/constate.c
@@ -546,7 +546,7 @@ int _gnutls_epoch_dup(gnutls_session_t session)
ret = _gnutls_epoch_get(session, EPOCH_NEXT, &next);
if (ret < 0) {
- ret = _gnutls_epoch_new(session, 0, &next);
+ ret = _gnutls_epoch_setup_next(session, 0, &next);
if (ret < 0)
return gnutls_assert_val(ret);
}
@@ -817,22 +817,33 @@ _gnutls_epoch_get(gnutls_session_t session, unsigned int epoch_rel,
return 0;
}
+/* Ensures that the next epoch is setup. When an epoch will null ciphers
+ * is to be setup, call with @null_epoch set to true. In that case
+ * the epoch is fully initialized after call.
+ */
int
-_gnutls_epoch_new(gnutls_session_t session, unsigned null_epoch, record_parameters_st **newp)
+_gnutls_epoch_setup_next(gnutls_session_t session, unsigned null_epoch, record_parameters_st **newp)
{
record_parameters_st **slot;
- _gnutls_record_log("REC[%p]: Allocating epoch #%u\n", session,
- session->security_parameters.epoch_next);
-
slot = epoch_get_slot(session, session->security_parameters.epoch_next);
/* If slot out of range or not empty. */
if (slot == NULL)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
- if (*slot != NULL)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (*slot != NULL) { /* already initialized */
+ if (unlikely(null_epoch && !(*slot)->initialized))
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ if (unlikely((*slot)->epoch != session->security_parameters.epoch_next))
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ goto finish;
+ }
+
+ _gnutls_record_log("REC[%p]: Allocating epoch #%u\n", session,
+ session->security_parameters.epoch_next);
*slot = gnutls_calloc(1, sizeof(record_parameters_st));
if (*slot == NULL)
@@ -854,6 +865,7 @@ _gnutls_epoch_new(gnutls_session_t session, unsigned null_epoch, record_paramete
UINT64DATA((*slot)->write.
sequence_number));
+ finish:
if (newp != NULL)
*newp = *slot;
diff --git a/lib/constate.h b/lib/constate.h
index 934cd3bba5..1d62edccfa 100644
--- a/lib/constate.h
+++ b/lib/constate.h
@@ -38,7 +38,7 @@ int _gnutls_epoch_dup(gnutls_session_t session);
int _gnutls_epoch_get(gnutls_session_t session, unsigned int epoch_rel,
record_parameters_st ** params_out);
-int _gnutls_epoch_new(gnutls_session_t session, unsigned null_epoch, record_parameters_st **newp);
+int _gnutls_epoch_setup_next(gnutls_session_t session, unsigned null_epoch, record_parameters_st **newp);
void _gnutls_epoch_gc(gnutls_session_t session);
void _gnutls_epoch_free(gnutls_session_t session,
record_parameters_st * state);
diff --git a/lib/handshake.c b/lib/handshake.c
index baae557c63..a530fb9a8c 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -2531,7 +2531,7 @@ int gnutls_handshake(gnutls_session_t session)
return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET);
ret =
- _gnutls_epoch_new(session, 0, NULL);
+ _gnutls_epoch_setup_next(session, 0, NULL);
if (ret < 0)
return gnutls_assert_val(ret);
diff --git a/lib/state.c b/lib/state.c
index 1062c446bf..a669cf3d6c 100644
--- a/lib/state.c
+++ b/lib/state.c
@@ -299,7 +299,7 @@ int gnutls_init(gnutls_session_t * session, unsigned int flags)
if (*session == NULL)
return GNUTLS_E_MEMORY_ERROR;
- ret = _gnutls_epoch_new(*session, 1, NULL);
+ ret = _gnutls_epoch_setup_next(*session, 1, NULL);
if (ret < 0) {
gnutls_free(*session);
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);