diff --git a/nss-1328318-v7-3.29.patch b/nss-1328318-v7-3.29.patch new file mode 100644 index 0000000..2e88942 --- /dev/null +++ b/nss-1328318-v7-3.29.patch @@ -0,0 +1,759 @@ +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 +@@ -31,16 +31,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,288 @@ ++/* -*- 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 "secerr.h" ++#include "ssl.h" ++#include "ssl3prot.h" ++#include "sslerr.h" ++#include "sslproto.h" ++#include "nss.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 +diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c +--- a/lib/ssl/sslsock.c ++++ b/lib/ssl/sslsock.c +@@ -2190,38 +2190,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; +@@ -2237,60 +2241,58 @@ 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); +@@ -2317,60 +2319,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); + +@@ -2394,41 +2452,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/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 +@@ -265,16 +265,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; + + if (!cfg_.get("server")) { + // Needed to make resumption work. + rv = SSL_SetURL(ssl_fd_, "server"); + if (rv != SECSuccess) return false; + } +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,20 @@ 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"; +@@ -140,16 +144,26 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc + EXPECT_NE(nullptr, ssl_fd_); + if (!ssl_fd_) return false; + pr_fd_ = nullptr; + + 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()); +@@ -375,16 +389,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/nss.spec b/nss.spec index e29d872..3dd8340 100644 --- a/nss.spec +++ b/nss.spec @@ -21,7 +21,7 @@ Name: nss Version: 3.29.3 # for Rawhide, please always use release >= 2 # for Fedora release branches, please use release < 2 (1.0, 1.1, ...) -Release: 1.1%{?dist} +Release: 1.2%{?dist} License: MPLv2.0 URL: http://www.mozilla.org/projects/security/pki/nss/ Group: System Environment/Libraries @@ -115,6 +115,7 @@ Patch59: nss-check-policy-file.patch Patch62: nss-skip-util-gtest.patch Patch63: nss-gcc7.patch Patch64: nss-1334976-1336487.patch +Patch65: nss-1328318-v7-3.29.patch %description Network Security Services (NSS) is a set of libraries designed to @@ -200,6 +201,7 @@ pushd nss %patch62 -p0 -b .skip_util_gtest %patch63 -p1 -b .gcc7 %patch64 -p1 -b .1334976-1336487 +%patch65 -p1 -b .1328318 popd ######################################################### @@ -808,6 +810,9 @@ fi %changelog +* Wed Mar 29 2017 Kai Engert - 3.29.3-1.2 +- Backport upstream mozbz#1328318 to support crypto policy FUTURE. + * Wed Mar 22 2017 Daiki Ueno - 3.29.3-1.1 - Re-add patch to check CKA_NSS_MOZILLA_CA_POLICY, which was mistakenly removed in the previous update