summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2018-05-14 16:05:27 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2018-05-26 04:12:04 +0000
commit34620f5b9291f5afb56012e04302df6006b7faf5 (patch)
treec929880d8a6372758957a48157efc39f79d9375e
parent87ce20ec7f43a1f90bea8d931f77422ddd94b951 (diff)
downloadgnutls-34620f5b9291f5afb56012e04302df6006b7faf5.tar.gz
handshake: TLS1.3 async messages trigger the handshake hook
That is, the callback set with gnutls_handshake_set_hook_function() is now called even on the async handshake messages received under TLS1.3, such as key update, etc. Resolves #441 Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r--lib/handshake-tls13.c8
-rw-r--r--lib/handshake.c31
-rw-r--r--lib/handshake.h5
-rw-r--r--tests/tls13/key_update.c53
4 files changed, 78 insertions, 19 deletions
diff --git a/lib/handshake-tls13.c b/lib/handshake-tls13.c
index 427392b6f3..ef7862f9e2 100644
--- a/lib/handshake-tls13.c
+++ b/lib/handshake-tls13.c
@@ -430,6 +430,10 @@ _gnutls13_recv_async_handshake(gnutls_session_t session, gnutls_buffer_st *buf)
if (ret < 0)
return gnutls_assert_val(ret);
+ ret = _gnutls_call_hook_func(session, type, GNUTLS_HOOK_PRE, 1, buf->data, buf->length);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
switch(type) {
case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST:
if (!(session->security_parameters.entity == GNUTLS_CLIENT) ||
@@ -474,6 +478,10 @@ _gnutls13_recv_async_handshake(gnutls_session_t session, gnutls_buffer_st *buf)
return GNUTLS_E_UNEXPECTED_PACKET;
}
+ ret = _gnutls_call_hook_func(session, type, GNUTLS_HOOK_POST, 1, buf->data, buf->length);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
return 0;
}
diff --git a/lib/handshake.c b/lib/handshake.c
index a023ab2ad4..c12ecefa8c 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -800,7 +800,7 @@ int _gnutls_send_finished(gnutls_session_t session, int again)
if (again == 0) {
bufel =
- _gnutls_handshake_alloc(session,
+ _gnutls_handshake_alloc(session,
MAX_VERIFY_DATA_SIZE);
if (bufel == NULL) {
gnutls_assert();
@@ -1116,11 +1116,10 @@ _gnutls_send_empty_handshake(gnutls_session_t session,
return _gnutls_send_handshake(session, bufel, type);
}
-inline
- static int call_hook_func(gnutls_session_t session,
- gnutls_handshake_description_t type,
- int post, unsigned incoming,
- const uint8_t *data, unsigned data_size)
+int _gnutls_call_hook_func(gnutls_session_t session,
+ gnutls_handshake_description_t type,
+ int post, unsigned incoming,
+ const uint8_t *data, unsigned data_size)
{
gnutls_datum_t msg = {(void*)data, data_size};
@@ -1214,8 +1213,8 @@ _gnutls_send_handshake(gnutls_session_t session, mbuffer_st * bufel,
return ret;
}
- ret = call_hook_func(session, type, GNUTLS_HOOK_PRE, 0,
- _mbuffer_get_udata_ptr(bufel), _mbuffer_get_udata_size(bufel));
+ ret = _gnutls_call_hook_func(session, type, GNUTLS_HOOK_PRE, 0,
+ _mbuffer_get_udata_ptr(bufel), _mbuffer_get_udata_size(bufel));
if (ret < 0) {
gnutls_assert();
_mbuffer_xfree(&bufel);
@@ -1231,8 +1230,8 @@ _gnutls_send_handshake(gnutls_session_t session, mbuffer_st * bufel,
return ret;
}
- ret = call_hook_func(session, type, GNUTLS_HOOK_POST, 0,
- _mbuffer_get_udata_ptr(bufel), _mbuffer_get_udata_size(bufel));
+ ret = _gnutls_call_hook_func(session, type, GNUTLS_HOOK_POST, 0,
+ _mbuffer_get_udata_ptr(bufel), _mbuffer_get_udata_size(bufel));
if (ret < 0) {
gnutls_assert();
return ret;
@@ -1441,7 +1440,7 @@ _gnutls_recv_handshake(gnutls_session_t session,
}
session->internals.last_handshake_in = hsk.htype;
- ret = call_hook_func(session, hsk.htype, GNUTLS_HOOK_PRE, 1, hsk.data.data, hsk.data.length);
+ ret = _gnutls_call_hook_func(session, hsk.htype, GNUTLS_HOOK_PRE, 1, hsk.data.data, hsk.data.length);
if (ret < 0) {
gnutls_assert();
goto cleanup;
@@ -1567,7 +1566,7 @@ _gnutls_recv_handshake(gnutls_session_t session,
goto cleanup;
}
- ret2 = call_hook_func(session, hsk.htype, GNUTLS_HOOK_POST, 1, hsk.data.data, hsk.data.length);
+ ret2 = _gnutls_call_hook_func(session, hsk.htype, GNUTLS_HOOK_POST, 1, hsk.data.data, hsk.data.length);
if (ret2 < 0) {
ret = ret2;
gnutls_assert();
@@ -3011,8 +3010,8 @@ ssize_t _gnutls_send_change_cipher_spec(gnutls_session_t session, int again)
session->internals.dtls.hsk_write_seq++;
}
- ret = call_hook_func(session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, GNUTLS_HOOK_PRE, 0,
- data, 1);
+ ret = _gnutls_call_hook_func(session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, GNUTLS_HOOK_PRE, 0,
+ data, 1);
if (ret < 0) {
_mbuffer_xfree(&bufel);
return gnutls_assert_val(ret);
@@ -3027,8 +3026,8 @@ ssize_t _gnutls_send_change_cipher_spec(gnutls_session_t session, int again)
return gnutls_assert_val(ret);
}
- ret = call_hook_func(session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, GNUTLS_HOOK_POST, 0,
- data, 1);
+ ret = _gnutls_call_hook_func(session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, GNUTLS_HOOK_POST, 0,
+ data, 1);
if (ret < 0) {
return gnutls_assert_val(ret);
}
diff --git a/lib/handshake.h b/lib/handshake.h
index bdd9efa76d..465ee03b80 100644
--- a/lib/handshake.h
+++ b/lib/handshake.h
@@ -142,6 +142,11 @@ int _gnutls_check_if_cert_hash_is_same(gnutls_session_t session, gnutls_certific
#define EXPORTER_LABEL "exp master"
#define RES_LABEL "res master"
+int _gnutls_call_hook_func(gnutls_session_t session,
+ gnutls_handshake_description_t type,
+ int post, unsigned incoming,
+ const uint8_t *data, unsigned data_size);
+
int _gnutls_run_verify_callback(gnutls_session_t session, unsigned int side);
int _gnutls_recv_finished(gnutls_session_t session);
int _gnutls_send_finished(gnutls_session_t session, int again);
diff --git a/tests/tls13/key_update.c b/tests/tls13/key_update.c
index ac5f5cc1a5..bed8a682b4 100644
--- a/tests/tls13/key_update.c
+++ b/tests/tls13/key_update.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Red Hat, Inc.
+ * Copyright (C) 2017-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -46,6 +46,26 @@ static void tls_log_func(int level, const char *str)
#define MAX_BUF 1024
#define MSG "Hello TLS, and hi and how are you and more data here... and more... and even more and even more more data..."
+static unsigned key_update_msg_inc = 0;
+static unsigned key_update_msg_out = 0;
+
+static int hsk_callback(gnutls_session_t session, unsigned int htype,
+ unsigned post, unsigned int incoming, const gnutls_datum_t *msg)
+{
+ assert(post == GNUTLS_HOOK_PRE);
+
+ assert(msg->size == 1);
+
+ if (htype == GNUTLS_HANDSHAKE_KEY_UPDATE) {
+ if (incoming)
+ key_update_msg_inc++;
+ else
+ key_update_msg_out++;
+ }
+
+ return 0;
+}
+
static void run(const char *name, unsigned test)
{
/* Server stuff. */
@@ -105,6 +125,7 @@ static void run(const char *name, unsigned test)
gnutls_transport_set_pull_function(client, client_pull);
gnutls_transport_set_ptr(client, client);
+
HANDSHAKE(client, server);
if (debug)
success("Handshake established\n");
@@ -169,6 +190,8 @@ static void run(const char *name, unsigned test)
TRANSFER(client, server, MSG, strlen(MSG), buffer, MAX_BUF);
TRANSFER(server, client, MSG, strlen(MSG), buffer, MAX_BUF);
EMPTY_BUF(server, client, buffer, MAX_BUF);
+
+ sec_sleep(2);
break;
case 5:
success("%s: client cork\n", name);
@@ -199,11 +222,34 @@ static void run(const char *name, unsigned test)
fail("cannot send: %s\n", gnutls_strerror(ret));
EMPTY_BUF(server, client, buffer, MAX_BUF);
+
+ sec_sleep(2);
+ break;
+ case 6:
+ key_update_msg_inc = 0;
+ key_update_msg_out = 0;
+
+ success("%s: callbacks are called\n", name);
+
+ gnutls_handshake_set_hook_function(client, -1, GNUTLS_HOOK_PRE, hsk_callback);
+ gnutls_handshake_set_hook_function(server, -1, GNUTLS_HOOK_PRE, hsk_callback);
+
+ do {
+ ret = gnutls_session_key_update(client, GNUTLS_KU_PEER);
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+ if (ret < 0)
+ fail("error in key update: %s\n", gnutls_strerror(ret));
+
+ /* server receives the client key update and sends data */
+ TRANSFER(client, server, MSG, strlen(MSG), buffer, MAX_BUF);
+ TRANSFER(server, client, MSG, strlen(MSG), buffer, MAX_BUF);
+ EMPTY_BUF(server, client, buffer, MAX_BUF);
+
+ assert(key_update_msg_inc == 2);
+ assert(key_update_msg_out == 2);
break;
}
- if (debug)
- fputs("\n", stdout);
gnutls_bye(client, GNUTLS_SHUT_WR);
gnutls_bye(server, GNUTLS_SHUT_WR);
@@ -225,5 +271,6 @@ void doit(void)
run("single", 3);
run("single", 4);
run("single", 5);
+ run("single", 6);
run("all", 0); /* all one after each other */
}