summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2021-04-22 16:42:01 +0200
committerDaiki Ueno <ueno@gnu.org>2021-04-22 16:45:57 +0200
commit24c9a24640c137b47bb1e8cc5fee2315f57219ad (patch)
tree22e557ccaf22f9d7131af407c68ca2dc32ed48b2
parent6805b30455680d5cf212030aa59c76bcdfa6b225 (diff)
downloadgnutls-24c9a24640c137b47bb1e8cc5fee2315f57219ad.tar.gz
handshake: don't regenerate legacy_session_id in second CH after HRR
According to RFC 8446 4.1.2, the client must send the same Client Hello after Hello Retry Request, except for the certain extensions, and thus legacy_session_id must be preserved. Signed-off-by: Daiki Ueno <ueno@gnu.org>
-rw-r--r--lib/handshake.c20
-rw-r--r--tests/tls13/hello_retry_request.c20
2 files changed, 31 insertions, 9 deletions
diff --git a/lib/handshake.c b/lib/handshake.c
index 33bc7f7be6..c30703ccbd 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -2216,15 +2216,17 @@ static int send_client_hello(gnutls_session_t session, int again)
if (max_ver->tls13_sem &&
session->internals.priorities->tls13_compat_mode &&
!resuming) {
- /* Under TLS1.3 we generate a random session ID to make
- * the TLS1.3 session look like a resumed TLS1.2 session */
- ret = _gnutls_generate_session_id(session->security_parameters.
- session_id,
- &session->security_parameters.
- session_id_size);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
+ if (!(session->internals.hsk_flags & HSK_HRR_RECEIVED)) {
+ /* Under TLS1.3 we generate a random session ID to make
+ * the TLS1.3 session look like a resumed TLS1.2 session */
+ ret = _gnutls_generate_session_id(session->security_parameters.
+ session_id,
+ &session->security_parameters.
+ session_id_size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
}
session_id = session->security_parameters.session_id;
session_id_len = session->security_parameters.session_id_size;
diff --git a/tests/tls13/hello_retry_request.c b/tests/tls13/hello_retry_request.c
index f90d4ad676..dd4506b6f9 100644
--- a/tests/tls13/hello_retry_request.c
+++ b/tests/tls13/hello_retry_request.c
@@ -69,9 +69,13 @@ static void client_log_func(int level, const char *str)
fprintf(stderr, "client|<%d>| %s", level, str);
}
+#define HANDSHAKE_SESSION_ID_POS 34
+
struct ctx_st {
unsigned hrr_seen;
unsigned hello_counter;
+ uint8_t session_id[32];
+ size_t session_id_len;
};
static int hello_callback(gnutls_session_t session, unsigned int htype,
@@ -84,12 +88,28 @@ static int hello_callback(gnutls_session_t session, unsigned int htype,
ctx->hrr_seen = 1;
if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO && post == GNUTLS_HOOK_POST) {
+ size_t session_id_len;
+ uint8_t *session_id;
+
+ assert(msg->size > HANDSHAKE_SESSION_ID_POS + 1);
+ session_id_len = msg->data[HANDSHAKE_SESSION_ID_POS];
+ session_id = &msg->data[HANDSHAKE_SESSION_ID_POS + 1];
+
if (ctx->hello_counter > 0) {
assert(msg->size > 4);
if (msg->data[0] != 0x03 || msg->data[1] != 0x03) {
fail("version is %d.%d expected 3,3\n", (int)msg->data[0], (int)msg->data[1]);
}
+
+ if (session_id_len != ctx->session_id_len ||
+ memcmp(session_id, ctx->session_id, session_id_len) != 0) {
+ fail("different legacy_session_id is sent after HRR\n");
+ }
}
+
+ ctx->session_id_len = session_id_len;
+ memcpy(ctx->session_id, session_id, session_id_len);
+
ctx->hello_counter++;
}