diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-04-17 10:59:25 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2018-04-18 16:17:44 +0200 |
commit | 2bc0a7f5cc4c203d3ad11e0b73c77986ffa5bf28 (patch) | |
tree | be8121c87b8e6e5a98751a9a4b1f837d377ffb18 | |
parent | dfc40f1250228278ec4c0d1d5bc29d396605b535 (diff) | |
download | gnutls-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.c | 26 | ||||
-rw-r--r-- | lib/constate.h | 2 | ||||
-rw-r--r-- | lib/handshake.c | 2 | ||||
-rw-r--r-- | lib/state.c | 2 |
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); |