Splitting SSL session state. To prevent configuration/established session confusion, the handshake session state is separated into the configured session (ssl->session) and the newly created session (ssl->s3->new_session). Upon conclusion of the handshake, the finalized session is stored in (ssl->s3->established_session). During the handshake, any requests for the session (SSL_get_session) return a non-resumable session, to prevent resumption of a partially filled session. Sessions should only be cached upon the completion of the full handshake, using the resulting established_session. The semantics of accessors on the session are maintained mid-renego. Change-Id: I4358aecb71fce4fe14a6746c5af1416a69935078 Reviewed-on: https://boringssl-review.googlesource.com/8612 Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: David Benjamin <davidben@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc index f26962f..5dd689b 100644 --- a/ssl/ssl_test.cc +++ b/ssl/ssl_test.cc
@@ -30,6 +30,7 @@ #include <openssl/ssl.h> #include <openssl/x509.h> +#include "internal.h" #include "test/scoped_types.h" #include "../crypto/test/test_util.h" @@ -1253,6 +1254,48 @@ return true; } +static bool TestSessionDuplication() { + ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method())); + ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method())); + if (!client_ctx || !server_ctx) { + return false; + } + + ScopedX509 cert = GetTestCertificate(); + ScopedEVP_PKEY key = GetTestKey(); + if (!cert || !key || + !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) || + !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) { + return false; + } + + ScopedSSL client, server; + if (!ConnectClientAndServer(&client, &server, client_ctx.get(), + server_ctx.get())) { + return false; + } + + SSL_SESSION *session0 = SSL_get_session(client.get()); + ScopedSSL_SESSION session1(SSL_SESSION_dup(session0, 1)); + if (!session1) { + return false; + } + + uint8_t *s0_bytes, *s1_bytes; + size_t s0_len, s1_len; + + if (!SSL_SESSION_to_bytes(session0, &s0_bytes, &s0_len)) { + return false; + } + ScopedOpenSSLBytes free_s0(s0_bytes); + + if (!SSL_SESSION_to_bytes(session1.get(), &s1_bytes, &s1_len)) { + return false; + } + ScopedOpenSSLBytes free_s1(s1_bytes); + + return s0_len == s1_len && memcmp(s0_bytes, s1_bytes, s0_len) == 0; +} static bool ExpectFDs(const SSL *ssl, int rfd, int wfd) { if (SSL_get_rfd(ssl) != rfd || SSL_get_wfd(ssl) != wfd) { @@ -1501,6 +1544,7 @@ !TestSequenceNumber(false /* TLS */) || !TestSequenceNumber(true /* DTLS */) || !TestOneSidedShutdown() || + !TestSessionDuplication() || !TestSetFD() || !TestGetPeerCertificate() || !TestRetainOnlySHA256OfCerts()) {