summaryrefslogtreecommitdiff
path: root/lib/ext
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2018-10-19 17:52:48 +0200
committerDaiki Ueno <dueno@redhat.com>2018-11-12 14:08:45 +0100
commit79f2f1cf5b91491be5f0e3486c416594ec522b25 (patch)
treeeec06e9a96e5c64449e3469c477fc1d332953d12 /lib/ext
parent8ada9c280c9044644dfad1f234e3da32f0df86a0 (diff)
downloadgnutls-79f2f1cf5b91491be5f0e3486c416594ec522b25.tar.gz
TLS 1.3: implement anti-replay measure using ClientHello recording
This implements ClientHello recording outlined in section 8.2 of RFC 8446. Signed-off-by: Daiki Ueno <dueno@redhat.com>
Diffstat (limited to 'lib/ext')
-rw-r--r--lib/ext/early_data.c3
-rw-r--r--lib/ext/pre_shared_key.c27
2 files changed, 29 insertions, 1 deletions
diff --git a/lib/ext/early_data.c b/lib/ext/early_data.c
index 729a528bd7..a58e473ae1 100644
--- a/lib/ext/early_data.c
+++ b/lib/ext/early_data.c
@@ -59,10 +59,13 @@ early_data_recv_params(gnutls_session_t session,
return gnutls_assert_val(0);
if (session->security_parameters.entity == GNUTLS_SERVER) {
+ /* The flag may be cleared by pre_shared_key
+ * extension, when replay is detected. */
if ((session->internals.flags & GNUTLS_ENABLE_EARLY_DATA) &&
/* Refuse early data when this is a second CH after HRR */
!(session->internals.hsk_flags & HSK_HRR_SENT))
session->internals.hsk_flags |= HSK_EARLY_DATA_ACCEPTED;
+
session->internals.hsk_flags |= HSK_EARLY_DATA_IN_FLIGHT;
} else {
if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_EE)
diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c
index 7e4374042b..bc7fc8aa95 100644
--- a/lib/ext/pre_shared_key.c
+++ b/lib/ext/pre_shared_key.c
@@ -25,6 +25,7 @@
#include "auth/psk.h"
#include "handshake.h"
#include "secrets.h"
+#include "tls13/anti_replay.h"
#include "tls13/psk_ext_parser.h"
#include "tls13/finished.h"
#include "tls13/session_ticket.h"
@@ -482,7 +483,9 @@ static int server_recv_params(gnutls_session_t session,
struct psk_st psk;
psk_auth_info_t info;
tls13_ticket_st ticket_data;
- uint32_t ticket_age;
+ /* These values should be set properly when session ticket is accepted. */
+ uint32_t ticket_age = UINT32_MAX;
+ struct timespec ticket_creation_time = { 0, 0 };
bool resuming;
ret = _gnutls13_psk_ext_parser_init(&psk_parser, data, len);
@@ -526,6 +529,10 @@ static int server_recv_params(gnutls_session_t session,
continue;
}
+ memcpy(&ticket_creation_time,
+ &ticket_data.creation_time,
+ sizeof(struct timespec));
+
tls13_ticket_deinit(&ticket_data);
resuming = 1;
@@ -612,6 +619,24 @@ static int server_recv_params(gnutls_session_t session,
info->username[psk.identity.size] = 0;
_gnutls_handshake_log("EXT[%p]: selected PSK identity: %s (%d)\n", session, info->username, psk_index);
} else {
+ if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
+ if (session->internals.anti_replay) {
+ ret = _gnutls_anti_replay_check(session,
+ ticket_age,
+ &ticket_creation_time,
+ &binder_recvd);
+ if (ret < 0) {
+ session->internals.hsk_flags &= ~HSK_EARLY_DATA_ACCEPTED;
+ _gnutls_handshake_log("EXT[%p]: replay detected; rejecting early data\n",
+ session);
+ }
+ } else {
+ _gnutls_handshake_log("EXT[%p]: anti-replay is not enabled; rejecting early data\n",
+ session);
+ session->internals.hsk_flags &= ~HSK_EARLY_DATA_ACCEPTED;
+ }
+ }
+
session->internals.resumed = RESUME_TRUE;
_gnutls_handshake_log("EXT[%p]: selected resumption PSK identity (%d)\n", session, psk_index);
}