]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
handshake: don't regenerate legacy_session_id in second CH after HRR
authorDaiki Ueno <ueno@gnu.org>
Thu, 22 Apr 2021 14:42:01 +0000 (16:42 +0200)
committerDaiki Ueno <ueno@gnu.org>
Thu, 22 Apr 2021 14:45:57 +0000 (16:45 +0200)
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>
lib/handshake.c
tests/tls13/hello_retry_request.c

index 33bc7f7be692b257f2693046e34ca1ca4779a072..c30703ccbd4740176f429a135d2f81a9ad5ac71f 100644 (file)
@@ -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;
index f90d4ad6760c8f1c909cf5ed46ec3035cda1091d..dd4506b6f94f6d48c0133a9f5f454d5ae6cbbbf4 100644 (file)
@@ -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++;
        }