diff --git a/gtests/nss_bogo_shim/nss_bogo_shim.cc b/gtests/nss_bogo_shim/nss_bogo_shim.cc --- a/gtests/nss_bogo_shim/nss_bogo_shim.cc +++ b/gtests/nss_bogo_shim/nss_bogo_shim.cc @@ -260,16 +260,22 @@ class TestAgent { if (rv != SECSuccess) return false; SSLVersionRange vrange; if (!GetVersionRange(&vrange, ssl_variant_stream)) return false; rv = SSL_VersionRangeSet(ssl_fd_, &vrange); if (rv != SECSuccess) return false; + SSLVersionRange verify_vrange; + rv = SSL_VersionRangeGet(ssl_fd_, &verify_vrange); + if (rv != SECSuccess) return false; + if (vrange.min != verify_vrange.min || vrange.max != verify_vrange.max) + return false; + rv = SSL_OptionSet(ssl_fd_, SSL_NO_CACHE, false); if (rv != SECSuccess) return false; auto alpn = cfg_.get("advertise-alpn"); if (!alpn.empty()) { assert(!cfg_.get("server")); rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_ALPN, PR_TRUE); diff --git a/gtests/ssl_gtest/tls_agent.cc b/gtests/ssl_gtest/tls_agent.cc --- a/gtests/ssl_gtest/tls_agent.cc +++ b/gtests/ssl_gtest/tls_agent.cc @@ -20,16 +20,21 @@ extern "C" { #define GTEST_HAS_RTTI 0 #include "gtest/gtest.h" #include "gtest_utils.h" #include "scoped_ptrs.h" extern std::string g_working_dir_path; +static bool SSLVersionRangesAreEqual(SSLVersionRange& vr1, + SSLVersionRange& vr2) { + return vr1.min == vr2.min && vr1.max == vr2.max; +} + namespace nss_test { const char* TlsAgent::states[] = {"INIT", "CONNECTING", "CONNECTED", "ERROR"}; const std::string TlsAgent::kClient = "client"; // both sign and encrypt const std::string TlsAgent::kRsa2048 = "rsa2048"; // bigger const std::string TlsAgent::kServerRsa = "rsa"; // both sign and encrypt const std::string TlsAgent::kServerRsaSign = "rsa_sign"; @@ -156,16 +161,26 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc return false; } dummy_fd.release(); // Now subsumed by ssl_fd_. SECStatus rv = SSL_VersionRangeSet(ssl_fd(), &vrange_); EXPECT_EQ(SECSuccess, rv); if (rv != SECSuccess) return false; + SSLVersionRange verify_vrange; + rv = SSL_VersionRangeGet(ssl_fd(), &verify_vrange); + EXPECT_EQ(SECSuccess, rv); + if (rv != SECSuccess) return false; + + bool ranges_are_equal = SSLVersionRangesAreEqual(vrange_, verify_vrange); + EXPECT_TRUE(ranges_are_equal) + << "System policy must not restrict the allowed min/max SSL/TLS range"; + if (!ranges_are_equal) return false; + if (role_ == SERVER) { EXPECT_TRUE(ConfigServerCert(name_, true)); rv = SSL_SNISocketConfigHook(ssl_fd(), SniHook, this); EXPECT_EQ(SECSuccess, rv); if (rv != SECSuccess) return false; ScopedCERTCertList anchors(CERT_NewCertList()); @@ -400,16 +415,23 @@ void TlsAgent::SetShortHeadersEnabled() void TlsAgent::SetVersionRange(uint16_t minver, uint16_t maxver) { vrange_.min = minver; vrange_.max = maxver; if (ssl_fd()) { SECStatus rv = SSL_VersionRangeSet(ssl_fd(), &vrange_); EXPECT_EQ(SECSuccess, rv); + + SSLVersionRange verify_vrange; + rv = SSL_VersionRangeGet(ssl_fd(), &verify_vrange); + EXPECT_EQ(SECSuccess, rv); + bool ranges_are_equal = SSLVersionRangesAreEqual(vrange_, verify_vrange); + EXPECT_TRUE(ranges_are_equal) + << "System policy must not restrict the allowed min/max SSL/TLS range"; } } void TlsAgent::GetVersionRange(uint16_t* minver, uint16_t* maxver) { *minver = vrange_.min; *maxver = vrange_.max; } diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c --- a/lib/ssl/sslsock.c +++ b/lib/ssl/sslsock.c @@ -2202,38 +2202,42 @@ ssl3_GetRangePolicy(SSLProtocolVariant p return SECFailure; /* don't accept an invalid policy */ } return SECSuccess; } /* * Constrain a single protocol variant's range based on the user policy */ -static SECStatus -ssl3_ConstrainVariantRangeByPolicy(SSLProtocolVariant protocolVariant) +static void +ssl3_ConstrainVariantRangeByPolicy(SSLProtocolVariant protocolVariant, + SSLVersionRange *rangeParam /* in and out */) { SSLVersionRange vrange; SSLVersionRange pvrange; SECStatus rv; - vrange = *VERSIONS_DEFAULTS(protocolVariant); + if (!rangeParam) { + return; + } + + vrange = *rangeParam; rv = ssl3_GetRangePolicy(protocolVariant, &pvrange); if (rv != SECSuccess) { - return SECSuccess; /* we don't have any policy */ + return; /* we don't have any policy */ } vrange.min = PR_MAX(vrange.min, pvrange.min); vrange.max = PR_MIN(vrange.max, pvrange.max); if (vrange.max >= vrange.min) { - *VERSIONS_DEFAULTS(protocolVariant) = vrange; + *rangeParam = vrange; } else { /* there was no overlap, turn off range altogether */ pvrange.min = pvrange.max = SSL_LIBRARY_VERSION_NONE; - *VERSIONS_DEFAULTS(protocolVariant) = pvrange; + *rangeParam = pvrange; } - return SECSuccess; } static PRBool ssl_VersionIsSupportedByPolicy(SSLProtocolVariant protocolVariant, SSL3ProtocolVersion version) { SSLVersionRange pvrange; SECStatus rv; @@ -2249,60 +2253,59 @@ ssl_VersionIsSupportedByPolicy(SSLProtoc /* * This is called at SSL init time to constrain the existing range based * on user supplied policy. */ SECStatus ssl3_ConstrainRangeByPolicy(void) { - SECStatus rv; - rv = ssl3_ConstrainVariantRangeByPolicy(ssl_variant_stream); - if (rv != SECSuccess) { - return rv; + ssl3_ConstrainVariantRangeByPolicy(ssl_variant_stream, + VERSIONS_DEFAULTS(ssl_variant_stream)); + ssl3_ConstrainVariantRangeByPolicy(ssl_variant_datagram, + VERSIONS_DEFAULTS(ssl_variant_datagram)); + return SECSuccess; +} + +PRBool +ssl3_VersionIsSupportedByCode(SSLProtocolVariant protocolVariant, + SSL3ProtocolVersion version) +{ + switch (protocolVariant) { + case ssl_variant_stream: + return (version >= SSL_LIBRARY_VERSION_3_0 && + version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED); + case ssl_variant_datagram: + return (version >= SSL_LIBRARY_VERSION_TLS_1_1 && + version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED); } - rv = ssl3_ConstrainVariantRangeByPolicy(ssl_variant_datagram); - if (rv != SECSuccess) { - return rv; - } - return SECSuccess; + + /* Can't get here */ + PORT_Assert(PR_FALSE); + return PR_FALSE; } PRBool ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant, SSL3ProtocolVersion version) { if (!ssl_VersionIsSupportedByPolicy(protocolVariant, version)) { return PR_FALSE; } - switch (protocolVariant) { - case ssl_variant_stream: - return (version >= SSL_LIBRARY_VERSION_3_0 && - version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED); - case ssl_variant_datagram: - return (version >= SSL_LIBRARY_VERSION_TLS_1_1 && - version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED); - default: - /* Can't get here */ - PORT_Assert(PR_FALSE); - return PR_FALSE; - } + return ssl3_VersionIsSupportedByCode(protocolVariant, version); } -/* Returns PR_TRUE if the given version range is valid and -** fully supported; otherwise, returns PR_FALSE. -*/ static PRBool ssl3_VersionRangeIsValid(SSLProtocolVariant protocolVariant, const SSLVersionRange *vrange) { return vrange && vrange->min <= vrange->max && - ssl3_VersionIsSupported(protocolVariant, vrange->min) && - ssl3_VersionIsSupported(protocolVariant, vrange->max) && + ssl3_VersionIsSupportedByCode(protocolVariant, vrange->min) && + ssl3_VersionIsSupportedByCode(protocolVariant, vrange->max) && (vrange->min > SSL_LIBRARY_VERSION_3_0 || vrange->max < SSL_LIBRARY_VERSION_TLS_1_3); } const SECItem * SSL_PeerSignedCertTimestamps(PRFileDesc *fd) { sslSocket *ss = ssl_FindSocket(fd); @@ -2329,60 +2332,116 @@ SSL_VersionRangeGetSupported(SSLProtocol PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } switch (protocolVariant) { case ssl_variant_stream: vrange->min = SSL_LIBRARY_VERSION_3_0; vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED; - // We don't allow SSLv3 and TLSv1.3 together. - if (vrange->max == SSL_LIBRARY_VERSION_TLS_1_3) { - vrange->min = SSL_LIBRARY_VERSION_TLS_1_0; - } + /* We don't allow SSLv3 and TLSv1.3 together. + * However, don't check yet, apply the policy first. + * Because if the effective supported range doesn't use TLS 1.3, + * then we don't need to increase the minimum. */ break; case ssl_variant_datagram: vrange->min = SSL_LIBRARY_VERSION_TLS_1_1; vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED; break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } + ssl3_ConstrainVariantRangeByPolicy(protocolVariant, vrange); + if (vrange->min == SSL_LIBRARY_VERSION_NONE) { + /* Library default and policy don't overlap. */ + return SECFailure; + } + + if (protocolVariant == ssl_variant_stream) { + /* We don't allow SSLv3 and TLSv1.3 together */ + if (vrange->max == SSL_LIBRARY_VERSION_TLS_1_3) { + vrange->min = PR_MAX(vrange->min, SSL_LIBRARY_VERSION_TLS_1_0); + } + } + return SECSuccess; } SECStatus SSL_VersionRangeGetDefault(SSLProtocolVariant protocolVariant, SSLVersionRange *vrange) { if ((protocolVariant != ssl_variant_stream && protocolVariant != ssl_variant_datagram) || !vrange) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } *vrange = *VERSIONS_DEFAULTS(protocolVariant); + ssl3_ConstrainVariantRangeByPolicy(protocolVariant, vrange); + + if (vrange->min == SSL_LIBRARY_VERSION_NONE) { + /* Library default and policy don't overlap. */ + return SECFailure; + } return SECSuccess; } -SECStatus -SSL_VersionRangeSetDefault(SSLProtocolVariant protocolVariant, - const SSLVersionRange *vrange) +static SECStatus +ssl3_CheckRangeValidAndConstrainByPolicy(SSLProtocolVariant protocolVariant, + SSLVersionRange *vrange) { if (!ssl3_VersionRangeIsValid(protocolVariant, vrange)) { PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE); return SECFailure; } - *VERSIONS_DEFAULTS(protocolVariant) = *vrange; - + /* Try to adjust the received range using our policy. + * If there's overlap, we'll use the (possibly reduced) range. + * If there isn't overlap, it's failure. */ + + ssl3_ConstrainVariantRangeByPolicy(protocolVariant, vrange); + if (vrange->min == SSL_LIBRARY_VERSION_NONE) { + return SECFailure; + } + + if (protocolVariant == ssl_variant_stream) { + /* We don't allow SSLv3 and TLSv1.3 together */ + if (vrange->max == SSL_LIBRARY_VERSION_TLS_1_3) { + vrange->min = + PR_MAX(vrange->min, SSL_LIBRARY_VERSION_TLS_1_0); + } + } + + return SECSuccess; +} + +SECStatus +SSL_VersionRangeSetDefault(SSLProtocolVariant protocolVariant, + const SSLVersionRange *vrange) +{ + SSLVersionRange constrainedRange; + SECStatus rv; + + if (!vrange) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + constrainedRange = *vrange; + rv = ssl3_CheckRangeValidAndConstrainByPolicy(protocolVariant, + &constrainedRange); + if (rv != SECSuccess) + return rv; + + *VERSIONS_DEFAULTS(protocolVariant) = constrainedRange; return SECSuccess; } SECStatus SSL_VersionRangeGet(PRFileDesc *fd, SSLVersionRange *vrange) { sslSocket *ss = ssl_FindSocket(fd); @@ -2406,41 +2465,50 @@ SSL_VersionRangeGet(PRFileDesc *fd, SSLV ssl_Release1stHandshakeLock(ss); return SECSuccess; } SECStatus SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange) { - sslSocket *ss = ssl_FindSocket(fd); - + SSLVersionRange constrainedRange; + sslSocket *ss; + SECStatus rv; + + if (!vrange) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + ss = ssl_FindSocket(fd); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in SSL_VersionRangeSet", SSL_GETPID(), fd)); return SECFailure; } - if (!ssl3_VersionRangeIsValid(ss->protocolVariant, vrange)) { - PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE); - return SECFailure; - } + constrainedRange = *vrange; + rv = ssl3_CheckRangeValidAndConstrainByPolicy(ss->protocolVariant, + &constrainedRange); + if (rv != SECSuccess) + return rv; ssl_Get1stHandshakeLock(ss); ssl_GetSSL3HandshakeLock(ss); if (ss->ssl3.downgradeCheckVersion && ss->vrange.max > ss->ssl3.downgradeCheckVersion) { PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE); ssl_ReleaseSSL3HandshakeLock(ss); ssl_Release1stHandshakeLock(ss); return SECFailure; } - ss->vrange = *vrange; + ss->vrange = constrainedRange; ssl_ReleaseSSL3HandshakeLock(ss); ssl_Release1stHandshakeLock(ss); return SECSuccess; } SECStatus diff --git a/gtests/ssl_gtest/Makefile b/gtests/ssl_gtest/Makefile --- a/gtests/ssl_gtest/Makefile +++ b/gtests/ssl_gtest/Makefile @@ -32,16 +32,18 @@ CFLAGS += -I$(CORE_DEPTH)/lib/ssl ifdef NSS_SSL_ENABLE_ZLIB include $(CORE_DEPTH)/coreconf/zlib.mk endif ifdef NSS_DISABLE_TLS_1_3 NSS_DISABLE_TLS_1_3=1 # Run parameterized tests only, for which we can easily exclude TLS 1.3 CPPSRCS := $(filter-out $(shell grep -l '^TEST_F' $(CPPSRCS)), $(CPPSRCS)) +# But always include ssl_versionpolicy_unittest.cc +CPPSRCS += ssl_versionpolicy_unittest.cc CFLAGS += -DNSS_DISABLE_TLS_1_3 endif ####################################################################### # (5) Execute "global" rules. (OPTIONAL) # ####################################################################### include $(CORE_DEPTH)/coreconf/rules.mk diff --git a/gtests/ssl_gtest/manifest.mn b/gtests/ssl_gtest/manifest.mn --- a/gtests/ssl_gtest/manifest.mn +++ b/gtests/ssl_gtest/manifest.mn @@ -33,16 +33,17 @@ CPPSRCS = \ ssl_hrr_unittest.cc \ ssl_loopback_unittest.cc \ ssl_record_unittest.cc \ ssl_resumption_unittest.cc \ ssl_skip_unittest.cc \ ssl_staticrsa_unittest.cc \ ssl_v2_client_hello_unittest.cc \ ssl_version_unittest.cc \ + ssl_versionpolicy_unittest.cc \ test_io.cc \ tls_agent.cc \ tls_connect.cc \ tls_hkdf_unittest.cc \ tls_filter.cc \ tls_parser.cc \ tls_protect.cc \ $(NULL) diff --git a/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc b/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc new file mode 100644 --- /dev/null +++ b/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc @@ -0,0 +1,281 @@ +/* -*- 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 "nss.h" +#include "secerr.h" +#include "ssl.h" +#include "ssl3prot.h" +#include "sslerr.h" +#include "sslproto.h" + +#include "gtest_utils.h" +#include "scoped_ptrs.h" +#include "tls_connect.h" +#include "tls_filter.h" +#include "tls_parser.h" + +static bool SSLVersionRangesAreEqual(SSLVersionRange &vr1, + SSLVersionRange &vr2) { + return vr1.min == vr2.min && vr1.max == vr2.max; +} + +namespace nss_test { + +class TestVersionRangePolicy : public ::testing::Test { + protected: + PRInt32 savedMinTLS; + PRInt32 savedMaxTLS; + PRInt32 savedMinDTLS; + PRInt32 savedMaxDTLS; + PRUint32 savedAlgorithmPolicy; + + public: + void SaveOriginalPolicy() { + NSS_OptionGet(NSS_TLS_VERSION_MIN_POLICY, &savedMinTLS); + NSS_OptionGet(NSS_TLS_VERSION_MAX_POLICY, &savedMaxTLS); + NSS_OptionGet(NSS_DTLS_VERSION_MIN_POLICY, &savedMinDTLS); + NSS_OptionGet(NSS_DTLS_VERSION_MAX_POLICY, &savedMaxDTLS); + NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &savedAlgorithmPolicy); + } + void SetUsePolicyInSSL() { + NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL, 0); + } + void RestoreOriginalPolicy() { + NSS_OptionSet(NSS_TLS_VERSION_MIN_POLICY, savedMinTLS); + NSS_OptionSet(NSS_TLS_VERSION_MAX_POLICY, savedMaxTLS); + NSS_OptionSet(NSS_DTLS_VERSION_MIN_POLICY, savedMinDTLS); + NSS_OptionSet(NSS_DTLS_VERSION_MAX_POLICY, savedMaxDTLS); + /* If it wasn't set initially, clear the bit that we set. */ + if (!(savedAlgorithmPolicy & NSS_USE_POLICY_IN_SSL)) { + NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, 0, + NSS_USE_POLICY_IN_SSL); + } + } + void SetTLSPolicy(SSLVersionRange &policy) { + NSS_OptionSet(NSS_TLS_VERSION_MIN_POLICY, policy.min); + NSS_OptionSet(NSS_TLS_VERSION_MAX_POLICY, policy.max); + } + void SetDTLSPolicy(SSLVersionRange &policy) { + /* SSL3 isn't allowed for DTLS, but isn't a problem to allow by policy */ + NSS_OptionSet(NSS_DTLS_VERSION_MIN_POLICY, policy.min); + NSS_OptionSet(NSS_DTLS_VERSION_MAX_POLICY, policy.max); + } + std::string version_to_string(PRInt32 v) { + switch (v) { + case SSL_LIBRARY_VERSION_3_0: + return "ssl3"; + case SSL_LIBRARY_VERSION_TLS_1_0: + return "tls1.0"; + case SSL_LIBRARY_VERSION_TLS_1_1: + return "tls1.1"; + case SSL_LIBRARY_VERSION_TLS_1_2: + return "tls1.2"; + case SSL_LIBRARY_VERSION_TLS_1_3: + return "tls1.3"; + case SSL_LIBRARY_VERSION_NONE: + return "NONE"; + } + return "undefined???"; + } + std::string info_str(const SSLVersionRange &policy, + const SSLVersionRange &vrange, + const SSLVersionRange *expectation, + const SSLVersionRange *result, bool testDTLS) { + return std::string(testDTLS ? "DTLS" : "TLS") + std::string(" policy: ") + + version_to_string(policy.min) + std::string(",") + + version_to_string(policy.max) + std::string(" input: ") + + version_to_string(vrange.min) + std::string(",") + + version_to_string(vrange.max) + + (expectation + ? (std::string(" expected: ") + + version_to_string(expectation->min) + std::string(",") + + version_to_string(expectation->max)) + : std::string()) + + (result + ? (std::string(" result: ") + version_to_string(result->min) + + std::string(",") + version_to_string(result->max)) + : std::string()); + } + void TestPolicyRangeExpectation(SSLVersionRange &policy, + SSLVersionRange &vrange, + SSLVersionRange &expectation, bool testDTLS) { + SECStatus rv; + + SetTLSPolicy(policy); + rv = SSL_VersionRangeSetDefault(ssl_variant_stream, &vrange); + EXPECT_EQ(SECSuccess, rv) + << "expected successful return from SSL_VersionRangeSetDefault with: " + << info_str(policy, vrange, &expectation, NULL, false); + + SSLVersionRange result; + rv = SSL_VersionRangeGetDefault(ssl_variant_stream, &result); + EXPECT_EQ(SECSuccess, rv) + << "expected successful return from SSL_VersionRangeGetDefault: " + << info_str(policy, vrange, &expectation, NULL, false); + + EXPECT_EQ(true, SSLVersionRangesAreEqual(result, expectation)) + << "range returned by SSL_VersionRangeGetDefault doesn't match " + "expectation: " + << info_str(policy, vrange, &expectation, &result, false); + + if (testDTLS) { + SetDTLSPolicy(policy); + rv = SSL_VersionRangeSetDefault(ssl_variant_datagram, &vrange); + EXPECT_EQ(SECSuccess, rv) + << "expected successful return from SSL_VersionRangeSetDefault with: " + << info_str(policy, vrange, &expectation, NULL, true); + + SSLVersionRange result; + rv = SSL_VersionRangeGetDefault(ssl_variant_datagram, &result); + EXPECT_EQ(SECSuccess, rv) + << "expected successful return from SSL_VersionRangeGetDefault: " + << info_str(policy, vrange, &expectation, NULL, true); + + EXPECT_EQ(true, SSLVersionRangesAreEqual(result, expectation)) + << "range returned by SSL_VersionRangeGetDefault doesn't match " + "expectation: " + << info_str(policy, vrange, &expectation, &result, true); + } + } + void TestPolicyRangeFailure(SSLVersionRange &policy, SSLVersionRange &vrange, + bool testDTLS) { + SECStatus rv; + + SetTLSPolicy(policy); + rv = SSL_VersionRangeSetDefault(ssl_variant_stream, &vrange); + EXPECT_EQ(SECFailure, rv) + << "expected failure return from SSL_VersionRangeSetDefault with: " + << info_str(policy, vrange, NULL, NULL, false); + + if (testDTLS) { + SetDTLSPolicy(policy); + rv = SSL_VersionRangeSetDefault(ssl_variant_datagram, &vrange); + EXPECT_EQ(SECFailure, rv) + << "expected failure return from SSL_VersionRangeSetDefault with: " + << info_str(policy, vrange, NULL, NULL, true); + } + } + void Run() { + SaveOriginalPolicy(); + SetUsePolicyInSSL(); + +#ifndef NSS_DISABLE_TLS_1_3 + SSLVersionRange range3to13{SSL_LIBRARY_VERSION_3_0, + SSL_LIBRARY_VERSION_TLS_1_3}; + SSLVersionRange range10to13{SSL_LIBRARY_VERSION_TLS_1_0, + SSL_LIBRARY_VERSION_TLS_1_3}; + SSLVersionRange range11to13{SSL_LIBRARY_VERSION_TLS_1_1, + SSL_LIBRARY_VERSION_TLS_1_3}; + SSLVersionRange range12to13{SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3}; + SSLVersionRange range13to13{SSL_LIBRARY_VERSION_TLS_1_3, + SSL_LIBRARY_VERSION_TLS_1_3}; +#endif + + SSLVersionRange range3to12{SSL_LIBRARY_VERSION_3_0, + SSL_LIBRARY_VERSION_TLS_1_2}; + SSLVersionRange range10to12{SSL_LIBRARY_VERSION_TLS_1_0, + SSL_LIBRARY_VERSION_TLS_1_2}; + SSLVersionRange range11to12{SSL_LIBRARY_VERSION_TLS_1_1, + SSL_LIBRARY_VERSION_TLS_1_2}; + SSLVersionRange range12to12{SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_2}; + + SSLVersionRange range3to11{SSL_LIBRARY_VERSION_3_0, + SSL_LIBRARY_VERSION_TLS_1_1}; + SSLVersionRange range10to11{SSL_LIBRARY_VERSION_TLS_1_0, + SSL_LIBRARY_VERSION_TLS_1_1}; + SSLVersionRange range11to11{SSL_LIBRARY_VERSION_TLS_1_1, + SSL_LIBRARY_VERSION_TLS_1_1}; + + SSLVersionRange range3to10{SSL_LIBRARY_VERSION_3_0, + SSL_LIBRARY_VERSION_TLS_1_0}; + SSLVersionRange range10to10{SSL_LIBRARY_VERSION_TLS_1_0, + SSL_LIBRARY_VERSION_TLS_1_0}; + + SSLVersionRange range3to3{SSL_LIBRARY_VERSION_3_0, SSL_LIBRARY_VERSION_3_0}; + +// When testing SSL3 or TLS1.0, we set "test DTLS" to false. + +#ifndef NSS_DISABLE_TLS_1_3 + // Invalid range input (cannot enable both SSL3 and TLS1.3) + TestPolicyRangeFailure(range3to13, range3to13, false); +#endif + + // No overlap between policy and range input + TestPolicyRangeFailure(range11to11, range10to10, false); + TestPolicyRangeFailure(range11to11, range12to12, true); + TestPolicyRangeFailure(range10to12, range3to3, false); +#ifndef NSS_DISABLE_TLS_1_3 + TestPolicyRangeFailure(range10to12, range13to13, true); +#endif + + // straightforward overlap tests + + TestPolicyRangeExpectation(range3to11, range10to12, range10to11, false); + TestPolicyRangeExpectation(range10to12, range10to12, range10to12, false); + + TestPolicyRangeExpectation(range11to12, range10to12, range11to12, false); + TestPolicyRangeExpectation(range11to12, range11to12, range11to12, true); + + TestPolicyRangeExpectation(range12to12, range10to12, range12to12, false); + + TestPolicyRangeExpectation(range3to12, range3to3, range3to3, false); + TestPolicyRangeExpectation(range3to12, range3to10, range3to10, false); + TestPolicyRangeExpectation(range3to12, range3to11, range3to11, false); + TestPolicyRangeExpectation(range3to12, range3to12, range3to12, false); + TestPolicyRangeExpectation(range3to12, range10to10, range10to10, false); + TestPolicyRangeExpectation(range3to12, range10to11, range10to11, false); + TestPolicyRangeExpectation(range3to12, range10to12, range10to12, false); + TestPolicyRangeExpectation(range3to12, range11to11, range11to11, true); + TestPolicyRangeExpectation(range3to12, range11to12, range11to12, true); + TestPolicyRangeExpectation(range3to12, range12to12, range12to12, true); + + TestPolicyRangeExpectation(range10to12, range3to10, range10to10, false); + TestPolicyRangeExpectation(range10to12, range3to11, range10to11, false); + TestPolicyRangeExpectation(range10to12, range3to12, range10to12, false); + TestPolicyRangeExpectation(range10to12, range10to10, range10to10, false); + TestPolicyRangeExpectation(range10to12, range10to11, range10to11, false); + TestPolicyRangeExpectation(range10to12, range10to12, range10to12, false); + TestPolicyRangeExpectation(range10to12, range11to11, range11to11, true); + TestPolicyRangeExpectation(range10to12, range11to12, range11to12, true); + TestPolicyRangeExpectation(range10to12, range12to12, range12to12, true); + +#ifndef NSS_DISABLE_TLS_1_3 + TestPolicyRangeExpectation(range3to12, range10to13, range10to12, false); + TestPolicyRangeExpectation(range10to13, range10to13, range10to13, false); + + TestPolicyRangeExpectation(range11to13, range10to13, range11to13, false); + TestPolicyRangeExpectation(range11to13, range11to13, range11to13, true); + + TestPolicyRangeExpectation(range12to13, range10to13, range12to13, false); + TestPolicyRangeExpectation(range12to13, range11to13, range12to13, true); + TestPolicyRangeExpectation(range12to13, range12to13, range12to13, true); + + TestPolicyRangeExpectation(range3to13, range3to3, range3to3, false); + TestPolicyRangeExpectation(range3to13, range3to10, range3to10, false); + TestPolicyRangeExpectation(range3to13, range3to11, range3to11, false); + TestPolicyRangeExpectation(range3to13, range3to12, range3to12, false); + TestPolicyRangeExpectation(range3to13, range10to10, range10to10, false); + TestPolicyRangeExpectation(range3to13, range10to11, range10to11, false); + TestPolicyRangeExpectation(range3to13, range10to12, range10to12, false); + TestPolicyRangeExpectation(range3to13, range10to13, range10to13, false); + TestPolicyRangeExpectation(range3to13, range11to11, range11to11, true); + TestPolicyRangeExpectation(range3to13, range11to12, range11to12, true); + TestPolicyRangeExpectation(range3to13, range12to12, range12to12, true); + TestPolicyRangeExpectation(range3to13, range12to13, range12to13, true); + TestPolicyRangeExpectation(range3to13, range13to13, range13to13, true); +#endif + + RestoreOriginalPolicy(); + } +}; + +TEST_F(TestVersionRangePolicy, TestVersionRangesAndCryptoPolicyInteraction) { + Run(); +} + +} // namespace nss_test