summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2019-04-11 12:00:46 +0200
committerDaiki Ueno <dueno@redhat.com>2019-04-19 07:44:34 +0200
commit163c32a8d6b107eca08bf404ee076b0d240bf942 (patch)
tree732e23b3b4ba0b41c64411cefcca46456af2eaa5
parent7137b3d492a83ffc5b89fa1ec426626e789b0868 (diff)
downloadgnutls-163c32a8d6b107eca08bf404ee076b0d240bf942.tar.gz
handshake: move early secrets calculation to pre_shared_key
TLS 1.3 Early Secret and the derived keys are calculated upon a PSK being selected, thus the code fits better in ext/pre_shared_key.c. Signed-off-by: Daiki Ueno <dueno@redhat.com>
-rw-r--r--lib/ext/pre_shared_key.c70
-rw-r--r--lib/ext/pre_shared_key.h2
-rw-r--r--lib/handshake.c159
-rw-r--r--lib/state.c2
4 files changed, 109 insertions, 124 deletions
diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c
index 771092fa9c..42f728286b 100644
--- a/lib/ext/pre_shared_key.c
+++ b/lib/ext/pre_shared_key.c
@@ -24,6 +24,7 @@
#include "gnutls_int.h"
#include "auth/psk.h"
#include "handshake.h"
+#include "kx.h"
#include "secrets.h"
#include "tls13/anti_replay.h"
#include "tls13/psk_ext_parser.h"
@@ -189,6 +190,58 @@ error:
}
static int
+generate_early_secrets(gnutls_session_t session,
+ const mac_entry_st *prf)
+{
+ int ret;
+
+ ret = _tls13_derive_secret2(prf, EARLY_TRAFFIC_LABEL, sizeof(EARLY_TRAFFIC_LABEL)-1,
+ session->internals.handshake_hash_buffer.data,
+ session->internals.handshake_hash_buffer_client_hello_len,
+ session->key.proto.tls13.temp_secret,
+ session->key.proto.tls13.e_ckey);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ _gnutls_nss_keylog_write(session, "CLIENT_EARLY_TRAFFIC_SECRET",
+ session->key.proto.tls13.e_ckey,
+ prf->output_size);
+
+ return 0;
+}
+
+/* Calculate TLS 1.3 Early Secret and the derived secrets from the
+ * selected PSK. */
+int
+_gnutls_generate_early_secrets_for_psk(gnutls_session_t session)
+{
+ const uint8_t *psk;
+ size_t psk_size;
+ const mac_entry_st *prf;
+ int ret;
+
+ psk = session->key.binders[0].psk.data;
+ psk_size = session->key.binders[0].psk.size;
+ prf = session->key.binders[0].prf;
+
+ if (unlikely(psk_size == 0))
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ ret = _tls13_init_secret2(prf, psk, psk_size,
+ session->key.proto.tls13.temp_secret);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ session->key.proto.tls13.temp_secret_size = prf->output_size;
+
+ ret = generate_early_secrets(session, session->key.binders[0].prf);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return 0;
+}
+
+static int
client_send_params(gnutls_session_t session,
gnutls_buffer_t extdata,
const gnutls_psk_client_credentials_t cred)
@@ -651,6 +704,12 @@ static int server_recv_params(gnutls_session_t session,
session->key.binders[0].prf = prf;
session->key.binders[0].resumption = resuming;
+ ret = _gnutls_generate_early_secrets_for_psk(session);
+ if (ret < 0) {
+ gnutls_assert();
+ goto fail;
+ }
+
return 0;
fail:
@@ -742,6 +801,7 @@ static int _gnutls_psk_recv_params(gnutls_session_t session,
unsigned i;
gnutls_psk_server_credentials_t pskcred;
const version_entry_st *vers = get_version(session);
+ int ret;
if (!vers || !vers->tls13_sem)
return 0;
@@ -759,9 +819,15 @@ static int _gnutls_psk_recv_params(gnutls_session_t session,
_gnutls_handshake_log("EXT[%p]: selected PSK mode\n", session);
}
- /* ensure that selected binder is set on (our) index zero */
- if (i != 0)
+ /* different PSK is selected, than the one we calculated early secrets */
+ if (i != 0) {
+ /* ensure that selected binder is set on (our) index zero */
swap_binders(session);
+
+ ret = _gnutls_generate_early_secrets_for_psk(session);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
session->internals.hsk_flags |= HSK_PSK_SELECTED;
}
}
diff --git a/lib/ext/pre_shared_key.h b/lib/ext/pre_shared_key.h
index 4ad7b240f3..71116e5d10 100644
--- a/lib/ext/pre_shared_key.h
+++ b/lib/ext/pre_shared_key.h
@@ -18,4 +18,6 @@ unsigned _gnutls_have_psk_credentials(const gnutls_psk_client_credentials_t cred
return 0;
}
+int _gnutls_generate_early_secrets_for_psk(gnutls_session_t session);
+
#endif
diff --git a/lib/handshake.c b/lib/handshake.c
index 45bf99a6f7..1e6164cabe 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -45,6 +45,7 @@
#include "constate.h"
#include <record.h>
#include <state.h>
+#include <ext/pre_shared_key.h>
#include <ext/srp.h>
#include <ext/session_ticket.h>
#include <ext/status_request.h>
@@ -826,6 +827,14 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
return ret;
}
+ /* Calculate TLS 1.3 Early Secret */
+ if (session->security_parameters.pversion->tls13_sem &&
+ !(session->internals.hsk_flags & HSK_PSK_SELECTED)) {
+ ret = _tls13_init_secret(session, NULL, 0);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
+
ret = set_auth_types(session);
if (ret < 0) {
gnutls_assert();
@@ -1265,7 +1274,7 @@ _gnutls_send_handshake2(gnutls_session_t session, mbuffer_st * bufel,
/* Here we keep the handshake messages in order to hash them...
*/
- if (!IS_ASYNC(type, vers))
+ if (!IS_ASYNC(type, vers)) {
if ((ret =
handshake_hash_add_sent(session, type, data,
datasize)) < 0) {
@@ -1273,6 +1282,19 @@ _gnutls_send_handshake2(gnutls_session_t session, mbuffer_st * bufel,
_mbuffer_xfree(&bufel);
return ret;
}
+ /* If we are sending a PSK, generate early secrets here.
+ * This cannot be done in pre_shared_key.c, because it
+ * relies on transcript hash of a Client Hello. */
+ if (type == GNUTLS_HANDSHAKE_CLIENT_HELLO &&
+ session->key.binders[0].prf != NULL) {
+ ret = _gnutls_generate_early_secrets_for_psk(session);
+ if (ret < 0) {
+ gnutls_assert();
+ _mbuffer_xfree(&bufel);
+ return ret;
+ }
+ }
+ }
ret = _gnutls_call_hook_func(session, type, GNUTLS_HOOK_PRE, 0,
_mbuffer_get_udata_ptr(bufel), _mbuffer_get_udata_size(bufel));
@@ -1807,26 +1829,6 @@ no_resume:
}
-static int generate_early_traffic_secret(gnutls_session_t session,
- const mac_entry_st *prf)
-{
- int ret;
-
- ret = _tls13_derive_secret2(prf, EARLY_TRAFFIC_LABEL, sizeof(EARLY_TRAFFIC_LABEL)-1,
- session->internals.handshake_hash_buffer.data,
- session->internals.handshake_hash_buffer_client_hello_len,
- session->key.proto.tls13.temp_secret,
- session->key.proto.tls13.e_ckey);
- if (ret < 0)
- return gnutls_assert_val(ret);
-
- _gnutls_nss_keylog_write(session, "CLIENT_EARLY_TRAFFIC_SECRET",
- session->key.proto.tls13.e_ckey,
- prf->output_size);
-
- return 0;
-}
-
/* This function reads and parses the server hello handshake message.
* This function also restores resumed parameters if we are resuming a
* session.
@@ -1840,12 +1842,10 @@ read_server_hello(gnutls_session_t session,
uint8_t *cs_pos, *comp_pos, *srandom_pos;
uint8_t major, minor;
int pos = 0;
- int ret = 0;
+ int ret;
int len = datalen;
unsigned ext_parse_flag = 0;
const version_entry_st *vers, *saved_vers;
- const uint8_t *psk = NULL;
- size_t psk_size = 0;
if (datalen < GNUTLS_RANDOM_SIZE+2) {
gnutls_assert();
@@ -1925,6 +1925,13 @@ read_server_hello(gnutls_session_t session,
if (ret < 0)
return gnutls_assert_val(ret);
+ /* reset keys and binders if we are not using TLS 1.3 */
+ if (!vers->tls13_sem) {
+ gnutls_memset(&session->key.proto.tls13, 0,
+ sizeof(session->key.proto.tls13));
+ reset_binders(session);
+ }
+
/* check if we are resuming and set the appropriate
* values;
*/
@@ -2016,31 +2023,17 @@ read_server_hello(gnutls_session_t session,
/* Calculate TLS 1.3 Early Secret */
if (vers->tls13_sem &&
- !(session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT)) {
- if (session->internals.hsk_flags & HSK_PSK_SELECTED) {
- psk = session->key.binders[0].psk.data;
- psk_size = session->key.binders[0].psk.size;
-
- if (psk_size == 0)
- return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
- }
-
- ret = _tls13_init_secret(session, psk, psk_size);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
+ !(session->internals.hsk_flags & HSK_PSK_SELECTED)) {
+ ret = _tls13_init_secret(session, NULL, 0);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
}
ret = set_auth_types(session);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
-cleanup:
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- return ret;
+ return 0;
}
/* This function copies the appropriate compression methods, to a locally allocated buffer
@@ -2064,56 +2057,6 @@ append_null_comp(gnutls_session_t session,
return ret;
}
-/* Calculate TLS 1.3 Early Secret and client_early_traffic_secret,
- * assuming that the PSK we offer will be accepted by the server */
-static int
-generate_early_traffic_secret_from_ticket(gnutls_session_t session)
-{
- int ret = 0;
- const uint8_t *psk;
- size_t psk_size;
- const mac_entry_st *prf;
-
- if (!(session->internals.hsk_flags & HSK_TLS13_TICKET_SENT)) {
- ret = GNUTLS_E_INVALID_REQUEST;
- gnutls_assert();
- goto cleanup;
- }
-
- psk = session->key.binders[0].psk.data;
- psk_size = session->key.binders[0].psk.size;
- prf = session->key.binders[0].prf;
-
- if (psk_size == 0) {
- ret = GNUTLS_E_INVALID_REQUEST;
- gnutls_assert();
- goto cleanup;
- }
-
- ret = _tls13_init_secret2(prf, psk, psk_size,
- session->key.proto.tls13.temp_secret);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
- session->key.proto.tls13.temp_secret_size = prf->output_size;
-
- ret = generate_early_traffic_secret(session, prf);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- return ret;
-
- cleanup:
- /* If any of the above calculation fails, we are not going to
- * send early data. */
- session->internals.hsk_flags &= ~HSK_EARLY_DATA_IN_FLIGHT;
-
- return ret;
-}
-
/* This function sends the client hello handshake message.
*/
static int send_client_hello(gnutls_session_t session, int again)
@@ -2349,9 +2292,6 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
const version_entry_st *vers;
uint8_t vbytes[2];
unsigned extflag = 0;
- const uint8_t *psk = NULL;
- size_t psk_size = 0;
- const mac_entry_st *prf = session->security_parameters.prf;
gnutls_ext_parse_type_t etype;
_gnutls_buffer_init(&buf);
@@ -2362,25 +2302,6 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
if (vers->tls13_sem) {
- /* TLS 1.3 Early Secret */
- if (session->internals.hsk_flags & HSK_PSK_SELECTED) {
- psk = session->key.binders[0].psk.data;
- psk_size = session->key.binders[0].psk.size;
- prf = session->key.binders[0].prf;
- }
-
- ret = _tls13_init_secret(session, psk, psk_size);
- if (ret < 0) {
- gnutls_assert();
- goto fail;
- }
-
- ret = generate_early_traffic_secret(session, prf);
- if (ret < 0) {
- gnutls_assert();
- goto fail;
- }
-
vbytes[0] = 0x03; /* TLS1.2 */
vbytes[1] = 0x03;
extflag |= GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO;
@@ -2971,10 +2892,6 @@ static int handshake_client(gnutls_session_t session)
ret = send_client_hello(session, AGAIN(STATE1));
STATE = STATE1;
IMED_RET("send hello", ret, 1);
- if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) {
- ret = generate_early_traffic_secret_from_ticket(session);
- IMED_RET_FATAL("generate early traffic keys from ticket", ret, 0);
- }
FALLTHROUGH;
case STATE2:
if (IS_DTLS(session)) {
diff --git a/lib/state.c b/lib/state.c
index fe40bd980a..97461e6722 100644
--- a/lib/state.c
+++ b/lib/state.c
@@ -345,7 +345,7 @@ static void deinit_keys(gnutls_session_t session)
gnutls_pk_params_release(&session->key.kshare.ecdh_params);
gnutls_pk_params_release(&session->key.kshare.dh_params);
- if (!vers->tls13_sem) {
+ if (!vers->tls13_sem && session->key.binders[0].prf == NULL) {
gnutls_pk_params_release(&session->key.proto.tls12.ecdh.params);
gnutls_pk_params_release(&session->key.proto.tls12.dh.params);
zrelease_temp_mpi_key(&session->key.proto.tls12.ecdh.x);