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 /lib/constate.c | |
parent | dfc40f1250228278ec4c0d1d5bc29d396605b535 (diff) | |
download | gnutls-2bc0a7f5cc4c203d3ad11e0b73c77986ffa5bf28.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>
Diffstat (limited to 'lib/constate.c')
-rw-r--r-- | lib/constate.c | 26 |
1 files changed, 19 insertions, 7 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; |