commit 90469d9da14828335fdf050657b5ab0742a220cf
parent 45119548c9489da1bffbcfff635a849d079b699f
Author: John M. Schanck <jschanck@mozilla.com>
Date: Wed, 3 Dec 2025 23:31:09 +0000
Bug 2000871 - upgrade NSS to NSS_3_119_BETA1. r=nss-reviewers,keeler UPGRADE_NSS_RELEASE
Differential Revision: https://phabricator.services.mozilla.com/D275007
Diffstat:
18 files changed, 162 insertions(+), 45 deletions(-)
diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO
@@ -1 +1 @@
-NSS_3_117_RTM
-\ No newline at end of file
+NSS_3_119_BETA1
+\ No newline at end of file
diff --git a/security/nss/automation/ossfuzz/build.sh b/security/nss/automation/ossfuzz/build.sh
@@ -9,9 +9,6 @@
# List of targets disabled for oss-fuzz.
declare -A disabled=()
-# List of targets we want to fuzz in TLS and non-TLS mode.
-declare -A tls_targets=([tls-client]=1 [tls-server]=1 [dtls-client]=1 [dtls-server]=1)
-
# Helper function that copies a fuzzer binary and its seed corpus.
copy_fuzzer()
{
@@ -38,7 +35,7 @@ CXX="$CXX -stdlib=libc++" LDFLAGS="$CFLAGS" \
for fuzzer in $(find ../dist/Debug/bin -name "nssfuzz-*" -printf "%f\n"); do
name=${fuzzer:8}
if [ -z "${disabled[$name]:-}" ]; then
- [ -n "${tls_targets[$name]:-}" ] && name="${name}-no_fuzzer_mode"
+ [ -f "fuzz/options/${name}-no_fuzzer_mode.options" ] && name="${name}-no_fuzzer_mode"
copy_fuzzer $fuzzer $name
fi
done
@@ -56,13 +53,16 @@ if [ -d "$SRC/nss-corpus/cryptofuzz" ]; then
zip $OUT/cryptofuzz_seed_corpus.zip $SRC/nss-corpus/cryptofuzz/*
fi
+# TLS Fuzzing mode: Totally Lacking Security
+# This mode disables a lot of cryptography to help the fuzzer.
+# It was originally used for the TLS-specific fuzzers but has been generalized.
# Build the library again (TLS fuzzing mode).
CXX="$CXX -stdlib=libc++" LDFLAGS="$CFLAGS" \
./build.sh -c -v --fuzz=oss --fuzz=tls --disable-tests
-# Copy dual mode targets in TLS mode.
-for name in "${!tls_targets[@]}"; do
- if [ -z "${disabled[$name]:-}" ]; then
- copy_fuzzer nssfuzz-$name $name
+for fuzzer in $(find ../dist/Debug/bin -name "nssfuzz-*" -printf "%f\n"); do
+ name=${fuzzer:8}
+ if [ -z "${disabled[$name]:-}" ] && [ -f "fuzz/options/${name}-no_fuzzer_mode.options" ]; then
+ copy_fuzzer "$fuzzer" "$name"
fi
done
diff --git a/security/nss/automation/taskcluster/scripts/build_cryptofuzz.sh b/security/nss/automation/taskcluster/scripts/build_cryptofuzz.sh
@@ -3,11 +3,15 @@
# NOTE: This file is used to build Cryptofuzz both on CI and OSS-Fuzz.
#
+set -e
+set -x
+set -o pipefail
+
# Do differential fuzzing with Botan (and not OpenSSL) since NSS has
# symbol collisions with OpenSSL and therefore they can't be used together
# in Cryptofuzz.
-export CRYPTOFUZZ_VERSION="687d3064c5cef2b0fe1f30824065a2f2c9c0bbd8"
-export BOTAN_VERSION="3.6.1"
+export CRYPTOFUZZ_VERSION="3d2377257129fc5da6effb92b0736e31db147dee"
+export BOTAN_VERSION="3.10.0"
git clone -q https://github.com/MozillaSecurity/cryptofuzz.git
git -C cryptofuzz checkout "$CRYPTOFUZZ_VERSION"
diff --git a/security/nss/cmd/rsaperf/rsaperf.c b/security/nss/cmd/rsaperf/rsaperf.c
@@ -343,7 +343,6 @@ main(int argc, char **argv)
int threadNum = DEFAULT_THREADS;
ThreadRunData **runDataArr = NULL;
PRThread **threadsArr = NULL;
- int calcThreads = 0;
progName = strrchr(argv[0], '/');
if (!progName)
@@ -651,14 +650,12 @@ main(int argc, char **argv)
0);
}
iters = 0;
- calcThreads = 0;
- for (i = 0; i < threadNum; i++, calcThreads++) {
+ for (i = 0; i < threadNum; i++) {
PR_JoinThread(threadsArr[i]);
if (runDataArr[i]->status != SECSuccess) {
const char *errStr = SECU_Strerror(runDataArr[i]->errNum);
fprintf(stderr, "Thread %d: Error in RSA operation: %d : %s\n",
i, runDataArr[i]->errNum, errStr);
- calcThreads -= 1;
} else {
iters += runDataArr[i]->iterRes;
}
diff --git a/security/nss/coreconf/Darwin.mk b/security/nss/coreconf/Darwin.mk
@@ -18,25 +18,26 @@ ifndef CPU_ARCH
CPU_ARCH := $(shell uname -p)
endif
-ifeq (,$(filter-out i%86,$(CPU_ARCH)))
-ifdef USE_64
+ifeq (x86_64,$(CPU_ARCH))
CC += -arch x86_64
CCC += -arch x86_64
override CPU_ARCH = x86_64
-else
+else ifeq (i386,$(CPU_ARCH))
OS_REL_CFLAGS = -Di386
CC += -arch i386
CCC += -arch i386
override CPU_ARCH = x86
-endif
-else
-ifeq (arm,$(CPU_ARCH))
-# Nothing set for arm currently.
-else
+else ifeq (,$(filter-out aarch64 arm,$(CPU_ARCH)))
+CC += -arch arm64
+CCC += -arch arm64
+override CPU_ARCH = aarch64
+else ifeq (powerpc,$(CPU_ARCH))
OS_REL_CFLAGS = -Dppc
CC += -arch ppc
CCC += -arch ppc
-endif
+override CPU_ARCH = ppc
+else
+ $(error Unknown CPU architecture)
endif
ifneq (,$(MACOS_SDK_DIR))
diff --git a/security/nss/coreconf/config.mk b/security/nss/coreconf/config.mk
@@ -148,7 +148,6 @@ ifndef NSS_DISABLE_AVX2
ifneq ($(CPU_ARCH),x86_64)
# Disable AVX2 entirely on non-Intel platforms
NSS_DISABLE_AVX2 = 1
- $(warning CPU_ARCH is not x86_64, disabling -mavx2)
else
# Clang reports its version as an older gcc, but it's OK
ifndef CC_IS_CLANG
diff --git a/security/nss/coreconf/sanitizers.sh b/security/nss/coreconf/sanitizers.sh
@@ -20,7 +20,10 @@ enable_sanitizer()
fi
local cflags
- cflags=$(${python:-python} $cwd/coreconf/sanitizers.py "$@")
+ cflags=$(${python:-python3} "${cwd}/coreconf/sanitizers.py" "$@")
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
sanitizer_flags="$sanitizer_flags $cflags"
}
diff --git a/security/nss/fuzz/options/pkcs12-no_fuzzer_mode.options b/security/nss/fuzz/options/pkcs12-no_fuzzer_mode.options
@@ -0,0 +1,4 @@
+[libfuzzer]
+len_control = 100
+max_len = 16777215
+rss_limit_mb = 4096
diff --git a/security/nss/gtests/ssl_gtest/tls_ech_unittest.cc b/security/nss/gtests/ssl_gtest/tls_ech_unittest.cc
@@ -111,10 +111,9 @@ class TlsConnectStreamTls13Ech : public TlsConnectTestBase {
DataBuffer name;
ASSERT_TRUE(parser.ReadVariable(&name, 2));
ASSERT_EQ(0U, parser.remaining());
- // Manual comparison to silence coverity false-positives.
- ASSERT_EQ(name.len(), kPublicName.length());
- ASSERT_EQ(0,
- memcmp(kPublicName.c_str(), name.data(), kPublicName.length()));
+ std::string captured_name(reinterpret_cast<const char*>(name.data()),
+ name.len());
+ EXPECT_EQ(expected_name, captured_name);
}
void DoEchRetry(const ScopedSECKEYPublicKey& server_pub,
@@ -2392,6 +2391,41 @@ TEST_F(TlsConnectStreamTls13, NoEchFromTls12Client) {
ASSERT_FALSE(filter->captured());
}
+TEST_F(TlsConnectStreamTls13Ech, CorrectPreLimInfoFromTls12ClientWithEch) {
+ EnsureTlsSetup();
+ SetupEch(client_, server_);
+ client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_2);
+ server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_3);
+ client_->ExpectEch(false);
+ server_->ExpectEch(false);
+ SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_2);
+ Connect();
+ SSLPreliminaryChannelInfo channelPreInfo;
+ SSL_GetPreliminaryChannelInfo(server_->ssl_fd(), &channelPreInfo,
+ sizeof(channelPreInfo));
+ EXPECT_EQ(PR_FALSE, channelPreInfo.echAccepted);
+ EXPECT_EQ(NULL, channelPreInfo.echPublicName);
+}
+
+TEST_F(TlsConnectStreamTls13Ech, CorrectSNIFromTls12ClientWithEch) {
+ EnsureTlsSetup();
+ SetupEch(client_, server_);
+ client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_2);
+ server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_3);
+ client_->ExpectEch(false);
+ server_->ExpectEch(false);
+ SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_2);
+ auto filter =
+ MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
+ Connect();
+ ASSERT_TRUE(filter->captured());
+ CheckSniExtension(filter->extension(), "server");
+}
+
TEST_F(TlsConnectStreamTls13, EchOuterWith12Max) {
EnsureTlsSetup();
SetupEch(client_, server_);
diff --git a/security/nss/lib/pk11wrap/pk11mech.c b/security/nss/lib/pk11wrap/pk11mech.c
@@ -802,6 +802,11 @@ PK11_GetIVLength(CK_MECHANISM_TYPE type)
case CKM_CAST_ECB:
case CKM_CAST3_ECB:
case CKM_CAST5_ECB:
+ case CKM_AES_KEY_WRAP:
+ case CKM_AES_KEY_WRAP_PAD:
+ case CKM_AES_KEY_WRAP_KWP:
+ case CKM_NSS_AES_KEY_WRAP:
+ case CKM_NSS_AES_KEY_WRAP_PAD:
return 0;
case CKM_RC2_CBC:
case CKM_DES_CBC:
@@ -909,6 +914,11 @@ pk11_ParamFromIVWithLen(CK_MECHANISM_TYPE type, SECItem *iv, int keyLen)
case CKM_CAST3_ECB:
case CKM_CAST5_ECB:
case CKM_RC4:
+ case CKM_AES_KEY_WRAP:
+ case CKM_AES_KEY_WRAP_PAD:
+ case CKM_AES_KEY_WRAP_KWP:
+ case CKM_NSS_AES_KEY_WRAP:
+ case CKM_NSS_AES_KEY_WRAP_PAD:
break;
case CKM_RC2_ECB:
rc2_ecb_params = (CK_RC2_PARAMS *)PORT_Alloc(sizeof(CK_RC2_PARAMS));
diff --git a/security/nss/lib/pk11wrap/pk11pbe.c b/security/nss/lib/pk11wrap/pk11pbe.c
@@ -1425,6 +1425,18 @@ pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
CK_PKCS5_PBKD2_PARAMS pbev2_1_params;
CK_ULONG pwLen;
#endif
+#ifdef UNSAFE_FUZZER_MODE
+ PK11SymKey *zeroKey = NULL;
+ unsigned char zeroBuff[32] = { 0 };
+ SECItem zeroItem = { siBuffer, zeroBuff, sizeof zeroBuff };
+
+ zeroKey = PK11_ImportSymKeyWithFlags(slot, type, PK11_OriginUnwrap,
+ CKA_FLAGS_ONLY, &zeroItem,
+ CKF_SIGN | CKF_ENCRYPT | CKF_DECRYPT |
+ CKF_UNWRAP | CKF_WRAP,
+ PR_FALSE, wincx);
+ return zeroKey;
+#else /* UNSAFE_FUZZER_MODE */
/* do some sanity checks */
if ((params == NULL) || (params->data == NULL)) {
@@ -1481,6 +1493,7 @@ pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, params, keyType, keyLen, NULL,
CKF_SIGN | CKF_ENCRYPT | CKF_DECRYPT | CKF_UNWRAP | CKF_WRAP,
0, wincx);
+#endif /* UNSAFE_FUZZER_MODE */
}
/*
diff --git a/security/nss/lib/pk11wrap/pk11wrap.gyp b/security/nss/lib/pk11wrap/pk11wrap.gyp
@@ -64,6 +64,13 @@
'NSS_SHLIB_VERSION=\"3\"',
'SOFTOKEN_SHLIB_VERSION=\"3\"'
],
+ 'conditions': [
+ [ 'fuzz_tls==1', {
+ 'defines': [
+ 'UNSAFE_FUZZER_MODE',
+ ],
+ }],
+ ],
},
'variables': {
'module': 'nss'
diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c
@@ -1318,6 +1318,38 @@ static const char bufferEnd[] = { "BufferEnd" };
#endif
#define FUDGE 128 /* must be as large as bufferEnd or more. */
+#ifdef UNSAFE_FUZZER_MODE
+static PRBool
+fuzzer_parity_check(const unsigned char *buf, size_t len)
+{
+ unsigned char p = 0;
+ for (size_t i = 0; i < len; i++)
+ p ^= buf[i];
+ return (p & 1) != 0;
+}
+
+static SECStatus
+sec_pkcs12_decoder_unsafe_parity_outcome(SEC_PKCS12DecoderContext *p12dcx)
+{
+ PRBool allow = PR_TRUE;
+ if (p12dcx->pfx.encodedMacData.data && p12dcx->pfx.encodedMacData.len) {
+ allow = fuzzer_parity_check(p12dcx->pfx.encodedMacData.data, p12dcx->pfx.encodedMacData.len);
+ }
+
+ if (p12dcx->dClose) {
+ (*p12dcx->dClose)(p12dcx->dArg, PR_TRUE);
+ p12dcx->dIsOpen = PR_FALSE;
+ }
+
+ if (!allow) {
+ PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC);
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+#endif /* UNSAFE_FUZZER_MODE */
+
/* verify the hmac by reading the data from the temporary file
* using the routines specified when the decodingContext was
* created and return SECSuccess if the hmac matches.
@@ -1340,6 +1372,9 @@ sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx)
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
+#ifdef UNSAFE_FUZZER_MODE
+ return sec_pkcs12_decoder_unsafe_parity_outcome(p12dcx);
+#endif /* UNSAFE_FUZZER_MODE */
buf = (unsigned char *)PORT_Alloc(IN_BUF_LEN + FUDGE);
if (!buf)
return SECFailure; /* error code has been set. */
@@ -1461,7 +1496,9 @@ SEC_PKCS12DecoderVerify(SEC_PKCS12DecoderContext *p12dcx)
if (rv != SECSuccess) {
return rv;
}
-
+#ifdef UNSAFE_FUZZER_MODE
+ return sec_pkcs12_decoder_unsafe_parity_outcome(p12dcx);
+#else /* UNSAFE_FUZZER_MODE */
/* check the signature or the mac depending on the type of
* integrity used.
*/
@@ -1480,6 +1517,7 @@ SEC_PKCS12DecoderVerify(SEC_PKCS12DecoderContext *p12dcx)
}
PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC);
return SECFailure;
+#endif /* UNSAFE_FUZZER_MODE */
}
/* SEC_PKCS12DecoderFinish
diff --git a/security/nss/lib/pkcs12/pkcs12.gyp b/security/nss/lib/pkcs12/pkcs12.gyp
@@ -20,10 +20,17 @@
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
- ]
+ ],
+ 'conditions': [
+ [ 'fuzz_tls==1', {
+ 'defines': [
+ 'UNSAFE_FUZZER_MODE',
+ ],
+ }],
+ ],
}
],
'variables': {
'module': 'nss'
}
-}
-\ No newline at end of file
+}
diff --git a/security/nss/lib/sqlite/sqlite.gyp b/security/nss/lib/sqlite/sqlite.gyp
@@ -11,7 +11,7 @@
'target_name': 'sqlite3',
'type': 'none',
'link_settings': {
- 'libraries': ['<(sqlite_libs)'],
+ 'libraries': ['<@(sqlite_libs)'],
},
}],
}, {
diff --git a/security/nss/lib/ssl/ssl3exthandle.c b/security/nss/lib/ssl/ssl3exthandle.c
@@ -80,8 +80,7 @@ ssl3_ClientSendServerNameXtn(const sslSocket *ss, TLSExtensionData *xtnData,
/* If ECH, write the public name. The real server name
* is emplaced while constructing CHInner extensions. */
- sslEchConfig *cfg = (sslEchConfig *)PR_LIST_HEAD(&ss->echConfigs);
- const char *sniContents = PR_CLIST_IS_EMPTY(&ss->echConfigs) ? url : cfg->contents.publicName;
+ const char *sniContents = ss->ssl3.hs.echHpkeCtx ? ss->ssl3.hs.echPublicName : url;
rv = ssl3_ClientFormatServerNameXtn(ss, sniContents, strlen(sniContents), xtnData, buf);
if (rv != SECSuccess) {
return SECFailure;
diff --git a/security/nss/lib/ssl/tls13ech.c b/security/nss/lib/ssl/tls13ech.c
@@ -1090,7 +1090,7 @@ tls13_OpenClientHelloInner(sslSocket *ss, const SECItem *outer, const SECItem *o
}
#else
rv = SECITEM_CopyItem(NULL, decryptedChInner, &ss->xtnData.ech->innerCh);
- if (rv != SECSuccess) {
+ if (rv != SECSuccess || decryptedChInner->len <= TLS13_ECH_AEAD_TAG_LEN) {
goto loser;
}
decryptedChInner->len -= TLS13_ECH_AEAD_TAG_LEN; /* Fake tag */
@@ -2697,6 +2697,8 @@ tls13_MaybeAcceptEch(sslSocket *ss, const SECItem *sidBytes, const PRUint8 *chOu
TLSExtension *hrrXtn;
PRBool previouslyOfferedEch;
+ PORT_Assert(!ss->ssl3.hs.echAccepted);
+
if (!ss->xtnData.ech || ss->xtnData.ech->receivedInnerXtn || IS_DTLS(ss)) {
ss->ssl3.hs.echDecided = PR_TRUE;
return SECSuccess;
@@ -2707,14 +2709,13 @@ tls13_MaybeAcceptEch(sslSocket *ss, const SECItem *sidBytes, const PRUint8 *chOu
if (ss->ssl3.hs.helloRetry) {
ss->ssl3.hs.echDecided = PR_TRUE;
PORT_Assert(!ss->ssl3.hs.echHpkeCtx);
+
hrrXtn = ssl3_FindExtension(ss, ssl_tls13_cookie_xtn);
if (!hrrXtn) {
/* If the client doesn't echo cookie, we can't decrypt. */
return SECSuccess;
}
- PORT_Assert(!ss->ssl3.hs.echHpkeCtx);
-
PRUint8 *tmp = hrrXtn->data.data;
PRUint32 len = hrrXtn->data.len;
rv = ssl3_ExtConsumeHandshakeVariable(ss, &cookieData, 2,
@@ -2735,8 +2736,8 @@ tls13_MaybeAcceptEch(sslSocket *ss, const SECItem *sidBytes, const PRUint8 *chOu
ss->ssl3.hs.echHpkeCtx = echData.hpkeCtx;
const PRUint8 greaseConstant[TLS13_ECH_SIGNAL_LEN] = { 0 };
- ss->ssl3.hs.echAccepted = previouslyOfferedEch &&
- !NSS_SecureMemcmp(greaseConstant, echData.signal, TLS13_ECH_SIGNAL_LEN);
+ PRBool signal = previouslyOfferedEch &&
+ !NSS_SecureMemcmp(greaseConstant, echData.signal, TLS13_ECH_SIGNAL_LEN);
if (echData.configId != ss->xtnData.ech->configId ||
echData.kdfId != ss->xtnData.ech->kdfId ||
@@ -2749,6 +2750,7 @@ tls13_MaybeAcceptEch(sslSocket *ss, const SECItem *sidBytes, const PRUint8 *chOu
if (!ss->ssl3.hs.echHpkeCtx) {
return SECSuccess;
}
+ ss->ssl3.hs.echAccepted = signal;
}
if (ss->ssl3.hs.echDecided && !ss->ssl3.hs.echAccepted) {
diff --git a/security/nss/moz.yaml b/security/nss/moz.yaml
@@ -9,8 +9,8 @@ origin:
description: nss
url: https://hg-edge.mozilla.org/projects/nss
- release: 28cc2eb89479695ce2b2cb0933dccaae85887697 (2025-11-24T20:15:29Z).
- revision: 28cc2eb89479695ce2b2cb0933dccaae85887697
+ release: 8c7bdebef8325c782fc5e1cce9a1940d326f1fb0 (2025-12-03T17:41:07Z).
+ revision: 8c7bdebef8325c782fc5e1cce9a1940d326f1fb0
license: MPL-2.0
license-file: COPYING