From 7b84ba9d8d04ba1d240f0549259d3657803d0065 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 20 Nov 2017 16:01:29 +0100 Subject: Introduce key usage limits under TLS1.3 That introduces a transparent key update for sending key after the safety limit is reached. Resolves #130 Signed-off-by: Nikos Mavrogiannopoulos --- lib/algorithms/ciphers.c | 2 ++ lib/gnutls_int.h | 1 + lib/includes/gnutls/gnutls.h.in | 5 ++++- lib/record.c | 11 +++++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c index 5f04eba72e..69c2613965 100644 --- a/lib/algorithms/ciphers.c +++ b/lib/algorithms/ciphers.c @@ -165,6 +165,8 @@ static const cipher_entry_st algorithms[] = { .explicit_iv = 0, .xor_nonce = 1, .cipher_iv = 12, + /* in chacha20 we don't need a rekey after 2^24 messages */ + .no_rekey = 1, .tagsize = 16 }, { .name = "CAMELLIA-128-GCM", diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index daee408e83..d3862d5a4f 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -514,6 +514,7 @@ typedef struct cipher_entry_st { uint16_t tagsize; bool xor_nonce; /* In this TLS AEAD cipher xor the implicit_iv with the nonce */ bool only_aead; /* When set, this cipher is only available through the new AEAD API */ + bool no_rekey; /* whether this tls1.3 cipher doesn't need to rekey after 2^24 messages */ } cipher_entry_st; typedef struct gnutls_cipher_suite_entry_st { diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index c334eaeae5..af3b57ee4b 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -370,6 +370,8 @@ typedef enum { * For example x25519. This option is the most performant for client (less CPU spent * generating keys), but if the server doesn't support the advertized option it may * result to more roundtrips needed to discover the server's choice. + * @GNUTLS_NO_AUTO_REKEY: Disable auto-rekeying under TLS1.3. If this option is not specified + * gnutls will force a rekey after 2^24 records have been sent. * * Enumeration of different flags for gnutls_init() function. All the flags * can be combined except @GNUTLS_SERVER and @GNUTLS_CLIENT which are mutually @@ -393,7 +395,8 @@ typedef enum { GNUTLS_NO_TICKETS = (1<<10), GNUTLS_KEY_SHARE_TOP = (1<<11), GNUTLS_KEY_SHARE_TOP2 = (1<<12), - GNUTLS_KEY_SHARE_TOP3 = (1<<13) + GNUTLS_KEY_SHARE_TOP3 = (1<<13), + GNUTLS_NO_AUTO_REKEY = (1<<15) } gnutls_init_flags_t; /* compatibility defines (previous versions of gnutls diff --git a/lib/record.c b/lib/record.c index 3f2d543868..cee139d80c 100644 --- a/lib/record.c +++ b/lib/record.c @@ -581,6 +581,17 @@ _gnutls_send_tlen_int(gnutls_session_t session, content_type_t type, _gnutls_packet2str(type), type, (int) record_params->epoch, (int) cipher_size); + if (vers->tls13_sem && !(session->internals.flags & GNUTLS_NO_AUTO_REKEY) && + !(record_params->cipher->no_rekey)) { + if (unlikely(record_state->sequence_number.i[7] == 0xfd && + record_state->sequence_number.i[6] == 0xff && + record_state->sequence_number.i[5] == 0xff)) { + /* After we have sent 2^24 messages, mark the session + * as needing a key update. */ + session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_1; + } + } + return retval; } -- cgit v1.2.1