Merge pull request #8576 from yanrayw/issue/fix-tls13-session_negotiate-assignment

TLS13: CLI: EarlyData: Assign ciphersuite after associated verification in EE
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 08cfe22..052df7e 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -1925,7 +1925,6 @@
 
     mbedtls_ssl_set_inbound_transform(ssl, handshake->transform_handshake);
     MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake keys for inbound traffic"));
-    ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id;
     ssl->session_in = ssl->session_negotiate;
 
 cleanup:
@@ -2153,9 +2152,7 @@
     int ret;
     unsigned char *buf;
     size_t buf_len;
-#if defined(MBEDTLS_SSL_EARLY_DATA)
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-#endif
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions"));
 
@@ -2185,11 +2182,19 @@
          * - The selected cipher suite
          * - The selected ALPN [RFC7301] protocol, if any
          *
-         * We check here that when early data is involved the server
-         * selected the cipher suite associated to the pre-shared key
-         * as it must have.
+         * The server has sent an early data extension in its Encrypted
+         * Extension message thus accepted to receive early data. We
+         * check here that the additional constraints on the handshake
+         * parameters, when early data are exchanged, are met,
+         * namely:
+         * - a PSK has been selected for the handshake
+         * - the selected PSK for the handshake was the first one proposed
+         *   by the client.
+         * - the selected ciphersuite for the handshake is the ciphersuite
+         *   associated with the selected PSK.
          */
-        if (handshake->selected_identity != 0 ||
+        if ((!mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) ||
+            handshake->selected_identity != 0 ||
             handshake->ciphersuite_info->id !=
             ssl->session_negotiate->ciphersuite) {
 
@@ -2203,6 +2208,18 @@
     }
 #endif
 
+    /*
+     * In case the client has proposed a PSK associated with a ticket,
+     * `ssl->session_negotiate->ciphersuite` still contains at this point the
+     * identifier of the ciphersuite associated with the ticket. This is that
+     * way because, if an exchange of early data is agreed upon, we need
+     * it to check that the ciphersuite selected for the handshake is the
+     * ticket ciphersuite (see above). This information is not needed
+     * anymore thus we can now set it to the identifier of the ciphersuite
+     * used in this session under negotiation.
+     */
+    ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id;
+
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
                              ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
                              buf, buf_len));