summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnder Juaristi <a@juaristi.eus>2017-12-01 22:23:32 +0100
committerAnder Juaristi <ajuaristi@gmx.es>2017-12-13 20:06:34 +0100
commit17dacac3eed57db052fc237c54eba099e106baa6 (patch)
treeb37e4158f7274602affded0af0a487275ab234c5
parentab50e053a6ef9fd6ed0eed5a284b5380bfe7aee5 (diff)
downloadgnutls-17dacac3eed57db052fc237c54eba099e106baa6.tar.gz
psk: Save full ClientHello buffer + derive from PSKs if available
Signed-off-by: Ander Juaristi <a@juaristi.eus>
-rw-r--r--lib/buffers.c4
-rw-r--r--lib/gnutls_int.h11
-rw-r--r--lib/handshake.c53
-rw-r--r--lib/hello_ext.c23
-rw-r--r--lib/hello_ext.h16
5 files changed, 101 insertions, 6 deletions
diff --git a/lib/buffers.c b/lib/buffers.c
index 414ea50307..b0f33099fb 100644
--- a/lib/buffers.c
+++ b/lib/buffers.c
@@ -50,6 +50,7 @@
#include <system.h>
#include <constate.h> /* gnutls_epoch_get */
#include <handshake.h> /* remaining_time() */
+#include <hello_ext.h> /* _gnutls_ext_set_full_client_hello */
#include <errno.h>
#include <system.h>
#include "debug.h"
@@ -1252,6 +1253,9 @@ int _gnutls_parse_record_buffered_msgs(gnutls_session_t session)
/* if packet is complete then return it
*/
if (recv_buf[0].length == recv_buf[0].data.length) {
+ /* Reference the full ClientHello in case an extension needs it */
+ if (recv_buf->htype == GNUTLS_HANDSHAKE_CLIENT_HELLO)
+ _gnutls_ext_set_full_client_hello(session, recv_buf);
return 0;
}
bufel =
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index bb422ddbe9..98b66acb64 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -1173,6 +1173,17 @@ typedef struct {
* they are reset to zero prior to handshake start by gnutls_handshake. */
unsigned hsk_flags;
time_t last_key_update;
+ unsigned tls13_psk_selected;
+ gnutls_datum_t tls13_psk;
+ /* Read-only pointer to the full ClientHello message */
+ gnutls_buffer_st full_client_hello;
+ /* The offset at which extensions start in the ClientHello buffer */
+ int extensions_offset;
+
+ unsigned crt_requested; /* 1 if client auth was requested (i.e., client cert).
+ * In case of a server this holds 1 if we should wait
+ * for a client certificate verify
+ */
gnutls_buffer_st hb_local_data;
gnutls_buffer_st hb_remote_data;
diff --git a/lib/handshake.c b/lib/handshake.c
index 179fcb8009..9e309e6189 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -83,6 +83,7 @@ handshake_hash_buffer_reset(gnutls_session_t session)
session->internals.handshake_hash_buffer_server_finished_len = 0;
session->internals.handshake_hash_buffer_prev_len = 0;
session->internals.handshake_hash_buffer.length = 0;
+ session->internals.full_client_hello.length = 0;
return;
}
@@ -108,6 +109,7 @@ void _gnutls_handshake_hash_buffers_clear(gnutls_session_t session)
{
handshake_hash_buffer_reset(session);
_gnutls_buffer_clear(&session->internals.handshake_hash_buffer);
+ _gnutls_buffer_clear(&session->internals.full_client_hello);
}
/* Replace handshake message buffer, with the special synthetic message
@@ -1624,6 +1626,8 @@ read_server_hello(gnutls_session_t session,
int len = datalen;
const version_entry_st *vers;
gnutls_ext_flags_t ext_parse_flag;
+ const uint8_t *psk = NULL;
+ size_t psk_size = 0;
if (datalen < GNUTLS_RANDOM_SIZE+2) {
gnutls_assert();
@@ -1762,6 +1766,30 @@ read_server_hello(gnutls_session_t session,
if (ret < 0)
return gnutls_assert_val(ret);
+ if (vers->tls13_sem) {
+ /* TLS 1.3 Early Secret */
+ if (session->internals.tls13_psk_selected) {
+ psk = session->internals.tls13_psk.data;
+ psk_size = session->internals.tls13_psk.size;
+ }
+
+ ret = _tls13_init_secret(session, psk, psk_size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = _tls13_derive_secret(session, DERIVED_LABEL, sizeof(DERIVED_LABEL)-1,
+ NULL, 0, session->key.temp_secret);
+ if (ret < 0)
+ gnutls_assert();
+ }
+
+cleanup:
+
+ if (session->internals.tls13_psk_selected)
+ _gnutls_free_datum(&session->internals.tls13_psk);
+
return ret;
}
@@ -1987,6 +2015,8 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
char tmpbuf[2 * GNUTLS_MAX_SESSION_ID_SIZE + 1];
const version_entry_st *vers;
gnutls_ext_flags_t ext_parse_flag;
+ const uint8_t *psk = NULL;
+ size_t psk_size = 0;
_gnutls_buffer_init(&buf);
@@ -1997,9 +2027,16 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
if (vers->tls13_sem) {
/* TLS 1.3 Early Secret */
- ret = _tls13_init_secret(session, NULL, 0);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (session->internals.tls13_psk_selected) {
+ psk = session->internals.tls13_psk.data;
+ psk_size = session->internals.tls13_psk.size;
+ }
+
+ ret = _tls13_init_secret(session, psk, psk_size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto fail;
+ }
ext_parse_flag = GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO;
} else {
@@ -2007,8 +2044,10 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
}
ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto fail;
+ }
ret = _gnutls_buffer_append_data(&buf, &vers->major, 1);
if (ret < 0) {
@@ -2091,7 +2130,9 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
_gnutls_send_handshake(session, bufel,
GNUTLS_HANDSHAKE_SERVER_HELLO);
- fail:
+fail:
+ if (session->internals.tls13_psk_selected)
+ _gnutls_free_temp_key_datum(&session->internals.tls13_psk);
_gnutls_buffer_clear(&buf);
return ret;
}
diff --git a/lib/hello_ext.c b/lib/hello_ext.c
index 4a4b2cc675..7d8085b3d1 100644
--- a/lib/hello_ext.c
+++ b/lib/hello_ext.c
@@ -352,6 +352,7 @@ _gnutls_gen_hello_extensions(gnutls_session_t session,
return gnutls_assert_val(ret);
pos = ret;
+ _gnutls_ext_set_extensions_offset(session, pos);
for (i=0; i < session->internals.rexts_size; i++) {
ctx.ext = &session->internals.rexts[i];
@@ -481,6 +482,28 @@ int _gnutls_hello_ext_pack(gnutls_session_t session, gnutls_buffer_st *packed)
return 0;
}
+void _gnutls_ext_set_full_client_hello(gnutls_session_t session,
+ handshake_buffer_st *recv_buf)
+{
+ gnutls_buffer_st *buf = &session->internals.full_client_hello;
+ _gnutls_buffer_clear(buf);
+ _gnutls_buffer_append_prefix(buf, 8, recv_buf->htype);
+ _gnutls_buffer_append_prefix(buf, 24, recv_buf->data.length);
+ _gnutls_buffer_append_data(buf, recv_buf->data.data, recv_buf->data.length);
+}
+
+int _gnutls_ext_get_full_client_hello(gnutls_session_t session,
+ gnutls_datum_t *datum)
+{
+ gnutls_buffer_st *buf = &session->internals.full_client_hello;
+
+ if (!datum)
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ _gnutls_set_datum(datum, buf->data, buf->length);
+ return buf->length;
+}
+
static void
_gnutls_ext_set_resumed_session_data(gnutls_session_t session,
extensions_t id,
diff --git a/lib/hello_ext.h b/lib/hello_ext.h
index 577775d08a..5fa42f42c7 100644
--- a/lib/hello_ext.h
+++ b/lib/hello_ext.h
@@ -63,6 +63,22 @@ inline static void _gnutls_ext_set_msg(gnutls_session_t session, gnutls_ext_flag
session->internals.ext_msg = msg;
}
+inline static void _gnutls_ext_set_extensions_offset(gnutls_session_t session,
+ int offset)
+{
+ session->internals.extensions_offset = offset;
+}
+
+inline static int _gnutls_ext_get_extensions_offset(gnutls_session_t session)
+{
+ return session->internals.extensions_offset;
+}
+
+void _gnutls_ext_set_full_client_hello(gnutls_session_t session,
+ handshake_buffer_st *recv_buf);
+int _gnutls_ext_get_full_client_hello(gnutls_session_t session,
+ gnutls_datum_t *datum);
+
/* for session packing */
int _gnutls_hello_ext_pack(gnutls_session_t session, gnutls_buffer_st * packed);
int _gnutls_hello_ext_unpack(gnutls_session_t session,