summaryrefslogtreecommitdiffstats
path: root/security/nss/gtests/ssl_gtest
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/gtests/ssl_gtest')
-rw-r--r--security/nss/gtests/ssl_gtest/manifest.mn1
-rw-r--r--security/nss/gtests/ssl_gtest/rsa8193.h2
-rw-r--r--security/nss/gtests/ssl_gtest/selfencrypt_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc30
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc329
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc27
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc8
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc41
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc10
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_ems_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc96
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc6
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc1
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_gtest.gyp1
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc97
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc199
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_record_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc10
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc306
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc35
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc46
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_version_unittest.cc95
-rw-r--r--security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc2
-rw-r--r--security/nss/gtests/ssl_gtest/test_io.cc28
-rw-r--r--security/nss/gtests/ssl_gtest/test_io.h2
-rw-r--r--security/nss/gtests/ssl_gtest/tls_agent.cc75
-rw-r--r--security/nss/gtests/ssl_gtest/tls_agent.h8
-rw-r--r--security/nss/gtests/ssl_gtest/tls_connect.cc8
-rw-r--r--security/nss/gtests/ssl_gtest/tls_esni_unittest.cc470
-rw-r--r--security/nss/gtests/ssl_gtest/tls_filter.cc34
-rw-r--r--security/nss/gtests/ssl_gtest/tls_filter.h27
-rw-r--r--security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc40
39 files changed, 1729 insertions, 325 deletions
diff --git a/security/nss/gtests/ssl_gtest/manifest.mn b/security/nss/gtests/ssl_gtest/manifest.mn
index 8547e56d1..7f4ee7953 100644
--- a/security/nss/gtests/ssl_gtest/manifest.mn
+++ b/security/nss/gtests/ssl_gtest/manifest.mn
@@ -52,6 +52,7 @@ CPPSRCS = \
tls_hkdf_unittest.cc \
tls_filter.cc \
tls_protect.cc \
+ tls_esni_unittest.cc \
$(NULL)
INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \
diff --git a/security/nss/gtests/ssl_gtest/rsa8193.h b/security/nss/gtests/ssl_gtest/rsa8193.h
index 626516389..1ac8503bc 100644
--- a/security/nss/gtests/ssl_gtest/rsa8193.h
+++ b/security/nss/gtests/ssl_gtest/rsa8193.h
@@ -206,4 +206,4 @@ static const uint8_t rsa8193[] = {
0x13, 0x34, 0x9d, 0x34, 0xb8, 0xef, 0x13, 0x3a, 0x20, 0xf5, 0x74, 0x02,
0x70, 0x3b, 0x41, 0x60, 0x1f, 0x5e, 0x76, 0x0a, 0xb1, 0x17, 0xd5, 0xcf,
0x79, 0xef, 0xf7, 0xab, 0xe7, 0xd6, 0x0f, 0xad, 0x85, 0x2c, 0x52, 0x67,
- 0xb5, 0xa0, 0x4a, 0xfd, 0xaf}; \ No newline at end of file
+ 0xb5, 0xa0, 0x4a, 0xfd, 0xaf};
diff --git a/security/nss/gtests/ssl_gtest/selfencrypt_unittest.cc b/security/nss/gtests/ssl_gtest/selfencrypt_unittest.cc
index 4bae9dec9..0c62c4cac 100644
--- a/security/nss/gtests/ssl_gtest/selfencrypt_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/selfencrypt_unittest.cc
@@ -19,7 +19,7 @@ extern "C" {
#include "databuffer.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
namespace nss_test {
diff --git a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
index 28fdc6631..07eadfbd1 100644
--- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc
@@ -16,7 +16,7 @@ extern "C" {
}
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
diff --git a/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc
index 6be3b61f8..c3455d130 100644
--- a/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc
@@ -34,7 +34,7 @@ const static uint8_t kCannedTls13ClientHello[] = {
0xc2, 0xb3, 0xc6, 0x80, 0x72, 0x86, 0x08, 0x86, 0x8f, 0x52, 0xc5, 0xcb,
0xbf, 0x2a, 0xb5, 0x59, 0x64, 0xcc, 0x0c, 0x49, 0x95, 0x36, 0xe4, 0xd9,
0x2f, 0xd4, 0x24, 0x66, 0x71, 0x6f, 0x5d, 0x70, 0xe2, 0xa0, 0xea, 0x26,
- 0x00, 0x2b, 0x00, 0x03, 0x02, 0x7f, kD13, 0x00, 0x0d, 0x00, 0x20, 0x00,
+ 0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04, 0x00, 0x0d, 0x00, 0x20, 0x00,
0x1e, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, 0x08, 0x04, 0x08,
0x05, 0x08, 0x06, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x04,
0x02, 0x05, 0x02, 0x06, 0x02, 0x02, 0x02};
@@ -64,8 +64,8 @@ TEST_P(TlsAgentTestClient13, CannedHello) {
auto sh = MakeCannedTls13ServerHello();
MakeHandshakeMessage(kTlsHandshakeServerHello, sh.data(), sh.len(),
&server_hello);
- MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
- server_hello.data(), server_hello.len(), &buffer);
+ MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data(),
+ server_hello.len(), &buffer);
ProcessMessage(buffer, TlsAgent::STATE_CONNECTING);
}
@@ -79,8 +79,8 @@ TEST_P(TlsAgentTestClient13, EncryptedExtensionsInClear) {
&encrypted_extensions, 1);
server_hello.Append(encrypted_extensions);
DataBuffer buffer;
- MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
- server_hello.data(), server_hello.len(), &buffer);
+ MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data(),
+ server_hello.len(), &buffer);
EnsureInit();
ExpectAlert(kTlsAlertUnexpectedMessage);
ProcessMessage(buffer, TlsAgent::STATE_ERROR,
@@ -97,11 +97,11 @@ TEST_F(TlsAgentStreamTestClient, EncryptedExtensionsInClearTwoPieces) {
&encrypted_extensions, 1);
server_hello.Append(encrypted_extensions);
DataBuffer buffer;
- MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
- server_hello.data(), kFirstFragmentSize, &buffer);
+ MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data(),
+ kFirstFragmentSize, &buffer);
DataBuffer buffer2;
- MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
+ MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3,
server_hello.data() + kFirstFragmentSize,
server_hello.len() - kFirstFragmentSize, &buffer2);
@@ -129,11 +129,11 @@ TEST_F(TlsAgentDgramTestClient, EncryptedExtensionsInClearTwoPieces) {
&encrypted_extensions, 1);
server_hello_frag2.Append(encrypted_extensions);
DataBuffer buffer;
- MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
+ MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3,
server_hello_frag1.data(), server_hello_frag1.len(), &buffer);
DataBuffer buffer2;
- MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
+ MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3,
server_hello_frag2.data(), server_hello_frag2.len(), &buffer2, 1);
EnsureInit();
@@ -150,7 +150,7 @@ TEST_F(TlsAgentDgramTestClient, AckWithBogusLengthField) {
// Length doesn't match
const uint8_t ackBuf[] = {0x00, 0x08, 0x00};
DataBuffer record;
- MakeRecord(variant_, kTlsAckType, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf,
+ MakeRecord(variant_, ssl_ct_ack, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf,
sizeof(ackBuf), &record, 0);
agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
SSL_LIBRARY_VERSION_TLS_1_3);
@@ -164,7 +164,7 @@ TEST_F(TlsAgentDgramTestClient, AckWithNonEvenLength) {
// Length isn't a multiple of 8
const uint8_t ackBuf[] = {0x00, 0x01, 0x00};
DataBuffer record;
- MakeRecord(variant_, kTlsAckType, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf,
+ MakeRecord(variant_, ssl_ct_ack, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf,
sizeof(ackBuf), &record, 0);
agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
SSL_LIBRARY_VERSION_TLS_1_3);
@@ -196,7 +196,7 @@ TEST_F(TlsAgentStreamTestClient, Set0RttOptionThenRead) {
agent_->StartConnect();
agent_->Set0RttEnabled(true);
DataBuffer buffer;
- MakeRecord(kTlsApplicationDataType, SSL_LIBRARY_VERSION_TLS_1_3,
+ MakeRecord(ssl_ct_application_data, SSL_LIBRARY_VERSION_TLS_1_3,
reinterpret_cast<const uint8_t *>(k0RttData), strlen(k0RttData),
&buffer);
ExpectAlert(kTlsAlertUnexpectedMessage);
@@ -214,10 +214,10 @@ TEST_F(TlsAgentStreamTestServer, Set0RttOptionClientHelloThenRead) {
agent_->StartConnect();
agent_->Set0RttEnabled(true);
DataBuffer buffer;
- MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
+ MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3,
kCannedTls13ClientHello, sizeof(kCannedTls13ClientHello), &buffer);
ProcessMessage(buffer, TlsAgent::STATE_CONNECTING);
- MakeRecord(kTlsApplicationDataType, SSL_LIBRARY_VERSION_TLS_1_3,
+ MakeRecord(ssl_ct_application_data, SSL_LIBRARY_VERSION_TLS_1_3,
reinterpret_cast<const uint8_t *>(k0RttData), strlen(k0RttData),
&buffer);
ExpectAlert(kTlsAlertBadRecordMac);
diff --git a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc
index e2a30e6bc..3a52ac20c 100644
--- a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc
@@ -15,7 +15,7 @@ extern "C" {
}
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@@ -37,6 +37,50 @@ TEST_P(TlsConnectGeneric, ServerAuthRsaChain) {
EXPECT_EQ(2UL, chain_length);
}
+TEST_P(TlsConnectTls12Plus, ServerAuthRsaPss) {
+ static const SSLSignatureScheme kSignatureSchemePss[] = {
+ ssl_sig_rsa_pss_pss_sha256};
+
+ Reset(TlsAgent::kServerRsaPss);
+ client_->SetSignatureSchemes(kSignatureSchemePss,
+ PR_ARRAY_SIZE(kSignatureSchemePss));
+ server_->SetSignatureSchemes(kSignatureSchemePss,
+ PR_ARRAY_SIZE(kSignatureSchemePss));
+ Connect();
+ CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_pss,
+ ssl_sig_rsa_pss_pss_sha256);
+}
+
+// PSS doesn't work with TLS 1.0 or 1.1 because we can't signal it.
+TEST_P(TlsConnectPre12, ServerAuthRsaPssFails) {
+ static const SSLSignatureScheme kSignatureSchemePss[] = {
+ ssl_sig_rsa_pss_pss_sha256};
+
+ Reset(TlsAgent::kServerRsaPss);
+ client_->SetSignatureSchemes(kSignatureSchemePss,
+ PR_ARRAY_SIZE(kSignatureSchemePss));
+ server_->SetSignatureSchemes(kSignatureSchemePss,
+ PR_ARRAY_SIZE(kSignatureSchemePss));
+ ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
+ server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
+ client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
+}
+
+// Check that a PSS certificate with no parameters works.
+TEST_P(TlsConnectTls12Plus, ServerAuthRsaPssNoParameters) {
+ static const SSLSignatureScheme kSignatureSchemePss[] = {
+ ssl_sig_rsa_pss_pss_sha256};
+
+ Reset("rsa_pss_noparam");
+ client_->SetSignatureSchemes(kSignatureSchemePss,
+ PR_ARRAY_SIZE(kSignatureSchemePss));
+ server_->SetSignatureSchemes(kSignatureSchemePss,
+ PR_ARRAY_SIZE(kSignatureSchemePss));
+ Connect();
+ CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_pss,
+ ssl_sig_rsa_pss_pss_sha256);
+}
+
TEST_P(TlsConnectGeneric, ServerAuthRsaPssChain) {
Reset("rsa_pss_chain");
Connect();
@@ -55,6 +99,76 @@ TEST_P(TlsConnectGeneric, ServerAuthRsaCARsaPssChain) {
EXPECT_EQ(2UL, chain_length);
}
+TEST_P(TlsConnectGeneric, ServerAuthRejected) {
+ EnsureTlsSetup();
+ client_->SetAuthCertificateCallback(
+ [](TlsAgent*, PRBool, PRBool) -> SECStatus { return SECFailure; });
+ ConnectExpectAlert(client_, kTlsAlertBadCertificate);
+ client_->CheckErrorCode(SSL_ERROR_BAD_CERTIFICATE);
+ server_->CheckErrorCode(SSL_ERROR_BAD_CERT_ALERT);
+ EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state());
+}
+
+struct AuthCompleteArgs : public PollTarget {
+ AuthCompleteArgs(const std::shared_ptr<TlsAgent>& a, PRErrorCode c)
+ : agent(a), code(c) {}
+
+ std::shared_ptr<TlsAgent> agent;
+ PRErrorCode code;
+};
+
+static void CallAuthComplete(PollTarget* target, Event event) {
+ EXPECT_EQ(TIMER_EVENT, event);
+ auto args = reinterpret_cast<AuthCompleteArgs*>(target);
+ std::cerr << args->agent->role_str() << ": call SSL_AuthCertificateComplete "
+ << (args->code ? PR_ErrorToName(args->code) : "no error")
+ << std::endl;
+ EXPECT_EQ(SECSuccess,
+ SSL_AuthCertificateComplete(args->agent->ssl_fd(), args->code));
+ args->agent->Handshake(); // Make the TlsAgent aware of the error.
+ delete args;
+}
+
+// Install an AuthCertificateCallback that blocks when called. Then
+// SSL_AuthCertificateComplete is called on a very short timer. This allows any
+// processing that might follow the callback to complete.
+static void SetDeferredAuthCertificateCallback(std::shared_ptr<TlsAgent> agent,
+ PRErrorCode code) {
+ auto args = new AuthCompleteArgs(agent, code);
+ agent->SetAuthCertificateCallback(
+ [args](TlsAgent*, PRBool, PRBool) -> SECStatus {
+ // This can't be 0 or we race the message from the client to the server,
+ // and tests assume that we lose that race.
+ std::shared_ptr<Poller::Timer> timer_handle;
+ Poller::Instance()->SetTimer(1U, args, CallAuthComplete, &timer_handle);
+ return SECWouldBlock;
+ });
+}
+
+TEST_P(TlsConnectTls13, ServerAuthRejectAsync) {
+ SetDeferredAuthCertificateCallback(client_, SEC_ERROR_REVOKED_CERTIFICATE);
+ ConnectExpectAlert(client_, kTlsAlertCertificateRevoked);
+ // We only detect the error here when we attempt to handshake, so all the
+ // client learns is that the handshake has already failed.
+ client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILED);
+ server_->CheckErrorCode(SSL_ERROR_REVOKED_CERT_ALERT);
+}
+
+// In TLS 1.2 and earlier, this will result in the client sending its Finished
+// before learning that the server certificate is bad. That means that the
+// server will believe that the handshake is complete.
+TEST_P(TlsConnectGenericPre13, ServerAuthRejectAsync) {
+ SetDeferredAuthCertificateCallback(client_, SEC_ERROR_EXPIRED_CERTIFICATE);
+ client_->ExpectSendAlert(kTlsAlertCertificateExpired);
+ server_->ExpectReceiveAlert(kTlsAlertCertificateExpired);
+ ConnectExpectFailOneSide(TlsAgent::CLIENT);
+ client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILED);
+
+ // The server might not receive the alert that the client sends, which would
+ // cause the test to fail when it cleans up. Reset expectations.
+ server_->ExpectReceiveAlert(kTlsAlertCloseNotify, kTlsAlertWarning);
+}
+
TEST_P(TlsConnectGeneric, ClientAuth) {
client_->SetupClientAuth();
server_->RequestClientAuth(true);
@@ -153,6 +267,81 @@ TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) {
2048);
}
+// Replaces the signature scheme in a CertificateVerify message.
+class TlsReplaceSignatureSchemeFilter : public TlsHandshakeFilter {
+ public:
+ TlsReplaceSignatureSchemeFilter(const std::shared_ptr<TlsAgent>& a,
+ SSLSignatureScheme scheme)
+ : TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}),
+ scheme_(scheme) {
+ EnableDecryption();
+ }
+
+ protected:
+ virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
+ const DataBuffer& input,
+ DataBuffer* output) {
+ *output = input;
+ output->Write(0, scheme_, 2);
+ return CHANGE;
+ }
+
+ private:
+ SSLSignatureScheme scheme_;
+};
+
+// Check if CertificateVerify signed with rsa_pss_rsae_* is properly
+// rejected when the certificate is RSA-PSS.
+//
+// This only works under TLS 1.2, because PSS doesn't work with TLS
+// 1.0 or TLS 1.1 and the TLS 1.3 1-RTT handshake is partially
+// successful at the client side.
+TEST_P(TlsConnectTls12, ClientAuthInconsistentRsaeSignatureScheme) {
+ static const SSLSignatureScheme kSignatureSchemePss[] = {
+ ssl_sig_rsa_pss_pss_sha256, ssl_sig_rsa_pss_rsae_sha256};
+
+ Reset(TlsAgent::kServerRsa, "rsa_pss");
+ client_->SetSignatureSchemes(kSignatureSchemePss,
+ PR_ARRAY_SIZE(kSignatureSchemePss));
+ server_->SetSignatureSchemes(kSignatureSchemePss,
+ PR_ARRAY_SIZE(kSignatureSchemePss));
+ client_->SetupClientAuth();
+ server_->RequestClientAuth(true);
+
+ EnsureTlsSetup();
+
+ MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(client_,
+ ssl_sig_rsa_pss_rsae_sha256);
+
+ ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
+}
+
+// Check if CertificateVerify signed with rsa_pss_pss_* is properly
+// rejected when the certificate is RSA.
+//
+// This only works under TLS 1.2, because PSS doesn't work with TLS
+// 1.0 or TLS 1.1 and the TLS 1.3 1-RTT handshake is partially
+// successful at the client side.
+TEST_P(TlsConnectTls12, ClientAuthInconsistentPssSignatureScheme) {
+ static const SSLSignatureScheme kSignatureSchemePss[] = {
+ ssl_sig_rsa_pss_rsae_sha256, ssl_sig_rsa_pss_pss_sha256};
+
+ Reset(TlsAgent::kServerRsa, "rsa");
+ client_->SetSignatureSchemes(kSignatureSchemePss,
+ PR_ARRAY_SIZE(kSignatureSchemePss));
+ server_->SetSignatureSchemes(kSignatureSchemePss,
+ PR_ARRAY_SIZE(kSignatureSchemePss));
+ client_->SetupClientAuth();
+ server_->RequestClientAuth(true);
+
+ EnsureTlsSetup();
+
+ MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(client_,
+ ssl_sig_rsa_pss_pss_sha256);
+
+ ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
+}
+
class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter {
public:
TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr<TlsAgent>& a)
@@ -197,9 +386,9 @@ class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter {
}
};
-// Check that we fall back to SHA-1 when the server doesn't provide any
+// Check that we send an alert when the server doesn't provide any
// supported_signature_algorithms in the CertificateRequest message.
-TEST_P(TlsConnectTls12, ClientAuthNoSigAlgsFallback) {
+TEST_P(TlsConnectTls12, ClientAuthNoSigAlgs) {
EnsureTlsSetup();
MakeTlsFilter<TlsZeroCertificateRequestSigAlgsFilter>(server_);
auto capture_cert_verify = MakeTlsFilter<TlsHandshakeRecorder>(
@@ -207,24 +396,19 @@ TEST_P(TlsConnectTls12, ClientAuthNoSigAlgsFallback) {
client_->SetupClientAuth();
server_->RequestClientAuth(true);
- ConnectExpectAlert(server_, kTlsAlertDecryptError);
-
- // We're expecting a bad signature here because we tampered with a handshake
- // message (CertReq). Previously, without the SHA-1 fallback, we would've
- // seen a malformed record alert.
- server_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE);
- client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
+ ConnectExpectAlert(client_, kTlsAlertHandshakeFailure);
- CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pkcs1_sha1, 1024);
+ server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT);
+ client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
}
-static const SSLSignatureScheme SignatureSchemeEcdsaSha384[] = {
+static const SSLSignatureScheme kSignatureSchemeEcdsaSha384[] = {
ssl_sig_ecdsa_secp384r1_sha384};
-static const SSLSignatureScheme SignatureSchemeEcdsaSha256[] = {
+static const SSLSignatureScheme kSignatureSchemeEcdsaSha256[] = {
ssl_sig_ecdsa_secp256r1_sha256};
-static const SSLSignatureScheme SignatureSchemeRsaSha384[] = {
+static const SSLSignatureScheme kSignatureSchemeRsaSha384[] = {
ssl_sig_rsa_pkcs1_sha384};
-static const SSLSignatureScheme SignatureSchemeRsaSha256[] = {
+static const SSLSignatureScheme kSignatureSchemeRsaSha256[] = {
ssl_sig_rsa_pkcs1_sha256};
static SSLNamedGroup NamedGroupForEcdsa384(uint16_t version) {
@@ -241,10 +425,10 @@ static SSLNamedGroup NamedGroupForEcdsa384(uint16_t version) {
// for TLS 1.1 and 1.0, where they should be ignored.
TEST_P(TlsConnectGeneric, SignatureAlgorithmServerAuth) {
Reset(TlsAgent::kServerEcdsa384);
- client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
- server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
+ client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
+ server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
Connect();
CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa,
ssl_sig_ecdsa_secp384r1_sha384);
@@ -273,8 +457,8 @@ TEST_P(TlsConnectGeneric, SignatureAlgorithmClientOnly) {
// Defaults on the client include the provided option.
TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) {
Reset(TlsAgent::kServerEcdsa384);
- server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
+ server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
Connect();
CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa,
ssl_sig_ecdsa_secp384r1_sha384);
@@ -283,16 +467,16 @@ TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) {
// In TLS 1.2, curve and hash aren't bound together.
TEST_P(TlsConnectTls12, SignatureSchemeCurveMismatch) {
Reset(TlsAgent::kServerEcdsa256);
- client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
+ client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
Connect();
}
// In TLS 1.3, curve and hash are coupled.
TEST_P(TlsConnectTls13, SignatureSchemeCurveMismatch) {
Reset(TlsAgent::kServerEcdsa256);
- client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
+ client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
@@ -301,16 +485,16 @@ TEST_P(TlsConnectTls13, SignatureSchemeCurveMismatch) {
// Configuring a P-256 cert with only SHA-384 signatures is OK in TLS 1.2.
TEST_P(TlsConnectTls12, SignatureSchemeBadConfig) {
Reset(TlsAgent::kServerEcdsa256); // P-256 cert can't be used.
- server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
+ server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
Connect();
}
// A P-256 certificate in TLS 1.3 needs a SHA-256 signature scheme.
TEST_P(TlsConnectTls13, SignatureSchemeBadConfig) {
Reset(TlsAgent::kServerEcdsa256); // P-256 cert can't be used.
- server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
+ server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
@@ -319,10 +503,10 @@ TEST_P(TlsConnectTls13, SignatureSchemeBadConfig) {
// Where there is no overlap on signature schemes, we still connect successfully
// if we aren't going to use a signature.
TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) {
- client_->SetSignatureSchemes(SignatureSchemeRsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeRsaSha384));
- server_->SetSignatureSchemes(SignatureSchemeRsaSha256,
- PR_ARRAY_SIZE(SignatureSchemeRsaSha256));
+ client_->SetSignatureSchemes(kSignatureSchemeRsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeRsaSha384));
+ server_->SetSignatureSchemes(kSignatureSchemeRsaSha256,
+ PR_ARRAY_SIZE(kSignatureSchemeRsaSha256));
EnableOnlyStaticRsaCiphers();
Connect();
CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt);
@@ -330,10 +514,10 @@ TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) {
TEST_P(TlsConnectTls12Plus, SignatureAlgorithmNoOverlapEcdsa) {
Reset(TlsAgent::kServerEcdsa256);
- client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
- server_->SetSignatureSchemes(SignatureSchemeEcdsaSha256,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha256));
+ client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
+ server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha256,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha256));
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
@@ -342,10 +526,10 @@ TEST_P(TlsConnectTls12Plus, SignatureAlgorithmNoOverlapEcdsa) {
// Pre 1.2, a mismatch on signature algorithms shouldn't affect anything.
TEST_P(TlsConnectPre12, SignatureAlgorithmNoOverlapEcdsa) {
Reset(TlsAgent::kServerEcdsa256);
- client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
- server_->SetSignatureSchemes(SignatureSchemeEcdsaSha256,
- PR_ARRAY_SIZE(SignatureSchemeEcdsaSha256));
+ client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
+ server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha256,
+ PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha256));
Connect();
}
@@ -366,29 +550,6 @@ TEST_P(TlsConnectTls12, SignatureAlgorithmDrop) {
server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}
-// Replaces the signature scheme in a TLS 1.3 CertificateVerify message.
-class TlsReplaceSignatureSchemeFilter : public TlsHandshakeFilter {
- public:
- TlsReplaceSignatureSchemeFilter(const std::shared_ptr<TlsAgent>& a,
- SSLSignatureScheme scheme)
- : TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}),
- scheme_(scheme) {
- EnableDecryption();
- }
-
- protected:
- virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
- const DataBuffer& input,
- DataBuffer* output) {
- *output = input;
- output->Write(0, scheme_, 2);
- return CHANGE;
- }
-
- private:
- SSLSignatureScheme scheme_;
-};
-
TEST_P(TlsConnectTls13, UnsupportedSignatureSchemeAlert) {
EnsureTlsSetup();
MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(server_, ssl_sig_none);
@@ -411,8 +572,8 @@ TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) {
}
TEST_P(TlsConnectTls12Plus, RequestClientAuthWithSha384) {
- server_->SetSignatureSchemes(SignatureSchemeRsaSha384,
- PR_ARRAY_SIZE(SignatureSchemeRsaSha384));
+ server_->SetSignatureSchemes(kSignatureSchemeRsaSha384,
+ PR_ARRAY_SIZE(kSignatureSchemeRsaSha384));
server_->RequestClientAuth(false);
Connect();
}
@@ -438,7 +599,7 @@ class BeforeFinished : public TlsRecordFilter {
switch (state_) {
case BEFORE_CCS:
// Awaken when we see the CCS.
- if (header.content_type() == kTlsChangeCipherSpecType) {
+ if (header.content_type() == ssl_ct_change_cipher_spec) {
before_ccs_();
// Write the CCS out as a separate write, so that we can make
@@ -455,7 +616,7 @@ class BeforeFinished : public TlsRecordFilter {
break;
case AFTER_CCS:
- EXPECT_EQ(kTlsHandshakeType, header.content_type());
+ EXPECT_EQ(ssl_ct_handshake, header.content_type());
// This could check that data contains a Finished message, but it's
// encrypted, so that's too much extra work.
@@ -552,25 +713,11 @@ TEST_F(TlsConnectDatagram13, AuthCompleteBeforeFinished) {
Connect();
}
-static void TriggerAuthComplete(PollTarget* target, Event event) {
- std::cerr << "client: call SSL_AuthCertificateComplete" << std::endl;
- EXPECT_EQ(TIMER_EVENT, event);
- TlsAgent* client = static_cast<TlsAgent*>(target);
- EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client->ssl_fd(), 0));
-}
-
// This test uses a simple AuthCertificateCallback. Due to the way that the
// entire server flight is processed, the call to SSL_AuthCertificateComplete
// will trigger after the Finished message is processed.
TEST_F(TlsConnectDatagram13, AuthCompleteAfterFinished) {
- client_->SetAuthCertificateCallback(
- [this](TlsAgent*, PRBool, PRBool) -> SECStatus {
- std::shared_ptr<Poller::Timer> timer_handle;
- // This is really just to unroll the stack.
- Poller::Instance()->SetTimer(1U, client_.get(), TriggerAuthComplete,
- &timer_handle);
- return SECWouldBlock;
- });
+ SetDeferredAuthCertificateCallback(client_, 0); // 0 = success.
Connect();
}
@@ -754,15 +901,15 @@ TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1SignAndKEX) {
PRFileDesc* ssl_fd = agent_->ssl_fd();
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_decrypt));
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_sign));
- EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
+ EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
- // Configuring for only rsa_sign, rsa_pss, or rsa_decrypt should work.
+ // Configuring for only rsa_sign or rsa_decrypt should work.
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
&ServerCertDataRsaPkcs1Decrypt));
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
&ServerCertDataRsaPkcs1Sign));
- EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
- &ServerCertDataRsaPss));
+ EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
+ &ServerCertDataRsaPss));
}
// Test RSA cert with usage=[signature].
@@ -772,17 +919,17 @@ TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1Sign) {
PRFileDesc* ssl_fd = agent_->ssl_fd();
EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_decrypt));
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_sign));
- EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
+ EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
// Configuring for only rsa_decrypt should fail.
EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
&ServerCertDataRsaPkcs1Decrypt));
- // Configuring for only rsa_sign or rsa_pss should work.
+ // Configuring for only rsa_sign should work.
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
&ServerCertDataRsaPkcs1Sign));
- EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
- &ServerCertDataRsaPss));
+ EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
+ &ServerCertDataRsaPss));
}
// Test RSA cert with usage=[encipherment].
diff --git a/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc
index ec289bdd6..194cbab47 100644
--- a/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc
@@ -84,6 +84,18 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
Reset(TlsAgent::kRsa2048);
auth_type_ = ssl_auth_rsa_sign;
break;
+ case ssl_sig_rsa_pss_pss_sha256:
+ Reset(TlsAgent::kServerRsaPss);
+ auth_type_ = ssl_auth_rsa_pss;
+ break;
+ case ssl_sig_rsa_pss_pss_sha384:
+ Reset("rsa_pss384");
+ auth_type_ = ssl_auth_rsa_pss;
+ break;
+ case ssl_sig_rsa_pss_pss_sha512:
+ Reset("rsa_pss512");
+ auth_type_ = ssl_auth_rsa_pss;
+ break;
case ssl_sig_ecdsa_secp256r1_sha256:
Reset(TlsAgent::kServerEcdsa256);
auth_type_ = ssl_auth_ecdsa;
@@ -270,7 +282,7 @@ TEST_P(TlsCipherSuiteTest, ReadLimit) {
} else {
epoch = 0;
}
- TlsAgentTestBase::MakeRecord(variant_, kTlsApplicationDataType, version_,
+ TlsAgentTestBase::MakeRecord(variant_, ssl_ct_application_data, version_,
payload, sizeof(payload), &record,
(epoch << 48) | record_limit());
client_->SendDirect(record);
@@ -310,14 +322,13 @@ static const auto kDummyNamedGroupParams = ::testing::Values(ssl_grp_none);
static const auto kDummySignatureSchemesParams =
::testing::Values(ssl_sig_none);
-#ifndef NSS_DISABLE_TLS_1_3
static SSLSignatureScheme kSignatureSchemesParamsArr[] = {
ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384,
ssl_sig_rsa_pkcs1_sha512, ssl_sig_ecdsa_secp256r1_sha256,
ssl_sig_ecdsa_secp384r1_sha384, ssl_sig_rsa_pss_rsae_sha256,
ssl_sig_rsa_pss_rsae_sha384, ssl_sig_rsa_pss_rsae_sha512,
-};
-#endif
+ ssl_sig_rsa_pss_pss_sha256, ssl_sig_rsa_pss_pss_sha384,
+ ssl_sig_rsa_pss_pss_sha512};
INSTANTIATE_CIPHER_TEST_P(RC4, Stream, V10ToV12, kDummyNamedGroupParams,
kDummySignatureSchemesParams,
@@ -372,6 +383,14 @@ INSTANTIATE_CIPHER_TEST_P(
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
+INSTANTIATE_CIPHER_TEST_P(
+ TLS12SigSchemes, All, V12, ::testing::ValuesIn(kFasterDHEGroups),
+ ::testing::ValuesIn(kSignatureSchemesParamsArr),
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+ TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256);
#ifndef NSS_DISABLE_TLS_1_3
INSTANTIATE_CIPHER_TEST_P(TLS13, All, V13,
::testing::ValuesIn(kFasterDHEGroups),
diff --git a/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc
index 5be62e506..68c789a38 100644
--- a/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc
@@ -132,7 +132,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionEmptyWriterServer) {
// Sending extensions that the client doesn't expect leads to extensions
// appearing even if the client didn't send one, or in the wrong messages.
client_->ExpectSendAlert(kTlsAlertUnsupportedExtension);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
}
@@ -350,7 +350,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionUnsolicitedServer) {
auto capture = MakeTlsFilter<TlsExtensionCapture>(server_, extension_code);
client_->ExpectSendAlert(kTlsAlertUnsupportedExtension);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_TRUE(capture->captured());
@@ -401,7 +401,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionClientReject) {
EXPECT_EQ(SECSuccess, rv);
client_->ExpectSendAlert(kTlsAlertHandshakeFailure);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
}
@@ -451,7 +451,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionClientRejectAlert) {
EXPECT_EQ(SECSuccess, rv);
client_->ExpectSendAlert(kCustomAlert);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
}
diff --git a/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc
index b8836d7fc..0723c9bee 100644
--- a/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc
@@ -17,7 +17,7 @@ extern "C" {
}
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
diff --git a/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc
index b99461632..f1ccc2864 100644
--- a/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc
@@ -13,7 +13,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@@ -643,4 +643,43 @@ TEST_P(TlsConnectGenericPre13, InvalidDERSignatureFfdhe) {
client_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}
+// Replace SignatureAndHashAlgorithm of a SKE.
+class DHEServerKEXSigAlgReplacer : public TlsHandshakeFilter {
+ public:
+ DHEServerKEXSigAlgReplacer(const std::shared_ptr<TlsAgent>& server,
+ SSLSignatureScheme sig_scheme)
+ : TlsHandshakeFilter(server, {kTlsHandshakeServerKeyExchange}),
+ sig_scheme_(sig_scheme) {}
+
+ protected:
+ virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
+ const DataBuffer& input,
+ DataBuffer* output) {
+ *output = input;
+
+ uint32_t len;
+ uint32_t idx = 0;
+ EXPECT_TRUE(output->Read(idx, 2, &len));
+ idx += 2 + len;
+ EXPECT_TRUE(output->Read(idx, 2, &len));
+ idx += 2 + len;
+ EXPECT_TRUE(output->Read(idx, 2, &len));
+ idx += 2 + len;
+ output->Write(idx, sig_scheme_, 2);
+
+ return CHANGE;
+ }
+
+ private:
+ SSLSignatureScheme sig_scheme_;
+};
+
+TEST_P(TlsConnectTls12, ConnectInconsistentSigAlgDHE) {
+ EnableOnlyDheCiphers();
+
+ MakeTlsFilter<DHEServerKEXSigAlgReplacer>(server_,
+ ssl_sig_ecdsa_secp256r1_sha256);
+ ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
+}
+
} // namespace nss_test
diff --git a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc
index e5b52ff06..f25efc77a 100644
--- a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc
@@ -14,7 +14,7 @@ extern "C" {
}
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@@ -123,7 +123,7 @@ class TlsDropDatagram13 : public TlsConnectDatagram13,
void Init(const std::shared_ptr<TlsAgent>& agent) {
records_ = std::make_shared<TlsRecordRecorder>(agent);
- ack_ = std::make_shared<TlsRecordRecorder>(agent, content_ack);
+ ack_ = std::make_shared<TlsRecordRecorder>(agent, ssl_ct_ack);
ack_->EnableDecryption();
drop_ = std::make_shared<SelectiveRecordDropFilter>(agent, 0, false);
chain_ = std::make_shared<ChainedPacketFilter>(
@@ -670,7 +670,7 @@ TEST_P(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) {
ASSERT_NE(nullptr, spec.get());
ASSERT_EQ(2, spec->epoch());
ASSERT_TRUE(client_->SendEncryptedRecord(spec, 0x0002000000000002,
- kTlsApplicationDataType,
+ ssl_ct_application_data,
DataBuffer(buf, sizeof(buf))));
// Now have the server consume the bogus message.
@@ -696,7 +696,7 @@ TEST_P(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) {
ASSERT_NE(nullptr, spec.get());
ASSERT_EQ(2, spec->epoch());
ASSERT_TRUE(client_->SendEncryptedRecord(spec, 0x0002000000000002,
- kTlsHandshakeType,
+ ssl_ct_handshake,
DataBuffer(buf, sizeof(buf))));
server_->Handshake();
EXPECT_EQ(2UL, server_filters_.ack_->count());
@@ -899,7 +899,7 @@ class TlsReplaceFirstRecordWithJunk : public TlsRecordFilter {
}
replaced_ = true;
TlsRecordHeader out_header(header.variant(), header.version(),
- kTlsApplicationDataType,
+ ssl_ct_application_data,
header.sequence_number());
static const uint8_t junk[] = {1, 2, 3, 4};
diff --git a/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc
index 12c6e8516..f1cf1fabc 100644
--- a/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc
@@ -17,7 +17,7 @@ extern "C" {
}
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
diff --git a/security/nss/gtests/ssl_gtest/ssl_ems_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_ems_unittest.cc
index dad6ca026..39b2d5873 100644
--- a/security/nss/gtests/ssl_gtest/ssl_ems_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_ems_unittest.cc
@@ -10,7 +10,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
diff --git a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc
index 6965e9ca7..5819af746 100644
--- a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc
@@ -9,6 +9,9 @@
#include "sslerr.h"
#include "sslproto.h"
+// This is only to get DTLS_1_3_DRAFT_VERSION
+#include "ssl3prot.h"
+
#include <memory>
#include "tls_connect.h"
@@ -41,28 +44,6 @@ class TlsExtensionTruncator : public TlsExtensionFilter {
size_t length_;
};
-class TlsExtensionDamager : public TlsExtensionFilter {
- public:
- TlsExtensionDamager(const std::shared_ptr<TlsAgent>& a, uint16_t extension,
- size_t index)
- : TlsExtensionFilter(a), extension_(extension), index_(index) {}
- virtual PacketFilter::Action FilterExtension(uint16_t extension_type,
- const DataBuffer& input,
- DataBuffer* output) {
- if (extension_type != extension_) {
- return KEEP;
- }
-
- *output = input;
- output->data()[index_] += 73; // Increment selected for maximum damage
- return CHANGE;
- }
-
- private:
- uint16_t extension_;
- size_t index_;
-};
-
class TlsExtensionAppender : public TlsHandshakeFilter {
public:
TlsExtensionAppender(const std::shared_ptr<TlsAgent>& a,
@@ -454,6 +435,25 @@ TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsOddLength) {
client_, ssl_signature_algorithms_xtn, extension));
}
+TEST_F(TlsExtensionTest13Stream, SignatureAlgorithmsPrecedingGarbage) {
+ // 31 unknown signature algorithms followed by sha-256, rsa
+ const uint8_t val[] = {
+ 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x01};
+ DataBuffer extension(val, sizeof(val));
+ MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_signature_algorithms_xtn,
+ extension);
+ client_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ ConnectExpectFail();
+ client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
+ server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
+}
+
TEST_P(TlsExtensionTestGeneric, NoSupportedGroups) {
ClientHelloErrorTest(
std::make_shared<TlsExtensionDropper>(client_, ssl_supported_groups_xtn),
@@ -563,10 +563,10 @@ TEST_F(TlsExtensionTest13Stream, DropServerKeyShare) {
EnsureTlsSetup();
MakeTlsFilter<TlsExtensionDropper>(server_, ssl_tls13_key_share_xtn);
client_->ExpectSendAlert(kTlsAlertMissingExtension);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code());
- EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
+ EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
TEST_F(TlsExtensionTest13Stream, WrongServerKeyShare) {
@@ -583,13 +583,12 @@ TEST_F(TlsExtensionTest13Stream, WrongServerKeyShare) {
EnsureTlsSetup();
MakeTlsFilter<TlsExtensionReplacer>(server_, ssl_tls13_key_share_xtn, buf);
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_RX_MALFORMED_KEY_SHARE, client_->error_code());
- EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
+ EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
-// TODO(ekr@rtfm.com): This is the wrong error code. See bug 1307269.
TEST_F(TlsExtensionTest13Stream, UnknownServerKeyShare) {
const uint16_t wrong_group = 0xffff;
@@ -603,11 +602,11 @@ TEST_F(TlsExtensionTest13Stream, UnknownServerKeyShare) {
DataBuffer buf(key_share, sizeof(key_share));
EnsureTlsSetup();
MakeTlsFilter<TlsExtensionReplacer>(server_, ssl_tls13_key_share_xtn, buf);
- client_->ExpectSendAlert(kTlsAlertMissingExtension);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ client_->ExpectSendAlert(kTlsAlertIllegalParameter);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
- EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code());
- EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
+ EXPECT_EQ(SSL_ERROR_RX_MALFORMED_KEY_SHARE, client_->error_code());
+ EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
TEST_F(TlsExtensionTest13Stream, AddServerSignatureAlgorithmsOnResumption) {
@@ -616,10 +615,10 @@ TEST_F(TlsExtensionTest13Stream, AddServerSignatureAlgorithmsOnResumption) {
MakeTlsFilter<TlsExtensionInjector>(server_, ssl_signature_algorithms_xtn,
empty);
client_->ExpectSendAlert(kTlsAlertUnsupportedExtension);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, client_->error_code());
- EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
+ EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
struct PskIdentity {
@@ -912,23 +911,32 @@ TEST_P(TlsExtensionTest13, RemoveTls13FromVersionListServerV12) {
// 3. Server supports 1.2 and 1.3, client supports 1.2 and 1.3
// but advertises 1.2 (because we changed things).
TEST_P(TlsExtensionTest13, RemoveTls13FromVersionListBothV12) {
+ client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
-#ifndef TLS_1_3_DRAFT_VERSION
- ExpectAlert(server_, kTlsAlertIllegalParameter);
-#else
- ExpectAlert(server_, kTlsAlertDecryptError);
+// The downgrade check is disabled in DTLS 1.3, so all that happens when we
+// tamper with the supported versions is that the Finished check fails.
+#ifdef DTLS_1_3_DRAFT_VERSION
+ if (variant_ == ssl_variant_datagram) {
+ ExpectAlert(server_, kTlsAlertDecryptError);
+ } else
#endif
+ {
+ ExpectAlert(client_, kTlsAlertIllegalParameter);
+ }
ConnectWithReplacementVersionList(SSL_LIBRARY_VERSION_TLS_1_2);
-#ifndef TLS_1_3_DRAFT_VERSION
- client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
- server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
-#else
- client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
- server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+#ifdef DTLS_1_3_DRAFT_VERSION
+ if (variant_ == ssl_variant_datagram) {
+ client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
+ server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+ } else
#endif
+ {
+ client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
+ server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+ }
}
TEST_P(TlsExtensionTest13, HrrThenRemoveSignatureAlgorithms) {
@@ -1017,7 +1025,7 @@ class TlsBogusExtensionTest13 : public TlsBogusExtensionTest {
client_->ExpectSendAlert(alert);
client_->Handshake();
if (variant_ == ssl_variant_stream) {
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
}
server_->Handshake();
}
diff --git a/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc
index 92947c2c7..375281263 100644
--- a/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc
@@ -10,7 +10,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@@ -106,8 +106,8 @@ class RecordFragmenter : public PacketFilter {
}
// Just rewrite the sequence number (CCS only).
- if (header.content_type() != kTlsHandshakeType) {
- EXPECT_EQ(kTlsChangeCipherSpecType, header.content_type());
+ if (header.content_type() != ssl_ct_handshake) {
+ EXPECT_EQ(ssl_ct_change_cipher_spec, header.content_type());
WriteRecord(header, record);
continue;
}
diff --git a/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc
index f0afc9118..f033b7843 100644
--- a/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc
@@ -33,7 +33,7 @@ class TlsApplicationDataRecorder : public TlsRecordFilter {
virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& input,
DataBuffer* output) {
- if (header.content_type() == kTlsApplicationDataType) {
+ if (header.content_type() == ssl_ct_application_data) {
buffer_.Append(input);
}
diff --git a/security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc
index f47b2f445..745432951 100644
--- a/security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc
@@ -15,6 +15,7 @@ class GatherV2ClientHelloTest : public TlsConnectTestBase {
void ConnectExpectMalformedClientHello(const DataBuffer &data) {
EnsureTlsSetup();
+ server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_TRUE);
server_->ExpectSendAlert(kTlsAlertIllegalParameter);
client_->SendDirect(data);
server_->StartConnect();
diff --git a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
index 17677713d..be1c4ea32 100644
--- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
@@ -51,6 +51,7 @@
'tls_connect.cc',
'tls_filter.cc',
'tls_hkdf_unittest.cc',
+ 'tls_esni_unittest.cc',
'tls_protect.cc'
],
'dependencies': [
diff --git a/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc
index 77b335e86..27bc03654 100644
--- a/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc
@@ -9,11 +9,11 @@
#include "sslerr.h"
#include "sslproto.h"
-// This is internal, just to get TLS_1_3_DRAFT_VERSION.
+// This is internal, just to get DTLS_1_3_DRAFT_VERSION.
#include "ssl3prot.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@@ -76,7 +76,7 @@ class CorrectMessageSeqAfterHrrFilter : public TlsRecordFilter {
PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& record, size_t* offset,
DataBuffer* output) {
- if (filtered_packets() > 0 || header.content_type() != content_handshake) {
+ if (filtered_packets() > 0 || header.content_type() != ssl_ct_handshake) {
return KEEP;
}
@@ -718,6 +718,86 @@ TEST_F(TlsConnectStreamTls13, RetryStatelessDamageSecondClientHello) {
client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
}
+// Stream because SSL_SendSessionTicket only supports that.
+TEST_F(TlsConnectStreamTls13, SecondClientHelloSendSameTicket) {
+ // This simulates the scenario described at:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1481271#c7
+ //
+ // Here two connections are interleaved. Tickets are issued on one
+ // connection. A HelloRetryRequest is triggered on the second connection,
+ // meaning that there are two ClientHellos. We need to check that both
+ // ClientHellos have the same ticket, even if a new ticket is issued on the
+ // other connection in the meantime.
+ //
+ // Connection 1: <handshake>
+ // Connection 1: S->C: NST=X
+ // Connection 2: C->S: CH [PSK_ID=X]
+ // Connection 1: S->C: NST=Y
+ // Connection 2: S->C: HRR
+ // Connection 2: C->S: CH [PSK_ID=Y]
+
+ // Connection 1, send a ticket after handshake is complete.
+ ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
+
+ Connect();
+
+ // Set this token so that RetryHelloWithToken() will check that this
+ // is the token that it receives in the HelloRetryRequest callback.
+ EXPECT_EQ(SECSuccess,
+ SSL_SendSessionTicket(server_->ssl_fd(), kApplicationToken,
+ sizeof(kApplicationToken)));
+ SendReceive(50);
+
+ // Connection 2, trigger HRR.
+ auto client2 =
+ std::make_shared<TlsAgent>(client_->name(), TlsAgent::CLIENT, variant_);
+ auto server2 =
+ std::make_shared<TlsAgent>(server_->name(), TlsAgent::SERVER, variant_);
+
+ client2->SetPeer(server2);
+ server2->SetPeer(client2);
+
+ client_.swap(client2);
+ server_.swap(server2);
+
+ ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
+
+ ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+
+ client_->StartConnect();
+ server_->StartConnect();
+
+ size_t cb_called = 0;
+ EXPECT_EQ(SECSuccess,
+ SSL_HelloRetryRequestCallback(server_->ssl_fd(),
+ RetryHelloWithToken, &cb_called));
+ client_->Handshake(); // Send ClientHello.
+ server_->Handshake(); // Process ClientHello, send HelloRetryRequest.
+
+ EXPECT_EQ(1U, cb_called) << "callback should be called once here";
+
+ // Connection 1, send another ticket.
+ client_.swap(client2);
+ server_.swap(server2);
+
+ // If the client uses this token, RetryHelloWithToken() will fail the test.
+ const uint8_t kAnotherApplicationToken[] = {0x92, 0x44, 0x01};
+ EXPECT_EQ(SECSuccess,
+ SSL_SendSessionTicket(server_->ssl_fd(), kAnotherApplicationToken,
+ sizeof(kAnotherApplicationToken)));
+ SendReceive(60);
+
+ // Connection 2, continue the handshake.
+ // The client should use kApplicationToken, not kAnotherApplicationToken.
+ client_.swap(client2);
+ server_.swap(server2);
+
+ client_->Handshake();
+ server_->Handshake();
+
+ EXPECT_EQ(2U, cb_called) << "callback should be called twice here";
+}
+
// Read the cipher suite from the HRR and disable it on the identified agent.
static void DisableSuiteFromHrr(
std::shared_ptr<TlsAgent>& agent,
@@ -844,10 +924,10 @@ TEST_F(TlsConnectStreamTls13, RetryWithDifferentCipherSuite) {
TLS_CHACHA20_POLY1305_SHA256);
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
- EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
+ EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
// This tests that the second attempt at sending a ClientHello (after receiving
@@ -1007,14 +1087,17 @@ class HelloRetryRequestAgentTest : public TlsAgentTestClient {
// Now the supported version.
i = hrr_data.Write(i, ssl_tls13_supported_versions_xtn, 2);
i = hrr_data.Write(i, 2, 2);
- i = hrr_data.Write(i, 0x7f00 | TLS_1_3_DRAFT_VERSION, 2);
+ i = hrr_data.Write(i, (variant_ == ssl_variant_datagram)
+ ? (0x7f00 | DTLS_1_3_DRAFT_VERSION)
+ : SSL_LIBRARY_VERSION_TLS_1_3,
+ 2);
if (len) {
hrr_data.Write(i, body, len);
}
DataBuffer hrr;
MakeHandshakeMessage(kTlsHandshakeServerHello, hrr_data.data(),
hrr_data.len(), &hrr, seq_num);
- MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, hrr.data(),
+ MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, hrr.data(),
hrr.len(), hrr_record, seq_num);
}
diff --git a/security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc
index d03775c25..d6ac99a58 100644
--- a/security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_keyupdate_unittest.cc
@@ -15,7 +15,7 @@ extern "C" {
}
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
diff --git a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
index 5adbd9dc7..12c2496a6 100644
--- a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc
@@ -18,7 +18,7 @@ extern "C" {
}
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@@ -65,7 +65,7 @@ class TlsAlertRecorder : public TlsRecordFilter {
if (level_ != 255) { // Already captured.
return KEEP;
}
- if (header.content_type() != kTlsAlertType) {
+ if (header.content_type() != ssl_ct_alert) {
return KEEP;
}
@@ -130,7 +130,7 @@ TEST_P(TlsConnectTls13, CaptureAlertClient) {
client_->Handshake();
if (variant_ == ssl_variant_stream) {
// DTLS just drops the alert it can't decrypt.
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
}
server_->Handshake();
EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
@@ -320,6 +320,53 @@ TEST_F(TlsConnectStreamTls13, DropRecordClient) {
SendReceive();
}
+// Check that a server can use 0.5 RTT if client authentication isn't enabled.
+TEST_P(TlsConnectTls13, WriteBeforeClientFinished) {
+ EnsureTlsSetup();
+ StartConnect();
+ client_->Handshake(); // ClientHello
+ server_->Handshake(); // ServerHello
+
+ server_->SendData(10);
+ client_->ReadBytes(10); // Client should emit the Finished as a side-effect.
+ server_->Handshake(); // Server consumes the Finished.
+ CheckConnected();
+}
+
+// We don't allow 0.5 RTT if client authentication is requested.
+TEST_P(TlsConnectTls13, WriteBeforeClientFinishedClientAuth) {
+ client_->SetupClientAuth();
+ server_->RequestClientAuth(false);
+ StartConnect();
+ client_->Handshake(); // ClientHello
+ server_->Handshake(); // ServerHello
+
+ static const uint8_t data[] = {1, 2, 3};
+ EXPECT_GT(0, PR_Write(server_->ssl_fd(), data, sizeof(data)));
+ EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
+
+ Handshake();
+ CheckConnected();
+ SendReceive();
+}
+
+// 0.5 RTT should fail with client authentication required.
+TEST_P(TlsConnectTls13, WriteBeforeClientFinishedClientAuthRequired) {
+ client_->SetupClientAuth();
+ server_->RequestClientAuth(true);
+ StartConnect();
+ client_->Handshake(); // ClientHello
+ server_->Handshake(); // ServerHello
+
+ static const uint8_t data[] = {1, 2, 3};
+ EXPECT_GT(0, PR_Write(server_->ssl_fd(), data, sizeof(data)));
+ EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
+
+ Handshake();
+ CheckConnected();
+ SendReceive();
+}
+
// The next two tests takes advantage of the fact that we
// automatically read the first 1024 bytes, so if
// we provide 1200 bytes, they overrun the read buffer
@@ -426,13 +473,15 @@ class TlsPreCCSHeaderInjector : public TlsRecordFilter {
virtual PacketFilter::Action FilterRecord(
const TlsRecordHeader& record_header, const DataBuffer& input,
size_t* offset, DataBuffer* output) override {
- if (record_header.content_type() != kTlsChangeCipherSpecType) return KEEP;
+ if (record_header.content_type() != ssl_ct_change_cipher_spec) {
+ return KEEP;
+ }
std::cerr << "Injecting Finished header before CCS\n";
const uint8_t hhdr[] = {kTlsHandshakeFinished, 0x00, 0x00, 0x0c};
DataBuffer hhdr_buf(hhdr, sizeof(hhdr));
TlsRecordHeader nhdr(record_header.variant(), record_header.version(),
- kTlsHandshakeType, 0);
+ ssl_ct_handshake, 0);
*offset = nhdr.Write(output, *offset, hhdr_buf);
*offset = record_header.Write(output, *offset, input);
return CHANGE;
@@ -477,6 +526,26 @@ TEST_P(TlsConnectTls13, AlertWrongLevel) {
client_->WaitForErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT, 2000);
}
+TEST_P(TlsConnectTls13, UnknownRecord) {
+ static const uint8_t kUknownRecord[] = {
+ 0xff, SSL_LIBRARY_VERSION_TLS_1_2 >> 8,
+ SSL_LIBRARY_VERSION_TLS_1_2 & 0xff, 0, 0};
+
+ Connect();
+ if (variant_ == ssl_variant_stream) {
+ // DTLS just drops the record with an invalid type.
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
+ }
+ client_->SendDirect(DataBuffer(kUknownRecord, sizeof(kUknownRecord)));
+ server_->ExpectReadWriteError();
+ server_->ReadBytes();
+ if (variant_ == ssl_variant_stream) {
+ EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
+ } else {
+ EXPECT_EQ(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, server_->error_code());
+ }
+}
+
TEST_F(TlsConnectStreamTls13, Tls13FailedWriteSecondFlight) {
EnsureTlsSetup();
StartConnect();
@@ -539,6 +608,126 @@ TEST_F(TlsConnectTest, OneNRecordSplitting) {
EXPECT_EQ(ExpectedCbcLen(20), records->record(2).buffer.len());
}
+// We can't test for randomness easily here, but we can test that we don't
+// produce a zero value, or produce the same value twice. There are 5 values
+// here: two ClientHello.random, two ServerHello.random, and one zero value.
+// Matrix them and fail if any are the same.
+TEST_P(TlsConnectGeneric, CheckRandoms) {
+ ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+
+ static const size_t random_len = 32;
+ uint8_t crandom1[random_len], srandom1[random_len];
+ uint8_t z[random_len] = {0};
+
+ auto ch = MakeTlsFilter<TlsHandshakeRecorder>(client_, ssl_hs_client_hello);
+ auto sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
+ Connect();
+ ASSERT_TRUE(ch->buffer().len() > (random_len + 2));
+ ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
+ memcpy(crandom1, ch->buffer().data() + 2, random_len);
+ memcpy(srandom1, sh->buffer().data() + 2, random_len);
+ EXPECT_NE(0, memcmp(crandom1, srandom1, random_len));
+ EXPECT_NE(0, memcmp(crandom1, z, random_len));
+ EXPECT_NE(0, memcmp(srandom1, z, random_len));
+
+ Reset();
+ ch = MakeTlsFilter<TlsHandshakeRecorder>(client_, ssl_hs_client_hello);
+ sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
+ Connect();
+ ASSERT_TRUE(ch->buffer().len() > (random_len + 2));
+ ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
+ const uint8_t* crandom2 = ch->buffer().data() + 2;
+ const uint8_t* srandom2 = sh->buffer().data() + 2;
+
+ EXPECT_NE(0, memcmp(crandom2, srandom2, random_len));
+ EXPECT_NE(0, memcmp(crandom2, z, random_len));
+ EXPECT_NE(0, memcmp(srandom2, z, random_len));
+
+ EXPECT_NE(0, memcmp(crandom1, crandom2, random_len));
+ EXPECT_NE(0, memcmp(crandom1, srandom2, random_len));
+ EXPECT_NE(0, memcmp(srandom1, crandom2, random_len));
+ EXPECT_NE(0, memcmp(srandom1, srandom2, random_len));
+}
+
+void FailOnCloseNotify(const PRFileDesc* fd, void* arg, const SSLAlert* alert) {
+ ADD_FAILURE() << "received alert " << alert->description;
+}
+
+void CheckCloseNotify(const PRFileDesc* fd, void* arg, const SSLAlert* alert) {
+ *reinterpret_cast<bool*>(arg) = true;
+ EXPECT_EQ(close_notify, alert->description);
+ EXPECT_EQ(alert_warning, alert->level);
+}
+
+TEST_P(TlsConnectGeneric, ShutdownOneSide) {
+ Connect();
+
+ // Setup to check alerts.
+ EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(server_->ssl_fd(),
+ FailOnCloseNotify, nullptr));
+ EXPECT_EQ(SECSuccess, SSL_AlertReceivedCallback(client_->ssl_fd(),
+ FailOnCloseNotify, nullptr));
+
+ bool client_sent = false;
+ EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(client_->ssl_fd(),
+ CheckCloseNotify, &client_sent));
+ bool server_received = false;
+ EXPECT_EQ(SECSuccess,
+ SSL_AlertReceivedCallback(server_->ssl_fd(), CheckCloseNotify,
+ &server_received));
+ EXPECT_EQ(PR_SUCCESS, PR_Shutdown(client_->ssl_fd(), PR_SHUTDOWN_SEND));
+
+ // Make sure that the server reads out the close_notify.
+ uint8_t buf[10];
+ EXPECT_EQ(0, PR_Read(server_->ssl_fd(), buf, sizeof(buf)));
+
+ // Reading and writing should still work in the one open direction.
+ EXPECT_TRUE(client_sent);
+ EXPECT_TRUE(server_received);
+ server_->SendData(10, 10);
+ client_->ReadBytes(10);
+
+ // Now close the other side and do the same checks.
+ bool server_sent = false;
+ EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(server_->ssl_fd(),
+ CheckCloseNotify, &server_sent));
+ bool client_received = false;
+ EXPECT_EQ(SECSuccess,
+ SSL_AlertReceivedCallback(client_->ssl_fd(), CheckCloseNotify,
+ &client_received));
+ EXPECT_EQ(PR_SUCCESS, PR_Shutdown(server_->ssl_fd(), PR_SHUTDOWN_SEND));
+
+ EXPECT_EQ(0, PR_Read(client_->ssl_fd(), buf, sizeof(buf)));
+ EXPECT_TRUE(server_sent);
+ EXPECT_TRUE(client_received);
+}
+
+TEST_P(TlsConnectGeneric, ShutdownOneSideThenCloseTcp) {
+ Connect();
+
+ bool client_sent = false;
+ EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(client_->ssl_fd(),
+ CheckCloseNotify, &client_sent));
+ bool server_received = false;
+ EXPECT_EQ(SECSuccess,
+ SSL_AlertReceivedCallback(server_->ssl_fd(), CheckCloseNotify,
+ &server_received));
+ EXPECT_EQ(PR_SUCCESS, PR_Shutdown(client_->ssl_fd(), PR_SHUTDOWN_SEND));
+
+ // Make sure that the server reads out the close_notify.
+ uint8_t buf[10];
+ EXPECT_EQ(0, PR_Read(server_->ssl_fd(), buf, sizeof(buf)));
+
+ // Now simulate the underlying connection closing.
+ client_->adapter()->Reset();
+
+ // Now close the other side and see that things don't explode.
+ EXPECT_EQ(PR_SUCCESS, PR_Shutdown(server_->ssl_fd(), PR_SHUTDOWN_SEND));
+
+ EXPECT_GT(0, PR_Read(client_->ssl_fd(), buf, sizeof(buf)));
+ EXPECT_EQ(PR_NOT_CONNECTED_ERROR, PR_GetError());
+}
+
INSTANTIATE_TEST_CASE_P(
GenericStream, TlsConnectGeneric,
::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
diff --git a/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc
index 53b11c61a..f1e85e898 100644
--- a/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc
@@ -111,7 +111,7 @@ class RecordReplacer : public TlsRecordFilter {
PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& data,
DataBuffer* changed) override {
- EXPECT_EQ(kTlsApplicationDataType, header.content_type());
+ EXPECT_EQ(ssl_ct_application_data, header.content_type());
changed->Allocate(size_);
for (size_t i = 0; i < size_; ++i) {
diff --git a/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc
index 00651aec5..0a54ae1a8 100644
--- a/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_recordsize_unittest.cc
@@ -10,7 +10,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@@ -34,7 +34,7 @@ class TlsRecordMaximum : public TlsRecordFilter {
DataBuffer* output) override {
std::cerr << "max: " << record << std::endl;
// Ignore unprotected packets.
- if (header.content_type() != kTlsApplicationDataType) {
+ if (header.content_type() != ssl_ct_application_data) {
return KEEP;
}
@@ -187,7 +187,7 @@ class TlsRecordExpander : public TlsRecordFilter {
virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& data,
DataBuffer* changed) {
- if (header.content_type() != kTlsApplicationDataType) {
+ if (header.content_type() != ssl_ct_application_data) {
return KEEP;
}
changed->Allocate(data.len() + expansion_);
@@ -252,7 +252,7 @@ class TlsRecordPadder : public TlsRecordFilter {
PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& record, size_t* offset,
DataBuffer* output) override {
- if (header.content_type() != kTlsApplicationDataType) {
+ if (header.content_type() != ssl_ct_application_data) {
return KEEP;
}
@@ -262,7 +262,7 @@ class TlsRecordPadder : public TlsRecordFilter {
return KEEP;
}
- if (inner_content_type != kTlsApplicationDataType) {
+ if (inner_content_type != ssl_ct_application_data) {
return KEEP;
}
diff --git a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
index 2cc98a327..264bde67f 100644
--- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc
@@ -18,7 +18,8 @@ extern "C" {
}
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
+#include "scoped_ptrs_ssl.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@@ -171,21 +172,143 @@ TEST_P(TlsConnectGenericResumption, ConnectResumeClientNoneServerBoth) {
SendReceive();
}
-TEST_P(TlsConnectGenericPre13, ConnectResumeWithHigherVersion) {
+TEST_P(TlsConnectGenericPre13, ResumeWithHigherVersionTls13) {
+ uint16_t lower_version = version_;
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ Connect();
+ SendReceive();
+ CheckKeys();
+
+ Reset();
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ EnsureTlsSetup();
+ auto psk_ext = std::make_shared<TlsExtensionCapture>(
+ client_, ssl_tls13_pre_shared_key_xtn);
+ auto ticket_ext =
+ std::make_shared<TlsExtensionCapture>(client_, ssl_session_ticket_xtn);
+ client_->SetFilter(std::make_shared<ChainedPacketFilter>(
+ ChainedPacketFilterInit({psk_ext, ticket_ext})));
+ SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+ client_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
+ server_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
+ ExpectResumption(RESUME_NONE);
+ Connect();
+
+ // The client shouldn't have sent a PSK, though it will send a ticket.
+ EXPECT_FALSE(psk_ext->captured());
+ EXPECT_TRUE(ticket_ext->captured());
+}
+
+class CaptureSessionId : public TlsHandshakeFilter {
+ public:
+ CaptureSessionId(const std::shared_ptr<TlsAgent>& a)
+ : TlsHandshakeFilter(
+ a, {kTlsHandshakeClientHello, kTlsHandshakeServerHello}),
+ sid_() {}
+
+ const DataBuffer& sid() const { return sid_; }
+
+ protected:
+ PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
+ const DataBuffer& input,
+ DataBuffer* output) override {
+ // The session_id is in the same place in both Hello messages:
+ size_t offset = 2 + 32; // Version(2) + Random(32)
+ uint32_t len = 0;
+ EXPECT_TRUE(input.Read(offset, 1, &len));
+ offset++;
+ if (input.len() < offset + len) {
+ ADD_FAILURE() << "session_id overflows the Hello message";
+ return KEEP;
+ }
+ sid_.Assign(input.data() + offset, len);
+ return KEEP;
+ }
+
+ private:
+ DataBuffer sid_;
+};
+
+// Attempting to resume from TLS 1.2 when 1.3 is possible should not result in
+// resumption, though it will appear to be TLS 1.3 compatibility mode if the
+// server uses a session ID.
+TEST_P(TlsConnectGenericPre13, ResumeWithHigherVersionTls13SessionId) {
+ uint16_t lower_version = version_;
ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
- ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_1);
- SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_1);
+ auto original_sid = MakeTlsFilter<CaptureSessionId>(server_);
+ Connect();
+ CheckKeys();
+ EXPECT_EQ(32U, original_sid->sid().len());
+
+ // The client should now attempt to resume with the session ID from the last
+ // connection. This looks like compatibility mode, we just want to ensure
+ // that we get TLS 1.3 rather than 1.2 (and no resumption).
+ Reset();
+ auto client_sid = MakeTlsFilter<CaptureSessionId>(client_);
+ auto server_sid = MakeTlsFilter<CaptureSessionId>(server_);
+ ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
+ SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+ client_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
+ server_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
+ ExpectResumption(RESUME_NONE);
+
+ Connect();
+ SendReceive();
+
+ EXPECT_EQ(client_sid->sid(), original_sid->sid());
+ if (variant_ == ssl_variant_stream) {
+ EXPECT_EQ(client_sid->sid(), server_sid->sid());
+ } else {
+ // DTLS servers don't echo the session ID.
+ EXPECT_EQ(0U, server_sid->sid().len());
+ }
+}
+
+TEST_P(TlsConnectPre12, ResumeWithHigherVersionTls12) {
+ uint16_t lower_version = version_;
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
Connect();
Reset();
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
EnsureTlsSetup();
- SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_2);
- client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
- SSL_LIBRARY_VERSION_TLS_1_2);
- server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
- SSL_LIBRARY_VERSION_TLS_1_2);
+ SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+ client_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
+ server_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
+ ExpectResumption(RESUME_NONE);
+ Connect();
+}
+
+TEST_P(TlsConnectGenericPre13, ResumeWithLowerVersionFromTls13) {
+ uint16_t original_version = version_;
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+ Connect();
+ SendReceive();
+ CheckKeys();
+
+ Reset();
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ ConfigureVersion(original_version);
ExpectResumption(RESUME_NONE);
Connect();
+ SendReceive();
+}
+
+TEST_P(TlsConnectPre12, ResumeWithLowerVersionFromTls12) {
+ uint16_t original_version = version_;
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_2);
+ Connect();
+ SendReceive();
+ CheckKeys();
+
+ Reset();
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ ConfigureVersion(original_version);
+ ExpectResumption(RESUME_NONE);
+ Connect();
+ SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicketForget) {
@@ -276,8 +399,13 @@ TEST_P(TlsConnectGeneric, ConnectResumeCorruptTicket) {
ASSERT_NE(nullptr, hmac_key);
SSLInt_SetSelfEncryptMacKey(hmac_key);
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
- ConnectExpectAlert(server_, illegal_parameter);
- server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+ if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ ExpectResumption(RESUME_NONE);
+ Connect();
+ } else {
+ ConnectExpectAlert(server_, illegal_parameter);
+ server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+ }
}
// This callback switches out the "server" cert used on the server with
@@ -394,6 +522,64 @@ TEST_P(TlsConnectTls13, TestTls13ResumeDifferentGroup) {
ssl_sig_rsa_pss_rsae_sha256);
}
+// Verify that TLS 1.3 server doesn't request certificate in the main
+// handshake, after resumption.
+TEST_P(TlsConnectTls13, TestTls13ResumeNoCertificateRequest) {
+ ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+ client_->SetupClientAuth();
+ server_->RequestClientAuth(true);
+ Connect();
+ SendReceive(); // Need to read so that we absorb the session ticket.
+ ScopedCERTCertificate cert1(SSL_LocalCertificate(client_->ssl_fd()));
+
+ Reset();
+ ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+ ExpectResumption(RESUME_TICKET);
+ server_->RequestClientAuth(false);
+ auto cr_capture =
+ MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_certificate_request);
+ cr_capture->EnableDecryption();
+ Connect();
+ SendReceive();
+ EXPECT_EQ(0U, cr_capture->buffer().len()) << "expect nothing captured yet";
+
+ // Sanity check whether the client certificate matches the one
+ // decrypted from ticket.
+ ScopedCERTCertificate cert2(SSL_PeerCertificate(server_->ssl_fd()));
+ EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
+}
+
+// Here we test that 0.5 RTT is available at the server when resuming, even if
+// configured to request a client certificate. The resumed handshake relies on
+// the authentication from the original handshake, so no certificate is
+// requested this time around. The server can write before the handshake
+// completes because the PSK binder is sufficient authentication for the client.
+TEST_P(TlsConnectTls13, WriteBeforeHandshakeCompleteOnResumption) {
+ ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+ client_->SetupClientAuth();
+ server_->RequestClientAuth(true);
+ Connect();
+ SendReceive(); // Absorb the session ticket.
+ ScopedCERTCertificate cert1(SSL_LocalCertificate(client_->ssl_fd()));
+
+ Reset();
+ ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
+ ExpectResumption(RESUME_TICKET);
+ server_->RequestClientAuth(false);
+ StartConnect();
+ client_->Handshake(); // ClientHello
+ server_->Handshake(); // ServerHello
+
+ server_->SendData(10);
+ client_->ReadBytes(10); // Client should emit the Finished as a side-effect.
+ server_->Handshake(); // Server consumes the Finished.
+ CheckConnected();
+
+ // Check whether the client certificate matches the one from the ticket.
+ ScopedCERTCertificate cert2(SSL_PeerCertificate(server_->ssl_fd()));
+ EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
+}
+
// We need to enable different cipher suites at different times in the following
// tests. Those cipher suites need to be suited to the version.
static uint16_t ChooseOneCipher(uint16_t version) {
@@ -467,7 +653,7 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) {
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
} else {
ExpectAlert(client_, kTlsAlertHandshakeFailure);
}
@@ -476,7 +662,7 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) {
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
// The reason this test is stream only: the server is unable to decrypt
// the alert that the client sends, see bug 1304603.
- server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
+ server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE);
} else {
server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT);
}
@@ -760,6 +946,36 @@ TEST_F(TlsConnectDatagram13, SendSessionTicketDtls) {
EXPECT_EQ(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION, PORT_GetError());
}
+TEST_F(TlsConnectStreamTls13, ExternalResumptionUseSecondTicket) {
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+
+ struct ResumptionTicketState {
+ std::vector<uint8_t> ticket;
+ size_t invoked = 0;
+ } ticket_state;
+ auto cb = [](PRFileDesc* fd, const PRUint8* ticket, unsigned int ticket_len,
+ void* arg) -> SECStatus {
+ auto state = reinterpret_cast<ResumptionTicketState*>(arg);
+ state->ticket.assign(ticket, ticket + ticket_len);
+ state->invoked++;
+ return SECSuccess;
+ };
+ SSL_SetResumptionTokenCallback(client_->ssl_fd(), cb, &ticket_state);
+
+ Connect();
+ EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0));
+ SendReceive();
+ EXPECT_EQ(2U, ticket_state.invoked);
+
+ Reset();
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ client_->SetResumptionToken(ticket_state.ticket);
+ ExpectResumption(RESUME_TICKET);
+ Connect();
+ SendReceive();
+}
+
TEST_F(TlsConnectTest, TestTls13ResumptionDowngrade) {
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
@@ -830,10 +1046,10 @@ TEST_F(TlsConnectTest, TestTls13ResumptionForcedDowngrade) {
// client expects to receive an unencrypted TLS 1.2 Certificate message.
// The server can't decrypt the alert.
client_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac); // Server can't read
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); // Server can't read
ConnectExpectFail();
client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA);
- server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
+ server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE);
}
TEST_P(TlsConnectGenericResumption, ReConnectTicket) {
@@ -908,6 +1124,36 @@ void CheckGetInfoResult(uint32_t alpnSize, uint32_t earlyDataSize,
EXPECT_EQ(0, memcmp("a", token->alpnSelection, token->alpnSelectionLen));
ASSERT_EQ(earlyDataSize, token->maxEarlyDataSize);
+
+ ASSERT_LT(ssl_TimeUsec(), token->expirationTime);
+}
+
+// The client should generate a new, randomized session_id
+// when resuming using an external token.
+TEST_P(TlsConnectGenericResumptionToken, CheckSessionId) {
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ auto original_sid = MakeTlsFilter<CaptureSessionId>(client_);
+ Connect();
+ SendReceive();
+
+ Reset();
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ ExpectResumption(RESUME_TICKET);
+
+ StartConnect();
+ ASSERT_TRUE(client_->MaybeSetResumptionToken());
+ auto resumed_sid = MakeTlsFilter<CaptureSessionId>(client_);
+
+ Handshake();
+ CheckConnected();
+ SendReceive();
+
+ if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
+ EXPECT_NE(resumed_sid->sid(), original_sid->sid());
+ EXPECT_EQ(32U, resumed_sid->sid().len());
+ } else {
+ EXPECT_EQ(0U, resumed_sid->sid().len());
+ }
}
TEST_P(TlsConnectGenericResumptionToken, ConnectResumeGetInfo) {
@@ -1026,4 +1272,34 @@ TEST_P(TlsConnectGenericResumption, ConnectResumeClientAuth) {
SendReceive();
}
+TEST_F(TlsConnectStreamTls13, ExternalTokenAfterHrr) {
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ Connect();
+ SendReceive();
+
+ Reset();
+ ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
+ ExpectResumption(RESUME_TICKET);
+
+ static const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1,
+ ssl_grp_ec_secp521r1};
+ server_->ConfigNamedGroups(groups);
+
+ StartConnect();
+ ASSERT_TRUE(client_->MaybeSetResumptionToken());
+
+ client_->Handshake(); // Send ClientHello.
+ server_->Handshake(); // Process ClientHello, send HelloRetryRequest.
+
+ auto& token = client_->GetResumptionToken();
+ SECStatus rv =
+ SSL_SetResumptionToken(client_->ssl_fd(), token.data(), token.size());
+ ASSERT_EQ(SECFailure, rv);
+ ASSERT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
+
+ Handshake();
+ CheckConnected();
+ SendReceive();
+}
+
} // namespace nss_test
diff --git a/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc
index 9ef19653b..3ed42e86b 100644
--- a/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc
@@ -32,7 +32,7 @@ class TlsHandshakeSkipFilter : public TlsRecordFilter {
virtual PacketFilter::Action FilterRecord(
const TlsRecordHeader& record_header, const DataBuffer& input,
DataBuffer* output) {
- if (record_header.content_type() != kTlsHandshakeType) {
+ if (record_header.content_type() != ssl_ct_handshake) {
return KEEP;
}
diff --git a/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc
index ff4091b9a..abddaa5b6 100644
--- a/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc
@@ -17,7 +17,7 @@ extern "C" {
}
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
diff --git a/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
index 42f1065f6..ecb63d476 100644
--- a/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
@@ -82,7 +82,7 @@ class Tls13CompatTest : public TlsConnectStreamTls13 {
// Only the second record can be a CCS.
bool expected_match = expected && (i == 1);
EXPECT_EQ(expected_match,
- kTlsChangeCipherSpecType ==
+ ssl_ct_change_cipher_spec ==
records_->record(i).header.content_type());
}
}
@@ -299,15 +299,15 @@ TEST_F(TlsConnectTest, TLS13NonCompatModeSessionID) {
MakeTlsFilter<TlsSessionIDInjectFilter>(server_);
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
- server_->ExpectSendAlert(kTlsAlertBadRecordMac);
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
- server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
+ server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE);
}
static const uint8_t kCannedCcs[] = {
- kTlsChangeCipherSpecType,
+ ssl_ct_change_cipher_spec,
SSL_LIBRARY_VERSION_TLS_1_2 >> 8,
SSL_LIBRARY_VERSION_TLS_1_2 & 0xff,
0,
@@ -362,6 +362,19 @@ TEST_F(TlsConnectStreamTls13, ChangeCipherSpecBeforeClientHello12) {
client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
}
+TEST_F(TlsConnectStreamTls13, ChangeCipherSpecAfterFinished13) {
+ EnsureTlsSetup();
+ ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+ Connect();
+ SendReceive(10);
+ // Client sends CCS after the handshake.
+ client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs)));
+ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
+ server_->ExpectReadWriteError();
+ server_->ReadBytes();
+ EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
+}
+
TEST_F(TlsConnectDatagram13, CompatModeDtlsClient) {
EnsureTlsSetup();
client_->SetOption(SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE);
@@ -370,14 +383,14 @@ TEST_F(TlsConnectDatagram13, CompatModeDtlsClient) {
Connect();
ASSERT_EQ(2U, client_records->count()); // CH, Fin
- EXPECT_EQ(kTlsHandshakeType, client_records->record(0).header.content_type());
- EXPECT_EQ(kTlsApplicationDataType,
+ EXPECT_EQ(ssl_ct_handshake, client_records->record(0).header.content_type());
+ EXPECT_EQ(ssl_ct_application_data,
client_records->record(1).header.content_type());
ASSERT_EQ(6U, server_records->count()); // SH, EE, CT, CV, Fin, Ack
- EXPECT_EQ(kTlsHandshakeType, server_records->record(0).header.content_type());
+ EXPECT_EQ(ssl_ct_handshake, server_records->record(0).header.content_type());
for (size_t i = 1; i < server_records->count(); ++i) {
- EXPECT_EQ(kTlsApplicationDataType,
+ EXPECT_EQ(ssl_ct_application_data,
server_records->record(i).header.content_type());
}
}
@@ -422,12 +435,12 @@ TEST_F(TlsConnectDatagram13, CompatModeDtlsServer) {
client_->Handshake();
ASSERT_EQ(1U, client_records->count());
- EXPECT_EQ(kTlsHandshakeType, client_records->record(0).header.content_type());
+ EXPECT_EQ(ssl_ct_handshake, client_records->record(0).header.content_type());
ASSERT_EQ(5U, server_records->count()); // SH, EE, CT, CV, Fin
- EXPECT_EQ(kTlsHandshakeType, server_records->record(0).header.content_type());
+ EXPECT_EQ(ssl_ct_handshake, server_records->record(0).header.content_type());
for (size_t i = 1; i < server_records->count(); ++i) {
- EXPECT_EQ(kTlsApplicationDataType,
+ EXPECT_EQ(ssl_ct_application_data,
server_records->record(i).header.content_type());
}
diff --git a/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc
index 100595732..cafbcce68 100644
--- a/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc
@@ -151,6 +151,7 @@ class SSLv2ClientHelloTestF : public TlsConnectTestBase {
void SetUp() override {
TlsConnectTestBase::SetUp();
filter_ = MakeTlsFilter<SSLv2ClientHelloFilter>(client_, version_);
+ server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_TRUE);
}
void SetExpectedVersion(uint16_t version) {
@@ -197,6 +198,27 @@ TEST_P(SSLv2ClientHelloTest, Connect) {
Connect();
}
+TEST_P(SSLv2ClientHelloTest, ConnectDisabled) {
+ server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_FALSE);
+ SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
+
+ StartConnect();
+ client_->Handshake(); // Send the modified ClientHello.
+ server_->Handshake(); // Read some.
+ // The problem here is that the v2 ClientHello puts the version where the v3
+ // ClientHello puts a version number. So the version number (0x0301+) appears
+ // to be a length and server blocks waiting for that much data.
+ EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
+
+ // This is usually what happens with v2-compatible: the server hangs.
+ // But to be certain, feed in more data to see if an error comes out.
+ uint8_t zeros[SSL_LIBRARY_VERSION_TLS_1_2] = {0};
+ client_->SendDirect(DataBuffer(zeros, sizeof(zeros)));
+ ExpectAlert(server_, kTlsAlertIllegalParameter);
+ server_->Handshake();
+ client_->Handshake();
+}
+
// Sending a v2 ClientHello after a no-op v3 record must fail.
TEST_P(SSLv2ClientHelloTest, ConnectAfterEmptyV3Record) {
DataBuffer buffer;
@@ -328,6 +350,30 @@ TEST_P(SSLv2ClientHelloTest, RequireSafeRenegotiationWithSCSV) {
Connect();
}
+TEST_P(SSLv2ClientHelloTest, CheckServerRandom) {
+ ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
+ SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
+
+ static const size_t random_len = 32;
+ uint8_t srandom1[random_len];
+ uint8_t z[random_len] = {0};
+
+ auto sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
+ Connect();
+ ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
+ memcpy(srandom1, sh->buffer().data() + 2, random_len);
+ EXPECT_NE(0, memcmp(srandom1, z, random_len));
+
+ Reset();
+ sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
+ Connect();
+ ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
+ const uint8_t* srandom2 = sh->buffer().data() + 2;
+
+ EXPECT_NE(0, memcmp(srandom2, z, random_len));
+ EXPECT_NE(0, memcmp(srandom1, srandom2, random_len));
+}
+
// Connect to the server with TLS 1.1, signalling that this is a fallback from
// a higher version. As the server doesn't support anything higher than TLS 1.1
// it must accept the connection.
diff --git a/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc
index 4e9099561..ffc0893e9 100644
--- a/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc
@@ -11,7 +11,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@@ -48,7 +48,6 @@ TEST_P(TlsConnectGeneric, ServerNegotiateTls12) {
SSL_LIBRARY_VERSION_TLS_1_2);
Connect();
}
-#ifndef TLS_1_3_DRAFT_VERSION
// Test the ServerRandom version hack from
// [draft-ietf-tls-tls13-11 Section 6.3.1.1].
@@ -56,71 +55,116 @@ TEST_P(TlsConnectGeneric, ServerNegotiateTls12) {
// two validate that we can also detect fallback using the
// SSL_SetDowngradeCheckVersion() API.
TEST_F(TlsConnectTest, TestDowngradeDetectionToTls11) {
+ client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
MakeTlsFilter<TlsClientHelloVersionSetter>(client_,
SSL_LIBRARY_VERSION_TLS_1_1);
- ConnectExpectFail();
- ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
+ ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
+ client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
+ server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}
-/* Attempt to negotiate the bogus DTLS 1.1 version. */
+// Attempt to negotiate the bogus DTLS 1.1 version.
TEST_F(DtlsConnectTest, TestDtlsVersion11) {
MakeTlsFilter<TlsClientHelloVersionSetter>(client_, ((~0x0101) & 0xffff));
- ConnectExpectFail();
+ ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
// It's kind of surprising that SSL_ERROR_NO_CYPHER_OVERLAP is
// what is returned here, but this is deliberate in ssl3_HandleAlert().
- EXPECT_EQ(SSL_ERROR_NO_CYPHER_OVERLAP, client_->error_code());
- EXPECT_EQ(SSL_ERROR_UNSUPPORTED_VERSION, server_->error_code());
+ client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
+ server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
}
-// Disabled as long as we have draft version.
TEST_F(TlsConnectTest, TestDowngradeDetectionToTls12) {
- EnsureTlsSetup();
- MakeTlsFilter<TlsClientHelloVersionSetter>(client_,
- SSL_LIBRARY_VERSION_TLS_1_2);
+ client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
+ MakeTlsFilter<TlsExtensionDropper>(client_, ssl_tls13_supported_versions_xtn);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
- ConnectExpectFail();
- ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
+ ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
+ client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
+ server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+}
+
+// Disabling downgrade checks will be caught when the Finished MAC check fails.
+TEST_F(TlsConnectTest, TestDisableDowngradeDetection) {
+ client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_FALSE);
+ MakeTlsFilter<TlsExtensionDropper>(client_, ssl_tls13_supported_versions_xtn);
+ client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_3);
+ server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_3);
+ ConnectExpectAlert(server_, kTlsAlertDecryptError);
+ client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
+ server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}
// TLS 1.1 clients do not check the random values, so we should
// instead get a handshake failure alert from the server.
TEST_F(TlsConnectTest, TestDowngradeDetectionToTls10) {
+ // Setting the option here has no effect.
+ client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
MakeTlsFilter<TlsClientHelloVersionSetter>(client_,
SSL_LIBRARY_VERSION_TLS_1_0);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_1);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2);
- ConnectExpectFail();
- ASSERT_EQ(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE, server_->error_code());
- ASSERT_EQ(SSL_ERROR_DECRYPT_ERROR_ALERT, client_->error_code());
+ ConnectExpectAlert(server_, kTlsAlertDecryptError);
+ server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+ client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
}
TEST_F(TlsConnectTest, TestFallbackFromTls12) {
- EnsureTlsSetup();
+ client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_2);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_1);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_2);
- ConnectExpectFail();
- ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
+ ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
+ client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
+ server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
+}
+
+static SECStatus AllowFalseStart(PRFileDesc* fd, void* arg,
+ PRBool* can_false_start) {
+ bool* false_start_attempted = reinterpret_cast<bool*>(arg);
+ *false_start_attempted = true;
+ *can_false_start = PR_TRUE;
+ return SECSuccess;
+}
+
+// If we disable the downgrade check, the sentinel is still generated, and we
+// disable false start instead.
+TEST_F(TlsConnectTest, DisableFalseStartOnFallback) {
+ // Don't call client_->EnableFalseStart(), because that sets the client up for
+ // success, and we want false start to fail.
+ client_->SetOption(SSL_ENABLE_FALSE_START, PR_TRUE);
+ bool false_start_attempted = false;
+ EXPECT_EQ(SECSuccess,
+ SSL_SetCanFalseStartCallback(client_->ssl_fd(), AllowFalseStart,
+ &false_start_attempted));
+
+ client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+ client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_2);
+ server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_3);
+ Connect();
+ EXPECT_FALSE(false_start_attempted);
}
TEST_F(TlsConnectTest, TestFallbackFromTls13) {
- EnsureTlsSetup();
+ client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_3);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_2);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_3);
- ConnectExpectFail();
- ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
+ ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
+ client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
+ server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}
-#endif
TEST_P(TlsConnectGeneric, TestFallbackSCSVVersionMatch) {
client_->SetOption(SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
@@ -132,6 +176,7 @@ TEST_P(TlsConnectGenericPre13, TestFallbackSCSVVersionMismatch) {
server_->SetVersionRange(version_, version_ + 1);
ConnectExpectAlert(server_, kTlsAlertInappropriateFallback);
client_->CheckErrorCode(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT);
+ server_->CheckErrorCode(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT);
}
// The TLS v1.3 spec section C.4 states that 'Implementations MUST NOT send or
@@ -158,7 +203,7 @@ TEST_P(TlsConnectGeneric, AlertBeforeServerHello) {
static const uint8_t kWarningAlert[] = {kTlsAlertWarning,
kTlsAlertUnrecognizedName};
DataBuffer alert;
- TlsAgentTestBase::MakeRecord(variant_, kTlsAlertType,
+ TlsAgentTestBase::MakeRecord(variant_, ssl_ct_alert,
SSL_LIBRARY_VERSION_TLS_1_0, kWarningAlert,
PR_ARRAY_SIZE(kWarningAlert), &alert);
client_->adapter()->PacketReceived(alert);
diff --git a/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc
index 09d7801e9..a75dbb7aa 100644
--- a/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc
@@ -12,7 +12,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
diff --git a/security/nss/gtests/ssl_gtest/test_io.cc b/security/nss/gtests/ssl_gtest/test_io.cc
index d76b3526c..6d792c520 100644
--- a/security/nss/gtests/ssl_gtest/test_io.cc
+++ b/security/nss/gtests/ssl_gtest/test_io.cc
@@ -31,6 +31,20 @@ ScopedPRFileDesc DummyPrSocket::CreateFD() {
return DummyIOLayerMethods::CreateFD(test_fd_identity, this);
}
+void DummyPrSocket::Reset() {
+ auto p = peer_.lock();
+ peer_.reset();
+ if (p) {
+ p->peer_.reset();
+ p->Reset();
+ }
+ while (!input_.empty()) {
+ input_.pop();
+ }
+ filter_ = nullptr;
+ write_error_ = 0;
+}
+
void DummyPrSocket::PacketReceived(const DataBuffer &packet) {
input_.push(Packet(packet));
}
@@ -42,6 +56,12 @@ int32_t DummyPrSocket::Read(PRFileDesc *f, void *data, int32_t len) {
return -1;
}
+ auto dst = peer_.lock();
+ if (!dst) {
+ PR_SetError(PR_NOT_CONNECTED_ERROR, 0);
+ return -1;
+ }
+
if (input_.empty()) {
LOGV("Read --> wouldblock " << len);
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
@@ -74,6 +94,12 @@ int32_t DummyPrSocket::Recv(PRFileDesc *f, void *buf, int32_t buflen,
return Read(f, buf, buflen);
}
+ auto dst = peer_.lock();
+ if (!dst) {
+ PR_SetError(PR_NOT_CONNECTED_ERROR, 0);
+ return -1;
+ }
+
if (input_.empty()) {
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
return -1;
@@ -101,7 +127,7 @@ int32_t DummyPrSocket::Write(PRFileDesc *f, const void *buf, int32_t length) {
auto dst = peer_.lock();
if (!dst) {
- PR_SetError(PR_IO_ERROR, 0);
+ PR_SetError(PR_NOT_CONNECTED_ERROR, 0);
return -1;
}
diff --git a/security/nss/gtests/ssl_gtest/test_io.h b/security/nss/gtests/ssl_gtest/test_io.h
index 8327373ce..062ae86c8 100644
--- a/security/nss/gtests/ssl_gtest/test_io.h
+++ b/security/nss/gtests/ssl_gtest/test_io.h
@@ -17,7 +17,7 @@
#include "databuffer.h"
#include "dummy_io.h"
#include "prio.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "sslt.h"
namespace nss_test {
diff --git a/security/nss/gtests/ssl_gtest/tls_agent.cc b/security/nss/gtests/ssl_gtest/tls_agent.cc
index 9bed1ce1b..fb66196b5 100644
--- a/security/nss/gtests/ssl_gtest/tls_agent.cc
+++ b/security/nss/gtests/ssl_gtest/tls_agent.cc
@@ -15,6 +15,9 @@
#include "tls_filter.h"
#include "tls_parser.h"
+// This is an internal header, used to get DTLS_1_3_DRAFT_VERSION.
+#include "ssl3prot.h"
+
extern "C" {
// This is not something that should make you happy.
#include "libssl_internals.h"
@@ -23,7 +26,7 @@ extern "C" {
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
extern std::string g_working_dir_path;
@@ -53,7 +56,7 @@ static const uint8_t kCannedTls13ServerHello[] = {
0x00, 0x1d, 0x00, 0x20, 0xc2, 0xcf, 0x23, 0x17, 0x64, 0x23, 0x03,
0xf0, 0xfb, 0x45, 0x98, 0x26, 0xd1, 0x65, 0x24, 0xa1, 0x6c, 0xa9,
0x80, 0x8f, 0x2c, 0xac, 0x0a, 0xea, 0x53, 0x3a, 0xcb, 0xe3, 0x08,
- 0x84, 0xae, 0x19, 0x00, 0x2b, 0x00, 0x02, 0x7f, kD13};
+ 0x84, 0xae, 0x19, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04};
TlsAgent::TlsAgent(const std::string& nm, Role rl, SSLProtocolVariant var)
: name_(nm),
@@ -226,6 +229,7 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc* modelSocket) {
bool TlsAgent::MaybeSetResumptionToken() {
if (!resumption_token_.empty()) {
+ LOG("setting external resumption token");
SECStatus rv = SSL_SetResumptionToken(ssl_fd(), resumption_token_.data(),
resumption_token_.size());
@@ -583,6 +587,7 @@ void TlsAgent::CheckAuthType(SSLAuthType auth,
// switch statement because default label is different.
switch (auth) {
case ssl_auth_rsa_sign:
+ case ssl_auth_rsa_pss:
EXPECT_EQ(ssl_auth_rsa_decrypt, csinfo_.authAlgorithm)
<< "authAlgorithm for RSA is always decrypt";
break;
@@ -934,8 +939,8 @@ void TlsAgent::SendRecordDirect(const TlsRecord& record) {
SendDirect(buf);
}
-static bool ErrorIsNonFatal(PRErrorCode code) {
- return code == PR_WOULD_BLOCK_ERROR || code == SSL_ERROR_RX_SHORT_DTLS_READ;
+static bool ErrorIsFatal(PRErrorCode code) {
+ return code != PR_WOULD_BLOCK_ERROR && code != SSL_ERROR_RX_SHORT_DTLS_READ;
}
void TlsAgent::SendData(size_t bytes, size_t blocksize) {
@@ -975,7 +980,7 @@ bool TlsAgent::SendEncryptedRecord(const std::shared_ptr<TlsCipherSpec>& spec,
LOGV("Encrypting " << buf.len() << " bytes");
// Ensure that we are doing TLS 1.3.
EXPECT_GE(expected_version_, SSL_LIBRARY_VERSION_TLS_1_3);
- TlsRecordHeader header(variant_, expected_version_, kTlsApplicationDataType,
+ TlsRecordHeader header(variant_, expected_version_, ssl_ct_application_data,
seq);
DataBuffer padded = buf;
padded.Write(padded.len(), ct, 1);
@@ -994,28 +999,39 @@ bool TlsAgent::SendEncryptedRecord(const std::shared_ptr<TlsCipherSpec>& spec,
void TlsAgent::ReadBytes(size_t amount) {
uint8_t block[16384];
- int32_t rv = PR_Read(ssl_fd(), block, (std::min)(amount, sizeof(block)));
- LOGV("ReadBytes " << rv);
- int32_t err;
+ size_t remaining = amount;
+ while (remaining > 0) {
+ int32_t rv = PR_Read(ssl_fd(), block, (std::min)(amount, sizeof(block)));
+ LOGV("ReadBytes " << rv);
- if (rv >= 0) {
- size_t count = static_cast<size_t>(rv);
- for (size_t i = 0; i < count; ++i) {
- ASSERT_EQ(recv_ctr_ & 0xff, block[i]);
- recv_ctr_++;
- }
- } else {
- err = PR_GetError();
- LOG("Read error " << PORT_ErrorToName(err) << ": "
- << PORT_ErrorToString(err));
- if (err != PR_WOULD_BLOCK_ERROR && expect_readwrite_error_) {
- error_code_ = err;
- expect_readwrite_error_ = false;
+ if (rv > 0) {
+ size_t count = static_cast<size_t>(rv);
+ for (size_t i = 0; i < count; ++i) {
+ ASSERT_EQ(recv_ctr_ & 0xff, block[i]);
+ recv_ctr_++;
+ }
+ remaining -= rv;
+ } else {
+ PRErrorCode err = 0;
+ if (rv < 0) {
+ err = PR_GetError();
+ LOG("Read error " << PORT_ErrorToName(err) << ": "
+ << PORT_ErrorToString(err));
+ if (err != PR_WOULD_BLOCK_ERROR && expect_readwrite_error_) {
+ error_code_ = err;
+ expect_readwrite_error_ = false;
+ }
+ }
+ if (err != 0 && ErrorIsFatal(err)) {
+ // If we hit a fatal error, we're done.
+ remaining = 0;
+ }
+ break;
}
}
// If closed, then don't bother waiting around.
- if (rv > 0 || (rv < 0 && ErrorIsNonFatal(err))) {
+ if (remaining) {
LOGV("Re-arming");
Poller::Instance()->Wait(READABLE_EVENT, adapter_, this,
&TlsAgent::ReadableCallback);
@@ -1104,7 +1120,7 @@ void TlsAgentTestBase::MakeRecord(SSLProtocolVariant variant, uint8_t type,
if (variant == ssl_variant_stream) {
index = out->Write(index, version, 2);
} else if (version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
- type == kTlsApplicationDataType) {
+ type == ssl_ct_application_data) {
uint32_t epoch = (sequence_number >> 48) & 0x3;
uint32_t seqno = sequence_number & ((1ULL << 30) - 1);
index = out->Write(index, (epoch << 30) | seqno, 4);
@@ -1157,10 +1173,10 @@ void TlsAgentTestBase::MakeTrivialHandshakeRecord(uint8_t hs_type,
size_t hs_len,
DataBuffer* out) {
size_t index = 0;
- index = out->Write(index, kTlsHandshakeType, 1); // Content Type
- index = out->Write(index, 3, 1); // Version high
- index = out->Write(index, 1, 1); // Version low
- index = out->Write(index, 4 + hs_len, 2); // Length
+ index = out->Write(index, ssl_ct_handshake, 1); // Content Type
+ index = out->Write(index, 3, 1); // Version high
+ index = out->Write(index, 1, 1); // Version low
+ index = out->Write(index, 4 + hs_len, 2); // Length
index = out->Write(index, hs_type, 1); // Handshake record type.
index = out->Write(index, hs_len, 3); // Handshake length
@@ -1173,6 +1189,11 @@ DataBuffer TlsAgentTestBase::MakeCannedTls13ServerHello() {
DataBuffer sh(kCannedTls13ServerHello, sizeof(kCannedTls13ServerHello));
if (variant_ == ssl_variant_datagram) {
sh.Write(0, SSL_LIBRARY_VERSION_DTLS_1_2_WIRE, 2);
+ // The version should be at the end.
+ uint32_t v;
+ EXPECT_TRUE(sh.Read(sh.len() - 2, 2, &v));
+ EXPECT_EQ(static_cast<uint32_t>(SSL_LIBRARY_VERSION_TLS_1_3), v);
+ sh.Write(sh.len() - 2, 0x7f00 | DTLS_1_3_DRAFT_VERSION, 2);
}
return sh;
}
diff --git a/security/nss/gtests/ssl_gtest/tls_agent.h b/security/nss/gtests/ssl_gtest/tls_agent.h
index a93d0c6ee..020221868 100644
--- a/security/nss/gtests/ssl_gtest/tls_agent.h
+++ b/security/nss/gtests/ssl_gtest/tls_agent.h
@@ -10,9 +10,6 @@
#include "prio.h"
#include "ssl.h"
-// This is an internal header, used to get TLS_1_3_DRAFT_VERSION.
-#include "ssl3prot.h"
-
#include <functional>
#include <iostream>
@@ -20,7 +17,8 @@
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
+#include "scoped_ptrs_ssl.h"
extern bool g_ssl_gtest_verbose;
@@ -60,8 +58,6 @@ typedef std::function<int32_t(TlsAgent* agent, const SECItem* srvNameArr,
PRUint32 srvNameArrSize)>
SniCallbackFunction;
-static const uint8_t kD13 = TLS_1_3_DRAFT_VERSION;
-
class TlsAgent : public PollTarget {
public:
enum Role { CLIENT, SERVER };
diff --git a/security/nss/gtests/ssl_gtest/tls_connect.cc b/security/nss/gtests/ssl_gtest/tls_connect.cc
index 68f6d21e9..c48ae38ec 100644
--- a/security/nss/gtests/ssl_gtest/tls_connect.cc
+++ b/security/nss/gtests/ssl_gtest/tls_connect.cc
@@ -14,7 +14,7 @@ extern "C" {
#include "databuffer.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
#include "sslproto.h"
extern std::string g_working_dir_path;
@@ -559,13 +559,15 @@ void TlsConnectTestBase::CheckResumption(SessionResumptionMode expected) {
EXPECT_EQ(stateless_count, stats->hsh_sid_stateless_resumes);
if (expected != RESUME_NONE) {
- if (client_->version() < SSL_LIBRARY_VERSION_TLS_1_3) {
+ if (client_->version() < SSL_LIBRARY_VERSION_TLS_1_3 &&
+ client_->GetResumptionToken().size() == 0) {
// Check that the last two session ids match.
ASSERT_EQ(1U + expected_resumptions_, session_ids_.size());
EXPECT_EQ(session_ids_[session_ids_.size() - 1],
session_ids_[session_ids_.size() - 2]);
} else {
- // TLS 1.3 only uses tickets.
+ // We've either chosen TLS 1.3 or are using an external resumption token,
+ // both of which only use tickets.
EXPECT_TRUE(expected & RESUME_TICKET);
}
}
diff --git a/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc b/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc
new file mode 100644
index 000000000..3c860a0b2
--- /dev/null
+++ b/security/nss/gtests/ssl_gtest/tls_esni_unittest.cc
@@ -0,0 +1,470 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <ctime>
+
+#include "secerr.h"
+#include "ssl.h"
+
+#include "gtest_utils.h"
+#include "tls_agent.h"
+#include "tls_connect.h"
+
+namespace nss_test {
+
+static const char* kDummySni("dummy.invalid");
+
+std::vector<uint16_t> kDefaultSuites = {TLS_AES_256_GCM_SHA384,
+ TLS_AES_128_GCM_SHA256};
+std::vector<uint16_t> kChaChaSuite = {TLS_CHACHA20_POLY1305_SHA256};
+std::vector<uint16_t> kBogusSuites = {0};
+std::vector<uint16_t> kTls12Suites = {
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256};
+
+static void NamedGroup2ECParams(SSLNamedGroup group, SECItem* params) {
+ auto groupDef = ssl_LookupNamedGroup(group);
+ ASSERT_NE(nullptr, groupDef);
+
+ auto oidData = SECOID_FindOIDByTag(groupDef->oidTag);
+ ASSERT_NE(nullptr, oidData);
+ ASSERT_NE(nullptr,
+ SECITEM_AllocItem(nullptr, params, (2 + oidData->oid.len)));
+
+ /*
+ * params->data needs to contain the ASN encoding of an object ID (OID)
+ * representing the named curve. The actual OID is in
+ * oidData->oid.data so we simply prepend 0x06 and OID length
+ */
+ params->data[0] = SEC_ASN1_OBJECT_ID;
+ params->data[1] = oidData->oid.len;
+ memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
+}
+
+/* Checksum is a 4-byte array. */
+static void UpdateEsniKeysChecksum(DataBuffer* buf) {
+ SECStatus rv;
+ PRUint8 sha256[32];
+
+ /* Stomp the checksum. */
+ PORT_Memset(buf->data() + 2, 0, 4);
+
+ rv = PK11_HashBuf(ssl3_HashTypeToOID(ssl_hash_sha256), sha256, buf->data(),
+ buf->len());
+ ASSERT_EQ(SECSuccess, rv);
+ buf->Write(2, sha256, 4);
+}
+
+static void GenerateEsniKey(time_t windowStart, SSLNamedGroup group,
+ std::vector<uint16_t>& cipher_suites,
+ DataBuffer* record,
+ ScopedSECKEYPublicKey* pubKey = nullptr,
+ ScopedSECKEYPrivateKey* privKey = nullptr) {
+ SECKEYECParams ecParams = {siBuffer, NULL, 0};
+ NamedGroup2ECParams(group, &ecParams);
+
+ SECKEYPublicKey* pub = nullptr;
+ SECKEYPrivateKey* priv = SECKEY_CreateECPrivateKey(&ecParams, &pub, nullptr);
+ ASSERT_NE(nullptr, priv);
+ SECITEM_FreeItem(&ecParams, PR_FALSE);
+ PRUint8 encoded[1024];
+ unsigned int encoded_len;
+
+ SECStatus rv = SSL_EncodeESNIKeys(
+ &cipher_suites[0], cipher_suites.size(), group, pub, 100, windowStart,
+ windowStart + 10, encoded, &encoded_len, sizeof(encoded));
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_GT(encoded_len, 0U);
+
+ if (pubKey) {
+ pubKey->reset(pub);
+ } else {
+ SECKEY_DestroyPublicKey(pub);
+ }
+ if (privKey) {
+ privKey->reset(priv);
+ } else {
+ SECKEY_DestroyPrivateKey(priv);
+ }
+ record->Truncate(0);
+ record->Write(0, encoded, encoded_len);
+}
+
+static void SetupEsni(const std::shared_ptr<TlsAgent>& client,
+ const std::shared_ptr<TlsAgent>& server,
+ SSLNamedGroup group = ssl_grp_ec_curve25519) {
+ ScopedSECKEYPublicKey pub;
+ ScopedSECKEYPrivateKey priv;
+ DataBuffer record;
+
+ GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record,
+ &pub, &priv);
+ SECStatus rv = SSL_SetESNIKeyPair(server->ssl_fd(), priv.get(), record.data(),
+ record.len());
+ ASSERT_EQ(SECSuccess, rv);
+
+ rv = SSL_EnableESNI(client->ssl_fd(), record.data(), record.len(), kDummySni);
+ ASSERT_EQ(SECSuccess, rv);
+}
+
+static void CheckSniExtension(const DataBuffer& data) {
+ TlsParser parser(data.data(), data.len());
+ uint32_t tmp;
+ ASSERT_TRUE(parser.Read(&tmp, 2));
+ ASSERT_EQ(parser.remaining(), tmp);
+ ASSERT_TRUE(parser.Read(&tmp, 1));
+ ASSERT_EQ(0U, tmp); /* sni_nametype_hostname */
+ DataBuffer name;
+ ASSERT_TRUE(parser.ReadVariable(&name, 2));
+ ASSERT_EQ(0U, parser.remaining());
+ DataBuffer expected(reinterpret_cast<const uint8_t*>(kDummySni),
+ strlen(kDummySni));
+ ASSERT_EQ(expected, name);
+}
+
+static void ClientInstallEsni(std::shared_ptr<TlsAgent>& agent,
+ const DataBuffer& record, PRErrorCode err = 0) {
+ SECStatus rv =
+ SSL_EnableESNI(agent->ssl_fd(), record.data(), record.len(), kDummySni);
+ if (err == 0) {
+ ASSERT_EQ(SECSuccess, rv);
+ } else {
+ ASSERT_EQ(SECFailure, rv);
+ ASSERT_EQ(err, PORT_GetError());
+ }
+}
+
+TEST_P(TlsAgentTestClient13, EsniInstall) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
+ ClientInstallEsni(agent_, record);
+}
+
+// The next set of tests fail at setup time.
+TEST_P(TlsAgentTestClient13, EsniInvalidHash) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
+ record.data()[2]++;
+ ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS);
+}
+
+TEST_P(TlsAgentTestClient13, EsniInvalidVersion) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
+ record.Write(0, 0xffff, 2);
+ ClientInstallEsni(agent_, record, SSL_ERROR_UNSUPPORTED_VERSION);
+}
+
+TEST_P(TlsAgentTestClient13, EsniShort) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
+ record.Truncate(record.len() - 1);
+ UpdateEsniKeysChecksum(&record);
+ ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS);
+}
+
+TEST_P(TlsAgentTestClient13, EsniLong) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
+ record.Write(record.len(), 1, 1);
+ UpdateEsniKeysChecksum(&record);
+ ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS);
+}
+
+TEST_P(TlsAgentTestClient13, EsniExtensionMismatch) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
+ record.Write(record.len() - 1, 1, 1);
+ UpdateEsniKeysChecksum(&record);
+ ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS);
+}
+
+// The following tests fail by ignoring the Esni block.
+TEST_P(TlsAgentTestClient13, EsniUnknownGroup) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
+ record.Write(8, 0xffff, 2); // Fake group
+ UpdateEsniKeysChecksum(&record);
+ ClientInstallEsni(agent_, record, 0);
+ auto filter =
+ MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
+ agent_->Handshake();
+ ASSERT_EQ(TlsAgent::STATE_CONNECTING, agent_->state());
+ ASSERT_TRUE(!filter->captured());
+}
+
+TEST_P(TlsAgentTestClient13, EsniUnknownCS) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kBogusSuites, &record);
+ ClientInstallEsni(agent_, record, 0);
+ auto filter =
+ MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
+ agent_->Handshake();
+ ASSERT_EQ(TlsAgent::STATE_CONNECTING, agent_->state());
+ ASSERT_TRUE(!filter->captured());
+}
+
+TEST_P(TlsAgentTestClient13, EsniInvalidCS) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kTls12Suites, &record);
+ UpdateEsniKeysChecksum(&record);
+ ClientInstallEsni(agent_, record, 0);
+ auto filter =
+ MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
+ agent_->Handshake();
+ ASSERT_EQ(TlsAgent::STATE_CONNECTING, agent_->state());
+ ASSERT_TRUE(!filter->captured());
+}
+
+TEST_P(TlsAgentTestClient13, EsniNotReady) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0) + 1000, ssl_grp_ec_curve25519, kDefaultSuites,
+ &record);
+ ClientInstallEsni(agent_, record, 0);
+ auto filter =
+ MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
+ agent_->Handshake();
+ ASSERT_TRUE(!filter->captured());
+}
+
+TEST_P(TlsAgentTestClient13, EsniExpired) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0) - 1000, ssl_grp_ec_curve25519, kDefaultSuites,
+ &record);
+ ClientInstallEsni(agent_, record, 0);
+ auto filter =
+ MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
+ agent_->Handshake();
+ ASSERT_TRUE(!filter->captured());
+}
+
+TEST_P(TlsAgentTestClient13, NoSniSoNoEsni) {
+ EnsureInit();
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
+ SSL_SetURL(agent_->ssl_fd(), "");
+ ClientInstallEsni(agent_, record, 0);
+ auto filter =
+ MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
+ agent_->Handshake();
+ ASSERT_TRUE(!filter->captured());
+}
+
+static int32_t SniCallback(TlsAgent* agent, const SECItem* srvNameAddr,
+ PRUint32 srvNameArrSize) {
+ EXPECT_EQ(1U, srvNameArrSize);
+ SECItem expected = {
+ siBuffer, reinterpret_cast<unsigned char*>(const_cast<char*>("server")),
+ 6};
+ EXPECT_TRUE(!SECITEM_CompareItem(&expected, &srvNameAddr[0]));
+ return SECSuccess;
+}
+
+TEST_P(TlsConnectTls13, ConnectEsni) {
+ EnsureTlsSetup();
+ SetupEsni(client_, server_);
+ auto cFilterSni =
+ MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
+ auto cFilterEsni =
+ MakeTlsFilter<TlsExtensionCapture>(client_, ssl_tls13_encrypted_sni_xtn);
+ client_->SetFilter(std::make_shared<ChainedPacketFilter>(
+ ChainedPacketFilterInit({cFilterSni, cFilterEsni})));
+ auto sfilter =
+ MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn);
+ sfilter->EnableDecryption();
+ server_->SetSniCallback(SniCallback);
+ Connect();
+ CheckSniExtension(cFilterSni->extension());
+ ASSERT_TRUE(cFilterEsni->captured());
+ // Check that our most preferred suite got chosen.
+ uint32_t suite;
+ ASSERT_TRUE(cFilterEsni->extension().Read(0, 2, &suite));
+ ASSERT_EQ(TLS_AES_128_GCM_SHA256, static_cast<PRUint16>(suite));
+ ASSERT_TRUE(!sfilter->captured());
+}
+
+TEST_P(TlsConnectTls13, ConnectEsniHrr) {
+ EnsureTlsSetup();
+ const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1};
+ server_->ConfigNamedGroups(groups);
+ SetupEsni(client_, server_);
+ auto hrr_capture = MakeTlsFilter<TlsHandshakeRecorder>(
+ server_, kTlsHandshakeHelloRetryRequest);
+ auto filter =
+ MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
+ auto cfilter =
+ MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
+ server_->SetSniCallback(SniCallback);
+ Connect();
+ CheckSniExtension(cfilter->extension());
+ EXPECT_NE(0UL, hrr_capture->buffer().len());
+}
+
+TEST_P(TlsConnectTls13, ConnectEsniNoDummy) {
+ EnsureTlsSetup();
+ ScopedSECKEYPublicKey pub;
+ ScopedSECKEYPrivateKey priv;
+ DataBuffer record;
+
+ GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record,
+ &pub, &priv);
+ SECStatus rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(),
+ record.data(), record.len());
+ ASSERT_EQ(SECSuccess, rv);
+ rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), "");
+ ASSERT_EQ(SECSuccess, rv);
+
+ auto cfilter =
+ MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
+ auto sfilter =
+ MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn);
+ server_->SetSniCallback(SniCallback);
+ Connect();
+ ASSERT_TRUE(!cfilter->captured());
+ ASSERT_TRUE(!sfilter->captured());
+}
+
+TEST_P(TlsConnectTls13, ConnectEsniNullDummy) {
+ EnsureTlsSetup();
+ ScopedSECKEYPublicKey pub;
+ ScopedSECKEYPrivateKey priv;
+ DataBuffer record;
+
+ GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record,
+ &pub, &priv);
+ SECStatus rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(),
+ record.data(), record.len());
+ ASSERT_EQ(SECSuccess, rv);
+ rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), nullptr);
+ ASSERT_EQ(SECSuccess, rv);
+
+ auto cfilter =
+ MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
+ auto sfilter =
+ MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn);
+ server_->SetSniCallback(SniCallback);
+ Connect();
+ ASSERT_TRUE(!cfilter->captured());
+ ASSERT_TRUE(!sfilter->captured());
+}
+
+/* Tell the client that it supports AES but the server that it supports ChaCha
+ */
+TEST_P(TlsConnectTls13, ConnectEsniCSMismatch) {
+ EnsureTlsSetup();
+ ScopedSECKEYPublicKey pub;
+ ScopedSECKEYPrivateKey priv;
+ DataBuffer record;
+
+ GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record,
+ &pub, &priv);
+ PRUint8 encoded[1024];
+ unsigned int encoded_len;
+
+ SECStatus rv = SSL_EncodeESNIKeys(
+ &kChaChaSuite[0], kChaChaSuite.size(), ssl_grp_ec_curve25519, pub.get(),
+ 100, time(0), time(0) + 10, encoded, &encoded_len, sizeof(encoded));
+ rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(), encoded, encoded_len);
+ ASSERT_EQ(SECSuccess, rv);
+ rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), "");
+ ASSERT_EQ(SECSuccess, rv);
+ ConnectExpectAlert(server_, illegal_parameter);
+ server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
+
+TEST_P(TlsConnectTls13, ConnectEsniP256) {
+ EnsureTlsSetup();
+ SetupEsni(client_, server_, ssl_grp_ec_secp256r1);
+ auto cfilter =
+ MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
+ auto sfilter =
+ MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn);
+ server_->SetSniCallback(SniCallback);
+ Connect();
+ CheckSniExtension(cfilter->extension());
+ ASSERT_TRUE(!sfilter->captured());
+}
+
+TEST_P(TlsConnectTls13, ConnectMismatchedEsniKeys) {
+ EnsureTlsSetup();
+ SetupEsni(client_, server_);
+ // Now install a new set of keys on the client, so we have a mismatch.
+ DataBuffer record;
+ GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
+ ClientInstallEsni(client_, record, 0);
+ ConnectExpectAlert(server_, illegal_parameter);
+ server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
+
+TEST_P(TlsConnectTls13, ConnectDamagedEsniExtensionCH) {
+ EnsureTlsSetup();
+ SetupEsni(client_, server_);
+ auto filter = MakeTlsFilter<TlsExtensionDamager>(
+ client_, ssl_tls13_encrypted_sni_xtn, 50); // in the ciphertext
+ ConnectExpectAlert(server_, illegal_parameter);
+ server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+}
+
+TEST_P(TlsConnectTls13, ConnectRemoveEsniExtensionEE) {
+ EnsureTlsSetup();
+ SetupEsni(client_, server_);
+ auto filter =
+ MakeTlsFilter<TlsExtensionDropper>(server_, ssl_tls13_encrypted_sni_xtn);
+ filter->EnableDecryption();
+ ConnectExpectAlert(client_, missing_extension);
+ client_->CheckErrorCode(SSL_ERROR_MISSING_ESNI_EXTENSION);
+}
+
+TEST_P(TlsConnectTls13, ConnectShortEsniExtensionEE) {
+ EnsureTlsSetup();
+ SetupEsni(client_, server_);
+ DataBuffer shortNonce;
+ auto filter = MakeTlsFilter<TlsExtensionReplacer>(
+ server_, ssl_tls13_encrypted_sni_xtn, shortNonce);
+ filter->EnableDecryption();
+ ConnectExpectAlert(client_, illegal_parameter);
+ client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_ESNI_EXTENSION);
+}
+
+TEST_P(TlsConnectTls13, ConnectBogusEsniExtensionEE) {
+ EnsureTlsSetup();
+ SetupEsni(client_, server_);
+ const uint8_t bogusNonceBuf[16] = {0};
+ DataBuffer bogusNonce(bogusNonceBuf, sizeof(bogusNonceBuf));
+ auto filter = MakeTlsFilter<TlsExtensionReplacer>(
+ server_, ssl_tls13_encrypted_sni_xtn, bogusNonce);
+ filter->EnableDecryption();
+ ConnectExpectAlert(client_, illegal_parameter);
+ client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_ESNI_EXTENSION);
+}
+
+// ESNI is a commitment to doing TLS 1.3 or above.
+// The TLS 1.2 server ignores ESNI and processes the dummy SNI.
+// The client then aborts when it sees the server did TLS 1.2.
+TEST_P(TlsConnectTls13, EsniButTLS12Server) {
+ EnsureTlsSetup();
+ SetupEsni(client_, server_);
+ client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_3);
+ server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_2);
+ ConnectExpectAlert(client_, kTlsAlertProtocolVersion);
+ client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
+ server_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT);
+ ASSERT_FALSE(SSLInt_ExtensionNegotiated(server_->ssl_fd(),
+ ssl_tls13_encrypted_sni_xtn));
+}
+}
diff --git a/security/nss/gtests/ssl_gtest/tls_filter.cc b/security/nss/gtests/ssl_gtest/tls_filter.cc
index aa03cba70..25ad606fc 100644
--- a/security/nss/gtests/ssl_gtest/tls_filter.cc
+++ b/security/nss/gtests/ssl_gtest/tls_filter.cc
@@ -131,7 +131,7 @@ PacketFilter::Action TlsRecordFilter::Filter(const DataBuffer& input,
// spec to another active cipher spec (KeyUpdate for instance) AND writes
// are consolidated across that change, this code could use the wrong
// sequence numbers when re-encrypting records with the old keys.
- if (header.content_type() == kTlsApplicationDataType) {
+ if (header.content_type() == ssl_ct_application_data) {
in_sequence_number_ =
(std::max)(in_sequence_number_, header.sequence_number() + 1);
}
@@ -194,7 +194,7 @@ PacketFilter::Action TlsRecordFilter::FilterRecord(
uint64_t seq_num;
if (header.is_dtls() || !cipher_spec_ ||
- header.content_type() != kTlsApplicationDataType) {
+ header.content_type() != ssl_ct_application_data) {
seq_num = header.sequence_number();
} else {
seq_num = out_sequence_number_++;
@@ -277,7 +277,7 @@ bool TlsRecordHeader::Parse(bool is_dtls13, uint64_t seqno, TlsParser* parser,
#ifndef UNSAFE_FUZZER_MODE
// Deal with the 7 octet header.
- if (content_type_ == kTlsApplicationDataType) {
+ if (content_type_ == ssl_ct_application_data) {
uint32_t tmp;
if (!parser->Read(&tmp, 4)) {
return false;
@@ -298,7 +298,7 @@ bool TlsRecordHeader::Parse(bool is_dtls13, uint64_t seqno, TlsParser* parser,
}
// Need to use the low 5 bits of the first octet too.
tmp |= (content_type_ & 0x1f) << 8;
- content_type_ = kTlsApplicationDataType;
+ content_type_ = ssl_ct_application_data;
sequence_number_ = ParseSequenceNumber(seqno, tmp, 12, 1);
if (!parser->ReadFromMark(&header_, parser->consumed() - mark, mark)) {
@@ -308,9 +308,9 @@ bool TlsRecordHeader::Parse(bool is_dtls13, uint64_t seqno, TlsParser* parser,
}
// The full 13 octet header can only be used for a few types.
- EXPECT_TRUE(content_type_ == kTlsAlertType ||
- content_type_ == kTlsHandshakeType ||
- content_type_ == kTlsAckType);
+ EXPECT_TRUE(content_type_ == ssl_ct_alert ||
+ content_type_ == ssl_ct_handshake ||
+ content_type_ == ssl_ct_ack);
#endif
}
@@ -347,7 +347,7 @@ size_t TlsRecordHeader::WriteHeader(DataBuffer* buffer, size_t offset,
size_t body_len) const {
offset = buffer->Write(offset, content_type_, 1);
if (is_dtls() && version_ >= SSL_LIBRARY_VERSION_TLS_1_3 &&
- content_type() == kTlsApplicationDataType) {
+ content_type() == ssl_ct_application_data) {
// application_data records in TLS 1.3 have a different header format.
// Always use the long header here for simplicity.
uint32_t e = (sequence_number_ >> 48) & 0x3;
@@ -377,7 +377,7 @@ bool TlsRecordFilter::Unprotect(const TlsRecordHeader& header,
const DataBuffer& ciphertext,
uint8_t* inner_content_type,
DataBuffer* plaintext) {
- if (!cipher_spec_ || header.content_type() != kTlsApplicationDataType) {
+ if (!cipher_spec_ || header.content_type() != ssl_ct_application_data) {
*inner_content_type = header.content_type();
*plaintext = ciphertext;
return true;
@@ -411,7 +411,7 @@ bool TlsRecordFilter::Protect(const TlsRecordHeader& header,
uint8_t inner_content_type,
const DataBuffer& plaintext,
DataBuffer* ciphertext, size_t padding) {
- if (!cipher_spec_ || header.content_type() != kTlsApplicationDataType) {
+ if (!cipher_spec_ || header.content_type() != ssl_ct_application_data) {
*ciphertext = plaintext;
return true;
}
@@ -453,8 +453,7 @@ PacketFilter::Action TlsHandshakeFilter::FilterRecord(
const TlsRecordHeader& record_header, const DataBuffer& input,
DataBuffer* output) {
// Check that the first byte is as requested.
- if ((record_header.content_type() != kTlsHandshakeType) &&
- (record_header.content_type() != kTlsAltHandshakeType)) {
+ if (record_header.content_type() != ssl_ct_handshake) {
return KEEP;
}
@@ -879,6 +878,17 @@ PacketFilter::Action TlsExtensionDropper::FilterExtension(
return KEEP;
}
+PacketFilter::Action TlsExtensionDamager::FilterExtension(
+ uint16_t extension_type, const DataBuffer& input, DataBuffer* output) {
+ if (extension_type != extension_) {
+ return KEEP;
+ }
+
+ *output = input;
+ output->data()[index_] += 73; // Increment selected for maximum damage
+ return CHANGE;
+}
+
PacketFilter::Action TlsExtensionInjector::FilterHandshake(
const HandshakeHeader& header, const DataBuffer& input,
DataBuffer* output) {
diff --git a/security/nss/gtests/ssl_gtest/tls_filter.h b/security/nss/gtests/ssl_gtest/tls_filter.h
index effda4aa0..2b6e88645 100644
--- a/security/nss/gtests/ssl_gtest/tls_filter.h
+++ b/security/nss/gtests/ssl_gtest/tls_filter.h
@@ -172,20 +172,19 @@ inline std::ostream& operator<<(std::ostream& stream,
hdr.WriteStream(stream);
stream << ' ';
switch (hdr.content_type()) {
- case kTlsChangeCipherSpecType:
+ case ssl_ct_change_cipher_spec:
stream << "CCS";
break;
- case kTlsAlertType:
+ case ssl_ct_alert:
stream << "Alert";
break;
- case kTlsHandshakeType:
- case kTlsAltHandshakeType:
+ case ssl_ct_handshake:
stream << "Handshake";
break;
- case kTlsApplicationDataType:
+ case ssl_ct_application_data:
stream << "Data";
break;
- case kTlsAckType:
+ case ssl_ct_ack:
stream << "ACK";
break;
default:
@@ -301,7 +300,7 @@ class TlsRecordRecorder : public TlsRecordFilter {
TlsRecordRecorder(const std::shared_ptr<TlsAgent>& a)
: TlsRecordFilter(a),
filter_(false),
- ct_(content_handshake), // dummy (<optional> is C++14)
+ ct_(ssl_ct_handshake), // dummy (<optional> is C++14)
records_() {}
virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& input,
@@ -466,6 +465,20 @@ class TlsExtensionInjector : public TlsHandshakeFilter {
const DataBuffer data_;
};
+class TlsExtensionDamager : public TlsExtensionFilter {
+ public:
+ TlsExtensionDamager(const std::shared_ptr<TlsAgent>& a, uint16_t extension,
+ size_t index)
+ : TlsExtensionFilter(a), extension_(extension), index_(index) {}
+ virtual PacketFilter::Action FilterExtension(uint16_t extension_type,
+ const DataBuffer& input,
+ DataBuffer* output);
+
+ private:
+ uint16_t extension_;
+ size_t index_;
+};
+
typedef std::function<void(void)> VoidFunction;
class AfterRecordN : public TlsRecordFilter {
diff --git a/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc b/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc
index 45f6cf2bd..004da3b1c 100644
--- a/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc
+++ b/security/nss/gtests/ssl_gtest/tls_hkdf_unittest.cc
@@ -11,7 +11,7 @@
#include "databuffer.h"
#include "gtest_utils.h"
-#include "scoped_ptrs.h"
+#include "nss_scoped_ptrs.h"
namespace nss_test {
@@ -60,9 +60,11 @@ const std::string kHashName[] = {"None", "MD5", "SHA-1", "SHA-224",
"SHA-256", "SHA-384", "SHA-512"};
static void ImportKey(ScopedPK11SymKey* to, const DataBuffer& key,
- PK11SlotInfo* slot) {
+ SSLHashType hash_type, PK11SlotInfo* slot) {
+ ASSERT_LT(hash_type, sizeof(kHashLength));
+ ASSERT_LE(kHashLength[hash_type], key.len());
SECItem key_item = {siBuffer, const_cast<uint8_t*>(key.data()),
- static_cast<unsigned int>(key.len())};
+ static_cast<unsigned int>(kHashLength[hash_type])};
PK11SymKey* inner =
PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, PK11_OriginUnwrap,
@@ -106,8 +108,8 @@ class TlsHkdfTest : public ::testing::Test,
}
void SetUp() {
- ImportKey(&k1_, kKey1, slot_.get());
- ImportKey(&k2_, kKey2, slot_.get());
+ ImportKey(&k1_, kKey1, hash_type_, slot_.get());
+ ImportKey(&k2_, kKey2, hash_type_, slot_.get());
}
void VerifyKey(const ScopedPK11SymKey& key, const DataBuffer& expected) {
@@ -183,9 +185,9 @@ TEST_P(TlsHkdfTest, HkdfKey1Only) {
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
- {0x11, 0x87, 0x38, 0x28, 0xa9, 0x19, 0x78, 0x11, 0x33, 0x91, 0x24,
- 0xb5, 0x8a, 0x1b, 0xb0, 0x9f, 0x7f, 0x0d, 0x8d, 0xbb, 0x10, 0xf4,
- 0x9c, 0x54, 0xbd, 0x1f, 0xd8, 0x85, 0xcd, 0x15, 0x30, 0x33},
+ {0x41, 0x6c, 0x53, 0x92, 0xb9, 0xf3, 0x6d, 0xf1, 0x88, 0xe9, 0x0e,
+ 0xb1, 0x4d, 0x17, 0xbf, 0x0d, 0xa1, 0x90, 0xbf, 0xdb, 0x7f, 0x1f,
+ 0x49, 0x56, 0xe6, 0xe5, 0x66, 0xa5, 0x69, 0xc8, 0xb1, 0x5c},
{0x51, 0xb1, 0xd5, 0xb4, 0x59, 0x79, 0x79, 0x08, 0x4a, 0x15, 0xb2, 0xdb,
0x84, 0xd3, 0xd6, 0xbc, 0xfc, 0x93, 0x45, 0xd9, 0xdc, 0x74, 0xda, 0x1a,
0x57, 0xc2, 0x76, 0x9f, 0x3f, 0x83, 0x45, 0x2f, 0xf6, 0xf3, 0x56, 0x1f,
@@ -201,11 +203,9 @@ TEST_P(TlsHkdfTest, HkdfKey2Only) {
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
- {
- 0x2f, 0x5f, 0x78, 0xd0, 0xa4, 0xc4, 0x36, 0xee, 0x6c, 0x8a, 0x4e,
- 0xf9, 0xd0, 0x43, 0x81, 0x02, 0x13, 0xfd, 0x47, 0x83, 0x63, 0x3a,
- 0xd2, 0xe1, 0x40, 0x6d, 0x2d, 0x98, 0x00, 0xfd, 0xc1, 0x87,
- },
+ {0x16, 0xaf, 0x00, 0x54, 0x3a, 0x56, 0xc8, 0x26, 0xa2, 0xa7, 0xfc,
+ 0xb6, 0x34, 0x66, 0x8a, 0xfd, 0x36, 0xdc, 0x8e, 0xce, 0xc4, 0xd2,
+ 0x6c, 0x7a, 0xdc, 0xe3, 0x70, 0x36, 0x3d, 0x60, 0xfa, 0x0b},
{0x7b, 0x40, 0xf9, 0xef, 0x91, 0xff, 0xc9, 0xd1, 0x29, 0x24, 0x5c, 0xbf,
0xf8, 0x82, 0x76, 0x68, 0xae, 0x4b, 0x63, 0xe8, 0x03, 0xdd, 0x39, 0xa8,
0xd4, 0x6a, 0xf6, 0xe5, 0xec, 0xea, 0xf8, 0x7d, 0x91, 0x71, 0x81, 0xf1,
@@ -221,11 +221,9 @@ TEST_P(TlsHkdfTest, HkdfKey1Key2) {
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
- {
- 0x79, 0x53, 0xb8, 0xdd, 0x6b, 0x98, 0xce, 0x00, 0xb7, 0xdc, 0xe8,
- 0x03, 0x70, 0x8c, 0xe3, 0xac, 0x06, 0x8b, 0x22, 0xfd, 0x0e, 0x34,
- 0x48, 0xe6, 0xe5, 0xe0, 0x8a, 0xd6, 0x16, 0x18, 0xe5, 0x48,
- },
+ {0xa5, 0x68, 0x02, 0x5a, 0x95, 0xc9, 0x7f, 0x55, 0x38, 0xbc, 0xf7,
+ 0x97, 0xcc, 0x0f, 0xd5, 0xf6, 0xa8, 0x8d, 0x15, 0xbc, 0x0e, 0x85,
+ 0x74, 0x70, 0x3c, 0xa3, 0x65, 0xbd, 0x76, 0xcf, 0x9f, 0xd3},
{0x01, 0x93, 0xc0, 0x07, 0x3f, 0x6a, 0x83, 0x0e, 0x2e, 0x4f, 0xb2, 0x58,
0xe4, 0x00, 0x08, 0x5c, 0x68, 0x9c, 0x37, 0x32, 0x00, 0x37, 0xff, 0xc3,
0x1c, 0x5b, 0x98, 0x0b, 0x02, 0x92, 0x3f, 0xfd, 0x73, 0x5a, 0x6f, 0x2a,
@@ -241,9 +239,9 @@ TEST_P(TlsHkdfTest, HkdfExpandLabel) {
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
- {0xc6, 0xdd, 0x6e, 0xc4, 0x76, 0xb8, 0x55, 0xf2, 0xa4, 0xfc, 0x59,
- 0x04, 0xa4, 0x90, 0xdc, 0xa7, 0xa7, 0x0d, 0x94, 0x8f, 0xc2, 0xdc,
- 0x15, 0x6d, 0x48, 0x93, 0x9d, 0x05, 0xbb, 0x9a, 0xbc, 0xc1},
+ {0x3e, 0x4e, 0x6e, 0xd0, 0xbc, 0xc4, 0xf4, 0xff, 0xf0, 0xf5, 0x69,
+ 0xd0, 0x6c, 0x1e, 0x0e, 0x10, 0x32, 0xaa, 0xd7, 0xa3, 0xef, 0xf6,
+ 0xa8, 0x65, 0x8e, 0xbe, 0xee, 0xc7, 0x1f, 0x01, 0x6d, 0x3c},
{0x41, 0xea, 0x77, 0x09, 0x8c, 0x90, 0x04, 0x10, 0xec, 0xbc, 0x37, 0xd8,
0x5b, 0x54, 0xcd, 0x7b, 0x08, 0x15, 0x13, 0x20, 0xed, 0x1e, 0x3f, 0x54,
0x74, 0xf7, 0x8b, 0x06, 0x38, 0x28, 0x06, 0x37, 0x75, 0x23, 0xa2, 0xb7,