commit b22abf7841d030ca92fa5d01dbba1a889452ac30 parent 18f142740af8ae86f3503c4ce4eef2981a8c631d Author: Updatebot <updatebot@mozilla.com> Date: Tue, 6 Jan 2026 17:03:10 +0000 Bug 2007635 - Update NSS to 213eff47d0697b06a123d954db4ce2fd46e5bd1a UPGRADE_NSS_RELEASE r=nss-reviewers,djackson Differential Revision: https://phabricator.services.mozilla.com/D277499 Diffstat:
18 files changed, 424 insertions(+), 34 deletions(-)
diff --git a/security/nss/.taskcluster.yml b/security/nss/.taskcluster.yml @@ -58,7 +58,7 @@ tasks: Action triggered by clientID `${clientId}` provisionerId: "${trustDomain}-${repository.level}" - workerType: "decision-gcp" + workerType: "decision" tags: $if: 'tasks_for == "hg-push"' diff --git a/security/nss/automation/abi-check/previous-nss-release b/security/nss/automation/abi-check/previous-nss-release @@ -1 +1 @@ -NSS_3_118_BRANCH +NSS_3_119_BRANCH diff --git a/security/nss/automation/taskcluster/scripts/build.sh b/security/nss/automation/taskcluster/scripts/build.sh @@ -4,8 +4,6 @@ set -e -test -v VCS_PATH - # builds write to the source dir (and its parent), so move the source trees to # our workspace from the (cached) checkout dir cp -a "${VCS_PATH}/nss" "${VCS_PATH}/nspr" . diff --git a/security/nss/automation/taskcluster/scripts/build_gyp.sh b/security/nss/automation/taskcluster/scripts/build_gyp.sh @@ -31,14 +31,9 @@ fi nss/build.sh -g -v --enable-libpkix -Denable_draft_hpke=1 "$@" # Package. -if [ "$(uname)" = "Darwin" ]; then - mkdir -p public - tar cvfjh public/dist.tar.bz2 dist +if [ "$(uname)" = Linux ]; then + ln -s /builds/worker/artifacts artifacts else - if [ "$(uname)" = Linux ]; then - ln -s /builds/worker/artifacts artifacts - else - mkdir artifacts - fi - tar cvfjh artifacts/dist.tar.bz2 dist + mkdir -p artifacts fi +tar cvfjh artifacts/dist.tar.bz2 dist diff --git a/security/nss/coreconf/Darwin.mk b/security/nss/coreconf/Darwin.mk @@ -18,15 +18,17 @@ ifndef CPU_ARCH CPU_ARCH := $(shell uname -p) endif -ifeq (x86_64,$(CPU_ARCH)) +ifeq (,$(filter-out i%86,$(CPU_ARCH))) +ifdef USE_64 CC += -arch x86_64 CCC += -arch x86_64 override CPU_ARCH = x86_64 -else ifeq (i386,$(CPU_ARCH)) +else OS_REL_CFLAGS = -Di386 CC += -arch i386 CCC += -arch i386 override CPU_ARCH = x86 +endif else ifeq (,$(filter-out aarch64 arm,$(CPU_ARCH))) CC += -arch arm64 CCC += -arch arm64 diff --git a/security/nss/doc/rst/releases/index.rst b/security/nss/doc/rst/releases/index.rst @@ -8,6 +8,7 @@ Release Notes :glob: :hidden: + nss_3_119_1.rst nss_3_119.rst nss_3_118_1.rst nss_3_118.rst @@ -98,8 +99,8 @@ Release Notes .. note:: - **NSS 3.119** is the latest version of NSS. - Complete release notes are available here: :ref:`mozilla_projects_nss_nss_3_119_release_notes` + **NSS 3.119.1** is the latest version of NSS. + Complete release notes are available here: :ref:`mozilla_projects_nss_nss_3_119_1_release_notes` **NSS 3.112.2 (ESR)** is the latest ESR version of NSS. Complete release notes are available here: :ref:`mozilla_projects_nss_nss_3_112_2_release_notes` diff --git a/security/nss/doc/rst/releases/nss_3_119_1.rst b/security/nss/doc/rst/releases/nss_3_119_1.rst @@ -0,0 +1,35 @@ +.. _mozilla_projects_nss_nss_3_119_1_release_notes: + +NSS 3.119.1 release notes +======================== + +`Introduction <#introduction>`__ +-------------------------------- + +.. container:: + + Network Security Services (NSS) 3.119.1 was released on *10 December 2025**. + +`Distribution Information <#distribution_information>`__ +-------------------------------------------------------- + +.. container:: + + The HG tag is NSS_3_119_1_RTM. NSS 3.119.1 requires NSPR 4.38.2 or newer. + + NSS 3.119.1 source distributions are available on ftp.mozilla.org for secure HTTPS download: + + - Source tarballs: + https://ftp.mozilla.org/pub/mozilla.org/security/nss/releases/NSS_3_119_1_RTM/src/ + + Other releases are available :ref:`mozilla_projects_nss_releases`. + +.. _changes_in_nss_3.119.1: + +`Changes in NSS 3.119.1 <#changes_in_nss_3.119.1>`__ +------------------------------------------------------------------ + +.. container:: + + - Bug 2004866 - restore coreconf/Darwin.mk behavior for intel archs. + diff --git a/security/nss/gtests/ssl_gtest/manifest.mn b/security/nss/gtests/ssl_gtest/manifest.mn @@ -48,6 +48,7 @@ CPPSRCS = \ ssl_resumption_unittest.cc \ ssl_skip_unittest.cc \ ssl_staticrsa_unittest.cc \ + ssl_timers_unittest.cc \ ssl_tls13compat_unittest.cc \ ssl_v2_client_hello_unittest.cc \ ssl_version_unittest.cc \ diff --git a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp @@ -48,6 +48,7 @@ 'ssl_resumption_unittest.cc', 'ssl_skip_unittest.cc', 'ssl_staticrsa_unittest.cc', + 'ssl_timers_unittest.cc', 'ssl_tls13compat_unittest.cc', 'ssl_v2_client_hello_unittest.cc', 'ssl_version_unittest.cc', diff --git a/security/nss/gtests/ssl_gtest/ssl_timers_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_timers_unittest.cc @@ -0,0 +1,319 @@ +/* -*- 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 "sslerr.h" +#include "sslproto.h" + +extern "C" { +// This is not something that should make you happy. +#include "libssl_internals.h" +} + +#include "gtest_utils.h" +#include "nss_scoped_ptrs.h" +#include "tls_connect.h" +#include "tls_filter.h" +#include "tls_parser.h" + +namespace nss_test { + +// Reproducing https://bugzilla.mozilla.org/show_bug.cgi?id=1978603 +// The test causes assertion failure: timer->cb == NULL, at +// lib/ssl/dtlscon.c:922 + +// The general problem in the bug was that each post-handshake message +// was starting a new retransmit timer. +// We've decided to change the timer logic such that a retransmit timer +// will be restarted when a new request for a timer arrives. + +// This test ensures that if two different post-handshake messages are queued +// for retransmission, the timer behaves correctly. When the second message is +// queued, we reset the timer. This means a message never waits longer than the +// minimum timer delay. The first message queued will be retransmitted a bit +// more aggressively than it would otherwise, but this is unlikely to be a +// problem. + +// We're currently supporting NewSessionTicker and KeyUpdate post-handshake +// messages. + +// The filter will be dropping Key Update and New Session Ticket until disabled +// When it's disabled, it will keep track of the New Session Ticket messages +// sent by the server, and when it founds one - it will record the sequence +// number This sequence number will then be provided to the second filter that +// will be checking the list of ACKs seaching for this message +class TLSSessionTicketAndKUDropper : public TlsRecordFilter { + public: + TLSSessionTicketAndKUDropper(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a), enabled_(true), sequenceNumberNST(0) {} + + void disable() { enabled_ = false; } + + uint64_t getSentSessionTicketSeqNum() { return sequenceNumberNST; } + + protected: + PacketFilter::Action FilterRecord(const TlsRecordHeader& header, + const DataBuffer& record, size_t* offset, + DataBuffer* output) override { + if (!header.is_protected()) { + return KEEP; + } + + uint16_t protection_epoch; + uint8_t inner_content_type; + DataBuffer plaintext; + TlsRecordHeader out_header; + + if (!Unprotect(header, record, &protection_epoch, &inner_content_type, + &plaintext, &out_header)) { + return KEEP; + } + + if (plaintext.data()[0] == ssl_hs_new_session_ticket) { + if (enabled_) { + return DROP; + } else { + sequenceNumberNST = out_header.sequence_number(); + } + } + + if (plaintext.data()[0] == ssl_hs_key_update && enabled_) { + return DROP; + } + + return KEEP; + } + + private: + bool enabled_; + uint64_t sequenceNumberNST; +}; + +class TLSACKRecorder : public TlsRecordFilter { + public: + TLSACKRecorder(const std::shared_ptr<TlsAgent>& a) + : TlsRecordFilter(a), + enabled_(false), + isSeqNumFound(false), + sequenceNumberToFindACKed(0) {} + + void EnableTLSACKCatcherWithSeqNum(uint64_t seqNum) { + enabled_ = true; + sequenceNumberToFindACKed = seqNum; + } + + bool isNSTACKFound() { return isSeqNumFound; } + + protected: + PacketFilter::Action FilterRecord(const TlsRecordHeader& header, + const DataBuffer& record, size_t* offset, + DataBuffer* output) override { + if (!enabled_) { + return KEEP; + } + + if (!header.is_protected()) { + return KEEP; + } + + uint16_t protection_epoch; + uint8_t inner_content_type; + DataBuffer plaintext; + TlsRecordHeader out_header; + + if (!Unprotect(header, record, &protection_epoch, &inner_content_type, + &plaintext, &out_header)) { + return KEEP; + } + + if (plaintext.data() == NULL || plaintext.len() == 0) { + return KEEP; + } + + if (decrypting() && inner_content_type != ssl_ct_ack) { + return KEEP; + } + + uint8_t ack_message_header_len = 2; + + uint8_t ack_message_len_one_ACK = 16; + size_t acks = plaintext.len() - ack_message_header_len; + EXPECT_EQ((uint64_t)0, acks % ack_message_len_one_ACK); + acks = acks / ack_message_len_one_ACK; + + // struct { + // uint64 epoch; + // uint64 sequence_number; + // } RecordNumber; + + // sequenceNumberToFindACKed has 16 bits for epoch and 48 for seqNum + uint64_t epoch = sequenceNumberToFindACKed >> 48; + uint64_t seqNum = sequenceNumberToFindACKed & 0xFFFFFFFFFFFF; + + uint64_t lastByteEpoch = 0; + uint64_t leastByteSequence = 0; + + for (size_t i = 0; i < acks; i++) { + // Here we check that the last byte of the epoch and the last byte of the + // sequence Because we just sent a couple of messages, so the values will + // be less than 256. + lastByteEpoch = plaintext.data()[2 + i * ack_message_len_one_ACK + 7]; + leastByteSequence = + plaintext.data()[2 + i * ack_message_len_one_ACK + 15]; + + if ((epoch % 256 == lastByteEpoch) && + (seqNum % 256) == leastByteSequence) { + isSeqNumFound = true; + return KEEP; + } + } + return KEEP; + } + + private: + bool enabled_; + bool isSeqNumFound; + uint64_t sequenceNumberToFindACKed; +}; + +TEST_F(TlsConnectDatagram13, SendTicketThenKeyUpdate) { + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + Connect(); + + SendReceive(); // Need to read so that we absorb the session tickets. + CheckKeys(); + + // Resume the connection. + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); + ExpectResumption(RESUME_TICKET); + + auto filter = MakeTlsFilter<TLSSessionTicketAndKUDropper>(server_); + filter->EnableDecryption(); + + auto ackRecorderFilter = MakeTlsFilter<TLSACKRecorder>(client_); + ackRecorderFilter->EnableDecryption(); + + // This should cause sending a NewSessionTicket (thus, starting the timer) + // Sending the NewSessionTicket will be blocked by the filter + Connect(); + + // Server sends Key Update + // The first Key Update will also be dropped by the server + EXPECT_EQ(SECSuccess, SSL_KeyUpdate(server_->ssl_fd(), false)); + + client_->ReadBytes(); + // Check that the client indeed has not received the KU. + SSLInt_SendImmediateACK(client_->ssl_fd()); + server_->ReadBytes(); + CheckEpochs(3, 3); + + // Disabling dropping the message, the effective retransmit will start + filter->disable(); + + // So, we don't have to wait until the next retransmit happens + ShiftDtlsTimers(); + server_->ReadBytes(); + // We get the Sequence number of the NewSessionTicket that the server has sent + uint64_t sequenceNumberNST = filter->getSentSessionTicketSeqNum(); + // And we check that the client has received (thus acked) the newly + // retransmitted NewSessionTicket + ackRecorderFilter->EnableTLSACKCatcherWithSeqNum(sequenceNumberNST); + + // Client Received NewSessionTicker and KU + client_->ReadBytes(); + SSLInt_SendImmediateACK(client_->ssl_fd()); + server_->ReadBytes(); + + // Client and Server both received and processed KU + CheckEpochs(3, 4); + + // Client has successfully received and sent an ACK for NST message + EXPECT_EQ(true, ackRecorderFilter->isNSTACKFound()); + + SendReceive(50); +} + +class TLSIthMessageSeqNumDropper : public TlsRecordFilter { + public: + TLSIthMessageSeqNumDropper(const std::shared_ptr<TlsAgent>& a, + uint8_t messageSeqNumToDrop) + : TlsRecordFilter(a), + enabled_(true), + messageSeqNumToDrop_(messageSeqNumToDrop), + currentMessageSeqNum_(0) {} + + void disable() { enabled_ = false; } + + protected: + PacketFilter::Action FilterRecord(const TlsRecordHeader& header, + const DataBuffer& record, size_t* offset, + DataBuffer* output) override { + if (enabled_ && currentMessageSeqNum_ == messageSeqNumToDrop_) { + enabled_ = false; + + uint16_t protection_epoch; + uint8_t inner_content_type; + DataBuffer plaintext; + TlsRecordHeader out_header; + + if (!Unprotect(header, record, &protection_epoch, &inner_content_type, + &plaintext, &out_header)) { + return KEEP; + } + + if (inner_content_type == ssl_ct_ack || + inner_content_type == ssl_ct_application_data) { + return KEEP; + } + + return DROP; + } + + currentMessageSeqNum_ += 1; + return KEEP; + } + + private: + bool enabled_; + uint8_t messageSeqNumToDrop_; + uint8_t currentMessageSeqNum_; +}; + +TEST_F(TlsConnectDatagram13, HandshakeDropIthMessageServer) { + uint8_t maxServerMessageSeq = 10; + + for (uint8_t currMesSeqNum = 0; currMesSeqNum < maxServerMessageSeq; + currMesSeqNum++) { + EnsureTlsSetup(); + auto filter = + MakeTlsFilter<TLSIthMessageSeqNumDropper>(server_, currMesSeqNum); + filter->EnableDecryption(); + + Connect(); + SendReceive(); + Reset(); + } +} + +TEST_F(TlsConnectDatagram13, HandshakeDropIthMessageClient) { + uint8_t maxClientMessageSeq = 10; + + for (uint8_t currMesSeqNum = 0; currMesSeqNum < maxClientMessageSeq; + currMesSeqNum++) { + EnsureTlsSetup(); + auto filter = + MakeTlsFilter<TLSIthMessageSeqNumDropper>(client_, currMesSeqNum); + filter->EnableDecryption(); + + Connect(); + SendReceive(); + Reset(); + } +} + +} // namespace nss_test diff --git 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 * "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]" */ -#define NSS_VERSION "3.119" _NSS_CUSTOMIZED +#define NSS_VERSION "3.120" _NSS_CUSTOMIZED " Beta" #define NSS_VMAJOR 3 -#define NSS_VMINOR 119 +#define NSS_VMINOR 120 #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/softoken/softkver.h b/security/nss/lib/softoken/softkver.h @@ -17,11 +17,11 @@ * The format of the version string should be * "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]" */ -#define SOFTOKEN_VERSION "3.119" SOFTOKEN_ECC_STRING +#define SOFTOKEN_VERSION "3.120" SOFTOKEN_ECC_STRING " Beta" #define SOFTOKEN_VMAJOR 3 -#define SOFTOKEN_VMINOR 119 +#define SOFTOKEN_VMINOR 120 #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/dtlscon.c b/security/nss/lib/ssl/dtlscon.c @@ -942,13 +942,32 @@ dtls_TimerActive(sslSocket *ss, dtlsTimer *timer) { return timer->cb != NULL; } + /* Start a timer for retransmission. */ static SECStatus dtls_StartRetransmitTimer(sslSocket *ss) { + dtlsTimer *timer = ss->ssl3.hs.rtTimer; + PRUint32 timeout = DTLS_RETRANSMIT_INITIAL_MS; + + if (dtls_TimerActive(ss, timer)) { + SSL_TRC(10, ("%d: SSL3[%d]: %s dtls timer %s is already active, restarting. New timeout is %d", + SSL_GETPID(), ss->fd, SSL_ROLE(ss), + timer->label, timeout)); + // If a post-handshake message has already been sent (thus activating the + // timer) and a second one is queued, reset the timer so no message waits + // longer than the minimum delay. The first message is retransmitted a + // bit more aggressively than it otherwise would be, but this is + // unlikely to be a problem. + (void)dtls_RestartTimer(ss, timer); + ss->ssl3.hs.rtRetries = 0; + timer->timeout = timeout; + return SECSuccess; + } + ss->ssl3.hs.rtRetries = 0; - return dtls_StartTimer(ss, ss->ssl3.hs.rtTimer, - DTLS_RETRANSMIT_INITIAL_MS, + return dtls_StartTimer(ss, timer, + timeout, dtls_RetransmitTimerExpiredCb); } diff --git 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 * "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]" */ -#define NSSUTIL_VERSION "3.119" +#define NSSUTIL_VERSION "3.120 Beta" #define NSSUTIL_VMAJOR 3 -#define NSSUTIL_VMINOR 119 +#define NSSUTIL_VMINOR 120 #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/moz.yaml b/security/nss/moz.yaml @@ -9,8 +9,8 @@ origin: description: nss url: https://hg-edge.mozilla.org/projects/nss - release: 2e158979a08f0a86d960f0fd89f878f25606a586 (2025-12-05T03:57:44Z). - revision: 2e158979a08f0a86d960f0fd89f878f25606a586 + release: 213eff47d0697b06a123d954db4ce2fd46e5bd1a (2025-12-19T12:24:11Z). + revision: 213eff47d0697b06a123d954db4ce2fd46e5bd1a license: MPL-2.0 license-file: COPYING diff --git a/security/nss/taskcluster/config.yml b/security/nss/taskcluster/config.yml @@ -12,12 +12,12 @@ workers: provisioner: 'nss-{level}' implementation: docker-worker os: linux - worker-type: linux-gcp + worker-type: linux-docker b-linux: provisioner: 'nss-{level}' implementation: docker-worker os: linux - worker-type: linux-gcp + worker-type: linux-docker b-win2022: provisioner: 'nss-{level}' implementation: generic-worker diff --git a/security/nss/taskcluster/kinds/build/macosx.yml b/security/nss/taskcluster/kinds/build/macosx.yml @@ -2,8 +2,9 @@ task-defaults: worker-type: b-osx worker: artifacts: - - type: directory - path: public + - type: directory + path: artifacts + name: public macosx64/opt: description: "Mac (opt)" @@ -15,3 +16,19 @@ macosx64/opt-static: macosx64/debug: description: "Mac (debug)" + +macosx64/opt-make: + description: "Mac (opt, make)" + attributes: + make: true + worker: + env: + USE_64: "1" + +macosx64/debug-make: + description: "Mac (debug, make)" + attributes: + make: true + worker: + env: + USE_64: "1" diff --git a/security/nss/taskcluster/nss_taskgraph/target_tasks.py b/security/nss/taskcluster/nss_taskgraph/target_tasks.py @@ -25,6 +25,7 @@ PLATFORM_ALIASES = { "win64": "windows2022-64", "win": "windows2022-32", "mac": "macosx64", + "mac-make": "macosx64", } @@ -45,6 +46,7 @@ def filter_platform(platform, task): or platform == "win64-make" or platform == "win-make" or platform == "aarch64-make" + or platform == "mac-make" ): keep &= task.attributes["make"] elif platform == "linux64-fuzz" or platform == "linux-fuzz":