76e454
# HG changeset patch
76e454
# User Daiki Ueno <dueno@redhat.com>
76e454
# Date 1542120846 -3600
76e454
#      Tue Nov 13 15:54:06 2018 +0100
76e454
# Node ID 5046749fa8a56a99c251bc1cdd1b3302f43947d2
76e454
# Parent  0d97145d524ab35b8bc2a4a8aea60a83bd244f14
76e454
Bug 1493936, add a new "DSA" policy keyword
76e454
76e454
Summary:
76e454
This adds a new policy keyword "DSA" to explicitly disable DSA in TLS 1.2 or earlier.
76e454
76e454
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.
76e454
76e454
Reviewers: kaie
76e454
76e454
Reviewed By: kaie
76e454
76e454
Bug #: 1493936
76e454
76e454
Differential Revision: https://phabricator.services.mozilla.com/D6777
76e454
76e454
diff --git a/lib/certhigh/certvfy.c b/lib/certhigh/certvfy.c
76e454
--- a/lib/certhigh/certvfy.c
76e454
+++ b/lib/certhigh/certvfy.c
76e454
@@ -37,7 +37,7 @@ CERT_CertTimesValid(CERTCertificate *c)
76e454
     return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
76e454
 }
76e454
 
76e454
-SECStatus
76e454
+static SECStatus
76e454
 checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
76e454
 {
76e454
     SECStatus rv;
76e454
@@ -47,6 +47,12 @@ checkKeyParams(const SECAlgorithmID *sig
76e454
     PRInt32 minLen, len;
76e454
 
76e454
     sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
76e454
+    rv = NSS_GetAlgorithmPolicy(sigAlg, &policyFlags);
76e454
+    if (rv == SECSuccess &&
76e454
+        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
76e454
+        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
76e454
+        return SECFailure;
76e454
+    }
76e454
 
76e454
     switch (sigAlg) {
76e454
         case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
76e454
diff --git a/lib/pk11wrap/pk11pars.c b/lib/pk11wrap/pk11pars.c
76e454
--- a/lib/pk11wrap/pk11pars.c
76e454
+++ b/lib/pk11wrap/pk11pars.c
76e454
@@ -384,18 +384,26 @@ static const oidValDef kxOptList[] = {
76e454
     { CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX },
76e454
 };
76e454
 
76e454
+static const oidValDef signOptList[] = {
76e454
+    /* Signatures */
76e454
+    { CIPHER_NAME("DSA"), SEC_OID_ANSIX9_DSA_SIGNATURE,
76e454
+      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
76e454
+};
76e454
+
76e454
 typedef struct {
76e454
     const oidValDef *list;
76e454
     PRUint32 entries;
76e454
     const char *description;
76e454
+    PRBool allowEmpty;
76e454
 } algListsDef;
76e454
 
76e454
 static const algListsDef algOptLists[] = {
76e454
-    { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC" },
76e454
-    { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH" },
76e454
-    { macOptList, PR_ARRAY_SIZE(macOptList), "MAC" },
76e454
-    { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER" },
76e454
-    { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX" },
76e454
+    { curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC", PR_FALSE },
76e454
+    { hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH", PR_FALSE },
76e454
+    { macOptList, PR_ARRAY_SIZE(macOptList), "MAC", PR_FALSE },
76e454
+    { cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER", PR_FALSE },
76e454
+    { kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX", PR_FALSE },
76e454
+    { signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_TRUE },
76e454
 };
76e454
 
76e454
 static const optionFreeDef sslOptList[] = {
76e454
@@ -718,7 +726,7 @@ secmod_sanityCheckCryptoPolicy(void)
76e454
     for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
76e454
         const algListsDef *algOptList = &algOptLists[i];
76e454
         fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]);
76e454
-        if (!enabledCount[i]) {
76e454
+        if (!enabledCount[i] && !algOptList->allowEmpty) {
76e454
             haveWarning = PR_TRUE;
76e454
         }
76e454
     }
76e454
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
76e454
--- a/lib/ssl/ssl3con.c
76e454
+++ b/lib/ssl/ssl3con.c
76e454
@@ -64,6 +64,7 @@ static SECStatus ssl3_FlushHandshakeMess
76e454
 static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType);
76e454
 static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash);
76e454
 PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme);
76e454
+PRBool ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme);
76e454
 
76e454
 const PRUint8 ssl_hello_retry_random[] = {
76e454
     0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
76e454
@@ -4309,6 +4310,22 @@ ssl_IsRsaPssSignatureScheme(SSLSignature
76e454
     return PR_FALSE;
76e454
 }
76e454
 
76e454
+PRBool
76e454
+ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme)
76e454
+{
76e454
+    switch (scheme) {
76e454
+        case ssl_sig_dsa_sha256:
76e454
+        case ssl_sig_dsa_sha384:
76e454
+        case ssl_sig_dsa_sha512:
76e454
+        case ssl_sig_dsa_sha1:
76e454
+            return PR_TRUE;
76e454
+
76e454
+        default:
76e454
+            return PR_FALSE;
76e454
+    }
76e454
+    return PR_FALSE;
76e454
+}
76e454
+
76e454
 SSLAuthType
76e454
 ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
76e454
 {
76e454
@@ -6017,6 +6034,13 @@ ssl_CanUseSignatureScheme(SSLSignatureSc
76e454
         return PR_FALSE;
76e454
     }
76e454
 
76e454
+    if (ssl_IsDsaSignatureScheme(scheme) &&
76e454
+        (NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) ==
76e454
+         SECSuccess) &&
76e454
+        !(policy & NSS_USE_ALG_IN_SSL_KX)) {
76e454
+        return PR_FALSE;
76e454
+    }
76e454
+
76e454
     hashType = ssl_SignatureSchemeToHashType(scheme);
76e454
     if (requireSha1 && (hashType != ssl_hash_sha1)) {
76e454
         return PR_FALSE;
76e454
@@ -9490,6 +9514,14 @@ ssl3_EncodeSigAlgs(const sslSocket *ss, 
76e454
             continue;
76e454
         }
76e454
 
76e454
+        /* Skip DSA scheme if it is disabled by policy. */
76e454
+        if (ssl_IsDsaSignatureScheme(ss->ssl3.signatureSchemes[i]) &&
76e454
+            (NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) ==
76e454
+             SECSuccess) &&
76e454
+            !(policy & NSS_USE_ALG_IN_SSL_KX)) {
76e454
+            continue;
76e454
+        }
76e454
+
76e454
         if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess) ||
76e454
             (policy & NSS_USE_ALG_IN_SSL_KX)) {
76e454
             rv = sslBuffer_AppendNumber(buf, ss->ssl3.signatureSchemes[i], 2);
76e454
diff --git a/tests/ssl/sslpolicy.txt b/tests/ssl/sslpolicy.txt
76e454
--- a/tests/ssl/sslpolicy.txt
76e454
+++ b/tests/ssl/sslpolicy.txt
76e454
@@ -74,6 +74,8 @@
76e454
 #	SECT409R1
76e454
 #	SECT571K1
76e454
 #	SECT571R1
76e454
+# Signatures:
76e454
+#	DSA
76e454
 # Hashes:
76e454
 #	MD2
76e454
 #	MD4
76e454
@@ -172,3 +174,4 @@
76e454
   1 noECC  SSL3   d    allow=tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Exlicitly
76e454
   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.
76e454
   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.
76e454
+  0 noECC  SSL3   d    disallow=dsa Disallow DSA Signatures Explicitly.