diff --git a/old-configure.in b/old-configure.in index c98707e43fb5..6570bb094b9b 100644 --- a/old-configure.in +++ b/old-configure.in @@ -1919,7 +1919,7 @@ MOZ_ARG_WITH_BOOL(system-nss, _USE_SYSTEM_NSS=1 ) if test -n "$_USE_SYSTEM_NSS"; then - AM_PATH_NSS(3.32, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])]) + AM_PATH_NSS(3.33, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])]) fi if test -n "$MOZ_SYSTEM_NSS"; then diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index 6c2d2b7cca1a..bc4662b8816b 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -NSS_3_32_RTM +a0a4e05dcdd5 diff --git a/security/nss/automation/abi-check/previous-nss-release b/security/nss/automation/abi-check/previous-nss-release index b8d28cde031c..0b2cd988f3b9 100644 --- a/security/nss/automation/abi-check/previous-nss-release +++ b/security/nss/automation/abi-check/previous-nss-release @@ -1 +1 @@ -NSS_3_31_BRANCH +NSS_3_32_BRANCH diff --git a/security/nss/automation/clang-format/run_clang_format.sh b/security/nss/automation/clang-format/run_clang_format.sh index 2ba5ebeb1a0b..378b00ff091a 100755 --- a/security/nss/automation/clang-format/run_clang_format.sh +++ b/security/nss/automation/clang-format/run_clang_format.sh @@ -6,6 +6,8 @@ if [[ $(id -u) -eq 0 ]]; then exec su worker -c "$0 $*" fi +set -e + # Apply clang-format on the provided folder and verify that this doesn't change any file. # If any file differs after formatting, the script eventually exits with 1. # Any differences between formatted and unformatted files is printed to stdout to give a hint what's wrong. @@ -21,17 +23,16 @@ blacklist=( "./lib/zlib" \ "./lib/sqlite" \ "./gtests/google_test" \ - "./.hg" \ "./out" \ ) -top="$(dirname $0)/../.." -cd "$top" +top=$(cd "$(dirname $0)/../.."; pwd -P) if [ $# -gt 0 ]; then dirs=("$@") else - dirs=($(find . -maxdepth 2 -mindepth 1 -type d ! -path . \( ! -regex '.*/' \))) + cd "$top" + dirs=($(find . -maxdepth 2 -mindepth 1 -type d ! -path '*/.*' -print)) fi format_folder() @@ -46,20 +47,20 @@ format_folder() } for dir in "${dirs[@]}"; do - if format_folder "$dir" ; then + if format_folder "$dir"; then c="${dir//[^\/]}" echo "formatting $dir ..." - depth="" + depth=() if [ "${#c}" == "1" ]; then - depth="-maxdepth 1" + depth+=(-maxdepth 1) fi - find "$dir" $depth -type f \( -name '*.[ch]' -o -name '*.cc' \) -exec clang-format -i {} \+ + find "$dir" "${depth[@]}" -type f \( -name '*.[ch]' -o -name '*.cc' \) -exec clang-format -i {} \+ fi done TMPFILE=$(mktemp /tmp/$(basename $0).XXXXXX) -trap 'rm $TMPFILE' exit -if (cd $(dirname $0); hg root >/dev/null 2>&1); then +trap 'rm -f $TMPFILE' exit +if [[ -d "$top/.hg" ]]; then hg diff --git "$top" | tee $TMPFILE else git -C "$top" diff | tee $TMPFILE diff --git a/security/nss/automation/release/nspr-version.txt b/security/nss/automation/release/nspr-version.txt index 98783a615299..9a4d1308957e 100644 --- a/security/nss/automation/release/nspr-version.txt +++ b/security/nss/automation/release/nspr-version.txt @@ -1,4 +1,4 @@ -4.16 +4.15 # The first line of this file must contain the human readable NSPR # version number, which is the minimum required version of NSPR diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c index cb4752df9ca7..25a58e10c528 100644 --- a/security/nss/cmd/lib/secutil.c +++ b/security/nss/cmd/lib/secutil.c @@ -991,7 +991,7 @@ secu_PrintUniversalString(FILE *out, const SECItem *i, const char *m, int level) for (s = my.data, d = tmp.data; len > 0; len--) { PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; s += 4; - if (!isprint(bmpChar)) + if (!isprint(bmpChar & 0xFF)) goto loser; *d++ = (unsigned char)bmpChar; } diff --git a/security/nss/cmd/modutil/error.h b/security/nss/cmd/modutil/error.h index b328afebc6f1..a75314f62a8f 100644 --- a/security/nss/cmd/modutil/error.h +++ b/security/nss/cmd/modutil/error.h @@ -109,7 +109,7 @@ static char *errStrings[] = { "ERROR: Failed to change default.\n", "ERROR: Unable to read from standard input.\n", "ERROR: Unknown error occurred.\n", - "ERROR: -nocertdb option can only be used with the -jar command.\n" + "ERROR: -nocertdb option can only be used with the -jar command.\n", "ERROR: NSS_Initialize() failed.\n" }; diff --git a/security/nss/cmd/pp/pp.c b/security/nss/cmd/pp/pp.c index 9f33d10a471e..d6e276834c37 100644 --- a/security/nss/cmd/pp/pp.c +++ b/security/nss/cmd/pp/pp.c @@ -84,6 +84,8 @@ main(int argc, char **argv) if (!inFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, optstate->value); + PORT_Free(typeTag); + PL_DestroyOptState(optstate); return -1; } break; @@ -93,6 +95,8 @@ main(int argc, char **argv) if (!outFile) { fprintf(stderr, "%s: unable to open \"%s\" for writing\n", progName, optstate->value); + PORT_Free(typeTag); + PL_DestroyOptState(optstate); return -1; } break; diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c index 959afec597ba..31cd030e3ef7 100644 --- a/security/nss/cmd/tstclnt/tstclnt.c +++ b/security/nss/cmd/tstclnt/tstclnt.c @@ -31,6 +31,7 @@ #include "ocsp.h" #include "ssl.h" #include "sslproto.h" +#include "sslexp.h" #include "pk11func.h" #include "secmod.h" #include "plgetopt.h" @@ -251,6 +252,7 @@ PrintParameterUsage(void) "%-20s The following values are valid:\n" "%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n", "-I", "", ""); + fprintf(stderr, "%-20s Enable alternate content type for TLS 1.3 ServerHello\n", "-X alt-server-hello"); } static void @@ -914,6 +916,7 @@ char *requestString = NULL; PRInt32 requestStringLen = 0; PRBool requestSent = PR_FALSE; PRBool enableZeroRtt = PR_FALSE; +PRBool enableAltServerHello = PR_FALSE; static int writeBytesToServer(PRFileDesc *s, const char *buf, int nb) @@ -1178,6 +1181,16 @@ run_client(void) } } + /* Alternate ServerHello content type (TLS 1.3 only) */ + if (enableAltServerHello) { + rv = SSL_UseAltServerHelloType(s, PR_TRUE); + if (rv != SECSuccess) { + SECU_PrintError(progName, "error enabling alternate ServerHello type"); + error = 1; + goto done; + } + } + /* require the use of fixed finite-field DH groups */ if (requireDHNamedGroups) { rv = SSL_OptionSet(s, SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE); @@ -1512,7 +1525,7 @@ main(int argc, char **argv) /* XXX: 'B' was used in the past but removed in 3.28, * please leave some time before resuing it. */ optstate = PL_CreateOptState(argc, argv, - "46A:CDFGHI:KL:M:OR:STUV:W:YZa:bc:d:fgh:m:n:op:qr:st:uvw:z"); + "46A:CDFGHI:KL:M:OR:STUV:W:X:YZa:bc:d:fgh:m:n:op:qr:st:uvw:z"); while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case '?': @@ -1618,6 +1631,13 @@ main(int argc, char **argv) } break; + case 'X': + if (!strcmp(optstate->value, "alt-server-hello")) { + enableAltServerHello = PR_TRUE; + } else { + Usage(progName); + } + break; case 'Y': PrintCipherUsage(progName); exit(0); diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep index 5182f75552c8..590d1bfaeee3 100644 --- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -10,3 +10,4 @@ */ #error "Do not include this header file." + diff --git a/security/nss/cpputil/tls_parser.h b/security/nss/cpputil/tls_parser.h index 15ba3b175b75..7a08091656a4 100644 --- a/security/nss/cpputil/tls_parser.h +++ b/security/nss/cpputil/tls_parser.h @@ -24,6 +24,7 @@ const uint8_t kTlsChangeCipherSpecType = 20; const uint8_t kTlsAlertType = 21; const uint8_t kTlsHandshakeType = 22; const uint8_t kTlsApplicationDataType = 23; +const uint8_t kTlsAltHandshakeType = 24; const uint8_t kTlsHandshakeClientHello = 1; const uint8_t kTlsHandshakeServerHello = 2; diff --git a/security/nss/fuzz/config/clone_libfuzzer.sh b/security/nss/fuzz/config/clone_libfuzzer.sh index f1dc2e14bbf7..c516057d7874 100755 --- a/security/nss/fuzz/config/clone_libfuzzer.sh +++ b/security/nss/fuzz/config/clone_libfuzzer.sh @@ -1,6 +1,6 @@ #!/bin/sh -LIBFUZZER_REVISION=56bd1d43451cca4b6a11d3be316bb77ab159b09d +LIBFUZZER_REVISION=6937e68f927b6aefe526fcb9db8953f497e6e74d d=$(dirname $0) $d/git-copy.sh https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer $LIBFUZZER_REVISION $d/../libFuzzer diff --git a/security/nss/gtests/certdb_gtest/alg1485_unittest.cc b/security/nss/gtests/certdb_gtest/alg1485_unittest.cc index b7c65941496f..ef6733092785 100644 --- a/security/nss/gtests/certdb_gtest/alg1485_unittest.cc +++ b/security/nss/gtests/certdb_gtest/alg1485_unittest.cc @@ -10,6 +10,7 @@ #include "nss.h" #include "scoped_ptrs.h" +#include "prprf.h" namespace nss_test { @@ -89,4 +90,23 @@ INSTANTIATE_TEST_CASE_P(ParseAVAStrings, Alg1485ParseTest, ::testing::ValuesIn(kAVATestStrings)); INSTANTIATE_TEST_CASE_P(CompareAVAStrings, Alg1485CompareTest, ::testing::ValuesIn(kAVACompareStrings)); + +TEST_F(Alg1485Test, ShortOIDTest) { + // This is not a valid OID (too short). CERT_GetOidString should return 0. + unsigned char data[] = {0x05}; + const SECItem oid = {siBuffer, data, sizeof(data)}; + char* result = CERT_GetOidString(&oid); + EXPECT_EQ(result, nullptr); +} + +TEST_F(Alg1485Test, BrokenOIDTest) { + // This is not a valid OID (first bit of last byte is not set). + // CERT_GetOidString should return 0. + unsigned char data[] = {0x81, 0x82, 0x83, 0x84}; + const SECItem oid = {siBuffer, data, sizeof(data)}; + char* result = CERT_GetOidString(&oid); + EXPECT_EQ(15U, strlen(result)); + EXPECT_EQ(0, strncmp("OID.UNSUPPORTED", result, 15)); + PR_smprintf_free(result); +} } diff --git a/security/nss/gtests/manifest.mn b/security/nss/gtests/manifest.mn index 1ae4cab776cc..3bc3664329bc 100644 --- a/security/nss/gtests/manifest.mn +++ b/security/nss/gtests/manifest.mn @@ -23,8 +23,9 @@ NSS_SRCDIRS = \ certdb_gtest \ certhigh_gtest \ pk11_gtest \ + softoken_gtest \ ssl_gtest \ - nss_bogo_shim \ + nss_bogo_shim \ $(NULL) endif endif diff --git a/security/nss/gtests/softoken_gtest/Makefile b/security/nss/gtests/softoken_gtest/Makefile new file mode 100644 index 000000000000..996669782d9e --- /dev/null +++ b/security/nss/gtests/softoken_gtest/Makefile @@ -0,0 +1,45 @@ +#! gmake +# +# 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/. + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + +include ../common/gtest.mk + +CFLAGS += -I$(CORE_DEPTH)/lib/util + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### diff --git a/security/nss/gtests/softoken_gtest/manifest.mn b/security/nss/gtests/softoken_gtest/manifest.mn new file mode 100644 index 000000000000..4b34c099f576 --- /dev/null +++ b/security/nss/gtests/softoken_gtest/manifest.mn @@ -0,0 +1,25 @@ +# -*- makefile -*- +# 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/. +CORE_DEPTH = ../.. +DEPTH = ../.. +MODULE = nss + +CPPSRCS = \ + softoken_gtest.cc \ + $(NULL) + +INCLUDES += \ + -I$(CORE_DEPTH)/gtests/google_test/gtest/include \ + -I$(CORE_DEPTH)/cpputil \ + $(NULL) + +REQUIRES = nspr gtest + +PROGRAM = softoken_gtest + +EXTRA_LIBS = \ + $(DIST)/lib/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)gtestutil.$(LIB_SUFFIX) \ + $(NULL) diff --git a/security/nss/gtests/softoken_gtest/softoken_gtest.cc b/security/nss/gtests/softoken_gtest/softoken_gtest.cc new file mode 100644 index 000000000000..2cddaed50040 --- /dev/null +++ b/security/nss/gtests/softoken_gtest/softoken_gtest.cc @@ -0,0 +1,125 @@ +#include + +#include "nspr.h" +#include "nss.h" +#include "pk11pub.h" + +#include "scoped_ptrs.h" + +#define GTEST_HAS_RTTI 0 +#include "gtest/gtest.h" + +namespace nss_test { + +// Given a prefix, attempts to create a unique directory that the user can do +// work in without impacting other tests. For example, if given the prefix +// "scratch", a directory like "scratch05c17b25" will be created in the current +// working directory (or the location specified by NSS_GTEST_WORKDIR, if +// defined). +// Upon destruction, the implementation will attempt to delete the directory. +// However, no attempt is made to first remove files in the directory - the +// user is responsible for this. If the directory is not empty, deleting it will +// fail. +// Statistically, it is technically possible to fail to create a unique +// directory name, but this is extremely unlikely given the expected workload of +// this implementation. +class ScopedUniqueDirectory { + public: + explicit ScopedUniqueDirectory(const std::string& prefix); + + // NB: the directory must be empty upon destruction + ~ScopedUniqueDirectory() { assert(rmdir(mPath.c_str()) == 0); } + + const std::string& GetPath() { return mPath; } + + private: + static const int RETRY_LIMIT = 5; + static void GenerateRandomName(/*in/out*/ std::string& prefix); + static bool TryMakingDirectory(/*in/out*/ std::string& prefix); + + std::string mPath; +}; + +ScopedUniqueDirectory::ScopedUniqueDirectory(const std::string& prefix) { + std::string path; + const char* workingDirectory = PR_GetEnvSecure("NSS_GTEST_WORKDIR"); + if (workingDirectory) { + path.assign(workingDirectory); + } + path.append(prefix); + for (int i = 0; i < RETRY_LIMIT; i++) { + std::string pathCopy(path); + // TryMakingDirectory will modify its input. If it fails, we want to throw + // away the modified result. + if (TryMakingDirectory(pathCopy)) { + mPath.assign(pathCopy); + break; + } + } + assert(mPath.length() > 0); +} + +void ScopedUniqueDirectory::GenerateRandomName(std::string& prefix) { + std::stringstream ss; + ss << prefix; + // RAND_MAX is at least 32767. + ss << std::setfill('0') << std::setw(4) << std::hex << rand() << rand(); + // This will overwrite the value of prefix. This is a little inefficient, but + // at least it makes the code simple. + ss >> prefix; +} + +bool ScopedUniqueDirectory::TryMakingDirectory(std::string& prefix) { + GenerateRandomName(prefix); +#if defined(_WIN32) + return _mkdir(prefix.c_str()) == 0; +#else + return mkdir(prefix.c_str(), 0777) == 0; +#endif +} + +class SoftokenTest : public ::testing::Test { + protected: + SoftokenTest() : mNSSDBDir("SoftokenTest.d-") {} + + virtual void SetUp() { + std::string nssInitArg("sql:"); + nssInitArg.append(mNSSDBDir.GetPath()); + ASSERT_EQ(SECSuccess, NSS_Initialize(nssInitArg.c_str(), "", "", SECMOD_DB, + NSS_INIT_NOROOTINIT)); + } + + virtual void TearDown() { + ASSERT_EQ(SECSuccess, NSS_Shutdown()); + const std::string& nssDBDirPath = mNSSDBDir.GetPath(); + ASSERT_EQ(0, unlink((nssDBDirPath + "/cert9.db").c_str())); + ASSERT_EQ(0, unlink((nssDBDirPath + "/key4.db").c_str())); + ASSERT_EQ(0, unlink((nssDBDirPath + "/pkcs11.txt").c_str())); + } + + ScopedUniqueDirectory mNSSDBDir; +}; + +TEST_F(SoftokenTest, ResetSoftokenEmptyPassword) { + ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); + ASSERT_TRUE(slot); + EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr)); + EXPECT_EQ(SECSuccess, PK11_ResetToken(slot.get(), nullptr)); + EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, nullptr)); +} + +TEST_F(SoftokenTest, ResetSoftokenNonEmptyPassword) { + ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); + ASSERT_TRUE(slot); + EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password")); + EXPECT_EQ(SECSuccess, PK11_ResetToken(slot.get(), nullptr)); + EXPECT_EQ(SECSuccess, PK11_InitPin(slot.get(), nullptr, "password2")); +} + +} // namespace nss_test + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/security/nss/gtests/softoken_gtest/softoken_gtest.gyp b/security/nss/gtests/softoken_gtest/softoken_gtest.gyp new file mode 100644 index 000000000000..cff0ea414a7d --- /dev/null +++ b/security/nss/gtests/softoken_gtest/softoken_gtest.gyp @@ -0,0 +1,51 @@ +# 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/. +{ + 'includes': [ + '../../coreconf/config.gypi', + '../common/gtest.gypi', + ], + 'targets': [ + { + 'target_name': 'softoken_gtest', + 'type': 'executable', + 'sources': [ + 'softoken_gtest.cc', + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports', + '<(DEPTH)/lib/util/util.gyp:nssutil3', + '<(DEPTH)/gtests/google_test/google_test.gyp:gtest', + ], + 'conditions': [ + [ 'test_build==1', { + 'dependencies': [ + '<(DEPTH)/lib/nss/nss.gyp:nss_static', + '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static', + '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi', + '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi', + '<(DEPTH)/lib/certdb/certdb.gyp:certdb', + '<(DEPTH)/lib/base/base.gyp:nssb', + '<(DEPTH)/lib/dev/dev.gyp:nssdev', + '<(DEPTH)/lib/pki/pki.gyp:nsspki', + '<(DEPTH)/lib/ssl/ssl.gyp:ssl', + ], + }, { + 'dependencies': [ + '<(DEPTH)/lib/nss/nss.gyp:nss3', + '<(DEPTH)/lib/ssl/ssl.gyp:ssl3', + ], + }], + ], + } + ], + 'target_defaults': { + 'include_dirs': [ + '../../lib/util' + ] + }, + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/gtests/ssl_gtest/manifest.mn b/security/nss/gtests/ssl_gtest/manifest.mn index cc729c0f161a..e7d3e10878f9 100644 --- a/security/nss/gtests/ssl_gtest/manifest.mn +++ b/security/nss/gtests/ssl_gtest/manifest.mn @@ -30,6 +30,7 @@ CPPSRCS = \ ssl_gtest.cc \ ssl_hrr_unittest.cc \ ssl_loopback_unittest.cc \ + ssl_misc_unittest.cc \ ssl_record_unittest.cc \ ssl_resumption_unittest.cc \ ssl_skip_unittest.cc \ diff --git a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc index 85b7011a1cd2..a144161d67b1 100644 --- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc @@ -7,6 +7,7 @@ #include "secerr.h" #include "ssl.h" #include "sslerr.h" +#include "sslexp.h" #include "sslproto.h" extern "C" { diff --git a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp index 8cd7d1009685..9bf147e4f549 100644 --- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp +++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp @@ -31,6 +31,7 @@ 'ssl_gtest.cc', 'ssl_hrr_unittest.cc', 'ssl_loopback_unittest.cc', + 'ssl_misc_unittest.cc', 'ssl_record_unittest.cc', 'ssl_resumption_unittest.cc', 'ssl_skip_unittest.cc', diff --git a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc index 77703dd8efba..d7a21f99db7a 100644 --- a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc @@ -6,10 +6,12 @@ #include #include +#include #include "secerr.h" #include "ssl.h" #include "sslerr.h" #include "sslproto.h" +#include "ssl3prot.h" extern "C" { // This is not something that should make you happy. @@ -323,6 +325,42 @@ TEST_F(TlsConnectStreamTls13, NegotiateShortHeaders) { Connect(); } +TEST_F(TlsConnectStreamTls13, ClientAltHandshakeType) { + client_->SetAltHandshakeTypeEnabled(); + auto filter = std::make_shared(); + server_->SetPacketFilter(filter); + Connect(); + ASSERT_EQ(kTlsHandshakeType, filter->header(0)->content_type()); +} + +TEST_F(TlsConnectStreamTls13, ServerAltHandshakeType) { + server_->SetAltHandshakeTypeEnabled(); + auto filter = std::make_shared(); + server_->SetPacketFilter(filter); + Connect(); + ASSERT_EQ(kTlsHandshakeType, filter->header(0)->content_type()); +} + +TEST_F(TlsConnectStreamTls13, BothAltHandshakeType) { + client_->SetAltHandshakeTypeEnabled(); + server_->SetAltHandshakeTypeEnabled(); + auto header_filter = std::make_shared(); + auto sh_filter = std::make_shared( + kTlsHandshakeServerHello); + std::vector> filters = {header_filter, + sh_filter}; + auto chained = std::make_shared(filters); + server_->SetPacketFilter(chained); + header_filter->SetAgent(server_.get()); + header_filter->EnableDecryption(); + Connect(); + ASSERT_EQ(kTlsAltHandshakeType, header_filter->header(0)->content_type()); + ASSERT_EQ(kTlsHandshakeType, header_filter->header(1)->content_type()); + uint32_t ver; + ASSERT_TRUE(sh_filter->buffer().Read(0, 2, &ver)); + ASSERT_EQ((uint32_t)(0x7a00 | TLS_1_3_DRAFT_VERSION), ver); +} + INSTANTIATE_TEST_CASE_P( GenericStream, TlsConnectGeneric, ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream, diff --git a/security/nss/gtests/ssl_gtest/ssl_misc_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_misc_unittest.cc new file mode 100644 index 000000000000..2b1b92dcd809 --- /dev/null +++ b/security/nss/gtests/ssl_gtest/ssl_misc_unittest.cc @@ -0,0 +1,20 @@ +/* -*- 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 "sslexp.h" + +#include "gtest_utils.h" + +namespace nss_test { + +class MiscTest : public ::testing::Test {}; + +TEST_F(MiscTest, NonExistentExperimentalAPI) { + EXPECT_EQ(nullptr, SSL_GetExperimentalAPI("blah")); + EXPECT_EQ(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API, PORT_GetError()); +} + +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/tls_agent.cc b/security/nss/gtests/ssl_gtest/tls_agent.cc index d6d91f7f7b94..7d76cffb26f0 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.cc +++ b/security/nss/gtests/ssl_gtest/tls_agent.cc @@ -10,6 +10,7 @@ #include "pk11func.h" #include "ssl.h" #include "sslerr.h" +#include "sslexp.h" #include "sslproto.h" #include "tls_parser.h" @@ -414,6 +415,13 @@ void TlsAgent::SetShortHeadersEnabled() { EXPECT_EQ(SECSuccess, rv); } +void TlsAgent::SetAltHandshakeTypeEnabled() { + EXPECT_TRUE(EnsureTlsSetup()); + + SECStatus rv = SSL_UseAltServerHelloType(ssl_fd(), true); + EXPECT_EQ(SECSuccess, rv); +} + void TlsAgent::SetVersionRange(uint16_t minver, uint16_t maxver) { vrange_.min = minver; vrange_.max = maxver; diff --git a/security/nss/gtests/ssl_gtest/tls_agent.h b/security/nss/gtests/ssl_gtest/tls_agent.h index 4bccb9a8498e..2ae10bbd0ac1 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.h +++ b/security/nss/gtests/ssl_gtest/tls_agent.h @@ -127,6 +127,7 @@ class TlsAgent : public PollTarget { void Set0RttEnabled(bool en); void SetFallbackSCSVEnabled(bool en); void SetShortHeadersEnabled(); + void SetAltHandshakeTypeEnabled(); void SetVersionRange(uint16_t minver, uint16_t maxver); void GetVersionRange(uint16_t* minver, uint16_t* maxver); void CheckPreliminaryInfo(); diff --git a/security/nss/gtests/ssl_gtest/tls_connect.cc b/security/nss/gtests/ssl_gtest/tls_connect.cc index c8de5a1fee1e..19ca0929bf2e 100644 --- a/security/nss/gtests/ssl_gtest/tls_connect.cc +++ b/security/nss/gtests/ssl_gtest/tls_connect.cc @@ -5,6 +5,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "tls_connect.h" +#include "sslexp.h" extern "C" { #include "libssl_internals.h" } diff --git a/security/nss/gtests/ssl_gtest/tls_filter.cc b/security/nss/gtests/ssl_gtest/tls_filter.cc index 76d9aaaffcbb..433b9bf7b788 100644 --- a/security/nss/gtests/ssl_gtest/tls_filter.cc +++ b/security/nss/gtests/ssl_gtest/tls_filter.cc @@ -227,7 +227,8 @@ 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) { + if ((record_header.content_type() != kTlsHandshakeType) && + (record_header.content_type() != kTlsAltHandshakeType)) { return KEEP; } @@ -369,6 +370,20 @@ PacketFilter::Action TlsConversationRecorder::FilterRecord( return KEEP; } +PacketFilter::Action TlsHeaderRecorder::FilterRecord( + const TlsRecordHeader& header, const DataBuffer& input, + DataBuffer* output) { + headers_.push_back(header); + return KEEP; +} + +const TlsRecordHeader* TlsHeaderRecorder::header(size_t index) { + if (index > headers_.size() + 1) { + return nullptr; + } + return &headers_[index]; +} + PacketFilter::Action ChainedPacketFilter::Filter(const DataBuffer& input, DataBuffer* output) { DataBuffer in(input); @@ -378,6 +393,7 @@ PacketFilter::Action ChainedPacketFilter::Filter(const DataBuffer& input, if (action == DROP) { return DROP; } + if (action == CHANGE) { in = *output; changed = true; diff --git a/security/nss/gtests/ssl_gtest/tls_filter.h b/security/nss/gtests/ssl_gtest/tls_filter.h index e4030e23f5aa..bb05664a5515 100644 --- a/security/nss/gtests/ssl_gtest/tls_filter.h +++ b/security/nss/gtests/ssl_gtest/tls_filter.h @@ -133,6 +133,7 @@ inline std::ostream& operator<<(std::ostream& stream, TlsRecordHeader& hdr) { stream << "Alert"; break; case kTlsHandshakeType: + case kTlsAltHandshakeType: stream << "Handshake"; break; case kTlsApplicationDataType: @@ -230,7 +231,19 @@ class TlsConversationRecorder : public TlsRecordFilter { DataBuffer* output); private: - DataBuffer& buffer_; + DataBuffer buffer_; +}; + +// Make a copy of the records +class TlsHeaderRecorder : public TlsRecordFilter { + public: + virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, + const DataBuffer& input, + DataBuffer* output); + const TlsRecordHeader* header(size_t index); + + private: + std::vector headers_; }; // Runs multiple packet filters in series. diff --git a/security/nss/lib/certdb/alg1485.c b/security/nss/lib/certdb/alg1485.c index 38b2fe4b51fb..bab23be1c49a 100644 --- a/security/nss/lib/certdb/alg1485.c +++ b/security/nss/lib/certdb/alg1485.c @@ -703,14 +703,19 @@ CERT_GetOidString(const SECItem* oid) return NULL; } + /* If the OID has length 1, we bail. */ + if (oid->len < 2) { + return NULL; + } + /* first will point to the next sequence of bytes to decode */ first = (PRUint8*)oid->data; /* stop points to one past the legitimate data */ stop = &first[oid->len]; /* - * Check for our pseudo-encoded single-digit OIDs - */ + * Check for our pseudo-encoded single-digit OIDs + */ if ((*first == 0x80) && (2 == oid->len)) { /* Funky encoding. The second byte is the number */ rvString = PR_smprintf("%lu", (PRUint32)first[1]); @@ -728,6 +733,10 @@ CERT_GetOidString(const SECItem* oid) break; } } + /* There's no first bit set, so this isn't valid. Bail.*/ + if (last == stop) { + goto unsupported; + } bytesBeforeLast = (unsigned int)(last - first); if (bytesBeforeLast <= 3U) { /* 0-28 bit number */ PRUint32 n = 0; @@ -748,12 +757,12 @@ CERT_GetOidString(const SECItem* oid) CASE(2, 0x7f); CASE(1, 0x7f); case 0: - n |= - last[0] & 0x7f; + n |= last[0] & 0x7f; break; } - if (last[0] & 0x80) + if (last[0] & 0x80) { goto unsupported; + } if (!rvString) { /* This is the first number.. decompose it */ diff --git a/security/nss/lib/freebl/config.mk b/security/nss/lib/freebl/config.mk index 918a66363f47..f15077096598 100644 --- a/security/nss/lib/freebl/config.mk +++ b/security/nss/lib/freebl/config.mk @@ -90,7 +90,12 @@ EXTRA_SHARED_LIBS += \ endif endif +ifeq ($(OS_ARCH), Linux) +CFLAGS += -std=gnu99 +endif + ifeq ($(OS_ARCH), Darwin) +CFLAGS += -std=gnu99 EXTRA_SHARED_LIBS += -dylib_file @executable_path/libplc4.dylib:$(DIST)/lib/libplc4.dylib -dylib_file @executable_path/libplds4.dylib:$(DIST)/lib/libplds4.dylib endif diff --git a/security/nss/lib/freebl/freebl.gyp b/security/nss/lib/freebl/freebl.gyp index 8c0d0dcd5d71..b357fb49ecc7 100644 --- a/security/nss/lib/freebl/freebl.gyp +++ b/security/nss/lib/freebl/freebl.gyp @@ -166,6 +166,7 @@ 'OTHER_CFLAGS': [ '-mpclmul', '-maes', + '-std=gnu99', ], }, }], @@ -232,6 +233,9 @@ 'FREEBL_LOWHASH', 'FREEBL_NO_DEPEND', ], + 'cflags': [ + '-std=gnu99', + ], }], [ 'OS=="linux" or OS=="android"', { 'conditions': [ diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index 61c50054e270..000d8d943207 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -22,12 +22,12 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define NSS_VERSION "3.32" _NSS_CUSTOMIZED +#define NSS_VERSION "3.33" _NSS_CUSTOMIZED " Beta" #define NSS_VMAJOR 3 -#define NSS_VMINOR 32 +#define NSS_VMINOR 33 #define NSS_VPATCH 0 #define NSS_VBUILD 0 -#define NSS_BETA PR_FALSE +#define NSS_BETA PR_TRUE #ifndef RC_INVOKED diff --git a/security/nss/lib/pki/pki3hack.c b/security/nss/lib/pki/pki3hack.c index 548853970b1c..fb3110a233ed 100644 --- a/security/nss/lib/pki/pki3hack.c +++ b/security/nss/lib/pki/pki3hack.c @@ -180,16 +180,18 @@ STAN_RemoveModuleFromDefaultTrustDomain( NSSTrustDomain *td; int i; td = STAN_GetDefaultTrustDomain(); - NSSRWLock_LockWrite(td->tokensLock); for (i = 0; i < module->slotCount; i++) { token = PK11Slot_GetNSSToken(module->slots[i]); if (token) { nssToken_NotifyCertsNotVisible(token); + NSSRWLock_LockWrite(td->tokensLock); nssList_Remove(td->tokenList, token); + NSSRWLock_UnlockWrite(td->tokensLock); PK11Slot_SetNSSToken(module->slots[i], NULL); nssToken_Destroy(token); } } + NSSRWLock_LockWrite(td->tokensLock); nssListIterator_Destroy(td->tokens); td->tokens = nssList_CreateIterator(td->tokenList); NSSRWLock_UnlockWrite(td->tokensLock); diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index a594fd501bd8..4e940990e9cd 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -3566,7 +3566,6 @@ NSC_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin, { SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); SFTKDBHandle *handle; - SFTKDBHandle *certHandle; SECStatus rv; unsigned int i; SFTKObject *object; @@ -3614,19 +3613,16 @@ NSC_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin, } rv = sftkdb_ResetKeyDB(handle); + /* clear the password */ + sftkdb_ClearPassword(handle); + /* update slot->needLogin (should be true now since no password is set) */ + sftk_checkNeedLogin(slot, handle); sftk_freeDB(handle); if (rv != SECSuccess) { return CKR_DEVICE_ERROR; } - /* finally mark all the user certs as non-user certs */ - certHandle = sftk_getCertDB(slot); - if (certHandle == NULL) - return CKR_OK; - - sftk_freeDB(certHandle); - - return CKR_OK; /*is this the right function for not implemented*/ + return CKR_OK; } /* NSC_InitPIN initializes the normal user's PIN. */ diff --git a/security/nss/lib/softoken/sdb.c b/security/nss/lib/softoken/sdb.c index 8690df34ca02..57337e3342ae 100644 --- a/security/nss/lib/softoken/sdb.c +++ b/security/nss/lib/softoken/sdb.c @@ -1600,7 +1600,7 @@ loser: return error; } -static const char RESET_CMD[] = "DROP TABLE IF EXISTS %s;"; +static const char RESET_CMD[] = "DELETE FROM %s;"; CK_RV sdb_Reset(SDB *sdb) { @@ -1621,17 +1621,19 @@ sdb_Reset(SDB *sdb) goto loser; } - /* delete the key table */ - newStr = sqlite3_mprintf(RESET_CMD, sdb_p->table); - if (newStr == NULL) { - error = CKR_HOST_MEMORY; - goto loser; - } - sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); - sqlite3_free(newStr); + if (tableExists(sqlDB, sdb_p->table)) { + /* delete the contents of the key table */ + newStr = sqlite3_mprintf(RESET_CMD, sdb_p->table); + if (newStr == NULL) { + error = CKR_HOST_MEMORY; + goto loser; + } + sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); + sqlite3_free(newStr); - if (sqlerr != SQLITE_OK) - goto loser; + if (sqlerr != SQLITE_OK) + goto loser; + } /* delete the password entry table */ sqlerr = sqlite3_exec(sqlDB, "DROP TABLE IF EXISTS metaData;", @@ -1866,30 +1868,29 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate, * so we use it for the cache (see sdb_buildCache for how it's done).*/ /* - * we decide whether or not to use the cache based on the following input. - * - * NSS_SDB_USE_CACHE environment variable is non-existant or set to - * anything other than "no" or "yes" ("auto", for instance). - * This is the normal case. NSS will measure the performance of access - * to the temp database versus the access to the users passed in - * database location. If the temp database location is "significantly" - * faster we will use the cache. - * - * NSS_SDB_USE_CACHE environment variable is set to "no": cache will not - * be used. - * - * NSS_SDB_USE_CACHE environment variable is set to "yes": cache will - * always be used. - * - * It is expected that most applications would use the "auto" selection, - * the environment variable is primarily to simplify testing, and to - * correct potential corner cases where */ + * we decide whether or not to use the cache based on the following input. + * + * NSS_SDB_USE_CACHE environment variable is set to anything other than + * "yes" or "no" (for instance, "auto"): NSS will measure the performance + * of access to the temp database versus the access to the user's + * passed-in database location. If the temp database location is + * "significantly" faster we will use the cache. + * + * NSS_SDB_USE_CACHE environment variable is nonexistent or set to "no": + * cache will not be used. + * + * NSS_SDB_USE_CACHE environment variable is set to "yes": cache will + * always be used. + * + * It is expected that most applications will not need this feature, and + * thus it is disabled by default. + */ env = PR_GetEnvSecure("NSS_SDB_USE_CACHE"); - if (env && PORT_Strcasecmp(env, "no") == 0) { + if (!env || PORT_Strcasecmp(env, "no") == 0) { enableCache = PR_FALSE; - } else if (env && PORT_Strcasecmp(env, "yes") == 0) { + } else if (PORT_Strcasecmp(env, "yes") == 0) { enableCache = PR_TRUE; } else { char *tempDir = NULL; @@ -2035,10 +2036,11 @@ s_open(const char *directory, const char *certPrefix, const char *keyPrefix, { char *env; env = PR_GetEnvSecure("NSS_SDB_USE_CACHE"); - /* If the environment variable is set to yes or no, sdb_init() will - * ignore the value of accessOps, and we can skip the measuring.*/ - if (!env || ((PORT_Strcasecmp(env, "no") != 0) && - (PORT_Strcasecmp(env, "yes") != 0))) { + /* If the environment variable is undefined or set to yes or no, + * sdb_init() will ignore the value of accessOps, and we can skip the + * measuring.*/ + if (env && PORT_Strcasecmp(env, "no") != 0 && + PORT_Strcasecmp(env, "yes") != 0) { accessOps = sdb_measureAccess(directory); } } diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h index bfc16afb227b..7e2ab84d1a96 100644 --- a/security/nss/lib/softoken/softkver.h +++ b/security/nss/lib/softoken/softkver.h @@ -21,11 +21,11 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define SOFTOKEN_VERSION "3.32" SOFTOKEN_ECC_STRING +#define SOFTOKEN_VERSION "3.33" SOFTOKEN_ECC_STRING " Beta" #define SOFTOKEN_VMAJOR 3 -#define SOFTOKEN_VMINOR 32 +#define SOFTOKEN_VMINOR 33 #define SOFTOKEN_VPATCH 0 #define SOFTOKEN_VBUILD 0 -#define SOFTOKEN_BETA PR_FALSE +#define SOFTOKEN_BETA PR_TRUE #endif /* _SOFTKVER_H_ */ diff --git a/security/nss/lib/ssl/SSLerrs.h b/security/nss/lib/ssl/SSLerrs.h index b73fb6bd04b3..db8e5e69b2fe 100644 --- a/security/nss/lib/ssl/SSLerrs.h +++ b/security/nss/lib/ssl/SSLerrs.h @@ -511,3 +511,12 @@ ER3(SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA, (SSL_ERROR_BASE + 160), ER3(SSL_ERROR_TOO_MUCH_EARLY_DATA, (SSL_ERROR_BASE + 161), "SSL received more early data than permitted.") + +ER3(SSL_ERROR_RX_UNEXPECTED_END_OF_EARLY_DATA, (SSL_ERROR_BASE + 162), + "SSL received an unexpected End of Early Data message.") + +ER3(SSL_ERROR_RX_MALFORMED_END_OF_EARLY_DATA, (SSL_ERROR_BASE + 163), + "SSL received a malformed End of Early Data message.") + +ER3(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API, (SSL_ERROR_BASE + 164), + "An experimental API was called, but not supported.") diff --git a/security/nss/lib/ssl/exports.gyp b/security/nss/lib/ssl/exports.gyp index e2123af84c2b..c3b34c6cc307 100644 --- a/security/nss/lib/ssl/exports.gyp +++ b/security/nss/lib/ssl/exports.gyp @@ -15,6 +15,7 @@ 'preenc.h', 'ssl.h', 'sslerr.h', + 'sslexp.h', 'sslproto.h', 'sslt.h' ], diff --git a/security/nss/lib/ssl/manifest.mn b/security/nss/lib/ssl/manifest.mn index fbb88baffa52..4c42e7e3779f 100644 --- a/security/nss/lib/ssl/manifest.mn +++ b/security/nss/lib/ssl/manifest.mn @@ -10,6 +10,7 @@ EXPORTS = \ ssl.h \ sslt.h \ sslerr.h \ + sslexp.h \ sslproto.h \ preenc.h \ $(NULL) diff --git a/security/nss/lib/ssl/ssl.def b/security/nss/lib/ssl/ssl.def index 94d3042239df..9a447dbefa83 100644 --- a/security/nss/lib/ssl/ssl.def +++ b/security/nss/lib/ssl/ssl.def @@ -234,3 +234,9 @@ SSL_AlertSentCallback; ;+ local: ;+*; ;+}; +;+NSS_3.33 { # NSS 3.33 release +;+ global: +SSL_GetExperimentalAPI; +;+ local: +;+*; +;+}; diff --git a/security/nss/lib/ssl/ssl.h b/security/nss/lib/ssl/ssl.h index 7e538ac1fce2..20244f59b8e7 100644 --- a/security/nss/lib/ssl/ssl.h +++ b/security/nss/lib/ssl/ssl.h @@ -1374,6 +1374,13 @@ extern const char *NSSSSL_GetVersion(void); */ SSL_IMPORT SECStatus SSL_AuthCertificateComplete(PRFileDesc *fd, PRErrorCode error); + +/* + * This is used to access experimental APIs. Don't call this directly. This is + * used to enable the experimental APIs that are defined in "sslexp.h". + */ +SSL_IMPORT void *SSL_GetExperimentalAPI(const char *name); + SEC_END_PROTOS #endif /* __ssl_h_ */ diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 686ac55140e2..c616e2a961bf 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -1090,7 +1090,8 @@ ssl_ClientReadVersion(sslSocket *ss, PRUint8 **b, unsigned int *len, PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION); return SECFailure; } - if (temp == tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3)) { + if (temp == tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3) || (ss->opt.enableAltHandshaketype && + (temp == tls13_EncodeAltDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3)))) { v = SSL_LIBRARY_VERSION_TLS_1_3; } else { v = (SSL3ProtocolVersion)temp; @@ -2977,6 +2978,7 @@ ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags) ssl_SEND_FLAG_CAP_RECORD_VERSION; PRInt32 count = -1; SECStatus rv; + SSL3ContentType ct = content_handshake; PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); @@ -2990,7 +2992,12 @@ ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags) PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - count = ssl3_SendRecord(ss, NULL, content_handshake, + /* Maybe send the first message with alt handshake type. */ + if (ss->ssl3.hs.altHandshakeType) { + ct = content_alt_handshake; + ss->ssl3.hs.altHandshakeType = PR_FALSE; + } + count = ssl3_SendRecord(ss, NULL, ct, ss->sec.ci.sendBuf.buf, ss->sec.ci.sendBuf.len, flags); if (count < 0) { @@ -9321,7 +9328,7 @@ ssl3_SendServerHello(sslSocket *ss) if (IS_DTLS(ss) && ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { version = dtls_TLSVersionToDTLSVersion(ss->version); } else { - version = tls13_EncodeDraftVersion(ss->version); + version = ss->ssl3.hs.altHandshakeType ? tls13_EncodeAltDraftVersion(ss->version) : tls13_EncodeDraftVersion(ss->version); } rv = ssl3_AppendHandshakeNumber(ss, version, 2); @@ -9752,13 +9759,12 @@ ssl3_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length, hashAlg = ssl_SignatureSchemeToHashType(sigScheme); - if (hashes->u.pointer_to_hash_input.data) { - rv = ssl3_ComputeHandshakeHash(hashes->u.pointer_to_hash_input.data, - hashes->u.pointer_to_hash_input.len, - hashAlg, &localHashes); - } else { - rv = SECFailure; - } + /* Read from the message buffer, but we need to use only up to the end + * of the previous handshake message. The length of the transcript up to + * that point is saved in |hashes->u.transcriptLen|. */ + rv = ssl3_ComputeHandshakeHash(ss->ssl3.hs.messages.buf, + hashes->u.transcriptLen, + hashAlg, &localHashes); if (rv == SECSuccess) { hashesForVerify = &localHashes; @@ -11658,15 +11664,15 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, * additional handshake messages will have been added to the * buffer, e.g. the certificate_verify message itself.) * - * Therefore, we use SSL3Hashes.u.pointer_to_hash_input - * to signal the current state of the buffer. + * Therefore, we use SSL3Hashes.u.transcriptLen to save how much + * data there is and read directly from ss->ssl3.hs.messages + * when calculating the hashes. * * ssl3_HandleCertificateVerify will detect * hashType == handshake_hash_record * and use that information to calculate the hash. */ - hashes.u.pointer_to_hash_input.data = ss->ssl3.hs.messages.buf; - hashes.u.pointer_to_hash_input.len = ss->ssl3.hs.messages.len; + hashes.u.transcriptLen = ss->ssl3.hs.messages.len; hashesPtr = &hashes; } else { computeHashes = PR_TRUE; @@ -12729,6 +12735,14 @@ process_it: */ ssl_GetSSL3HandshakeLock(ss); + /* Special case: allow alt content type for TLS 1.3 ServerHello. */ + if ((rType == content_alt_handshake) && + (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3) && + (ss->ssl3.hs.ws == wait_server_hello) && + (ss->opt.enableAltHandshaketype) && + (!IS_DTLS(ss))) { + rType = content_handshake; + } /* All the functions called in this switch MUST set error code if ** they return SECFailure or SECWouldBlock. */ diff --git a/security/nss/lib/ssl/ssl3prot.h b/security/nss/lib/ssl/ssl3prot.h index dede24438d1b..97487ca6718b 100644 --- a/security/nss/lib/ssl/ssl3prot.h +++ b/security/nss/lib/ssl/ssl3prot.h @@ -41,7 +41,8 @@ typedef enum { content_change_cipher_spec = 20, content_alert = 21, content_handshake = 22, - content_application_data = 23 + content_application_data = 23, + content_alt_handshake = 24 } SSL3ContentType; typedef struct { @@ -235,7 +236,7 @@ typedef struct { union { PRUint8 raw[64]; SSL3HashesIndividually s; - SECItem pointer_to_hash_input; + unsigned int transcriptLen; } u; } SSL3Hashes; diff --git a/security/nss/lib/ssl/sslerr.h b/security/nss/lib/ssl/sslerr.h index 865077cda6fe..0db576bce6ec 100644 --- a/security/nss/lib/ssl/sslerr.h +++ b/security/nss/lib/ssl/sslerr.h @@ -246,6 +246,11 @@ typedef enum { SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES = (SSL_ERROR_BASE + 159), SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA = (SSL_ERROR_BASE + 160), SSL_ERROR_TOO_MUCH_EARLY_DATA = (SSL_ERROR_BASE + 161), + SSL_ERROR_RX_UNEXPECTED_END_OF_EARLY_DATA = (SSL_ERROR_BASE + 162), + SSL_ERROR_RX_MALFORMED_END_OF_EARLY_DATA = (SSL_ERROR_BASE + 163), + + SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API = (SSL_ERROR_BASE + 164), + SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ } SSLErrorCodes; #endif /* NO_SECURITY_ERROR_ENUM */ diff --git a/security/nss/lib/ssl/sslexp.h b/security/nss/lib/ssl/sslexp.h new file mode 100644 index 000000000000..eee60280a4ad --- /dev/null +++ b/security/nss/lib/ssl/sslexp.h @@ -0,0 +1,37 @@ +/* + * This file contains prototypes for experimental SSL functions. + * + * 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/. */ + +#ifndef __sslexp_h_ +#define __sslexp_h_ + +#include "ssl.h" +#include "sslerr.h" + +SEC_BEGIN_PROTOS + +/* The functions in this header file are not guaranteed to remain available in + * future NSS versions. Code that uses these functions needs to safeguard + * against the function not being available. */ + +#define SSL_EXPERIMENTAL_API(name, arglist, args) \ + (SSL_GetExperimentalAPI(name) \ + ? ((SECStatus(*) arglist)SSL_GetExperimentalAPI(name))args \ + : SECFailure) + +/* Allow the ServerHello to be record type 24. Experiment to test: + * https://github.com/tlswg/tls13-spec/pull/1051 + * This will either become part of the standard or be disabled + * after we have tested it. + */ +#define SSL_UseAltServerHelloType(fd, enable) \ + SSL_EXPERIMENTAL_API("SSL_UseAltServerHelloType", \ + (PRFileDesc * _fd, PRBool _enable), \ + (fd, enable)) + +SEC_END_PROTOS + +#endif /* __sslexp_h_ */ diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index 64694b0df9e9..0ffaa3a6a64f 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -298,6 +298,7 @@ typedef struct sslOptionsStr { unsigned int requireDHENamedGroups : 1; unsigned int enable0RttData : 1; unsigned int enableShortHeaders : 1; + unsigned int enableAltHandshaketype : 1; } sslOptions; typedef enum { sslHandshakingUndetermined = 0, @@ -883,6 +884,7 @@ typedef struct SSL3HandshakeStateStr { ssl3KEADef kea_def_mutable; /* Used to hold the writable kea_def * we use for TLS 1.3 */ PRBool shortHeaders; /* Assigned if we are doing short headers. */ + PRBool altHandshakeType; /* Assigned if we are doing the wrapped handshake. */ } SSL3HandshakeState; /* diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index 99828c85b19b..9a7880c493d9 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -11,6 +11,7 @@ #include "cert.h" #include "keyhi.h" #include "ssl.h" +#include "sslexp.h" #include "sslimpl.h" #include "sslproto.h" #include "nspr.h" @@ -80,10 +81,11 @@ static sslOptions ssl_defaults = { PR_FALSE, /* requireDHENamedGroups */ PR_FALSE, /* enable0RttData */ #ifdef NSS_ENABLE_TLS13_SHORT_HEADERS - PR_TRUE /* enableShortHeaders */ + PR_TRUE, /* enableShortHeaders */ #else - PR_FALSE /* enableShortHeaders */ + PR_FALSE, /* enableShortHeaders */ #endif + PR_FALSE /* enableAltHandshaketype */ }; /* @@ -2214,7 +2216,7 @@ ssl3_GetEffectiveVersionPolicy(SSLProtocolVariant variant, return SECSuccess; } -/* +/* * Assumes that rangeParam values are within the supported boundaries, * but should contain all potentially allowed versions, even if they contain * conflicting versions. @@ -3840,3 +3842,48 @@ SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey, *pcanbypass = PR_FALSE; return SECSuccess; } + +/* Functions that are truly experimental use EXP, functions that are no longer + * experimental use PUB. + * + * When initially defining a new API, add that API here using the EXP() macro + * and name the function with a SSLExp_ prefix. Define the experimental API as + * a macro in sslexp.h using the SSL_EXPERIMENTAL_API() macro defined there. + * + * Once an API is stable and proven, move the macro definition in sslexp.h to a + * proper function declaration in ssl.h. Keeping the function in this list + * ensures that code built against the release that contained the experimental + * API will continue to work; use PUB() to reference the public function. + */ +#define EXP(n) \ + { \ + "SSL_" #n, SSLExp_##n \ + } +#define PUB(n) \ + { \ + "SSL_" #n, SSL_##n \ + } +struct { + const char *const name; + void *function; +} ssl_experimental_functions[] = { +#ifndef SSL_DISABLE_EXPERIMENTAL_API + EXP(UseAltServerHelloType), +#endif + { "", NULL } +}; +#undef EXP +#undef PUB + +void * +SSL_GetExperimentalAPI(const char *name) +{ + unsigned int i; + for (i = 0; i < PR_ARRAY_SIZE(ssl_experimental_functions); ++i) { + if (strcmp(name, ssl_experimental_functions[i].name) == 0) { + return ssl_experimental_functions[i].function; + } + } + PORT_SetError(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API); + return NULL; +} diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c index 560493848b4f..fff6f71f4e8a 100644 --- a/security/nss/lib/ssl/tls13con.c +++ b/security/nss/lib/ssl/tls13con.c @@ -4475,6 +4475,17 @@ tls13_EncodeDraftVersion(SSL3ProtocolVersion version) return (PRUint16)version; } +PRUint16 +tls13_EncodeAltDraftVersion(SSL3ProtocolVersion version) +{ +#ifdef TLS_1_3_DRAFT_VERSION + if (version == SSL_LIBRARY_VERSION_TLS_1_3) { + return 0x7a00 | TLS_1_3_DRAFT_VERSION; + } +#endif + return (PRUint16)version; +} + /* Pick the highest version we support that is also advertised. */ SECStatus tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supported_versions) @@ -4496,6 +4507,7 @@ tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supported_versions) } for (version = ss->vrange.max; version >= ss->vrange.min; --version) { PRUint16 wire = tls13_EncodeDraftVersion(version); + PRUint16 alt_wire = tls13_EncodeAltDraftVersion(version); unsigned long offset; for (offset = 0; offset < versions.len; offset += 2) { @@ -4505,9 +4517,33 @@ tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supported_versions) ss->version = version; return SECSuccess; } + if (ss->opt.enableAltHandshaketype && !IS_DTLS(ss) && + supported == alt_wire) { + ss->version = version; + ss->ssl3.hs.altHandshakeType = PR_TRUE; + return SECSuccess; + } } } FATAL_ERROR(ss, SSL_ERROR_UNSUPPORTED_VERSION, protocol_version); return SECFailure; } + +SECStatus +SSLExp_UseAltServerHelloType(PRFileDesc *fd, PRBool enable) +{ + sslSocket *ss; + + ss = ssl_FindSocket(fd); + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSLExp_UseAltServerHelloType", + SSL_GETPID(), fd)); + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + ss->opt.enableAltHandshaketype = enable; + + return SECSuccess; +} diff --git a/security/nss/lib/ssl/tls13con.h b/security/nss/lib/ssl/tls13con.h index 92eb545b0004..899b4490de1e 100644 --- a/security/nss/lib/ssl/tls13con.h +++ b/security/nss/lib/ssl/tls13con.h @@ -81,9 +81,10 @@ SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss); SECStatus tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf); PRBool tls13_ClientAllow0Rtt(const sslSocket *ss, const sslSessionID *sid); PRUint16 tls13_EncodeDraftVersion(SSL3ProtocolVersion version); -PRUint16 tls13_DecodeDraftVersion(PRUint16 version); +PRUint16 tls13_EncodeAltDraftVersion(SSL3ProtocolVersion version); SECStatus tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supported_versions); SECStatus tls13_SendNewSessionTicket(sslSocket *ss); +SECStatus SSLExp_UseAltServerHelloType(PRFileDesc *fd, PRBool enable); #endif /* __tls13con_h_ */ diff --git a/security/nss/lib/ssl/tls13exthandle.c b/security/nss/lib/ssl/tls13exthandle.c index c2ce390fff8a..c7466be81675 100644 --- a/security/nss/lib/ssl/tls13exthandle.c +++ b/security/nss/lib/ssl/tls13exthandle.c @@ -896,6 +896,10 @@ tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnD extensions_len = 2 + 2 + 1 + 2 * (ss->vrange.max - ss->vrange.min + 1); + if (ss->opt.enableAltHandshaketype && !IS_DTLS(ss)) { + extensions_len += 2; + } + if (maxBytes < (PRUint32)extensions_len) { PORT_Assert(0); return 0; @@ -914,6 +918,15 @@ tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnD if (rv != SECSuccess) return -1; + if (ss->opt.enableAltHandshaketype && !IS_DTLS(ss)) { + rv = ssl3_ExtAppendHandshakeNumber( + ss, tls13_EncodeAltDraftVersion( + SSL_LIBRARY_VERSION_TLS_1_3), + 2); + if (rv != SECSuccess) + return -1; + } + for (version = ss->vrange.max; version >= ss->vrange.min; --version) { rv = ssl3_ExtAppendHandshakeNumber( ss, tls13_EncodeDraftVersion(version), 2); diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h index 5d7f22f35891..921a31276756 100644 --- a/security/nss/lib/util/nssutil.h +++ b/security/nss/lib/util/nssutil.h @@ -19,12 +19,12 @@ * The format of the version string should be * ".[.[.]][ ]" */ -#define NSSUTIL_VERSION "3.32" +#define NSSUTIL_VERSION "3.33 Beta" #define NSSUTIL_VMAJOR 3 -#define NSSUTIL_VMINOR 32 +#define NSSUTIL_VMINOR 33 #define NSSUTIL_VPATCH 0 #define NSSUTIL_VBUILD 0 -#define NSSUTIL_BETA PR_FALSE +#define NSSUTIL_BETA PR_TRUE SEC_BEGIN_PROTOS diff --git a/security/nss/lib/util/secoid.c b/security/nss/lib/util/secoid.c index da03b7c06e81..a05621c59e5a 100644 --- a/security/nss/lib/util/secoid.c +++ b/security/nss/lib/util/secoid.c @@ -1841,13 +1841,11 @@ secoid_FindDynamic(const SECItem *key) { SECOidData *ret = NULL; + NSSRWLock_LockRead(dynOidLock); if (dynOidHash) { - NSSRWLock_LockRead(dynOidLock); - if (dynOidHash) { /* must check it again with lock held. */ - ret = (SECOidData *)PL_HashTableLookup(dynOidHash, key); - } - NSSRWLock_UnlockRead(dynOidLock); + ret = (SECOidData *)PL_HashTableLookup(dynOidHash, key); } + NSSRWLock_UnlockRead(dynOidLock); if (ret == NULL) { PORT_SetError(SEC_ERROR_UNRECOGNIZED_OID); } @@ -1866,14 +1864,12 @@ secoid_FindDynamicByTag(SECOidTag tagnum) } tagNumDiff = tagnum - SEC_OID_TOTAL; - if (dynOidTable) { - NSSRWLock_LockRead(dynOidLock); - if (dynOidTable != NULL && /* must check it again with lock held. */ - tagNumDiff < dynOidEntriesUsed) { - dxo = dynOidTable[tagNumDiff]; - } - NSSRWLock_UnlockRead(dynOidLock); + NSSRWLock_LockRead(dynOidLock); + if (dynOidTable != NULL && + tagNumDiff < dynOidEntriesUsed) { + dxo = dynOidTable[tagNumDiff]; } + NSSRWLock_UnlockRead(dynOidLock); if (dxo == NULL) { PORT_SetError(SEC_ERROR_UNRECOGNIZED_OID); } diff --git a/security/nss/mach b/security/nss/mach index 22546d732b59..3592299e607b 100755 --- a/security/nss/mach +++ b/security/nss/mach @@ -20,12 +20,16 @@ cwd = os.path.dirname(os.path.abspath(__file__)) class cfAction(argparse.Action): docker_command = ["docker"] + restorecon = None def __call__(self, parser, args, values, option_string=None): if "noroot" not in values: self.setDockerCommand() else: values.remove("noroot") + files = [os.path.join('/home/worker/nss', + os.path.relpath(os.path.abspath(x), start=cwd)) + for x in values] # First check if we can run docker. try: @@ -55,10 +59,12 @@ class cfAction(argparse.Action): self.buildImage(docker_image, cf_docker_folder) command = self.docker_command + [ - 'run', '-v', cwd + ':/home/worker/nss', '--rm', '-ti', docker_image + 'run', '-v', cwd + ':/home/worker/nss:Z', '--rm', '-ti', docker_image ] # The clang format script returns 1 if something's to do. We don't care. - subprocess.call(command + values) + subprocess.call(command + files) + if self.restorecon is not None: + subprocess.call([self.restorecon, '-R', cwd]) def filesChanged(self, path): hash = sha256() @@ -87,6 +93,8 @@ class cfAction(argparse.Action): def setDockerCommand(self): if platform.system() == "Linux": + from distutils.spawn import find_executable + self.restorecon = find_executable('restorecon') self.docker_command = ["sudo"] + self.docker_command @@ -114,6 +122,13 @@ class testAction(argparse.Action): self.runTest(values) +class commandsAction(argparse.Action): + commands = [] + def __call__(self, parser, args, values, option_string=None): + for c in commandsAction.commands: + print(c) + + def parse_arguments(): parser = argparse.ArgumentParser( description='NSS helper script. ' + @@ -143,6 +158,16 @@ def parse_arguments(): ] parser_test.add_argument( 'test', choices=tests, help="Available tests", action=testAction) + + parser_commands = subparsers.add_parser( + 'mach-commands', + help="list commands") + parser_commands.add_argument( + 'mach-commands', + nargs='*', + action=commandsAction) + + commandsAction.commands = [c for c in subparsers.choices] return parser.parse_args() diff --git a/security/nss/nss.gyp b/security/nss/nss.gyp index e62d28449d8b..1727dbe0b966 100644 --- a/security/nss/nss.gyp +++ b/security/nss/nss.gyp @@ -168,6 +168,7 @@ 'gtests/certdb_gtest/certdb_gtest.gyp:certdb_gtest', 'gtests/freebl_gtest/freebl_gtest.gyp:prng_gtest', 'gtests/pk11_gtest/pk11_gtest.gyp:pk11_gtest', + 'gtests/softoken_gtest/softoken_gtest.gyp:softoken_gtest', 'gtests/ssl_gtest/ssl_gtest.gyp:ssl_gtest', 'gtests/util_gtest/util_gtest.gyp:util_gtest', 'gtests/nss_bogo_shim/nss_bogo_shim.gyp:nss_bogo_shim', diff --git a/security/nss/tests/gtests/gtests.sh b/security/nss/tests/gtests/gtests.sh index c785241c4e16..6de1ee4b72de 100755 --- a/security/nss/tests/gtests/gtests.sh +++ b/security/nss/tests/gtests/gtests.sh @@ -83,7 +83,7 @@ gtest_cleanup() } ################## main ################################################# -GTESTS="prng_gtest certhigh_gtest certdb_gtest der_gtest pk11_gtest util_gtest freebl_gtest" +GTESTS="prng_gtest certhigh_gtest certdb_gtest der_gtest pk11_gtest util_gtest freebl_gtest softoken_gtest" SOURCE_DIR="$PWD"/../.. gtest_init $0 gtest_start