Blob Blame History Raw
diff -up ./lib/nss/nss.h.orig ./lib/nss/nss.h
--- ./lib/nss/nss.h.orig	2020-06-16 15:50:59.000000000 -0700
+++ ./lib/nss/nss.h	2020-10-29 13:17:16.386664203 -0700
@@ -299,6 +299,8 @@ SECStatus NSS_UnregisterShutdown(NSS_Shu
  * old NSS versions.  This option might be removed in the future NSS
  * releases; don't rely on it. */
 #define __NSS_PKCS12_DECODE_FORCE_UNICODE 0x00c
+#define NSS_DEFAULT_LOCKS 0x00d /* lock default values */
+#define NSS_DEFAULT_SSL_LOCK 1  /* lock the ssl default values */
 
 /*
  * Set and get global options for the NSS library.
diff -up ./lib/nss/nssoptions.c.orig ./lib/nss/nssoptions.c
--- ./lib/nss/nssoptions.c.orig	2020-06-16 15:50:59.000000000 -0700
+++ ./lib/nss/nssoptions.c	2020-10-29 13:17:16.386664203 -0700
@@ -14,6 +14,7 @@
 #include "secoid.h"
 #include "nss.h"
 #include "nssoptions.h"
+#include "secerr.h"
 
 struct nssOps {
     PRInt32 rsaMinKeySize;
@@ -24,6 +25,7 @@ struct nssOps {
     PRInt32 dtlsVersionMinPolicy;
     PRInt32 dtlsVersionMaxPolicy;
     PRInt32 pkcs12DecodeForceUnicode;
+    PRInt32 defaultLocks;
 };
 
 static struct nssOps nss_ops = {
@@ -34,7 +36,8 @@ static struct nssOps nss_ops = {
     0xffff, /* set TLS max to more than the largest legal SSL value */
     1,
     0xffff,
-    PR_FALSE
+    PR_FALSE,
+    0
 };
 
 SECStatus
@@ -42,6 +45,11 @@ NSS_OptionSet(PRInt32 which, PRInt32 val
 {
     SECStatus rv = SECSuccess;
 
+    if (NSS_IsPolicyLocked()) {
+        PORT_SetError(SEC_ERROR_POLICY_LOCKED);
+        return SECFailure;
+    }
+
     switch (which) {
         case NSS_RSA_MIN_KEY_SIZE:
             nss_ops.rsaMinKeySize = value;
@@ -67,7 +75,11 @@ NSS_OptionSet(PRInt32 which, PRInt32 val
         case __NSS_PKCS12_DECODE_FORCE_UNICODE:
             nss_ops.pkcs12DecodeForceUnicode = value;
             break;
+        case NSS_DEFAULT_LOCKS:
+            nss_ops.defaultLocks = value;
+            break;
         default:
+            PORT_SetError(SEC_ERROR_INVALID_ARGS);
             rv = SECFailure;
     }
 
@@ -104,6 +116,9 @@ NSS_OptionGet(PRInt32 which, PRInt32 *va
         case __NSS_PKCS12_DECODE_FORCE_UNICODE:
             *value = nss_ops.pkcs12DecodeForceUnicode;
             break;
+        case NSS_DEFAULT_LOCKS:
+            *value = nss_ops.defaultLocks;
+            break;
         default:
             rv = SECFailure;
     }
diff -up ./lib/pk11wrap/pk11pars.c.orig ./lib/pk11wrap/pk11pars.c
--- ./lib/pk11wrap/pk11pars.c.orig	2020-10-29 13:14:14.119727304 -0700
+++ ./lib/pk11wrap/pk11pars.c	2020-10-29 13:17:16.387664208 -0700
@@ -158,16 +158,17 @@ SECMOD_CreateModule(const char *library,
  * Disallow values are parsed first, then allow values, independent of the
  * order they appear.
  *
- * Future key words (not yet implemented):
+ * flags: turn on the following flags:
+ *    policy-lock: turn off the ability for applications to change policy with
+ *                 the call NSS_SetAlgorithmPolicy or the other system policy
+ *                 calls (SSL_SetPolicy, etc.)
+ *    ssl-lock:    turn off the ability to change the ssl defaults.
+ *
+ * The following only apply to ssl cipher suites (future smime)
+ *
  * enable: turn on ciphersuites by default.
  * disable: turn off ciphersuites by default without disallowing them by policy.
- * flags: turn on the following flags:
- *     ssl-lock: turn off the ability for applications to change policy with
- *               the SSL_SetCipherPolicy (or SSL_SetPolicy).
- *     policy-lock: turn off the ability for applications to change policy with
- *               the call NSS_SetAlgorithmPolicy.
- *     ssl-default-lock: turn off the ability for applications to change cipher
- *               suite states with SSL_EnableCipher, SSL_DisableCipher.
+ *
  *
  */
 
@@ -389,7 +390,13 @@ static const oidValDef kxOptList[] = {
 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 },
+      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
+    { CIPHER_NAME("RSA-PKCS"), SEC_OID_PKCS1_RSA_ENCRYPTION,
+      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
+    { CIPHER_NAME("RSA-PSS"), SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
+      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
+    { CIPHER_NAME("ECDSA"), SEC_OID_ANSIX962_EC_PUBLIC_KEY,
+      NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE },
 };
 
 typedef struct {
@@ -405,7 +412,7 @@ static const algListsDef algOptLists[] =
     { 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 },
+    { signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_FALSE },
 };
 
 static const optionFreeDef sslOptList[] = {
@@ -443,10 +450,19 @@ static const policyFlagDef policyFlagLis
     /* add other key exhanges in the future */
     { CIPHER_NAME("KEY-EXCHANGE"), NSS_USE_ALG_IN_SSL_KX },
     { CIPHER_NAME("CERT-SIGNATURE"), NSS_USE_ALG_IN_CERT_SIGNATURE },
-    /* add other signatures in the future */
-    { CIPHER_NAME("SIGNATURE"), NSS_USE_ALG_IN_CERT_SIGNATURE },
-    /* enable everything */
-    { CIPHER_NAME("ALL"), NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
+    { CIPHER_NAME("CMS-SIGNATURE"), NSS_USE_ALG_IN_CMS_SIGNATURE },
+    { CIPHER_NAME("ALL-SIGNATURE"), NSS_USE_ALG_IN_SIGNATURE },
+    /* sign turns off all signatures, but doesn't change the
+     * allowance for specific sigantures... for example:
+     * disallow=sha256/all allow=sha256/signature doesn't allow
+     * cert-sigantures, where disallow=sha256/all allow=sha256/all-signature
+     * does.
+     * however, disallow=sha356/signature and disallow=sha256/all-siganture are
+     * equivalent in effect */
+    { CIPHER_NAME("SIGNATURE"), NSS_USE_ALG_IN_ANY_SIGNATURE },
+    /* enable/disable everything */
+    { CIPHER_NAME("ALL"), NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX |
+                              NSS_USE_ALG_IN_SIGNATURE },
     { CIPHER_NAME("NONE"), 0 }
 };
 
@@ -538,8 +554,82 @@ secmod_getPolicyOptValue(const char *pol
     return SECFailure;
 }
 
+/* Policy operations:
+ *     Disallow: operation is disallowed by policy. Implies disabled.
+ *     Allow: operation is allowed by policy (but could be disabled).
+ *     Disable: operation is turned off by default (but could be allowed).
+ *     Enable: operation is enabled by default. Implies allowed.
+ */
+typedef enum {
+    NSS_DISALLOW,
+    NSS_ALLOW,
+    NSS_DISABLE,
+    NSS_ENABLE
+} NSSPolicyOperation;
+
+/* apply the operator specific policy */
+SECStatus
+secmod_setPolicyOperation(SECOidTag oid, NSSPolicyOperation operation,
+                          PRUint32 value)
+{
+    SECStatus rv = SECSuccess;
+    switch (operation) {
+        case NSS_DISALLOW:
+            /* clear the requested policy bits */
+            rv = NSS_SetAlgorithmPolicy(oid, 0, value);
+            break;
+        case NSS_ALLOW:
+            /* set the requested policy bits */
+            rv = NSS_SetAlgorithmPolicy(oid, value, 0);
+            break;
+        /* enable/disable only apply to SSL cipher suites (future S/MIME).
+         * Enable/disable is implemented by clearing the DEFAULT_NOT_VALID
+         * flag, then setting the NSS_USE_DEFAULT_SSL_ENABLE flag to the
+         * correct value. The ssl policy code will then sort out what to
+         * set based on ciphers and cipher suite values.*/
+        case NSS_DISABLE:
+            if (value & (NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX)) {
+                /* clear not valid and enable */
+                rv = NSS_SetAlgorithmPolicy(oid, 0,
+                                            NSS_USE_DEFAULT_NOT_VALID |
+                                                NSS_USE_DEFAULT_SSL_ENABLE);
+            }
+            break;
+        case NSS_ENABLE:
+            if (value & (NSS_USE_ALG_IN_SSL | NSS_USE_ALG_IN_SSL_KX)) {
+                /* set enable, clear not valid. NOTE: enable implies allow! */
+                rv = NSS_SetAlgorithmPolicy(oid, value | NSS_USE_DEFAULT_SSL_ENABLE,
+                                            NSS_USE_DEFAULT_NOT_VALID);
+            }
+            break;
+        default:
+            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+            rv = SECFailure;
+            break;
+    }
+    return rv;
+}
+
+const char *
+secmod_getOperationString(NSSPolicyOperation operation)
+{
+    switch (operation) {
+        case NSS_DISALLOW:
+            return "disallow";
+        case NSS_ALLOW:
+            return "allow";
+        case NSS_DISABLE:
+            return "disable";
+        case NSS_ENABLE:
+            return "enable";
+        default:
+            break;
+    }
+    return "invalid";
+}
+
 static SECStatus
-secmod_applyCryptoPolicy(const char *policyString, PRBool allow,
+secmod_applyCryptoPolicy(const char *policyString, NSSPolicyOperation operation,
                          PRBool printPolicyFeedback)
 {
     const char *cipher, *currentString;
@@ -573,18 +663,10 @@ secmod_applyCryptoPolicy(const char *pol
             for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
                 const algListsDef *algOptList = &algOptLists[i];
                 for (j = 0; j < algOptList->entries; j++) {
-                    PRUint32 enable, disable;
                     if (!newValue) {
                         value = algOptList->list[j].val;
                     }
-                    if (allow) {
-                        enable = value;
-                        disable = 0;
-                    } else {
-                        enable = 0;
-                        disable = value;
-                    }
-                    NSS_SetAlgorithmPolicy(algOptList->list[j].oid, enable, disable);
+                    secmod_setPolicyOperation(algOptList->list[j].oid, operation, value);
                 }
             }
             continue;
@@ -603,20 +685,12 @@ secmod_applyCryptoPolicy(const char *pol
                 if ((newOption || algOpt->name_size == length) &&
                     PORT_Strncasecmp(algOpt->name, cipher, name_size) == 0) {
                     PRUint32 value = algOpt->val;
-                    PRUint32 enable, disable;
                     if (newOption) {
                         value = secmod_parsePolicyValue(&cipher[name_size] + 1,
                                                         length - name_size - 1,
                                                         printPolicyFeedback);
                     }
-                    if (allow) {
-                        enable = value;
-                        disable = 0;
-                    } else {
-                        enable = 0;
-                        disable = value;
-                    }
-                    rv = NSS_SetAlgorithmPolicy(algOpt->oid, enable, disable);
+                    rv = secmod_setPolicyOperation(algOptList->list[j].oid, operation, value);
                     if (rv != SECSuccess) {
                         /* could not enable option */
                         /* NSS_SetAlgorithPolicy should have set the error code */
@@ -666,7 +740,7 @@ secmod_applyCryptoPolicy(const char *pol
         if (unknown && printPolicyFeedback) {
             PR_SetEnv("NSS_POLICY_FAIL=1");
             fprintf(stderr, "NSS-POLICY-FAIL %s: unknown identifier: %.*s\n",
-                    allow ? "allow" : "disallow", length, cipher);
+                    secmod_getOperationString(operation), length, cipher);
         }
     }
     return rv;
@@ -709,7 +783,8 @@ secmod_sanityCheckCryptoPolicy(void)
                 anyEnabled = PR_TRUE;
                 fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for SSL\n", algOpt->name);
             }
-            if ((algOpt->val & NSS_USE_ALG_IN_CERT_SIGNATURE) && (value & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
+            if ((algOpt->val & NSS_USE_ALG_IN_CERT_SIGNATURE) &&
+                ((value & NSS_USE_CERT_SIGNATURE_OK) == NSS_USE_CERT_SIGNATURE_OK)) {
                 ++num_sig_enabled;
                 anyEnabled = PR_TRUE;
                 fprintf(stderr, "NSS-POLICY-INFO: %s is enabled for CERT-SIGNATURE\n", algOpt->name);
@@ -740,7 +815,7 @@ secmod_sanityCheckCryptoPolicy(void)
 static SECStatus
 secmod_parseCryptoPolicy(const char *policyConfig, PRBool printPolicyFeedback)
 {
-    char *disallow, *allow;
+    char *args;
     SECStatus rv;
 
     if (policyConfig == NULL) {
@@ -752,20 +827,46 @@ secmod_parseCryptoPolicy(const char *pol
     if (rv != SECSuccess) {
         return rv;
     }
-    disallow = NSSUTIL_ArgGetParamValue("disallow", policyConfig);
-    rv = secmod_applyCryptoPolicy(disallow, PR_FALSE, printPolicyFeedback);
-    if (disallow)
-        PORT_Free(disallow);
+    args = NSSUTIL_ArgGetParamValue("disallow", policyConfig);
+    rv = secmod_applyCryptoPolicy(args, NSS_DISALLOW, printPolicyFeedback);
+    if (args)
+        PORT_Free(args);
     if (rv != SECSuccess) {
         return rv;
     }
-    allow = NSSUTIL_ArgGetParamValue("allow", policyConfig);
-    rv = secmod_applyCryptoPolicy(allow, PR_TRUE, printPolicyFeedback);
-    if (allow)
-        PORT_Free(allow);
+    args = NSSUTIL_ArgGetParamValue("allow", policyConfig);
+    rv = secmod_applyCryptoPolicy(args, NSS_ALLOW, printPolicyFeedback);
+    if (args)
+        PORT_Free(args);
     if (rv != SECSuccess) {
         return rv;
     }
+    args = NSSUTIL_ArgGetParamValue("disable", policyConfig);
+    rv = secmod_applyCryptoPolicy(args, NSS_DISABLE, printPolicyFeedback);
+    if (args)
+        PORT_Free(args);
+    if (rv != SECSuccess) {
+        return rv;
+    }
+    args = NSSUTIL_ArgGetParamValue("enable", policyConfig);
+    rv = secmod_applyCryptoPolicy(args, NSS_ENABLE, printPolicyFeedback);
+    if (args)
+        PORT_Free(args);
+    if (rv != SECSuccess) {
+        return rv;
+    }
+    /* this has to be last. Everything after this will be a noop */
+    if (NSSUTIL_ArgHasFlag("flags", "ssl-lock", policyConfig)) {
+        PRInt32 locks;
+        /* don't overwrite other (future) lock flags */
+        rv = NSS_OptionGet(NSS_DEFAULT_LOCKS, &locks);
+        if (rv == SECSuccess) {
+            NSS_OptionSet(NSS_DEFAULT_LOCKS, locks | NSS_DEFAULT_SSL_LOCK);
+        }
+    }
+    if (NSSUTIL_ArgHasFlag("flags", "policy-lock", policyConfig)) {
+        NSS_LockPolicy();
+    }
     if (printPolicyFeedback) {
         /* This helps to distinguish configurations that don't contain any
          * policy config= statement. */
diff -up ./lib/ssl/ssl3con.c.orig ./lib/ssl/ssl3con.c
--- ./lib/ssl/ssl3con.c.orig	2020-10-29 13:14:14.122727319 -0700
+++ ./lib/ssl/ssl3con.c	2020-10-29 13:23:11.101487525 -0700
@@ -13534,6 +13534,61 @@ ssl3_DestroySSL3Info(sslSocket *ss)
     tls13_DestroyEarlyData(&ss->ssl3.hs.bufferedEarlyData);
 }
 
+/*
+ * parse the policy value for a single algorithm in a cipher_suite,
+ *   return TRUE if we disallow by the cipher suite by policy
+ *   (we don't have to parse any more algorithm policies on this cipher suite),
+ *  otherwise return FALSE.
+ *   1. If we don't have the required policy, disable by default, disallow by
+ *      policy and return TRUE (no more processing needed).
+ *   2. If we have the required policy, and we are disabled, return FALSE,
+ *      (if we are disabled, we only need to parse policy, not default).
+ *   3. If we have the required policy, and we aren't adjusting the defaults
+ *      return FALSE. (only parsing the policy, not default).
+ *   4. We have the required policy and we are adjusting the defaults.
+ *      If we are setting default = FALSE, set isDisabled to true so that
+ *      we don't try to re-enable the cipher suite based on a different
+ *      algorithm.
+ */
+PRBool
+ssl_HandlePolicy(int cipher_suite, SECOidTag policyOid,
+                 PRUint32 requiredPolicy, PRBool *isDisabled)
+{
+    PRUint32 policy;
+    SECStatus rv;
+
+    /* first fetch the policy for this algorithm */
+    rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
+    if (rv != SECSuccess) {
+        return PR_FALSE; /* no policy value, continue to the next algorithm */
+    }
+    /* first, are we allowed by policy, if not turn off allow and disable */
+    if (!(policy & requiredPolicy)) {
+        ssl_CipherPrefSetDefault(cipher_suite, PR_FALSE);
+        ssl_CipherPolicySet(cipher_suite, SSL_NOT_ALLOWED);
+        return PR_TRUE;
+    }
+    /* If we are already disabled, or the policy isn't setting a default
+     * we are done processing this algorithm */
+    if (*isDisabled || (policy & NSS_USE_DEFAULT_NOT_VALID)) {
+        return PR_FALSE;
+    }
+    /* set the default value for the cipher suite. If we disable the cipher
+     * suite, remember that so we don't process the next default. This has
+     * the effect of disabling the whole cipher suite if any of the
+     * algorithms it uses are disabled by default. We still have to
+     * process the upper level because the cipher suite is still allowed
+     * by policy, and we may still have to disallow it based on other
+     * algorithms in the cipher suite. */
+    if (policy & NSS_USE_DEFAULT_SSL_ENABLE) {
+        ssl_CipherPrefSetDefault(cipher_suite, PR_TRUE);
+    } else {
+        *isDisabled = PR_TRUE;
+        ssl_CipherPrefSetDefault(cipher_suite, PR_FALSE);
+    }
+    return PR_FALSE;
+}
+
 #define MAP_NULL(x) (((x) != 0) ? (x) : SEC_OID_NULL_CIPHER)
 
 SECStatus
@@ -13552,30 +13607,30 @@ ssl3_ApplyNSSPolicy(void)
     for (i = 1; i < PR_ARRAY_SIZE(cipher_suite_defs); ++i) {
         const ssl3CipherSuiteDef *suite = &cipher_suite_defs[i];
         SECOidTag policyOid;
+        PRBool isDisabled = PR_FALSE;
+
+        /* if we haven't explicitly disabled it below enable by policy */
+        ssl_CipherPolicySet(suite->cipher_suite, SSL_ALLOWED);
 
+        /* now check the various key exchange, ciphers and macs and
+         * if we ever disallow by policy, we are done, go to the next cipher
+         */
         policyOid = MAP_NULL(kea_defs[suite->key_exchange_alg].oid);
-        rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
-        if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL_KX)) {
-            ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
-            ssl_CipherPolicySet(suite->cipher_suite, SSL_NOT_ALLOWED);
+        if (ssl_HandlePolicy(suite->cipher_suite, policyOid,
+                             NSS_USE_ALG_IN_SSL_KX, &isDisabled)) {
             continue;
         }
 
         policyOid = MAP_NULL(ssl_GetBulkCipherDef(suite)->oid);
-        rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
-        if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL)) {
-            ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
-            ssl_CipherPolicySet(suite->cipher_suite, SSL_NOT_ALLOWED);
+        if (ssl_HandlePolicy(suite->cipher_suite, policyOid,
+                             NSS_USE_ALG_IN_SSL, &isDisabled)) {
             continue;
         }
 
         if (ssl_GetBulkCipherDef(suite)->type != type_aead) {
             policyOid = MAP_NULL(ssl_GetMacDefByAlg(suite->mac_alg)->oid);
-            rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
-            if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL)) {
-                ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
-                ssl_CipherPolicySet(suite->cipher_suite,
-                                    SSL_NOT_ALLOWED);
+            if (ssl_HandlePolicy(suite->cipher_suite, policyOid,
+                                 NSS_USE_ALG_IN_SSL, &isDisabled)) {
                 continue;
             }
         }
diff -up ./lib/ssl/sslsock.c.orig ./lib/ssl/sslsock.c
--- ./lib/ssl/sslsock.c.orig	2020-10-29 13:14:14.201727725 -0700
+++ ./lib/ssl/sslsock.c	2020-10-29 13:17:16.389664218 -0700
@@ -1447,6 +1447,10 @@ SSL_CipherPolicySet(PRInt32 which, PRInt
     if (rv != SECSuccess) {
         return rv;
     }
+    if (NSS_IsPolicyLocked()) {
+        PORT_SetError(SEC_ERROR_POLICY_LOCKED);
+        return SECFailure;
+    }
     return ssl_CipherPolicySet(which, policy);
 }
 
@@ -1493,10 +1497,15 @@ SECStatus
 SSL_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
 {
     SECStatus rv = ssl_Init();
+    PRInt32 locks;
 
     if (rv != SECSuccess) {
         return rv;
     }
+    rv = NSS_OptionGet(NSS_DEFAULT_LOCKS, &locks);
+    if ((rv == SECSuccess) && (locks & NSS_DEFAULT_SSL_LOCK)) {
+        return SECSuccess;
+    }
     return ssl_CipherPrefSetDefault(which, enabled);
 }
 
@@ -1522,11 +1531,17 @@ SECStatus
 SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
 {
     sslSocket *ss = ssl_FindSocket(fd);
+    PRInt32 locks;
+    SECStatus rv;
 
     if (!ss) {
         SSL_DBG(("%d: SSL[%d]: bad socket in CipherPrefSet", SSL_GETPID(), fd));
         return SECFailure;
     }
+    rv = NSS_OptionGet(NSS_DEFAULT_LOCKS, &locks);
+    if ((rv == SECSuccess) && (locks & NSS_DEFAULT_SSL_LOCK)) {
+        return SECSuccess;
+    }
     if (ssl_IsRemovedCipherSuite(which))
         return SECSuccess;
     return ssl3_CipherPrefSet(ss, (ssl3CipherSuite)which, enabled);
diff -up ./lib/util/nssutil.def.orig ./lib/util/nssutil.def
--- ./lib/util/nssutil.def.orig	2020-06-16 15:50:59.000000000 -0700
+++ ./lib/util/nssutil.def	2020-10-29 13:17:16.390664223 -0700
@@ -334,3 +334,10 @@ NSSUTIL_AddNSSFlagToModuleSpec;
 ;+    local:
 ;+       *;
 ;+};
+;+NSSUTIL_3.59 {         # NSS Utilities 3.59 release
+;+    global:
+NSS_IsPolicyLocked;
+NSS_LockPolicy;
+;+    local:
+;+       *;
+;+};
diff -up ./lib/util/secerr.h.orig ./lib/util/secerr.h
--- ./lib/util/secerr.h.orig	2020-10-29 13:17:16.390664223 -0700
+++ ./lib/util/secerr.h	2020-10-29 13:28:22.701093270 -0700
@@ -210,6 +210,11 @@ typedef enum {
 
     SEC_ERROR_APPLICATION_CALLBACK_ERROR = (SEC_ERROR_BASE + 178),
 
+    SEC_ERROR_INVALID_STATE = (SEC_ERROR_BASE + 179),
+
+    SEC_ERROR_POLICY_LOCKED = (SEC_ERROR_BASE + 180),
+    SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED = (SEC_ERROR_BASE + 181),
+
     /* Add new error codes above here. */
     SEC_ERROR_END_OF_LIST
 } SECErrorCodes;
diff -up ./lib/util/SECerrs.h.orig ./lib/util/SECerrs.h
--- ./lib/util/SECerrs.h.orig	2020-10-29 13:17:16.389664218 -0700
+++ ./lib/util/SECerrs.h	2020-10-29 13:26:46.960599243 -0700
@@ -549,3 +549,12 @@ ER3(SEC_ERROR_LEGACY_DATABASE, (SEC_ERRO
 
 ER3(SEC_ERROR_APPLICATION_CALLBACK_ERROR, (SEC_ERROR_BASE + 178),
     "The certificate was rejected by extra checks in the application.")
+
+ER3(SEC_ERROR_INVALID_STATE, (SEC_ERROR_BASE + 179),
+    "The attempted operation is invalid for the current state.")
+
+ER3(SEC_ERROR_POLICY_LOCKED, (SEC_ERROR_BASE + 180),
+    "Could not change the policy because the policy is now locked.")
+
+ER3(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED, (SEC_ERROR_BASE + 181),
+    "Could not create or verify a signature using a signature algorithm that is disabled because it is not secure.")
diff -up ./lib/util/secoid.c.orig ./lib/util/secoid.c
--- ./lib/util/secoid.c.orig	2020-10-29 13:14:14.119727304 -0700
+++ ./lib/util/secoid.c	2020-10-29 13:17:16.390664223 -0700
@@ -2257,6 +2257,8 @@ NSS_GetAlgorithmPolicy(SECOidTag tag, PR
     return SECSuccess;
 }
 
+static PRBool nss_policy_locked = PR_FALSE;
+
 /* The Set function modifies the stored value according to the following
  * algorithm:
  *   policy[tag] = (policy[tag] & ~clearBits) | setBits;
@@ -2268,6 +2270,11 @@ NSS_SetAlgorithmPolicy(SECOidTag tag, PR
     PRUint32 policyFlags;
     if (!pxo)
         return SECFailure;
+
+    if (nss_policy_locked) {
+        PORT_SetError(SEC_ERROR_POLICY_LOCKED);
+        return SECFailure;
+    }
     /* The stored policy flags are the ones complement of the flags as
      * seen by the user.  This is not atomic, but these changes should
      * be done rarely, e.g. at initialization time.
@@ -2278,6 +2285,20 @@ NSS_SetAlgorithmPolicy(SECOidTag tag, PR
     return SECSuccess;
 }
 
+/* Get the state of nss_policy_locked */
+PRBool
+NSS_IsPolicyLocked(void)
+{
+    return nss_policy_locked;
+}
+
+/* Once the policy is locked, it can't be unlocked */
+void
+NSS_LockPolicy(void)
+{
+    nss_policy_locked = PR_TRUE;
+}
+
 /* --------- END OF opaque extended OID table accessor functions ---------*/
 
 /* for now, this is only used in a single place, so it can remain static */
@@ -2339,6 +2360,9 @@ SECOID_Shutdown(void)
         dynOidEntriesAllocated = 0;
         dynOidEntriesUsed = 0;
     }
+    /* we are trashing the old policy state now, also reenable changing
+     * the policy as well */
+    nss_policy_locked = PR_FALSE;
     memset(xOids, 0, sizeof xOids);
     return SECSuccess;
 }
diff -up ./lib/util/secoid.h.orig ./lib/util/secoid.h
--- ./lib/util/secoid.h.orig	2020-06-16 15:50:59.000000000 -0700
+++ ./lib/util/secoid.h	2020-10-29 13:17:16.390664223 -0700
@@ -135,6 +135,15 @@ extern SECStatus NSS_GetAlgorithmPolicy(
 extern SECStatus
 NSS_SetAlgorithmPolicy(SECOidTag tag, PRUint32 setBits, PRUint32 clearBits);
 
+/* Lock the policy so NSS_SetAlgorithmPolicy (and other policy functions)
+ * No longer function */
+void
+NSS_LockPolicy(void);
+
+/* return true if policy changes are now locked out */
+PRBool
+NSS_IsPolicyLocked(void);
+
 SEC_END_PROTOS
 
 #endif /* _SECOID_H_ */
diff -up ./lib/util/secoidt.h.orig ./lib/util/secoidt.h
--- ./lib/util/secoidt.h.orig	2020-06-16 15:50:59.000000000 -0700
+++ ./lib/util/secoidt.h	2020-10-29 13:17:16.390664223 -0700
@@ -538,7 +538,24 @@ struct SECOidDataStr {
 #define NSS_USE_ALG_IN_SSL_KX 0x00000004         /* used in SSL key exchange */
 #define NSS_USE_ALG_IN_SSL 0x00000008            /* used in SSL record protocol */
 #define NSS_USE_POLICY_IN_SSL 0x00000010         /* enable policy in SSL protocol */
-#define NSS_USE_ALG_RESERVED 0xfffffffc          /* may be used in future */
+#define NSS_USE_ALG_IN_ANY_SIGNATURE 0x00000020  /* used in S/MIME */
+#define NSS_USE_DEFAULT_NOT_VALID 0x80000000     /* clear to make the default flag valid */
+#define NSS_USE_DEFAULT_SSL_ENABLE 0x40000000    /* default cipher suite setting 1=enable */
+
+/* Combo policy bites */
+#define NSS_USE_ALG_RESERVED 0x3fffffc0 /* may be used in future */
+/* Alias of all the signature values. */
+#define NSS_USE_ALG_IN_SIGNATURE (NSS_USE_ALG_IN_CERT_SIGNATURE | \
+                                  NSS_USE_ALG_IN_CMS_SIGNATURE |  \
+                                  NSS_USE_ALG_IN_ANY_SIGNATURE)
+/* all the bits needed for a certificate signature
+ * and only the bits needed for a certificate signature */
+#define NSS_USE_CERT_SIGNATURE_OK (NSS_USE_ALG_IN_CERT_SIGNATURE | \
+                                   NSS_USE_ALG_IN_ANY_SIGNATURE)
+/* all the bits needed for an SMIME signature
+ * and only the bits needed for an SMIME signature */
+#define NSS_USE_CMS_SIGNATURE_OK (NSS_USE_ALG_IN_CMS_SIGNATURE | \
+                                  NSS_USE_ALG_IN_ANY_SIGNATURE)
 
 /* Code MUST NOT SET or CLEAR reserved bits, and must NOT depend on them
  * being all zeros or having any other known value.  The reserved bits
diff -up ./tests/policy/crypto-policy.txt.orig ./tests/policy/crypto-policy.txt
--- ./tests/policy/crypto-policy.txt.orig	2020-06-16 15:50:59.000000000 -0700
+++ ./tests/policy/crypto-policy.txt	2020-10-29 13:17:16.390664223 -0700
@@ -3,14 +3,15 @@
 # col 3: an extended regular expression, expected to match the output
 # col 4: description of the test
 #
-0 disallow=ALL_allow=HMAC-SHA256:HMAC-SHA1:HMAC-SHA384:HMAC-SHA512:SECP256R1:SECP384R1:SECP521R1:aes256-gcm:chacha20-poly1305:aes256-cbc:camellia256-cbc:aes128-gcm:aes128-cbc:camellia128-cbc:SHA256:SHA384:SHA512:SHA1:ECDHE-RSA:ECDHE-ECDSA:RSA:DHE-RSA:tls-version-min=tls1.0:dtls-version-min=dtls1.0:DH-MIN=1023:DSA-MIN=2048:RSA-MIN=2048 NSS-POLICY-INFO.*LOADED-SUCCESSFULLY Standard policy
-0 disallow=ALL_allow=HMAC-SHA1:HMAC-SHA256:HMAC-SHA384:HMAC-SHA512:SECP256R1:SECP384R1:SECP521R1:aes256-gcm:chacha20-poly1305:aes256-cbc:camellia256-cbc:aes128-gcm:aes128-cbc:camellia128-cbc:des-ede3-cbc:rc4:SHA256:SHA384:SHA512:SHA1:ECDHE-RSA:ECDHE-ECDSA:RSA:DHE-RSA:DHE-DSS:tls-version-min=tls1.0:dtls-version-min=tls1.0:DH-MIN=1023:DSA-MIN=1023:RSA-MIN=1023 NSS-POLICY-INFO.*LOADED-SUCCESSFULLY Legacy policy
-0 disallow=ALL_allow=HMAC-SHA256:HMAC-SHA384:HMAC-SHA512:SECP384R1:SECP521R1:aes256-gcm:chacha20-poly1305:SHA384:SHA512:ECDHE-RSA:ECDHE-ECDSA:RSA:DHE-RSA:tls-version-min=tls1.2:dtls-version-min=dtls1.2:DH-MIN=3072:DSA-MIN=3072:RSA-MIN=3072 NSS-POLICY-INFO.*LOADED-SUCCESSFULLY Reduced policy
+0 disallow=ALL_allow=HMAC-SHA256:HMAC-SHA1:HMAC-SHA384:HMAC-SHA512:SECP256R1:SECP384R1:SECP521R1:aes256-gcm:chacha20-poly1305:aes256-cbc:camellia256-cbc:aes128-gcm:aes128-cbc:camellia128-cbc:SHA256:SHA384:SHA512:SHA1:ECDHE-RSA:ECDHE-ECDSA:RSA:DHE-RSA:rsa-pkcs:rsa-pss:ecdsa:tls-version-min=tls1.0:dtls-version-min=dtls1.0:DH-MIN=1023:DSA-MIN=2048:RSA-MIN=2048 NSS-POLICY-INFO.*LOADED-SUCCESSFULLY Standard policy
+0 disallow=ALL_allow=HMAC-SHA1:HMAC-SHA256:HMAC-SHA384:HMAC-SHA512:SECP256R1:SECP384R1:SECP521R1:aes256-gcm:chacha20-poly1305:aes256-cbc:camellia256-cbc:aes128-gcm:aes128-cbc:camellia128-cbc:des-ede3-cbc:rc4:SHA256:SHA384:SHA512:SHA1:ECDHE-RSA:ECDHE-ECDSA:RSA:DHE-RSA:DHE-DSS:rsa-pkcs:rsa-pss:ecdsa:tls-version-min=tls1.0:dtls-version-min=tls1.0:DH-MIN=1023:DSA-MIN=1023:RSA-MIN=1023 NSS-POLICY-INFO.*LOADED-SUCCESSFULLY Legacy policy
+0 disallow=ALL_allow=HMAC-SHA256:HMAC-SHA384:HMAC-SHA512:SECP384R1:SECP521R1:aes256-gcm:chacha20-poly1305:SHA384:SHA512:ECDHE-RSA:ECDHE-ECDSA:RSA:DHE-RSA:rsa-pkcs:rsa-pss:ecdsa:tls-version-min=tls1.2:dtls-version-min=dtls1.2:DH-MIN=3072:DSA-MIN=3072:RSA-MIN=3072 NSS-POLICY-INFO.*LOADED-SUCCESSFULLY Reduced policy
 2 disallow=ALL_allow=dtls-version-min=:dtls-version-max= NSS-POLICY-FAIL Missing value
 2 disallow=ALL_allow=RSA-MIN=whatever NSS-POLICY-FAIL Invalid value
 2 disallow=ALL_allow=flower NSS-POLICY-FAIL Invalid identifier
 1 disallow=all NSS-POLICY-WARN.*NUMBER-OF-CERT-SIG disallow all
-1 disallow=ALL_allow=HMAC-SHA256:HMAC-SHA384:HMAC-SHA512:SECP384R1:SECP521R1:aes256-gcm:chacha20-poly1305:ECDHE-RSA:ECDHE-ECDSA:RSA:DHE-RSA:tls-version-min=tls1.2:dtls-version-min=dtls1.2:DH-MIN=3072:DSA-MIN=3072:RSA-MIN=3072 NSS-POLICY-WARN.*NUMBER-OF-HASH No Hashes
+1 disallow=all/signature NSS-POLICY-WARN.*NUMBER-OF-CERT-SIG disallow all signatures
+1 disallow=ALL_allow=HMAC-SHA256:HMAC-SHA384:HMAC-SHA512:SECP384R1:SECP521R1:aes256-gcm:chacha20-poly1305:ECDHE-RSA:ECDHE-ECDSA:RSA:DHE-RSA:rsa-pkcs:tls-version-min=tls1.2:dtls-version-min=dtls1.2:DH-MIN=3072:DSA-MIN=3072:RSA-MIN=3072 NSS-POLICY-WARN.*NUMBER-OF-HASH No Hashes
 1 disallow=ALL_allow=tls-version-min=0:tls-version-max=0 NSS-POLICY-WARN.*NUMBER-OF-TLS-VERSIONS All TLS versions disabled
 1 disallow=ALL_allow=dtls-version-min=0:dtls-version-max=0 NSS-POLICY-WARN.*NUMBER-OF-DTLS-VERSIONS All DTLS versions disabled
 1 disallow=ALL_allow=tls-version-min=tls1.2:tls-version-max=tls1.1 NSS-POLICY-WARN.*NUMBER-OF-TLS-VERSIONS Invalid range of TLS versions
diff -up ./tests/policy/policy.sh.orig ./tests/policy/policy.sh
--- ./tests/policy/policy.sh.orig	2020-06-16 15:50:59.000000000 -0700
+++ ./tests/policy/policy.sh	2020-10-29 13:17:16.391664228 -0700
@@ -12,6 +12,28 @@
 #
 ########################################################################
 
+policy_init()
+{
+  SCRIPTNAME=policy.sh      # sourced - $0 would point to all.sh
+
+  if [ -z "${CLEANUP}" ] ; then     # if nobody else is responsible for
+      CLEANUP="${SCRIPTNAME}"       # cleaning this script will do it
+  fi
+
+  if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then
+      cd ../common
+      . ./init.sh
+  fi
+  SCRIPTNAME=policy.sh
+
+}
+
+policy_cleanup()
+{
+  cd ${QADIR}
+  . common/cleanup.sh
+}
+
 ignore_blank_lines()
 {
   LC_ALL=C egrep -v '^[[:space:]]*(#|$)' "$1"
@@ -53,6 +75,9 @@ NSS=flags=policyOnly,moduleDB
     html_msg $ret 0 "\"${testname}\" output is expected to match \"${match}\""
 
   done
+  html "</TABLE><BR>"
 }
 
+policy_init
 policy_run_tests
+policy_cleanup
diff -up ./tests/ssl/sslpolicy.txt.orig ./tests/ssl/sslpolicy.txt
--- ./tests/ssl/sslpolicy.txt.orig	2020-06-16 15:50:59.000000000 -0700
+++ ./tests/ssl/sslpolicy.txt	2020-10-29 13:17:16.391664228 -0700
@@ -7,8 +7,14 @@
 # The policy string is set to the config= line in the pkcs11.txt
 # it currently has 2 keywords:
 #
-# disallow= turn off the use of this algorithm by policy.
+# disallow= turn off the use of this algorithm by policy. (implies disable)
 # allow= allow this algorithm to by used if selected by policy.
+# disable= turn off the use of this algorithm even if allowed by policy 
+#          (application can override)
+# enable= turn off this algorithm by default (implies allow)
+# flags= policy-lock: can't change policy with NSS_SetAlgorithmPolicy,
+#  NSS_SetOption, or SSL_SetCipherPolicy
+#        ssl-lock: can't change the cipher suite settings with the application.
 #
 # The syntax is disallow=algorithm{/uses}:algorithm{/uses}
 # where {} signifies an optional element
@@ -76,6 +82,9 @@
 #	SECT571R1
 # Signatures:
 #	DSA
+#	RSA-PKCS
+#	RSA-PSS
+#       ECDSA
 # Hashes:
 #	MD2
 #	MD4
@@ -137,7 +146,8 @@
 #    ssl-key-exchange
 #    key-exchange (includes ssl-key-exchange)
 #    cert-signature
-#    signature (includes cert-signature)
+#    all-signature (includes cert-signature)
+#    signature (all signatures off, some signature allowed based on other option)
 #    all (includes all of the above)
 #-----------------------------------------------
 # In addition there are the following options:
@@ -147,31 +157,48 @@
 #  they have the following syntax:
 #  allow=min-rsa=512:min-dh=1024
 #
+# in the following tests, we use the cipher suite 'd':
+# d    SSL3 RSA WITH 3DES EDE CBC SHA  (=:000a).
+# NOTE: the certificates used in validation are rsa-pkcs1/sha256 signed.
+#
 # Exp Enable Enable Cipher Config Policy      Test Name
 # Ret  EC     TLS
 # turn on single cipher 
-  0 noECC  SSL3   d    disallow=all_allow=hmac-sha1:sha256:rsa:des-ede3-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Allowed by Narrow Policy
-  0 noECC  SSL3   d    disallow=all_allow=hmac-sha1/ssl,ssl-key-exchange:sha256/cert-signature:rsa/ssl-key-exchange:des-ede3-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Allowed by Strict Policy
-  0 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=ssl2.0:tls-version-max=tls1.2 Allow All Explicitly
-  1 noECC  SSL3   d    disallow=all Disallow All Explicitly.
+  0 noECC  SSL3   d    disallow=all_allow=hmac-sha1:sha256:rsa-pkcs:rsa:des-ede3-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Allowed by Narrow Policy
+  0 noECC  SSL3   d    disallow=all_allow=hmac-sha1/ssl,ssl-key-exchange:sha256/all-signature:rsa-pkcs/all-signature:rsa/ssl-key-exchange:des-ede3-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Allowed by Strict Policy
+  0 noECC  SSL3   d    disallow=all_allow=md2/all:md4/all:md5/all:sha1/all:sha256/all:sha384/all:sha512/all:rsa-pkcs/all:dsa/all:rsa-pss/all:ecdsa/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=ssl2.0:tls-version-max=tls1.2 Allow All Explicitly
+  1 noECC  SSL3   d    disallow=all Disallow All Explicitly
 # turn off signature only
-  1 noECC  SSL3   d    disallow=sha256 Disallow SHA256 Signatures Explicitly.
-  1 noECC  SSL3   d    disallow=all_allow=hmac-sha1:rsa/ssl-key-exchange:des-ede3-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Disallow SHA256 Signatures Implicitly Narrow.
-  1 noECC  SSL3   d    disallow=all_allow=md2/all:md4/all:md5/all:sha1/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=ssl2.0:tls-version-max=tls1.2 Disallow SHA256 Signatures Implicitly.
+  0 noECC  SSL3   d    disallow=all/signature Disallow all signatures with Explicitly
+  1 noECC  SSL3   d    disallow=sha256 Disallow SHA256 Explicitly
+  1 noECC  SSL3   d    disallow=sha256/cert-signature Disallow SHA256 Certificate signature Explicitly
+  0 noECC  SSL3   d    disallow=sha256/signature Disallow All SHA256 signatures Explicitly
+  1 noECC  SSL3   d    disallow=sha256/all-signature Disallow Any SHA256 signature Explicitly
+  1 noECC  SSL3   d    disallow=all_allow=hmac-sha1:rsa/ssl-key-exchange:des-ede3-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Disallow SHA256 Signatures Implicitly Narrow
+  1 noECC  SSL3   d    disallow=all_allow=md2/all:md4/all:md5/all:sha1/all:sha384/all:sha512/all:rsa-pkcs/all:rsa-pss/all:dsa/all:ecdsa/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=ssl2.0:tls-version-max=tls1.2 Disallow SHA256 Signatures Implicitly
 # turn off single cipher 
   1 noECC  SSL3   d    disallow=des-ede3-cbc Disallow Cipher Explicitly
-  1 noECC  SSL3   d    disallow=all_allow=hmac-sha1:sha256:rsa:des-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Disallow Cipher 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-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=ssl2.0:tls-verion-max=tls1.2 Disallow Cipher Implicitly.
+  1 noECC  SSL3   d    disallow=all_allow=hmac-sha1:sha256:rsa-pkcs:rsa:des-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Disallow Cipher Implicitly Narrow
+  1 noECC  SSL3   d    disallow=all_allow=md2/all:md4/all:md5/all:sha1/all:sha256/all:sha384/all:sha512/all:rsa-pkcs/all:rsa-pss/all:ecdsa/all:dsa/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-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=ssl2.0:tls-verion-max=tls1.2 Disallow Cipher Implicitly
 # turn off H-Mac
   1 noECC  SSL3   d    disallow=hmac-sha1 Disallow HMAC Explicitly
-  1 noECC  SSL3   d    disallow=all_allow=md5:sha256:rsa:des-ede3-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Disallow HMAC Implicitly Narrow.
-  1 noECC  SSL3   d    disallow=all_allow=md2/all:md4/all:md5/all:sha1/all:sha256/all:sha384/all:sha512/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=ssl2.0:tls-version-max=tls1.2 Disallow HMAC Signatures Implicitly.
+  1 noECC  SSL3   d    disallow=all_allow=md5:sha256:rsa:des-ede3-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Disallow HMAC Implicitly Narrow
+  1 noECC  SSL3   d    disallow=all_allow=md2/all:md4/all:md5/all:sha1/all:sha256/all:sha384/all:sha512/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=ssl2.0:tls-version-max=tls1.2 Disallow HMAC Signatures Implicitly
 # turn off key exchange 
-  1 noECC  SSL3   d    disallow=rsa/ssl-key-exchange Disallow Key Exchange Explicitly.
-  1 noECC  SSL3   d    disallow=all_allow=hmac-sha1:sha256:dh-dss:des-ede3-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Disallow Key Exchange 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-export/all:dhe-rsa/all:dhe-dss/all:ecdhe-ecdsa/all:ecdhe-rsa/all:ecdh-ecdsa/all:ecdh-rsa/all:tls-version-min=ssl2.0:tls-version-max=tls1.2 Disallow Key Exchnage Signatures Implicitly.
+  1 noECC  SSL3   d    disallow=rsa/ssl-key-exchange Disallow Key Exchange Explicitly
+  1 noECC  SSL3   d    disallow=all_allow=hmac-sha1:sha256:rsa-pkcs:dh-dss:des-ede3-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0 Disallow Key Exchange Implicitly Narrow
+  1 noECC  SSL3   d    disallow=all_allow=md2/all:md4/all:md5/all:sha1/all:sha256/all:sha384/all:sha512/all:rsa-pkcs/all:rsa-pss/all:ecdsa/all:dsa/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-export/all:dhe-rsa/all:dhe-dss/all:ecdhe-ecdsa/all:ecdhe-rsa/all:ecdh-ecdsa/all:ecdh-rsa/all:tls-version-min=ssl2.0:tls-version-max=tls1.2 Disallow Key Exchange Signatures Implicitly
 # turn off  version
   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.
+  1 noECC  SSL3   d    disallow=all_allow=hmac-sha1:sha256:rsa-pkcs: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:rsa-pkcs/all:rsa-pss/all:ecdsa/all:dsa/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
+  1 noECC  SSL3   d    disallow=rsa-pkcs Disallow RSA PKCS 1 Signatures Explicitly
+# test default settings
+# NOTE: tstclient will attempt to overide the defaults, so we detect we
+# were successful by locking in our settings
+  0 noECC  SSL3   d    allow=all_disable=all Disable all by default, application override
+  1 noECC SSL3    d    allow=all_disable=all_flags=ssl-lock,policy-lock Disable all by default, prevent application from enabling
+  0 noECC SSL3    d    allow=all_disable=all_flags=policy-lock Disable all by default, lock policy (application can still change the ciphers)
+# explicitly enable :002f  RSA_AES_128_CBC_SHA1 and lock it in
+  0 noECC SSL3    d    allow=all_disable=all_enable=hmac-sha1:sha256:rsa-pkcs:rsa:aes128-cbc:tls-version-min=ssl3.0:tls-version-max=ssl3.0_flags=ssl-lock Lock in a different ciphersuite that the one the application asks for
diff -up ./tests/ssl/ssl.sh.orig ./tests/ssl/ssl.sh
--- ./tests/ssl/ssl.sh.orig	2020-06-16 15:50:59.000000000 -0700
+++ ./tests/ssl/ssl.sh	2020-10-29 13:17:16.391664228 -0700
@@ -886,6 +886,7 @@ ssl_policy_listsuites()
   cp ${P_R_CLIENTDIR}/pkcs11.txt ${P_R_CLIENTDIR}/pkcs11.txt.sav
 
   # Disallow all explicitly
+  testname="listsuites with all cipher disallowed by policy"
   setup_policy "disallow=all" ${P_R_CLIENTDIR}
   RET_EXP=1
   list_enabled_suites | grep '^TLS_'
@@ -894,6 +895,7 @@ ssl_policy_listsuites()
            "produced a returncode of $RET, expected is $RET_EXP"
 
   # Disallow RSA in key exchange explicitly
+  testname="listsuites with rsa cipher disallowed by policy"
   setup_policy "disallow=rsa/ssl-key-exchange" ${P_R_CLIENTDIR}
   RET_EXP=1
   list_enabled_suites | grep '^TLS_RSA_'
@@ -901,6 +903,34 @@ ssl_policy_listsuites()
   html_msg $RET $RET_EXP "${testname}" \
            "produced a returncode of $RET, expected is $RET_EXP"
 
+  # allow by policy, but disable by default
+  testname="listsuites with all ciphers enabled by policy but disabled by default"
+  setup_policy "allow=all disable=all" ${P_R_CLIENTDIR}
+  RET_EXP=1
+  list_enabled_suites | grep '^TLS_'
+  RET=$?
+  html_msg $RET $RET_EXP "${testname}" \
+           "produced a returncode of $RET, expected is $RET_EXP"
+
+  # allow by policy, but disable by default just rsa-kea
+  testname="listsuites with all ciphers enabled by policy but rsa disabled by default"
+  setup_policy "allow=all disable=rsa/ssl-key-exchange" ${P_R_CLIENTDIR}
+  RET_EXP=1
+  list_enabled_suites | grep '^TLS_RSA_'
+  RET=$?
+  html_msg $RET $RET_EXP "${testname}" \
+           "produced a returncode of $RET, expected is $RET_EXP"
+
+  # list_enabled_suites tries to set a policy value explicitly, This will
+  # cause list_enabled_suites to fail if we lock the policy
+  testname="listsuites with policy locked"
+  setup_policy "allow=all flags=policy-lock" ${P_R_CLIENTDIR}
+  RET_EXP=1
+  SSL_DIR="${P_R_CLIENTDIR}" ${BINDIR}/listsuites
+  RET=$?
+  html_msg $RET $RET_EXP "${testname}" \
+           "produced a returncode of $RET, expected is $RET_EXP"
+
   cp ${P_R_CLIENTDIR}/pkcs11.txt.sav ${P_R_CLIENTDIR}/pkcs11.txt
 
   html "</TABLE><BR>"
@@ -925,6 +955,7 @@ ssl_policy_selfserv()
   cp ${P_R_SERVERDIR}/pkcs11.txt ${P_R_SERVERDIR}/pkcs11.txt.sav
 
   # Disallow RSA in key exchange explicitly
+  testname="Disallow RSA key exchange explicitly"
   setup_policy "disallow=rsa/ssl-key-exchange" ${P_R_SERVERDIR}
 
   SAVE_SERVER_OPTIONS=${SERVER_OPTIONS}