Fix client handling of 0-RTT rejects with cipher mismatch.

Servers can only accept 0-RTT if the ciphers match. If they reject
0-RTT, however, they may change the cipher suite and even the PRF hash.
This is tricky, however, because the 0-RTT accept or reject signal comes
in EncryptedExtensions, which is *after* the new cipher suite is
installed. (Although a client could infer 0-RTT is rejected based on the
cipher suite if it wanted.)

While we correctly handled the PRF hash switch, we get the cipher suite
mixed up due to dependency on SSL_get_session and incorrectly decrypt
EncryptedExtensions. Fix this and add some tests.

Change-Id: Ia20f2ed665cf601d30a38f0c8d4786c4c111019f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40005
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/ssl/ssl_session.cc b/ssl/ssl_session.cc
index 77d3f4c..6635703 100644
--- a/ssl/ssl_session.cc
+++ b/ssl/ssl_session.cc
@@ -624,10 +624,14 @@
          ssl->server == session->is_server &&
          // The session must not be expired.
          ssl_session_is_time_valid(ssl, session) &&
-         /* Only resume if the session's version matches the negotiated
-          * version. */
+         // Only resume if the session's version matches the negotiated
+         // version.
          ssl->version == session->ssl_version &&
-         // Only resume if the session's cipher matches the negotiated one.
+         // Only resume if the session's cipher matches the negotiated one. This
+         // is stricter than necessary for TLS 1.3, which allows cross-cipher
+         // resumption if the PRF hashes match. We require an exact match for
+         // simplicity. If loosening this, the 0-RTT accept logic must be
+         // updated to check the cipher.
          hs->new_cipher == session->cipher &&
          // If the session contains a client certificate (either the full
          // certificate or just the hash) then require that the form of the