tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 61e325b163674c8a9c9035fcf12d68b9a37d7e60
parent 9fcc8e7f0b1624433e4228228e4ae911456e5ab0
Author: Updatebot <updatebot@mozilla.com>
Date:   Tue,  4 Nov 2025 16:49:13 +0000

Bug 1998076 - Update NSS to cd2ce1a24014a9afaff0df7b484f6065d845de7a. UPGRADE_NSS_RELEASE r=jschanck

Differential Revision: https://phabricator.services.mozilla.com/D271182

Diffstat:
Msecurity/nss/automation/abi-check/expected-report-libnss3.so.txt | 5+++--
Msecurity/nss/automation/abi-check/expected-report-libnssutil3.so.txt | 5+++--
Msecurity/nss/automation/abi-check/expected-report-libsmime3.so.txt | 5+++--
Msecurity/nss/automation/abi-check/expected-report-libssl3.so.txt | 5+++--
Msecurity/nss/automation/release/nss-release-helper.py | 2+-
Msecurity/nss/automation/taskcluster/scripts/fuzz.sh | 2+-
Msecurity/nss/automation/taskcluster/scripts/run_hacl.sh | 2+-
Msecurity/nss/automation/taskcluster/windows/build_gyp.sh | 6+++---
Msecurity/nss/build.sh | 6+++---
Msecurity/nss/cmd/lib/secutil.c | 1+
Msecurity/nss/coreconf/check_cc.py | 3+--
Msecurity/nss/coreconf/config.gypi | 2+-
Msecurity/nss/coreconf/detect_host_arch.py | 2+-
Msecurity/nss/coreconf/sanitizers.py | 2+-
Msecurity/nss/coreconf/shlibsign.py | 2+-
Msecurity/nss/coreconf/werror.py | 2+-
Msecurity/nss/doc/rst/build.rst | 12+-----------
Msecurity/nss/gtests/pk11_gtest/pk11_kem_unittest.cc | 9+++++++++
Msecurity/nss/gtests/pk11_gtest/pk11_keygen.cc | 6+++++-
Msecurity/nss/gtests/ssl_gtest/tls_agent.cc | 35++++++++++++++++++++++++-----------
Msecurity/nss/gtests/ssl_gtest/tls_mlkem_unittest.cc | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msecurity/nss/lib/ckfw/builtins/certdata.py | 2+-
Msecurity/nss/lib/pk11wrap/pk11akey.c | 13+++++++++++--
Msecurity/nss/lib/pk11wrap/pk11pars.c | 2++
Msecurity/nss/lib/softoken/kem.c | 13+++++++++++++
Msecurity/nss/lib/ssl/sslimpl.h | 2+-
Msecurity/nss/lib/ssl/sslsock.c | 2++
Msecurity/nss/lib/ssl/sslt.h | 1+
Msecurity/nss/lib/ssl/tls13con.c | 39+++++++++++++++++++++++++++++++++++++++
Msecurity/nss/lib/ssl/tls13exthandle.c | 10+++++++---
Msecurity/nss/lib/util/eccutil.h | 1+
Msecurity/nss/lib/util/secoid.c | 2++
Msecurity/nss/lib/util/secoidt.h | 1+
Msecurity/nss/mach | 2+-
Msecurity/nss/moz.yaml | 4++--
Msecurity/nss/tests/ssl/ssl.sh | 6++++--
Msecurity/nss/tests/ssl/sslcov.txt | 3+++
37 files changed, 220 insertions(+), 67 deletions(-)

diff --git a/security/nss/automation/abi-check/expected-report-libnss3.so.txt b/security/nss/automation/abi-check/expected-report-libnss3.so.txt @@ -5,11 +5,12 @@ parameter 2 of type 'typedef SECOidTag' has sub-type changes: underlying type 'enum __anonymous_enum__' at secoidt.h:34:1 changed: type size hasn't changed - 1 enumerator insertion: + 2 enumerator insertions: '__anonymous_enum__::SEC_OID_SECP256R1MLKEM768' value '394' + '__anonymous_enum__::SEC_OID_SECP384R1MLKEM1024' value '395' 1 enumerator change: - '__anonymous_enum__::SEC_OID_TOTAL' from value '394' to '395' at secoidt.h:34:1 + '__anonymous_enum__::SEC_OID_TOTAL' from value '394' to '396' at secoidt.h:34:1 diff --git a/security/nss/automation/abi-check/expected-report-libnssutil3.so.txt b/security/nss/automation/abi-check/expected-report-libnssutil3.so.txt @@ -5,11 +5,12 @@ return type changed: underlying type 'enum __anonymous_enum__' at secoidt.h:34:1 changed: type size hasn't changed - 1 enumerator insertion: + 2 enumerator insertions: '__anonymous_enum__::SEC_OID_SECP256R1MLKEM768' value '394' + '__anonymous_enum__::SEC_OID_SECP384R1MLKEM1024' value '395' 1 enumerator change: - '__anonymous_enum__::SEC_OID_TOTAL' from value '394' to '395' at secoidt.h:34:1 + '__anonymous_enum__::SEC_OID_TOTAL' from value '394' to '396' at secoidt.h:34:1 diff --git a/security/nss/automation/abi-check/expected-report-libsmime3.so.txt b/security/nss/automation/abi-check/expected-report-libsmime3.so.txt @@ -30,11 +30,12 @@ type of 'SECOidTag SECOidDataStr::offset' changed: underlying type 'enum __anonymous_enum__' at secoidt.h:34:1 changed: type size hasn't changed - 1 enumerator insertion: + 2 enumerator insertions: '__anonymous_enum__::SEC_OID_SECP256R1MLKEM768' value '394' + '__anonymous_enum__::SEC_OID_SECP384R1MLKEM1024' value '395' 1 enumerator change: - '__anonymous_enum__::SEC_OID_TOTAL' from value '394' to '395' at secoidt.h:34:1 + '__anonymous_enum__::SEC_OID_TOTAL' from value '394' to '396' at secoidt.h:34:1 diff --git a/security/nss/automation/abi-check/expected-report-libssl3.so.txt b/security/nss/automation/abi-check/expected-report-libssl3.so.txt @@ -17,11 +17,12 @@ type of 'SECOidTag SECKEYMLDSAPublicKeyStr::paramSet' changed: underlying type 'enum __anonymous_enum__' at secoidt.h:34:1 changed: type size hasn't changed - 1 enumerator insertion: + 2 enumerator insertions: '__anonymous_enum__::SEC_OID_SECP256R1MLKEM768' value '394' + '__anonymous_enum__::SEC_OID_SECP384R1MLKEM1024' value '395' 1 enumerator change: - '__anonymous_enum__::SEC_OID_TOTAL' from value '394' to '395' at secoidt.h:34:1 + '__anonymous_enum__::SEC_OID_TOTAL' from value '394' to '396' at secoidt.h:34:1 diff --git a/security/nss/automation/release/nss-release-helper.py b/security/nss/automation/release/nss-release-helper.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # 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/. diff --git a/security/nss/automation/taskcluster/scripts/fuzz.sh b/security/nss/automation/taskcluster/scripts/fuzz.sh @@ -32,7 +32,7 @@ popd objdir=$(cat dist/latest) # Get libFuzzer options. -readarray -t options < <(python nss/fuzz/config/libfuzzer_options.py nss/fuzz/options/"$corpus".options) +readarray -t options < <(python3 nss/fuzz/config/libfuzzer_options.py nss/fuzz/options/"$corpus".options) # Run nssfuzz. dist/"$objdir"/bin/nssfuzz-"$target" "nss/fuzz/corpus/$corpus" "${options[@]}" "$@" diff --git a/security/nss/automation/taskcluster/scripts/run_hacl.sh b/security/nss/automation/taskcluster/scripts/run_hacl.sh @@ -73,7 +73,7 @@ done files=($(find ${VCS_PATH}/nss/lib/freebl/verified/ -type f -name '*.[ch]' -not -path "*/freebl/verified/internal/*" -not -path "*/freebl/verified/config.h" -not -path "*/freebl/verified/libcrux*")) for f in "${files[@]}"; do file_name=$(basename "$f") - hacl_file=($(find ${HACL_STAR}/dist/mozilla/ ${KARAMEL}/include/ ${KARAMEL}/krmllib/dist/ ${LIBCRUX}/libcrux-ml-kem/extracts/c/generated/ -type f -name $file_name -not -path "*/hacl-star/dist/mozilla/internal/*" -not -path "*/libcrux-ml-kem/extracts/c/generated/internal/*")) + hacl_file=($(find ${HACL_STAR}/dist/mozilla/ ${KARAMEL}/include/ ${KARAMEL}/krmllib/dist/minimal/ ${LIBCRUX}/libcrux-ml-kem/extracts/c/generated/ -type f -name $file_name -not -path "*/hacl-star/dist/mozilla/internal/*" -not -path "*/libcrux-ml-kem/extracts/c/generated/internal/*")) if [ $file_name == "Hacl_P384.c" \ -o $file_name == "Hacl_P384.h" \ -o $file_name == "Hacl_P521.c" \ diff --git a/security/nss/automation/taskcluster/windows/build_gyp.sh b/security/nss/automation/taskcluster/windows/build_gyp.sh @@ -18,9 +18,9 @@ git clone https://chromium.googlesource.com/external/gyp # Install GYP. pushd gyp -python -m venv ./test-env -test-env/Scripts/python setup.py install -test-env/Scripts/python -m pip install --upgrade pip +python3 -m venv ./test-env +test-env/Scripts/python3 setup.py install +test-env/Scripts/python3 -m pip install --upgrade pip test-env/Scripts/pip install --upgrade 'setuptools<45.0.0' six # Fool GYP. touch "${VSPATH}/VC/vcvarsall.bat" diff --git a/security/nss/build.sh b/security/nss/build.sh @@ -132,8 +132,8 @@ while [ $# -gt 0 ]; do --disable-keylog) sslkeylogfile=0 ;; --enable-legacy-db) gyp_params+=(-Ddisable_dbm=0) ;; --mozilla-central) gyp_params+=(-Dmozilla_central=1) ;; - --python) python="$2"; shift ;; - --python=*) python="${1#*=}" ;; + --python) python="$2"; shift ;; + --python=*) python="${1#*=}" ;; -D*) gyp_params+=("$1") ;; *) show_help; exit 2 ;; esac @@ -158,7 +158,7 @@ fi if [ -z "$target_arch" ]; then # Assume that the target architecture is the same as the host by default. - host_arch=$(${python:-python} "$cwd/coreconf/detect_host_arch.py") + host_arch=$(${python:-python3} "$cwd/coreconf/detect_host_arch.py") target_arch=$host_arch fi diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c @@ -4247,6 +4247,7 @@ static const struct SSLNamedGroupString { #endif { NAME_AND_LEN("x25519mlkem768"), ssl_grp_kem_mlkem768x25519 }, { NAME_AND_LEN("secp256r1mlkem768"), ssl_grp_kem_secp256r1mlkem768 }, + { NAME_AND_LEN("secp384r1mlkem1024"), ssl_grp_kem_secp384r1mlkem1024 }, // keep for compatibility { NAME_AND_LEN("mlkem768x25519"), ssl_grp_kem_mlkem768x25519 }, }; diff --git a/security/nss/coreconf/check_cc.py b/security/nss/coreconf/check_cc.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import subprocess @@ -24,4 +24,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/security/nss/coreconf/config.gypi b/security/nss/coreconf/config.gypi @@ -7,7 +7,7 @@ 'variables': { 'variables': { 'variables': { - 'python%': 'python', + 'python%': 'python3', }, # chromium uses pymod_do_main, but gyp doesn't set a sensible # Python sys.path (gyp_chromium does). diff --git a/security/nss/coreconf/detect_host_arch.py b/security/nss/coreconf/detect_host_arch.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # 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, diff --git a/security/nss/coreconf/sanitizers.py b/security/nss/coreconf/sanitizers.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 from __future__ import print_function import sys diff --git a/security/nss/coreconf/shlibsign.py b/security/nss/coreconf/shlibsign.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # # 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 diff --git a/security/nss/coreconf/werror.py b/security/nss/coreconf/werror.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import os import subprocess diff --git a/security/nss/doc/rst/build.rst b/security/nss/doc/rst/build.rst @@ -44,15 +44,6 @@ Building NSS brew install mercurial git ninja python3-pip python3 -m pip install gyp-next - It is also necessary to make sure that a `python` (not just `python3`) - executable is in the path. - The Homebrew Python installation has the necessary symlink but may require - explicit adding to the PATH variable, for example like this: - - .. code:: - - export PATH="/opt/homebrew/opt/python/libexec/bin:$PATH" - **On Windows:** .. code:: @@ -298,4 +289,4 @@ Building NSS - ``libfort.so``/``libfort.sl``/``fort32.dll`` provides support for hardware FORTEZZA. - ``libswft.so``/``libswft.sl``/``swft32.dll`` provides support for software FORTEZZA. - ``libnssckbi.so``/``libnssckbi.sl``/``nssckbi.dll`` defines the default set - of trusted root certificates. -\ No newline at end of file + of trusted root certificates. diff --git a/security/nss/gtests/pk11_gtest/pk11_kem_unittest.cc b/security/nss/gtests/pk11_gtest/pk11_kem_unittest.cc @@ -74,6 +74,9 @@ class Pkcs11KEMTest return CKM_NSS_KYBER_KEY_PAIR_GEN; case CKP_NSS_ML_KEM_768: return CKM_NSS_ML_KEM_KEY_PAIR_GEN; + case CKP_ML_KEM_768: + case CKP_ML_KEM_1024: + return CKM_ML_KEM_KEY_PAIR_GEN; default: EXPECT_TRUE(false); return 0; @@ -86,6 +89,9 @@ class Pkcs11KEMTest return CKM_NSS_KYBER; case CKP_NSS_ML_KEM_768: return CKM_NSS_ML_KEM; + case CKP_ML_KEM_768: + case CKP_ML_KEM_1024: + return CKM_ML_KEM; default: EXPECT_TRUE(false); return 0; @@ -99,6 +105,9 @@ TEST_P(Pkcs11KEMTest, KemConsistencyTest) { ScopedSECKEYPublicKey pub; generator.GenerateKey(&priv, &pub, false); + ASSERT_NE(nullptr, pub); + ASSERT_NE(nullptr, priv); + // Copy the public key to simulate receiving the key as an octet string ScopedSECKEYPublicKey pubCopy(SECKEY_CopyPublicKey(pub.get())); ASSERT_NE(nullptr, pubCopy); diff --git a/security/nss/gtests/pk11_gtest/pk11_keygen.cc b/security/nss/gtests/pk11_gtest/pk11_keygen.cc @@ -172,8 +172,12 @@ std::unique_ptr<ParamHolder> Pkcs11KeyPairGenerator::MakeParams() const { case CKM_NSS_ML_KEM_KEY_PAIR_GEN: std::cerr << "Generate ML-KEM768 pair" << std::endl; + return std::unique_ptr<ParamHolder>(new KyberParamHolder(CKP_ML_KEM_768)); + + case CKM_ML_KEM_KEY_PAIR_GEN: + std::cerr << "Generate ML-KEM1024 pair" << std::endl; return std::unique_ptr<ParamHolder>( - new KyberParamHolder(CKP_NSS_ML_KEM_768)); + new KyberParamHolder(CKP_ML_KEM_1024)); default: ADD_FAILURE() << "unknown OID " << mech_; diff --git a/security/nss/gtests/ssl_gtest/tls_agent.cc b/security/nss/gtests/ssl_gtest/tls_agent.cc @@ -519,15 +519,21 @@ void TlsAgent::DisableAllCiphers() { // Not actually all groups, just the ones that we are actually willing // to use. const std::vector<SSLNamedGroup> kAllDHEGroups = { - ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, - ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1, - ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072, - ssl_grp_ffdhe_4096, ssl_grp_ffdhe_6144, + ssl_grp_ec_curve25519, + ssl_grp_ec_secp256r1, + ssl_grp_ec_secp384r1, + ssl_grp_ec_secp521r1, + ssl_grp_ffdhe_2048, + ssl_grp_ffdhe_3072, + ssl_grp_ffdhe_4096, + ssl_grp_ffdhe_6144, ssl_grp_ffdhe_8192, #ifndef NSS_DISABLE_KYBER ssl_grp_kem_xyber768d00, #endif - ssl_grp_kem_mlkem768x25519, ssl_grp_kem_secp256r1mlkem768, + ssl_grp_kem_mlkem768x25519, + ssl_grp_kem_secp256r1mlkem768, + ssl_grp_kem_secp384r1mlkem1024, }; const std::vector<SSLNamedGroup> kNonPQDHEGroups = { @@ -537,12 +543,13 @@ const std::vector<SSLNamedGroup> kNonPQDHEGroups = { }; const std::vector<SSLNamedGroup> kECDHEGroups = { - ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, - ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1, + ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, + ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1, #ifndef NSS_DISABLE_KYBER ssl_grp_kem_xyber768d00, #endif - ssl_grp_kem_mlkem768x25519, ssl_grp_kem_secp256r1mlkem768, + ssl_grp_kem_mlkem768x25519, ssl_grp_kem_secp256r1mlkem768, + ssl_grp_kem_secp384r1mlkem1024, }; const std::vector<SSLNamedGroup> kFFDHEGroups = { @@ -551,13 +558,17 @@ const std::vector<SSLNamedGroup> kFFDHEGroups = { // Defined because the big DHE groups are ridiculously slow. const std::vector<SSLNamedGroup> kFasterDHEGroups = { - ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, - ssl_grp_ec_secp384r1, ssl_grp_ffdhe_2048, + ssl_grp_ec_curve25519, + ssl_grp_ec_secp256r1, + ssl_grp_ec_secp384r1, + ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072, #ifndef NSS_DISABLE_KYBER ssl_grp_kem_xyber768d00, #endif - ssl_grp_kem_mlkem768x25519, ssl_grp_kem_secp256r1mlkem768, + ssl_grp_kem_mlkem768x25519, + ssl_grp_kem_secp256r1mlkem768, + ssl_grp_kem_secp384r1mlkem1024, }; const std::vector<SSLNamedGroup> kEcdhHybridGroups = { @@ -566,6 +577,7 @@ const std::vector<SSLNamedGroup> kEcdhHybridGroups = { #endif ssl_grp_kem_mlkem768x25519, ssl_grp_kem_secp256r1mlkem768, + ssl_grp_kem_secp384r1mlkem1024, }; void TlsAgent::EnableCiphersByKeyExchange(SSLKEAType kea) { @@ -741,6 +753,7 @@ void TlsAgent::CheckKEA(SSLKEAType kea, SSLNamedGroup kea_group, case ssl_grp_ec_secp256r1: kea_size = 256; break; + case ssl_grp_kem_secp384r1mlkem1024: case ssl_grp_ec_secp384r1: kea_size = 384; break; diff --git a/security/nss/gtests/ssl_gtest/tls_mlkem_unittest.cc b/security/nss/gtests/ssl_gtest/tls_mlkem_unittest.cc @@ -39,6 +39,15 @@ TEST_P(TlsKeyExchangeTest13, Secp256r1Mlkem768Supported) { ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); } +TEST_P(TlsKeyExchangeTest13, Secp384r1Mlkem1024Supported) { + EnsureKeyShareSetup(); + ConfigNamedGroups({ssl_grp_kem_secp384r1mlkem1024}); + + Connect(); + CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_secp384r1mlkem1024, + ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); +} + TEST_P(TlsKeyExchangeTest, Tls12ClientMlkem768x25519NotSupported) { EnsureKeyShareSetup(); client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, @@ -57,6 +66,7 @@ TEST_P(TlsKeyExchangeTest, Tls12ClientMlkem768x25519NotSupported) { for (auto group : groups) { EXPECT_NE(group, ssl_grp_kem_mlkem768x25519); EXPECT_NE(group, ssl_grp_kem_secp256r1mlkem768); + EXPECT_NE(group, ssl_grp_kem_secp384r1mlkem1024); } } @@ -148,16 +158,36 @@ TEST_P(TlsKeyExchangeTest13, Secp256r1Mlkem768ServerDisabledByPolicy) { {ssl_grp_kem_secp256r1mlkem768}, ssl_grp_ec_secp256r1); } +TEST_P(TlsKeyExchangeTest13, Secp384r1Mlkem1024ClientDisabledByPolicy) { + EnsureKeyShareSetup(); + client_->SetPolicy(SEC_OID_SECP384R1MLKEM1024, 0, NSS_USE_ALG_IN_SSL_KX); + ConfigNamedGroups({ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp256r1}); + + Connect(); + CheckKEXDetails({ssl_grp_ec_secp256r1}, {ssl_grp_ec_secp256r1}); +} + +TEST_P(TlsKeyExchangeTest13, Secp384r1Mlkem1024ServerDisabledByPolicy) { + EnsureKeyShareSetup(); + server_->SetPolicy(SEC_OID_SECP384R1MLKEM1024, 0, NSS_USE_ALG_IN_SSL_KX); + ConfigNamedGroups({ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp256r1}); + + Connect(); + CheckKEXDetails({ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp256r1}, + {ssl_grp_kem_secp384r1mlkem1024}, ssl_grp_ec_secp256r1); +} + static void CheckECDHShareReuse( const std::shared_ptr<TlsExtensionCapture>& capture) { EXPECT_TRUE(capture->captured()); const DataBuffer& ext = capture->extension(); - DataBuffer hybrid_share[4]; - DataBuffer ecdh_share[4]; - int hybrid_offset[4]; - SSLNamedGroup hybrid_ec_type[4]; - SSLNamedGroup ec_type[4]; - int ecdh_index[4]; + const int max_count = 4; + DataBuffer hybrid_share[max_count]; + DataBuffer ecdh_share[max_count]; + int hybrid_offset[max_count]; + SSLNamedGroup hybrid_ec_type[max_count]; + SSLNamedGroup ec_type[max_count]; + int ecdh_index[max_count]; int nextHybrid = 0; int nextECDH = 0; @@ -199,8 +229,8 @@ static void CheckECDHShareReuse( } EXPECT_EQ(offset, ext.len()); - ASSERT_TRUE(nextECDH > 0); - ASSERT_TRUE(nextHybrid > 0); + ASSERT_TRUE(nextECDH <= max_count); + ASSERT_TRUE(nextHybrid <= max_count); /* setup the hybrid ecdh indeces */ for (int i = 0; i < nextHybrid; i++) { ecdh_index[i] = -1; @@ -272,6 +302,30 @@ TEST_P(TlsKeyExchangeTest13, Secp256r1Mlkem768ShareReuseSecond) { CheckECDHShareReuse(shares_capture_); } +TEST_P(TlsKeyExchangeTest13, Secp384r1Mlkem1024ShareReuseFirst) { + EnsureKeyShareSetup(); + ConfigNamedGroups({ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp384r1}); + EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); + + Connect(); + + CheckKEXDetails({ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp384r1}, + {ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp384r1}); + CheckECDHShareReuse(shares_capture_); +} + +TEST_P(TlsKeyExchangeTest13, Secp384r1Mlkem1024ShareReuseSecond) { + EnsureKeyShareSetup(); + ConfigNamedGroups({ssl_grp_ec_secp384r1, ssl_grp_kem_secp384r1mlkem1024}); + EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); + + Connect(); + + CheckKEXDetails({ssl_grp_ec_secp384r1, ssl_grp_kem_secp384r1mlkem1024}, + {ssl_grp_ec_secp384r1, ssl_grp_kem_secp384r1mlkem1024}); + CheckECDHShareReuse(shares_capture_); +} + class Mlkem768x25519ShareDamager : public TlsExtensionFilter { public: typedef enum { diff --git a/security/nss/lib/ckfw/builtins/certdata.py b/security/nss/lib/ckfw/builtins/certdata.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # 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 diff --git a/security/nss/lib/pk11wrap/pk11akey.c b/security/nss/lib/pk11wrap/pk11akey.c @@ -363,8 +363,13 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, #endif case params_ml_kem768: case params_ml_kem768_test_mode: - keyType = CKK_NSS_ML_KEM; - kemParams = CKP_NSS_ML_KEM_768; + keyType = CKK_ML_KEM; + kemParams = CKP_ML_KEM_768; + break; + case params_ml_kem1024: + case params_ml_kem1024_test_mode: + keyType = CKK_ML_KEM; + kemParams = CKP_ML_KEM_1024; break; default: kemParams = CKP_INVALID_ID; @@ -1024,8 +1029,12 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot, KeyType keyType, CK_OBJECT_HANDLE id) break; #endif case CKP_NSS_ML_KEM_768: + case CKP_ML_KEM_768: pubKey->u.kyber.params = params_ml_kem768; break; + case CKP_ML_KEM_1024: + pubKey->u.kyber.params = params_ml_kem1024; + break; default: pubKey->u.kyber.params = params_kyber_invalid; break; diff --git a/security/nss/lib/pk11wrap/pk11pars.c b/security/nss/lib/pk11wrap/pk11pars.c @@ -256,6 +256,8 @@ static const oidValDef curveOptList[] = { NSS_USE_ALG_IN_SSL_KX }, { CIPHER_NAME("SECP256R1MLKEM768"), SEC_OID_SECP256R1MLKEM768, NSS_USE_ALG_IN_SSL_KX }, + { CIPHER_NAME("SECP384R1MLKEM1024"), SEC_OID_SECP384R1MLKEM1024, + NSS_USE_ALG_IN_SSL_KX }, { CIPHER_NAME("MLKEM768X25519"), SEC_OID_MLKEM768X25519, NSS_USE_ALG_IN_SSL_KX }, /* ANSI X9.62 named elliptic curves (characteristic two field) */ diff --git a/security/nss/lib/softoken/kem.c b/security/nss/lib/softoken/kem.c @@ -25,6 +25,8 @@ sftk_kyber_PK11ParamToInternal(CK_ML_KEM_PARAMETER_SET_TYPE pk11ParamSet) case CKP_NSS_ML_KEM_768: case CKP_ML_KEM_768: return params_ml_kem768; + case CKP_ML_KEM_1024: + return params_ml_kem1024; default: return params_kyber_invalid; } @@ -41,6 +43,9 @@ sftk_kyber_AllocPubKeyItem(KyberParams params, SECItem *pubkey) case params_ml_kem768: case params_ml_kem768_test_mode: return SECITEM_AllocItem(NULL, pubkey, KYBER768_PUBLIC_KEY_BYTES); + case params_ml_kem1024: + case params_ml_kem1024_test_mode: + return SECITEM_AllocItem(NULL, pubkey, MLKEM1024_PUBLIC_KEY_BYTES); default: return NULL; } @@ -57,6 +62,9 @@ sftk_kyber_AllocPrivKeyItem(KyberParams params, SECItem *privkey) case params_ml_kem768: case params_ml_kem768_test_mode: return SECITEM_AllocItem(NULL, privkey, KYBER768_PRIVATE_KEY_BYTES); + case params_ml_kem1024: + case params_ml_kem1024_test_mode: + return SECITEM_AllocItem(NULL, privkey, MLKEM1024_PRIVATE_KEY_BYTES); default: return NULL; } @@ -73,6 +81,9 @@ sftk_kyber_AllocCiphertextItem(KyberParams params, SECItem *ciphertext) case params_ml_kem768: case params_ml_kem768_test_mode: return SECITEM_AllocItem(NULL, ciphertext, KYBER768_CIPHERTEXT_BYTES); + case params_ml_kem1024: + case params_ml_kem1024_test_mode: + return SECITEM_AllocItem(NULL, ciphertext, MLKEM1024_CIPHERTEXT_BYTES); default: return NULL; } @@ -161,6 +172,8 @@ sftk_kem_CiphertextLen(CK_MECHANISM_PTR pMechanism, CK_ULONG paramSet) case CKP_NSS_ML_KEM_768: case CKP_ML_KEM_768: return KYBER768_CIPHERTEXT_BYTES; + case CKP_ML_KEM_1024: + return MLKEM1024_CIPHERTEXT_BYTES; default: break; } diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h @@ -132,7 +132,7 @@ typedef enum { SSLAppOpRead = 0, #define DTLS_RETRANSMIT_FINISHED_MS 30000 /* default number of entries in namedGroupPreferences */ -#define SSL_NAMED_GROUP_COUNT 34 +#define SSL_NAMED_GROUP_COUNT 35 /* The maximum DH and RSA bit-length supported. */ #define SSL_MAX_DH_KEY_BITS 8192 diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c @@ -173,6 +173,7 @@ const sslNamedGroupDef ssl_named_groups[] = { ECGROUP(secp384r1, 384, SECP384R1, PR_TRUE), ECGROUP(secp521r1, 521, SECP521R1, PR_TRUE), HYGROUP(secp256r1, mlkem768, 256, SECP256R1, MLKEM768, PR_TRUE), + HYGROUP(secp384r1, mlkem1024, 256, SECP384R1, MLKEM1024, PR_TRUE), { ssl_grp_kem_xyber768d00, 256, ssl_kea_ecdh_hybrid, SEC_OID_XYBER768D00, PR_FALSE }, FFGROUP(2048), FFGROUP(3072), @@ -206,6 +207,7 @@ PR_STATIC_ASSERT(SSL_NAMED_GROUP_COUNT == PR_ARRAY_SIZE(ssl_named_groups)); #undef ECGROUP #undef FFGROUP +#undef HYGROUP /* forward declarations. */ static sslSocket *ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant variant); diff --git a/security/nss/lib/ssl/sslt.h b/security/nss/lib/ssl/sslt.h @@ -261,6 +261,7 @@ typedef enum { ssl_grp_ffdhe_6144 = 259, ssl_grp_ffdhe_8192 = 260, ssl_grp_kem_secp256r1mlkem768 = 4587, + ssl_grp_kem_secp384r1mlkem1024 = 4589, ssl_grp_kem_mlkem768x25519 = 4588, ssl_grp_kem_xyber768d00 = 25497, /* draft-tls-westerbaan-xyber768d00-02 */ ssl_grp_none = 65537, /* special value */ diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c @@ -391,6 +391,10 @@ tls13_CreateKEMKeyPair(sslSocket *ss, const sslNamedGroupDef *groupDef, mechanism = CKM_ML_KEM_KEY_PAIR_GEN; paramSet = CKP_ML_KEM_768; break; + case ssl_grp_kem_secp384r1mlkem1024: + mechanism = CKM_ML_KEM_KEY_PAIR_GEN; + paramSet = CKP_ML_KEM_1024; + break; default: PORT_Assert(0); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); @@ -495,6 +499,10 @@ tls13_FindHybridKeyPair(sslSocket *ss, const sslNamedGroupDef *groupDef) hybridPair = ssl_LookupEphemeralKeyPair(ss, ssl_LookupNamedGroup(ssl_grp_kem_secp256r1mlkem768)); break; + case ssl_grp_ec_secp384r1: + hybridPair = ssl_LookupEphemeralKeyPair(ss, + ssl_LookupNamedGroup(ssl_grp_kem_secp384r1mlkem1024)); + break; case ssl_grp_ec_curve25519: { /* a loop to check multiple named groups */ SSLNamedGroup gnames[] = { ssl_grp_kem_xyber768d00, @@ -531,6 +539,9 @@ tls13_CreateKeyShare(sslSocket *ss, const sslNamedGroupDef *groupDef, case ssl_grp_kem_secp256r1mlkem768: ecGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp256r1); break; + case ssl_grp_kem_secp384r1mlkem1024: + ecGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp384r1); + break; case ssl_grp_kem_xyber768d00: case ssl_grp_kem_mlkem768x25519: ecGroup = ssl_LookupNamedGroup(ssl_grp_ec_curve25519); @@ -781,6 +792,9 @@ tls13_ImportKEMKeyShare(SECKEYPublicKey *peerKey, TLS13KeyShareEntry *entry) case ssl_grp_kem_secp256r1mlkem768: expected_len = SECP256_PUBLIC_KEY_BYTES + KYBER768_PUBLIC_KEY_BYTES; break; + case ssl_grp_kem_secp384r1mlkem1024: + expected_len = SECP384_PUBLIC_KEY_BYTES + MLKEM1024_PUBLIC_KEY_BYTES; + break; default: PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); return SECFailure; @@ -813,6 +827,13 @@ tls13_ImportKEMKeyShare(SECKEYPublicKey *peerKey, TLS13KeyShareEntry *entry) pk.data = entry->key_exchange.data + SECP256_PUBLIC_KEY_BYTES; pk.len = KYBER768_PUBLIC_KEY_BYTES; break; + case ssl_grp_kem_secp384r1mlkem1024: + peerKey->keyType = kyberKey; + peerKey->u.kyber.params = params_ml_kem1024; + /* key_exchange.data is `secp384 || mlkem1024` */ + pk.data = entry->key_exchange.data + SECP384_PUBLIC_KEY_BYTES; + pk.len = MLKEM1024_PUBLIC_KEY_BYTES; + break; default: PORT_Assert(0); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); @@ -859,6 +880,14 @@ tls13_HandleKEMCiphertext(sslSocket *ss, TLS13KeyShareEntry *entry, sslKeyPair * ct.data = entry->key_exchange.data + SECP256_PUBLIC_KEY_BYTES; ct.len = KYBER768_CIPHERTEXT_BYTES; break; + case ssl_grp_kem_secp384r1mlkem1024: + if (entry->key_exchange.len != SECP384_PUBLIC_KEY_BYTES + MLKEM1024_CIPHERTEXT_BYTES) { + ssl_MapLowLevelError(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE); + return SECFailure; + } + ct.data = entry->key_exchange.data + SECP384_PUBLIC_KEY_BYTES; + ct.len = MLKEM1024_CIPHERTEXT_BYTES; + break; default: PORT_Assert(0); ssl_MapLowLevelError(SEC_ERROR_LIBRARY_FAILURE); @@ -990,6 +1019,14 @@ tls13_HandleKeyShare(sslSocket *ss, : entry->key_exchange.data; ecGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp256r1); break; + case ssl_grp_kem_secp384r1mlkem1024: + ec_len = SECP384_PUBLIC_KEY_BYTES; + /* secp384 share is at the beginning */ + ec_data = entry->key_exchange.len < ec_len + ? NULL + : entry->key_exchange.data; + ecGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp256r1); + break; default: ec_data = NULL; break; @@ -2869,6 +2906,7 @@ tls13_HandleClientKeyShare(sslSocket *ss, TLS13KeyShareEntry *peerShare) goto loser; /* Error set by tls13_HandleKEMKey */ } switch (peerShare->group->name) { + case ssl_grp_kem_secp384r1mlkem1024: case ssl_grp_kem_secp256r1mlkem768: case ssl_grp_kem_xyber768d00: ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(dheSecret, kemSecret, CKM_HKDF_DERIVE, CKA_DERIVE); @@ -3729,6 +3767,7 @@ tls13_HandleServerKeyShare(sslSocket *ss) goto loser; /* Error set by tls13_HandleKEMCiphertext */ } switch (entry->group->name) { + case ssl_grp_kem_secp384r1mlkem1024: case ssl_grp_kem_secp256r1mlkem768: case ssl_grp_kem_xyber768d00: ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(dheSecret, kemSecret, CKM_HKDF_DERIVE, CKA_DERIVE); diff --git a/security/nss/lib/ssl/tls13exthandle.c b/security/nss/lib/ssl/tls13exthandle.c @@ -82,7 +82,8 @@ tls13_SizeOfKeyShareEntry(const sslEphemeralKeyPair *keyPair) PORT_Assert(!keyPair->kemCt); PORT_Assert(keyPair->group->name == ssl_grp_kem_xyber768d00 || keyPair->group->name == ssl_grp_kem_mlkem768x25519 || - keyPair->group->name == ssl_grp_kem_secp256r1mlkem768); + keyPair->group->name == ssl_grp_kem_secp256r1mlkem768 || + keyPair->group->name == ssl_grp_kem_secp384r1mlkem1024); pubKey = keyPair->kemKeys->pubKey; size += pubKey->u.kyber.publicValue.len; } @@ -90,7 +91,8 @@ tls13_SizeOfKeyShareEntry(const sslEphemeralKeyPair *keyPair) PORT_Assert(!keyPair->kemKeys); PORT_Assert(keyPair->group->name == ssl_grp_kem_xyber768d00 || keyPair->group->name == ssl_grp_kem_mlkem768x25519 || - keyPair->group->name == ssl_grp_kem_secp256r1mlkem768); + keyPair->group->name == ssl_grp_kem_secp256r1mlkem768 || + keyPair->group->name == ssl_grp_kem_secp384r1mlkem1024); size += keyPair->kemCt->len; } @@ -101,7 +103,8 @@ static SECStatus tls13_WriteHybridECCKeyFirst(sslBuffer *buf, sslEphemeralKeyPair *keyPair) { PORT_Assert(keyPair->group->name == ssl_grp_kem_xyber768d00 || - keyPair->group->name == ssl_grp_kem_secp256r1mlkem768); + keyPair->group->name == ssl_grp_kem_secp256r1mlkem768 || + keyPair->group->name == ssl_grp_kem_secp384r1mlkem1024); PORT_Assert(keyPair->keys->pubKey->keyType == ecKey); // Encode the ecc share first, then the MLKEM key or ciphertext. @@ -196,6 +199,7 @@ tls13_EncodeKeyShareEntry(sslBuffer *buf, sslEphemeralKeyPair *keyPair) rv = tls13_WriteHybridHybridKeyFirst(buf, keyPair); break; case ssl_grp_kem_secp256r1mlkem768: + case ssl_grp_kem_secp384r1mlkem1024: case ssl_grp_kem_xyber768d00: rv = tls13_WriteHybridECCKeyFirst(buf, keyPair); break; diff --git a/security/nss/lib/util/eccutil.h b/security/nss/lib/util/eccutil.h @@ -7,6 +7,7 @@ #define X25519_PUBLIC_KEY_BYTES 32U #define SECP256_PUBLIC_KEY_BYTES 65U +#define SECP384_PUBLIC_KEY_BYTES 97U /* deprecated */ typedef enum { diff --git a/security/nss/lib/util/secoid.c b/security/nss/lib/util/secoid.c @@ -1914,6 +1914,8 @@ const static SECOidData oids[SEC_OID_TOTAL] = { OD(mlDsa87, SEC_OID_ML_DSA_87, "ML-DSA-87", CKM_ML_DSA, INVALID_CERT_EXTENSION), ODE(SEC_OID_SECP256R1MLKEM768, "SECP256R1+ML-KEM-768 Hybrid key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION), + ODE(SEC_OID_SECP384R1MLKEM1024, + "SECP384R1+ML-KEM-1024 Hybrid key exchange", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION), }; diff --git a/security/nss/lib/util/secoidt.h b/security/nss/lib/util/secoidt.h @@ -540,6 +540,7 @@ typedef enum { SEC_OID_ML_DSA_87 = 393, SEC_OID_SECP256R1MLKEM768 = 394, + SEC_OID_SECP384R1MLKEM1024 = 395, SEC_OID_TOTAL } SECOidTag; diff --git a/security/nss/mach b/security/nss/mach @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # 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 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: 415413a2f83f1652586df85083d2219172eec15c (2025-10-15T00:41:30Z). - revision: 415413a2f83f1652586df85083d2219172eec15c + release: cd2ce1a24014a9afaff0df7b484f6065d845de7a (2025-10-29T01:57:49Z). + revision: cd2ce1a24014a9afaff0df7b484f6065d845de7a license: MPL-2.0 license-file: COPYING diff --git a/security/nss/tests/ssl/ssl.sh b/security/nss/tests/ssl/ssl.sh @@ -124,9 +124,9 @@ ssl_init() # in fips mode, turn off curve25519 until it's NIST approved FIPS_OPTIONS="" # in fips mode, turn off curve25519 until it's NIST approved - ALL_GROUPS="P256,P384,P521,x25519,FF2048,FF3072,FF4096,FF6144,FF8192,xyber768d00,x25519mlkem768,secp256r1mlkem768" + ALL_GROUPS="P256,P384,P521,x25519,FF2048,FF3072,FF4096,FF6144,FF8192,xyber768d00,x25519mlkem768,secp256r1mlkem768,secp384r1mlkem1024" NON_PQ_GROUPS="P256,P384,P521,x25519,FF2048,FF3072,FF4096,FF6144,FF8192" - FIPS_GROUPS="P256,P384,P521,FF2048,FF3072,FF4096,FF6144,FF8192,mx25519mlkem768,secp256r1mlkem768" + FIPS_GROUPS="P256,P384,P521,FF2048,FF3072,FF4096,FF6144,FF8192,mx25519mlkem768,secp256r1mlkem768,secp384r1mlkem1024" FIPS_NON_PQ_GROUPS="P256,P384,P521,FF2048,FF3072,FF4096,FF6144,FF8192" @@ -390,6 +390,8 @@ ssl_cov() TLS_GROUPS="x25519mlkem768" elif [ "$ectype" = "MLKEM256" ]; then TLS_GROUPS="secp256r1mlkem768" + elif [ "$ectype" = "MLKEM384" ]; then + TLS_GROUPS="secp384r1mlkem1024" fi echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -I \"${TLS_GROUPS}\" -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} \\" diff --git a/security/nss/tests/ssl/sslcov.txt b/security/nss/tests/ssl/sslcov.txt @@ -159,6 +159,9 @@ MLKEM219 TLS13 :1303 ECC TLS13_X25519MLKEM768_WITH_CHACHA20_POLY1305_SHA256 MLKEM256 TLS13 :1301 ECC TLS13_SECP256R1MLKEM768_WITH_AES_128_GCM_SHA256 MLKEM256 TLS13 :1302 ECC TLS13_SECP256R1MLKEM768_WITH_AES_256_GCM_SHA384 MLKEM256 TLS13 :1303 ECC TLS13_SECP256R1MLKEM768_WITH_CHACHA20_POLY1305_SHA256 +MLKEM384 TLS13 :1301 ECC TLS13_SECP384R1MLKEM1024_WITH_AES_128_GCM_SHA256 +MLKEM384 TLS13 :1302 ECC TLS13_SECP384R1MLKEM1024_WITH_AES_256_GCM_SHA384 +MLKEM384 TLS13 :1303 ECC TLS13_SECP384R1MLKEM1024_WITH_CHACHA20_POLY1305_SHA256 # need to turn on policy in selfserv/tstclnt to make these work #XYBER TLS13 :1301 ECC TLS13_XYBER768D00_WITH_AES_128_GCM_SHA256 #XYBER TLS13 :1302 ECC TLS13_XYBER768D00_WITH_AES_256_GCM_SHA384