Skip to content

Commit 3c18fbd

Browse files
committed
feat(manager/ssl,browser/components): Disable ML-DSA by default in TLS and certificate signatures
- Added a new configuration option (about:config) to enable the use of ML-DSA in TLS protocol. The option affects also the policy of enabled algorithms for certificate signatures. - mozpkix's VerifySignedData rejects a signature algorithm only if the bitflag NSS_USE_ALG_IN_SIGNATURE is not set. - NSS's algorithms policies provide also the bitflag NSS_USE_ALG_IN_CERT_SIGNATURE but it's not being checked by VerifySignedData. That flag is checked by certvfy component for signing certificates (e.g., normal NSS tooling operations). - The new option security.tls.enable_mldsa is set to false by defaut. - An ML-DSA signature algorithm used in the handshake will cause a SEC_ERROR_SSL_CYPHER_NO_OVERLAP error. Instead when it's being used in certificate signatures it will cause a SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED error. Signed-off-by: Francesco Rollo <eferollo@gmail.com>
1 parent 4ac0ffe commit 3c18fbd

File tree

3 files changed

+84
-7
lines changed

3 files changed

+84
-7
lines changed

modules/libpref/init/StaticPrefList.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17430,6 +17430,18 @@
1743017430
mirror: always
1743117431
rust: true
1743217432

17433+
# Controls whether pure ML-DSA signature algorithms are enabled for TLS and
17434+
# certificate signatures (for verifying certificate chains).
17435+
# When true, Firefox explicitly enables ML-DSA at the NSS algorithm-policy
17436+
# level (SECOid) and at the TLS sigalg-policy level.
17437+
# When false (the default), Firefox explicitly disables ML-DSA via NSS
17438+
# policies, rather than relying on NSS defaults, to remain robust if
17439+
# NSS policy defaults change in the future.
17440+
- name: security.tls.enable_mldsa
17441+
type: RelaxedAtomicBool
17442+
value: false
17443+
mirror: always
17444+
1743317445
- name: security.tls.client_hello.send_p256_keyshare
1743417446
type: RelaxedAtomicBool
1743517447
value: @IS_NOT_NIGHTLY_BUILD@

security/manager/ssl/nsNSSComponent.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,56 @@ void SetKyberPolicy() {
10121012
}
10131013
}
10141014

1015+
/*
1016+
* Enable ML-DSA at the lowest NSS (SECOid) level for all signature uses and
1017+
* configure the required policy flags so ML-DSA can be selected during
1018+
* the TLS handshake.
1019+
*/
1020+
void SetMlDsaPolicy() {
1021+
if (StaticPrefs::security_tls_enable_mldsa()) {
1022+
/*
1023+
* Enable ML-DSA for all signature contexts at the NSS algorithm policy
1024+
* level. NSS_USE_ALG_IN_SIGNATURE expands to allow use in certificates,
1025+
* S/MIME, and any other signature operations.
1026+
*
1027+
* #define NSS_USE_ALG_IN_SIGNATURE (NSS_USE_ALG_IN_CERT_SIGNATURE | \
1028+
* NSS_USE_ALG_IN_SMIME_SIGNATURE | \
1029+
* NSS_USE_ALG_IN_ANY_SIGNATURE)
1030+
*/
1031+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_44, NSS_USE_ALG_IN_SIGNATURE, 0);
1032+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_65, NSS_USE_ALG_IN_SIGNATURE, 0);
1033+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_87, NSS_USE_ALG_IN_SIGNATURE, 0);
1034+
/*
1035+
* For TLS signature schemes, NSS requires both
1036+
* NSS_USE_ALG_IN_ANY_SIGNATURE and NSS_USE_ALG_IN_SSL_KX to be set.
1037+
*
1038+
* Although NSS_USE_ALG_IN_SSL_KX does not semantically apply to signature
1039+
* algorithms, the TLS policy checks expect this flag to be present in
1040+
* order to enable the algorithm during handshake negotiation.
1041+
*
1042+
* const PRUint32 kSSLSigSchemePolicy =
1043+
* NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_ANY_SIGNATURE;
1044+
*/
1045+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_44, NSS_USE_ALG_IN_SSL_KX, 0);
1046+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_65, NSS_USE_ALG_IN_SSL_KX, 0);
1047+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_87, NSS_USE_ALG_IN_SSL_KX, 0);
1048+
} else {
1049+
/*
1050+
* Pure ML-DSA is currently disabled by default in NSS, and Firefox also
1051+
* sets security.tls.enable_mldsa to false by default. If NSS's default
1052+
* policies change in the future, this branch ensures that ML-DSA can still
1053+
* be explicitly disabled, rather than assuming it remains disabled by NSS.
1054+
*/
1055+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_44, 0, NSS_USE_ALG_IN_SIGNATURE);
1056+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_65, 0, NSS_USE_ALG_IN_SIGNATURE);
1057+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_87, 0, NSS_USE_ALG_IN_SIGNATURE);
1058+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_44, 0, NSS_USE_ALG_IN_SSL_KX);
1059+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_65, 0, NSS_USE_ALG_IN_SSL_KX);
1060+
NSS_SetAlgorithmPolicy(SEC_OID_ML_DSA_87, 0, NSS_USE_ALG_IN_SSL_KX);
1061+
}
1062+
}
1063+
1064+
10151065
nsresult CipherSuiteChangeObserver::Observe(nsISupports* /*aSubject*/,
10161066
const char* aTopic,
10171067
const char16_t* someData) {
@@ -1029,6 +1079,7 @@ nsresult CipherSuiteChangeObserver::Observe(nsISupports* /*aSubject*/,
10291079
}
10301080
SetDeprecatedTLS1CipherPrefs();
10311081
SetKyberPolicy();
1082+
SetMlDsaPolicy();
10321083
nsNSSComponent::DoClearSSLExternalAndInternalSessionCache();
10331084
} else if (nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
10341085
Preferences::RemoveObserver(this, "security.");
@@ -2252,6 +2303,7 @@ nsresult InitializeCipherSuite() {
22522303
NSS_OptionSet(NSS_RSA_MIN_KEY_SIZE, 512);
22532304

22542305
SetKyberPolicy();
2306+
SetMlDsaPolicy();
22552307

22562308
// Observe preference change around cipher suite setting.
22572309
return CipherSuiteChangeObserver::StartObserve();

security/manager/ssl/nsNSSIOLayer.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "sslerr.h"
5454
#include "sslexp.h"
5555
#include "sslproto.h"
56+
#include "sslt.h"
5657
#include "zlib.h"
5758
#include "brotli/decode.h"
5859
#include "zstd/zstd.h"
@@ -1301,9 +1302,6 @@ static PRFileDesc* nsSSLIOLayerImportFD(PRFileDesc* fd,
13011302
// here. See NOTE at SSL_SignatureSchemePrefSet call site.
13021303
static const SSLSignatureScheme sEnabledSignatureSchemes[] = {
13031304
ssl_sig_mldsa65_ed25519,
1304-
ssl_sig_mldsa87,
1305-
ssl_sig_mldsa65,
1306-
ssl_sig_mldsa44,
13071305
ssl_sig_ecdsa_secp256r1_sha256,
13081306
ssl_sig_ecdsa_secp384r1_sha384,
13091307
ssl_sig_ecdsa_secp521r1_sha512,
@@ -1681,10 +1679,25 @@ static nsresult nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS,
16811679
// is properly rejected. NSS will not advertise PKCS1 or RSAE schemes (which
16821680
// the |ssl_sig_rsa_pss_*| defines alias, meaning we will not currently accept
16831681
// any RSA DC.
1684-
if (SECSuccess !=
1685-
SSL_SignatureSchemePrefSet(fd, sEnabledSignatureSchemes,
1686-
std::size(sEnabledSignatureSchemes))) {
1687-
return NS_ERROR_FAILURE;
1682+
if (StaticPrefs::security_tls_enable_mldsa() &&
1683+
range.max >= SSL_LIBRARY_VERSION_TLS_1_3) {
1684+
std::vector<SSLSignatureScheme> sigSchemes(std::begin(sEnabledSignatureSchemes),
1685+
std::end(sEnabledSignatureSchemes));
1686+
sigSchemes.push_back(ssl_sig_mldsa44);
1687+
sigSchemes.push_back(ssl_sig_mldsa65);
1688+
sigSchemes.push_back(ssl_sig_mldsa87);
1689+
if (SECSuccess != SSL_SignatureSchemePrefSet(fd,
1690+
sigSchemes.data(),
1691+
sigSchemes.size())) {
1692+
return NS_ERROR_FAILURE;
1693+
}
1694+
} else {
1695+
/* Fallback to default enabled signature schemes */
1696+
if (SECSuccess !=
1697+
SSL_SignatureSchemePrefSet(fd, sEnabledSignatureSchemes,
1698+
std::size(sEnabledSignatureSchemes))) {
1699+
return NS_ERROR_FAILURE;
1700+
}
16881701
}
16891702

16901703
bool enabled = StaticPrefs::security_ssl_enable_ocsp_stapling();

0 commit comments

Comments
 (0)