summaryrefslogtreecommitdiff
path: root/lib/tls13
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2018-10-12 11:45:59 +0200
committerDaiki Ueno <dueno@redhat.com>2018-11-11 07:03:43 +0100
commit957f7537604b21653c0d456e55fabed600052508 (patch)
tree0e818d620669b1efe8f024eb1e4caf3f1d4217bd /lib/tls13
parentf39af59c4e7f7062b548c6c97e785bb6b6284371 (diff)
downloadgnutls-957f7537604b21653c0d456e55fabed600052508.tar.gz
handshake: handle early data
This plumbers early data handling in the handshake processes, which consists of: - traffic key updates taking into account of client_early_traffic_secret - early data buffering in both server and client - the EndOfEarlyData message handling - making use of max_early_data_size extension in NewSessionTicket Signed-off-by: Daiki Ueno <dueno@redhat.com>
Diffstat (limited to 'lib/tls13')
-rw-r--r--lib/tls13/early_data.c101
-rw-r--r--lib/tls13/early_data.h25
-rw-r--r--lib/tls13/session_ticket.c41
3 files changed, 164 insertions, 3 deletions
diff --git a/lib/tls13/early_data.c b/lib/tls13/early_data.c
new file mode 100644
index 0000000000..dd977fc410
--- /dev/null
+++ b/lib/tls13/early_data.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "gnutls_int.h"
+#include "handshake.h"
+#include "tls13/early_data.h"
+
+int _gnutls13_send_early_data(gnutls_session_t session)
+{
+ int ret;
+
+ if (!(session->security_parameters.entity == GNUTLS_CLIENT &&
+ session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT))
+ return 0;
+
+ while (session->internals.early_data_presend_buffer.length > 0) {
+ ret =
+ gnutls_record_send(session,
+ session->internals.
+ early_data_presend_buffer.data,
+ session->internals.
+ early_data_presend_buffer.
+ length);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ session->internals.early_data_presend_buffer.data += ret;
+ session->internals.early_data_presend_buffer.length -= ret;
+ }
+
+
+ return 0;
+}
+
+int _gnutls13_send_end_of_early_data(gnutls_session_t session, unsigned again)
+{
+ int ret;
+ mbuffer_st *bufel = NULL;
+ gnutls_buffer_st buf;
+
+ if (!(session->security_parameters.entity == GNUTLS_CLIENT &&
+ session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED))
+ return 0;
+
+ if (again == 0) {
+ ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ bufel = _gnutls_buffer_to_mbuffer(&buf);
+ }
+
+ return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_END_OF_EARLY_DATA);
+}
+
+int _gnutls13_recv_end_of_early_data(gnutls_session_t session)
+{
+ int ret;
+ gnutls_buffer_st buf;
+
+ if (!(session->security_parameters.entity == GNUTLS_SERVER &&
+ session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED))
+ return 0;
+
+ ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_END_OF_EARLY_DATA, 0, &buf);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ if (buf.length != 0) {
+ gnutls_assert();
+ ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+ goto cleanup;
+ }
+
+ session->internals.hsk_flags &= ~HSK_EARLY_DATA_IN_FLIGHT;
+
+ ret = 0;
+cleanup:
+
+ _gnutls_buffer_clear(&buf);
+ return ret;
+}
diff --git a/lib/tls13/early_data.h b/lib/tls13/early_data.h
new file mode 100644
index 0000000000..ddbd983293
--- /dev/null
+++ b/lib/tls13/early_data.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+int _gnutls13_send_end_of_early_data(gnutls_session_t session, unsigned again);
+int _gnutls13_recv_end_of_early_data(gnutls_session_t session);
+int _gnutls13_send_early_data(gnutls_session_t session);
diff --git a/lib/tls13/session_ticket.c b/lib/tls13/session_ticket.c
index ad04a60919..b34de41029 100644
--- a/lib/tls13/session_ticket.c
+++ b/lib/tls13/session_ticket.c
@@ -229,6 +229,23 @@ generate_session_ticket(gnutls_session_t session, tls13_ticket_st *ticket)
return 0;
}
+static int append_nst_extension(void *ctx, gnutls_buffer_st *buf)
+{
+ gnutls_session_t session = ctx;
+ int ret;
+
+ if (!(session->internals.flags & GNUTLS_ENABLE_EARLY_DATA))
+ return 0;
+
+ ret = _gnutls_buffer_append_prefix(buf, 32,
+ session->security_parameters.
+ max_early_data_size);
+ if (ret < 0)
+ gnutls_assert();
+
+ return ret;
+}
+
int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigned again)
{
int ret = 0;
@@ -253,6 +270,8 @@ int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigne
if (again == 0) {
for (i=0;i<nr;i++) {
+ unsigned init_pos;
+
memset(&ticket, 0, sizeof(tls13_ticket_st));
bufel = NULL;
@@ -296,13 +315,28 @@ int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigne
goto cleanup;
}
- ret = _gnutls_buffer_append_prefix(&buf, 16, 0);
+ _gnutls_free_datum(&ticket.ticket);
+
+ /* append extensions */
+ ret = _gnutls_extv_append_init(&buf);
if (ret < 0) {
gnutls_assert();
goto cleanup;
}
+ init_pos = ret;
- _gnutls_free_datum(&ticket.ticket);
+ ret = _gnutls_extv_append(&buf, ext_mod_early_data.tls_id, session,
+ (extv_append_func)append_nst_extension);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = _gnutls_extv_append_final(&buf, init_pos);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
bufel = _gnutls_buffer_to_mbuffer(&buf);
@@ -337,7 +371,8 @@ static int parse_nst_extension(void *ctx, unsigned tls_id, const unsigned char *
if (data_size < 4)
return gnutls_assert_val(GNUTLS_E_TLS_PACKET_DECODING_ERROR);
size = _gnutls_read_uint32(data);
- session->security_parameters.max_early_data_size = size;
+ if (size < session->security_parameters.max_early_data_size)
+ session->security_parameters.max_early_data_size = size;
}
return 0;
}