Blob Blame History Raw
# HG changeset patch
# User Daiki Ueno <dueno@redhat.com>
# Date 1542120846 -3600
#      Tue Nov 13 15:54:06 2018 +0100
# Node ID 5046749fa8a56a99c251bc1cdd1b3302f43947d2
# Parent  0d97145d524ab35b8bc2a4a8aea60a83bd244f14
Bug 1493936, add a new "DSA" policy keyword

Summary:
This adds a new policy keyword "DSA" to explicitly disable DSA in TLS 1.2 or earlier.

We could make this a bit more generic, e.g., by adding "ECDSA", "RSA-PSS" etc.   However, considering the current use of policy in [fedora-crypto-policies](https://gitlab.com/redhat-crypto/fedora-crypto-policies), I realized that adding new keywords may cause compatibility problems; because the Fedora configuration has `disallow=ALL`, all new keywords would be disabled by default.   I think it's okay for DSA, though.

Reviewers: kaie

Reviewed By: kaie

Bug #: 1493936

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

diff --git a/lib/certhigh/certvfy.c b/lib/certhigh/certvfy.c
--- a/lib/certhigh/certvfy.c
+++ b/lib/certhigh/certvfy.c
@@ -37,7 +37,7 @@ CERT_CertTimesValid(CERTCertificate *c)
     return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
 }
 
-SECStatus
+static SECStatus
 checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
 {
     SECStatus rv;
@@ -47,6 +47,12 @@ checkKeyParams(const SECAlgorithmID *sig
     PRInt32 minLen, len;
 
     sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
+    rv = NSS_GetAlgorithmPolicy(sigAlg, &policyFlags);
+    if (rv == SECSuccess &&
+        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
+        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
+        return SECFailure;
+    }
 
     switch (sigAlg) {
         case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
diff --git a/lib/pk11wrap/pk11pars.c b/lib/pk11wrap/pk11pars.c
--- a/lib/pk11wrap/pk11pars.c
+++ b/lib/pk11wrap/pk11pars.c
@@ -384,18 +384,26 @@ static const oidValDef kxOptList[] = {
     { CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX },
 };
 
+static const oidValDef signOptList[] = {
+    /* Signatures */
+    { CIPHER_NAME("DSA"), SEC_OID_ANSIX9_DSA_SIGNATURE,
+      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
+};
+
 typedef struct {
     const oidValDef *list;
     PRUint32 entries;
     const char *description;
+    PRBool allowEmpty;
 } algListsDef;
 
 static const algListsDef algOptLists[] = {
-    { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC" },
-    { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH" },
-    { macOptList, PR_ARRAY_SIZE(macOptList), "MAC" },
-    { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER" },
-    { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX" },
+    { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC", PR_FALSE },
+    { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH", PR_FALSE },
+    { macOptList, PR_ARRAY_SIZE(macOptList), "MAC", PR_FALSE },
+    { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER", PR_FALSE },
+    { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX", PR_FALSE },
+    { signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_TRUE },
 };
 
 static const optionFreeDef sslOptList[] = {
@@ -718,7 +726,7 @@ secmod_sanityCheckCryptoPolicy(void)
     for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
         const algListsDef *algOptList = &algOptLists[i];
         fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]);
-        if (!enabledCount[i]) {
+        if (!enabledCount[i] && !algOptList->allowEmpty) {
             haveWarning = PR_TRUE;
         }
     }
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -64,6 +64,7 @@ static SECStatus ssl3_FlushHandshakeMess
 static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType);
 static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash);
 PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme);
+PRBool ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme);
 
 const PRUint8 ssl_hello_retry_random[] = {
     0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
@@ -4309,6 +4310,22 @@ ssl_IsRsaPssSignatureScheme(SSLSignature
     return PR_FALSE;
 }
 
+PRBool
+ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme)
+{
+    switch (scheme) {
+        case ssl_sig_dsa_sha256:
+        case ssl_sig_dsa_sha384:
+        case ssl_sig_dsa_sha512:
+        case ssl_sig_dsa_sha1:
+            return PR_TRUE;
+
+        default:
+            return PR_FALSE;
+    }
+    return PR_FALSE;
+}
+
 SSLAuthType
 ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
 {
@@ -6017,6 +6034,13 @@ ssl_CanUseSignatureScheme(SSLSignatureSc
         return PR_FALSE;
     }
 
+    if (ssl_IsDsaSignatureScheme(scheme) &&
+        (NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) ==
+         SECSuccess) &&
+        !(policy & NSS_USE_ALG_IN_SSL_KX)) {
+        return PR_FALSE;
+    }
+
     hashType = ssl_SignatureSchemeToHashType(scheme);
     if (requireSha1 && (hashType != ssl_hash_sha1)) {
         return PR_FALSE;
@@ -9490,6 +9514,14 @@ ssl3_EncodeSigAlgs(const sslSocket *ss, 
             continue;
         }
 
+        /* Skip DSA scheme if it is disabled by policy. */
+        if (ssl_IsDsaSignatureScheme(ss->ssl3.signatureSchemes[i]) &&
+            (NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) ==
+             SECSuccess) &&
+            !(policy & NSS_USE_ALG_IN_SSL_KX)) {
+            continue;
+        }
+
         if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess) ||
             (policy & NSS_USE_ALG_IN_SSL_KX)) {
             rv = sslBuffer_AppendNumber(buf, ss->ssl3.signatureSchemes[i], 2);
diff --git a/tests/ssl/sslpolicy.txt b/tests/ssl/sslpolicy.txt
--- a/tests/ssl/sslpolicy.txt
+++ b/tests/ssl/sslpolicy.txt
@@ -74,6 +74,8 @@
 #	SECT409R1
 #	SECT571K1
 #	SECT571R1
+# Signatures:
+#	DSA
 # Hashes:
 #	MD2
 #	MD4
@@ -172,3 +174,4 @@
   1 noECC  SSL3   d    allow=tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Exlicitly
   1 noECC  SSL3   d    disallow=all_allow=hmac-sha1:sha256:rsa:des-ede3-cbc:tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Implicitly Narrow.
   1 noECC  SSL3   d    disallow=all_allow=md2/all:md4/all:md5/all:sha1/all:sha256/all:sha384/all:sha512/all:hmac-sha1/all:hmac-sha224/all:hmac-sha256/all:hmac-sha384/all:hmac-sha512/all:hmac-md5/all:camellia128-cbc/all:camellia192-cbc/all:camellia256-cbc/all:seed-cbc/all:des-ede3-cbc/all:des-40-cbc/all:des-cbc/all:null-cipher/all:rc2/all:rc4/all:idea/all:rsa/all:rsa-export/all:dhe-rsa/all:dhe-dss/all:ecdhe-ecdsa/all:ecdhe-rsa/all:ecdh-ecdsa/all:ecdh-rsa/all:tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Implicitly.
+  0 noECC  SSL3   d    disallow=dsa Disallow DSA Signatures Explicitly.