diff --git a/nss-3.79-enable-POST-rerun.patch b/nss-3.79-enable-POST-rerun.patch new file mode 100644 index 0000000..47c1ff8 --- /dev/null +++ b/nss-3.79-enable-POST-rerun.patch @@ -0,0 +1,522 @@ +diff --git a/cmd/bltest/blapitest.c b/cmd/bltest/blapitest.c +--- a/cmd/bltest/blapitest.c ++++ b/cmd/bltest/blapitest.c +@@ -3870,17 +3870,17 @@ main(int argc, char **argv) + rv = blapi_selftest(modesToTest, numModesToTest, inoff, outoff, + encrypt, decrypt); + PORT_Free(cipherInfo); + return rv == SECSuccess ? 0 : 1; + } + + /* Do FIPS self-test */ + if (bltest.commands[cmd_FIPS].activated) { +- CK_RV ckrv = sftk_FIPSEntryOK(); ++ CK_RV ckrv = sftk_FIPSEntryOK(PR_FALSE); + fprintf(stdout, "CK_RV: %ld.\n", ckrv); + PORT_Free(cipherInfo); + if (ckrv == CKR_OK) + return SECSuccess; + return SECFailure; + } + + /* +diff --git a/cmd/pk11mode/pk11mode.c b/cmd/pk11mode/pk11mode.c +--- a/cmd/pk11mode/pk11mode.c ++++ b/cmd/pk11mode/pk11mode.c +@@ -318,23 +318,25 @@ static PRBool verbose = PR_FALSE; + + int + main(int argc, char **argv) + { + CK_C_GetFunctionList pC_GetFunctionList; + CK_FUNCTION_LIST_PTR pFunctionList; + CK_RV crv = CKR_OK; + CK_C_INITIALIZE_ARGS_NSS initArgs; ++ CK_C_INITIALIZE_ARGS_NSS initArgsRerun; /* rerun selftests */ + CK_SLOT_ID *pSlotList = NULL; + CK_TOKEN_INFO tokenInfo; + CK_ULONG slotID = 0; /* slotID == 0 for FIPSMODE */ + + CK_UTF8CHAR *pwd = NULL; + CK_ULONG pwdLen = 0; + char *moduleSpec = NULL; ++ char *moduleSpecRerun = NULL; + char *configDir = NULL; + char *dbPrefix = NULL; + char *disableUnload = NULL; + PRBool doForkTests = PR_TRUE; + + PLOptStatus os; + PLOptState *opt = PL_CreateOptState(argc, argv, "nvhf:Fd:p:"); + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { +@@ -458,18 +460,23 @@ main(int argc, char **argv) + initArgs.CreateMutex = NULL; + initArgs.DestroyMutex = NULL; + initArgs.LockMutex = NULL; + initArgs.UnlockMutex = NULL; + initArgs.flags = CKF_OS_LOCKING_OK; + moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' " + "keyPrefix='%s' secmod='secmod.db' flags= ", + configDir, dbPrefix, dbPrefix); ++ moduleSpecRerun = PR_smprintf("configdir='%s' certPrefix='%s' " ++ "keyPrefix='%s' secmod='secmod.db' flags=forcePOST ", ++ configDir, dbPrefix, dbPrefix); + initArgs.LibraryParameters = (CK_CHAR_PTR *)moduleSpec; + initArgs.pReserved = NULL; ++ initArgsRerun = initArgs; ++ initArgsRerun.LibraryParameters = (CK_CHAR_PTR *)moduleSpecRerun; + + /*DebugBreak();*/ + /* FIPSMODE invokes FC_Initialize as pFunctionList->C_Initialize */ + /* NSS cryptographic module library initialization for the FIPS */ + /* Approved mode when FC_Initialize is envoked will perfom */ + /* software integrity test, and power-up self-tests before */ + /* FC_Initialize returns */ + crv = pFunctionList->C_Initialize(&initArgs); +@@ -705,17 +712,17 @@ main(int argc, char **argv) + PKM_Error("PKM_HybridMode failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); + goto cleanup; + } + + if (doForkTests) { + /* testing one more C_Initialize / C_Finalize to exercise getpid() + * fork check code */ +- crv = pFunctionList->C_Initialize(&initArgs); ++ crv = pFunctionList->C_Initialize(&initArgsRerun); + if (crv == CKR_OK) { + PKM_LogIt("C_Initialize succeeded\n"); + } else { + PKM_Error("C_Initialize failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); + goto cleanup; + } + crv = pFunctionList->C_Finalize(NULL); +@@ -741,16 +748,19 @@ cleanup: + free(configDir); + } + if (dbPrefix) { + free(dbPrefix); + } + if (moduleSpec) { + PR_smprintf_free(moduleSpec); + } ++ if (moduleSpecRerun) { ++ PR_smprintf_free(moduleSpecRerun); ++ } + + #ifdef _WIN32 + FreeLibrary(hModule); + #else + disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD"); + if (!disableUnload) { + PR_UnloadLibrary(lib); + } +diff --git a/lib/freebl/blapii.h b/lib/freebl/blapii.h +--- a/lib/freebl/blapii.h ++++ b/lib/freebl/blapii.h +@@ -24,17 +24,17 @@ typedef SECStatus (*freeblAeadFunc)(void + void *params, unsigned int paramsLen, + const unsigned char *aad, unsigned int aadLen, + unsigned int blocksize); + typedef void (*freeblDestroyFunc)(void *cx, PRBool freeit); + + SEC_BEGIN_PROTOS + + #ifndef NSS_FIPS_DISABLED +-SECStatus BL_FIPSEntryOK(PRBool freeblOnly); ++SECStatus BL_FIPSEntryOK(PRBool freeblOnly, PRBool rerun); + PRBool BL_POSTRan(PRBool freeblOnly); + #endif + + #if defined(XP_UNIX) && !defined(NO_FORK_CHECK) + + extern PRBool bl_parentForkedAfterC_Initialize; + + #define SKIP_AFTER_FORK(x) \ +diff --git a/lib/freebl/blapit.h b/lib/freebl/blapit.h +--- a/lib/freebl/blapit.h ++++ b/lib/freebl/blapit.h +@@ -223,16 +223,21 @@ typedef int __BLAPI_DEPRECATED __attribu + * + * If we arbitrarily set p = 10^-18 (1 chance in trillion trillion operation) + * we get GCMIV_RANDOM_BIRTHDAY_BITS = -(-18)/.301 -1 = 59 (.301 = log10 2) + * GCMIV_RANDOM_BIRTHDAY_BITS should be at least 59, call it a round 64. NOTE: + * the variable IV size for TLS is 64 bits, which explains why it's not safe + * to use a random value for the nonce in TLS. */ + #define GCMIV_RANDOM_BIRTHDAY_BITS 64 + ++/* flag to tell BLAPI_Verify* to rerun the post and integrity tests */ ++#define BLAPI_FIPS_RERUN_FLAG '\377' /* 0xff, 255 invalide code for UFT8/ASCII */ ++#define BLAPI_FIPS_RERUN_FLAG_STRING "\377" /* The above as a C string */ ++ ++ + /*************************************************************************** + ** Opaque objects + */ + + struct DESContextStr; + struct RC2ContextStr; + struct RC4ContextStr; + struct RC5ContextStr; +diff --git a/lib/freebl/fipsfreebl.c b/lib/freebl/fipsfreebl.c +--- a/lib/freebl/fipsfreebl.c ++++ b/lib/freebl/fipsfreebl.c +@@ -2211,29 +2211,37 @@ bl_startup_tests(void) + } + + /* + * this is called from the freebl init entry points that controll access to + * all other freebl functions. This prevents freebl from operating if our + * power on selftest failed. + */ + SECStatus +-BL_FIPSEntryOK(PRBool freebl_only) ++BL_FIPSEntryOK(PRBool freebl_only, PRBool rerun) + { + #ifdef NSS_NO_INIT_SUPPORT + /* this should only be set on platforms that can't handle one of the INIT + * schemes. This code allows those platforms to continue to function, + * though they don't meet the strict NIST requirements. If NSS_NO_INIT_SUPPORT + * is not set, and init support has not been properly enabled, freebl + * will always fail because of the test below + */ + if (!self_tests_freebl_ran) { + bl_startup_tests(); + } + #endif ++ if (rerun) { ++ /* reset the flags */ ++ self_tests_freebl_ran = PR_FALSE; ++ self_tests_success = PR_FALSE; ++ self_tests_success = PR_FALSE; ++ self_tests_freebl_success = PR_FALSE; ++ bl_startup_tests(); ++ } + /* if the general self tests succeeded, we're done */ + if (self_tests_success) { + return SECSuccess; + } + /* standalone freebl can initialize */ + if (freebl_only && self_tests_freebl_success) { + return SECSuccess; + } +diff --git a/lib/freebl/nsslowhash.c b/lib/freebl/nsslowhash.c +--- a/lib/freebl/nsslowhash.c ++++ b/lib/freebl/nsslowhash.c +@@ -55,17 +55,17 @@ NSSLOW_Init(void) + #ifdef FREEBL_NO_DEPEND + (void)FREEBL_InitStubs(); + #endif + + #ifndef NSS_FIPS_DISABLED + /* make sure the FIPS product is installed if we are trying to + * go into FIPS mode */ + if (nsslow_GetFIPSEnabled()) { +- if (BL_FIPSEntryOK(PR_TRUE) != SECSuccess) { ++ if (BL_FIPSEntryOK(PR_TRUE, PR_FALSE) != SECSuccess) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + post_failed = PR_TRUE; + return NULL; + } + } + #endif + post_failed = PR_FALSE; + +diff --git a/lib/freebl/shvfy.c b/lib/freebl/shvfy.c +--- a/lib/freebl/shvfy.c ++++ b/lib/freebl/shvfy.c +@@ -282,52 +282,62 @@ readItem(PRFileDesc *fd, SECItem *item) + PORT_Free(item->data); + item->data = NULL; + item->len = 0; + return SECFailure; + } + return SECSuccess; + } + +-static PRBool blapi_SHVerifyFile(const char *shName, PRBool self); ++static PRBool blapi_SHVerifyFile(const char *shName, PRBool self, PRBool rerun); + + static PRBool +-blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self) ++blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self, PRBool rerun) + { + PRBool result = PR_FALSE; /* if anything goes wrong, + * the signature does not verify */ + /* find our shared library name */ + char *shName = PR_GetLibraryFilePathname(name, addr); + if (!shName) { + goto loser; + } +- result = blapi_SHVerifyFile(shName, self); ++ result = blapi_SHVerifyFile(shName, self, rerun); + + loser: + if (shName != NULL) { + PR_Free(shName); + } + + return result; + } + + PRBool + BLAPI_SHVerify(const char *name, PRFuncPtr addr) + { +- return blapi_SHVerify(name, addr, PR_FALSE); ++ PRBool rerun = PR_FALSE; ++ if (name && *name == BLAPI_FIPS_RERUN_FLAG) { ++ name++; ++ rerun = PR_TRUE; ++ } ++ return blapi_SHVerify(name, addr, PR_FALSE, rerun); + } + + PRBool + BLAPI_SHVerifyFile(const char *shName) + { +- return blapi_SHVerifyFile(shName, PR_FALSE); ++ PRBool rerun = PR_FALSE; ++ if (shName && *shName == BLAPI_FIPS_RERUN_FLAG) { ++ shName++; ++ rerun = PR_TRUE; ++ } ++ return blapi_SHVerifyFile(shName, PR_FALSE, rerun); + } + + static PRBool +-blapi_SHVerifyFile(const char *shName, PRBool self) ++blapi_SHVerifyFile(const char *shName, PRBool self, PRBool rerun) + { + char *checkName = NULL; + PRFileDesc *checkFD = NULL; + PRFileDesc *shFD = NULL; + void *hashcx = NULL; + const SECHashObject *hashObj = NULL; + SECItem signature = { 0, NULL, 0 }; + SECItem hash; +@@ -346,17 +356,17 @@ blapi_SHVerifyFile(const char *shName, P + unsigned char hashBuf[HASH_LENGTH_MAX]; + + PORT_Memset(&key, 0, sizeof(key)); + hash.data = hashBuf; + hash.len = sizeof(hashBuf); + + /* If our integrity check was never ran or failed, fail any other + * integrity checks to prevent any token going into FIPS mode. */ +- if (!self && (BL_FIPSEntryOK(PR_FALSE) != SECSuccess)) { ++ if (!self && (BL_FIPSEntryOK(PR_FALSE, rerun) != SECSuccess)) { + return PR_FALSE; + } + + if (!shName) { + goto loser; + } + + /* figure out the name of our check file */ +@@ -536,17 +546,17 @@ BLAPI_VerifySelf(const char *name) + { + if (name == NULL) { + /* + * If name is NULL, freebl is statically linked into softoken. + * softoken will call BLAPI_SHVerify next to verify itself. + */ + return PR_TRUE; + } +- return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE); ++ return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE, PR_FALSE); + } + + #else /* NSS_FIPS_DISABLED */ + + PRBool + BLAPI_SHVerifyFile(const char *shName) + { + return PR_FALSE; +diff --git a/lib/softoken/fipstest.c b/lib/softoken/fipstest.c +--- a/lib/softoken/fipstest.c ++++ b/lib/softoken/fipstest.c +@@ -684,22 +684,25 @@ sftk_fips_HKDF_PowerUpSelfTest(void) + + static PRBool sftk_self_tests_ran = PR_FALSE; + static PRBool sftk_self_tests_success = PR_FALSE; + + /* + * This function is called at dll load time, the code tha makes this + * happen is platform specific on defined above. + */ +-static void +-sftk_startup_tests(void) ++void sftk_startup_tests_with_rerun(PRBool rerun) + { + SECStatus rv; +- const char *libraryName = SOFTOKEN_LIB_NAME; +- ++ /*const char *nlibraryName = SOFTOKEN_LIB_NAME; ++ const char *rlibraryName = BLAPI_FIPS_RERUN_FLAG_STRING SOFTOKEN_LIB_NAME; */ ++ const char *libraryName = rerun ? ++ BLAPI_FIPS_RERUN_FLAG_STRING SOFTOKEN_LIB_NAME : ++ SOFTOKEN_LIB_NAME; ++ + PORT_Assert(!sftk_self_tests_ran); + PORT_Assert(!sftk_self_tests_success); + sftk_self_tests_ran = PR_TRUE; + sftk_self_tests_success = PR_FALSE; /* just in case */ + + /* need to initiallize the oid library before the RSA tests */ + rv = SECOID_Init(); + if (rv != SECSuccess) { +@@ -746,35 +749,46 @@ sftk_startup_tests(void) + rv = sftk_fips_pbkdf_PowerUpSelfTests(); + if (rv != SECSuccess) { + return; + } + + sftk_self_tests_success = PR_TRUE; + } + ++static void ++sftk_startup_tests(void) ++{ ++ sftk_startup_tests_with_rerun(PR_FALSE); ++} ++ + /* + * this is called from nsc_Common_Initizialize entry points that gates access + * to * all other pkcs11 functions. This prevents softoken operation if our + * power on selftest failed. + */ + CK_RV +-sftk_FIPSEntryOK() ++sftk_FIPSEntryOK(PRBool rerun) + { + #ifdef NSS_NO_INIT_SUPPORT + /* this should only be set on platforms that can't handle one of the INIT + * schemes. This code allows those platforms to continue to function, + * though they don't meet the strict NIST requirements. If NSS_NO_INIT_SUPPORT + * is not set, and init support has not been properly enabled, softken + * will always fail because of the test below + */ + if (!sftk_self_tests_ran) { + sftk_startup_tests(); + } + #endif ++ if (rerun) { ++ sftk_self_tests_ran = PR_FALSE; ++ sftk_self_tests_success = PR_FALSE; ++ sftk_startup_tests_with_rerun(PR_TRUE); ++ } + if (!sftk_self_tests_success) { + return CKR_DEVICE_ERROR; + } + return CKR_OK; + } + #else + #include "pkcs11t.h" + CK_RV +diff --git a/lib/softoken/fipstokn.c b/lib/softoken/fipstokn.c +--- a/lib/softoken/fipstokn.c ++++ b/lib/softoken/fipstokn.c +@@ -524,25 +524,32 @@ fc_log_init_error(CK_RV crv) + } + + /* FC_Initialize initializes the PKCS #11 library. */ + CK_RV + FC_Initialize(CK_VOID_PTR pReserved) + { + const char *envp; + CK_RV crv; ++ PRBool rerun; + + if ((envp = PR_GetEnv("NSS_ENABLE_AUDIT")) != NULL) { + sftk_audit_enabled = (atoi(envp) == 1); + } + ++ /* if we have the forcePOST flag on, rerun the integrity checks */ ++ /* we need to know this before we fully parse the arguments in ++ * nsc_CommonInitialize, so read it now */ ++ rerun = sftk_RawArgHasFlag("flags", "forcePost", pReserved); ++ + /* At this point we should have already done post and integrity checks. + * if we haven't, it probably means the FIPS product has not been installed +- * or the tests failed. Don't let an application try to enter FIPS mode */ +- crv = sftk_FIPSEntryOK(); ++ * or the tests failed. Don't let an application try to enter FIPS mode. This ++ * also forces the tests to be rerun if forcePOST is set. */ ++ crv = sftk_FIPSEntryOK(rerun); + if (crv != CKR_OK) { + sftk_fatalError = PR_TRUE; + fc_log_init_error(crv); + return crv; + } + + sftk_ForkReset(pReserved, &crv); + +diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h +--- a/lib/softoken/pkcs11i.h ++++ b/lib/softoken/pkcs11i.h +@@ -869,16 +869,17 @@ extern CK_RV sftk_MechAllowsOperation(CK + * acquiring a reference to the keydb from the slot */ + NSSLOWKEYPrivateKey *sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey); + + /* + * parameter parsing functions + */ + CK_RV sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS); + void sftk_freeParams(sftk_parameters *params); ++PRBool sftk_RawArgHasFlag(const char *entry, const char *flag, const void *pReserved); + + /* + * narrow objects + */ + SFTKSessionObject *sftk_narrowToSessionObject(SFTKObject *); + SFTKTokenObject *sftk_narrowToTokenObject(SFTKObject *); + + /* +diff --git a/lib/softoken/sftkpars.c b/lib/softoken/sftkpars.c +--- a/lib/softoken/sftkpars.c ++++ b/lib/softoken/sftkpars.c +@@ -244,8 +244,21 @@ sftk_freeParams(sftk_parameters *params) + FREE_CLEAR(params->configdir); + FREE_CLEAR(params->secmodName); + FREE_CLEAR(params->man); + FREE_CLEAR(params->libdes); + FREE_CLEAR(params->tokens); + FREE_CLEAR(params->updatedir); + FREE_CLEAR(params->updateID); + } ++ ++PRBool ++sftk_RawArgHasFlag(const char *entry, const char *flag, const void *pReserved) ++{ ++ CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *)pReserved; ++ ++ /* if we don't have any params, the flag isn't set */ ++ if ((!init_args || !init_args->LibraryParameters)) { ++ return PR_FALSE; ++ } ++ ++ return NSSUTIL_ArgHasFlag(entry, flag, (const char *)init_args->LibraryParameters); ++} +diff --git a/lib/softoken/softoken.h b/lib/softoken/softoken.h +--- a/lib/softoken/softoken.h ++++ b/lib/softoken/softoken.h +@@ -52,17 +52,17 @@ extern unsigned char *CBC_PadBuffer(PLAr + unsigned int inlen, unsigned int *outlen, + int blockSize); + + /****************************************/ + /* + ** Power-Up selftests are required for FIPS. + */ + /* make sure Power-up selftests have been run. */ +-extern CK_RV sftk_FIPSEntryOK(void); ++extern CK_RV sftk_FIPSEntryOK(PRBool rerun); + + /* + ** make known fixed PKCS #11 key types to their sizes in bytes + */ + unsigned long sftk_MapKeySize(CK_KEY_TYPE keyType); + + /* + ** FIPS 140-2 auditing diff --git a/nss-3.79-rhel-9-fips-signature-policy.patch b/nss-3.79-rhel-9-fips-signature-policy.patch new file mode 100644 index 0000000..109a480 --- /dev/null +++ b/nss-3.79-rhel-9-fips-signature-policy.patch @@ -0,0 +1,709 @@ +diff -up ./cmd/crmftest/testcrmf.c.signature-policy ./cmd/crmftest/testcrmf.c +--- ./cmd/crmftest/testcrmf.c.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./cmd/crmftest/testcrmf.c 2022-06-21 09:16:23.916905015 -0700 +@@ -85,7 +85,7 @@ + #include "sechash.h" + #endif + +-#define MAX_KEY_LEN 512 ++#define MAX_KEY_LEN 1024 + #define PATH_LEN 150 + #define BUFF_SIZE 150 + #define UID_BITS 800 +diff -up ./gtests/pk11_gtest/pk11_rsapkcs1_unittest.cc.signature-policy ./gtests/pk11_gtest/pk11_rsapkcs1_unittest.cc +--- ./gtests/pk11_gtest/pk11_rsapkcs1_unittest.cc.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./gtests/pk11_gtest/pk11_rsapkcs1_unittest.cc 2022-06-21 09:16:23.916905015 -0700 +@@ -16,6 +16,7 @@ + #include "secerr.h" + #include "sechash.h" + #include "pk11_signature_test.h" ++#include "blapit.h" + + #include "testvectors/rsa_signature_2048_sha224-vectors.h" + #include "testvectors/rsa_signature_2048_sha256-vectors.h" +@@ -109,7 +110,11 @@ class Pkcs11RsaPkcs1WycheproofTest + * Use 6 as the invalid value since modLen % 16 must be zero. + */ + TEST(RsaPkcs1Test, Pkcs1MinimumPadding) { +- const size_t kRsaShortKeyBits = 736; ++#define RSA_SHORT_KEY_LENGTH 736 ++/* if our minimum supported key length is big enough to handle ++ * our largest Hash function, we can't test a short length */ ++#if RSA_MIN_MODULUS_BITS < RSA_SHORT_KEY_LENGTH ++ const size_t kRsaShortKeyBits = RSA_SHORT_KEY_LENGTH; + const size_t kRsaKeyBits = 752; + static const std::vector kMsg{'T', 'E', 'S', 'T'}; + static const std::vector kSha512DigestInfo{ +@@ -209,6 +214,9 @@ TEST(RsaPkcs1Test, Pkcs1MinimumPadding) + SEC_OID_PKCS1_RSA_ENCRYPTION, SEC_OID_SHA512, + nullptr); + EXPECT_EQ(SECSuccess, rv); ++#else ++ GTEST_SKIP(); ++#endif + } + + TEST(RsaPkcs1Test, RequireNullParameter) { +diff -up ./gtests/ssl_gtest/tls_subcerts_unittest.cc.signature-policy ./gtests/ssl_gtest/tls_subcerts_unittest.cc +--- ./gtests/ssl_gtest/tls_subcerts_unittest.cc.signature-policy 2022-06-21 09:16:23.901904919 -0700 ++++ ./gtests/ssl_gtest/tls_subcerts_unittest.cc 2022-06-21 09:19:12.482981408 -0700 +@@ -9,6 +9,8 @@ + #include "prtime.h" + #include "secerr.h" + #include "ssl.h" ++#include "nss.h" ++#include "blapit.h" + + #include "gtest_utils.h" + #include "tls_agent.h" +@@ -357,9 +359,14 @@ static void GenerateWeakRsaKey(ScopedSEC + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + ASSERT_TRUE(slot); + PK11RSAGenParams rsaparams; +- // The absolute minimum size of RSA key that we can use with SHA-256 is +- // 256bit (hash) + 256bit (salt) + 8 (start byte) + 8 (end byte) = 528. ++// The absolute minimum size of RSA key that we can use with SHA-256 is ++// 256bit (hash) + 256bit (salt) + 8 (start byte) + 8 (end byte) = 528. ++#define RSA_WEAK_KEY 528 ++#if RSA_MIN_MODULUS_BITS < RSA_WEAK_KEY + rsaparams.keySizeInBits = 528; ++#else ++ rsaparams.keySizeInBits = RSA_MIN_MODULUS_BITS + 1; ++#endif + rsaparams.pe = 65537; + + // Bug 1012786: PK11_GenerateKeyPair can fail if there is insufficient +@@ -399,6 +406,18 @@ TEST_P(TlsConnectTls13, DCWeakKey) { + ssl_sig_rsa_pss_pss_sha256}; + client_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes)); + server_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes)); ++#if RSA_MIN_MODULUS_BITS > RSA_WEAK_KEY ++ // save the MIN POLICY length. ++ PRInt32 minRsa; ++ ++ ASSERT_EQ(SECSuccess, NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minRsa)); ++#if RSA_MIN_MODULUS_BITS >= 2048 ++ ASSERT_EQ(SECSuccess, ++ NSS_OptionSet(NSS_RSA_MIN_KEY_SIZE, RSA_MIN_MODULUS_BITS + 1024)); ++#else ++ ASSERT_EQ(SECSuccess, NSS_OptionSet(NSS_RSA_MIN_KEY_SIZE, 2048)); ++#endif ++#endif + + ScopedSECKEYPrivateKey dc_priv; + ScopedSECKEYPublicKey dc_pub; +@@ -421,6 +440,9 @@ TEST_P(TlsConnectTls13, DCWeakKey) { + auto cfilter = MakeTlsFilter( + client_, ssl_delegated_credentials_xtn); + ConnectExpectAlert(client_, kTlsAlertInsufficientSecurity); ++#if RSA_MIN_MODULUS_BITS > RSA_WEAK_KEY ++ ASSERT_EQ(SECSuccess, NSS_OptionSet(NSS_RSA_MIN_KEY_SIZE, minRsa)); ++#endif + } + + class ReplaceDCSigScheme : public TlsHandshakeFilter { +diff -up ./lib/cryptohi/keyhi.h.signature-policy ./lib/cryptohi/keyhi.h +--- ./lib/cryptohi/keyhi.h.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/cryptohi/keyhi.h 2022-06-21 09:16:23.917905021 -0700 +@@ -53,6 +53,11 @@ extern unsigned SECKEY_PublicKeyStrength + extern unsigned SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk); + + /* ++** Return the strength of the private key in bits ++*/ ++extern unsigned SECKEY_PrivateKeyStrengthInBits(const SECKEYPrivateKey *privk); ++ ++/* + ** Return the length of the signature in bytes + */ + extern unsigned SECKEY_SignatureLen(const SECKEYPublicKey *pubk); +diff -up ./lib/cryptohi/keyi.h.signature-policy ./lib/cryptohi/keyi.h +--- ./lib/cryptohi/keyi.h.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/cryptohi/keyi.h 2022-06-21 09:16:23.917905021 -0700 +@@ -4,6 +4,7 @@ + + #ifndef _KEYI_H_ + #define _KEYI_H_ ++#include "secerr.h" + + SEC_BEGIN_PROTOS + /* NSS private functions */ +@@ -36,6 +37,9 @@ SECStatus sec_DecodeRSAPSSParamsToMechan + const SECItem *params, + CK_RSA_PKCS_PSS_PARAMS *mech); + ++/* make sure the key length matches the policy for keyType */ ++SECStatus seckey_EnforceKeySize(KeyType keyType, unsigned keyLength, ++ SECErrorCodes error); + SEC_END_PROTOS + + #endif /* _KEYHI_H_ */ +diff -up ./lib/cryptohi/seckey.c.signature-policy ./lib/cryptohi/seckey.c +--- ./lib/cryptohi/seckey.c.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/cryptohi/seckey.c 2022-06-21 09:16:23.917905021 -0700 +@@ -14,6 +14,7 @@ + #include "secdig.h" + #include "prtime.h" + #include "keyi.h" ++#include "nss.h" + + SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) + SEC_ASN1_MKSUB(SEC_IntegerTemplate) +@@ -1042,6 +1043,62 @@ SECKEY_PublicKeyStrengthInBits(const SEC + return bitSize; + } + ++unsigned ++SECKEY_PrivateKeyStrengthInBits(const SECKEYPrivateKey *privk) ++{ ++ unsigned bitSize = 0; ++ CK_ATTRIBUTE_TYPE attribute = CKT_INVALID_TYPE; ++ SECItem params; ++ SECStatus rv; ++ ++ if (!privk) { ++ PORT_SetError(SEC_ERROR_INVALID_KEY); ++ return 0; ++ } ++ ++ /* interpret modulus length as key strength */ ++ switch (privk->keyType) { ++ case rsaKey: ++ case rsaPssKey: ++ case rsaOaepKey: ++ /* some tokens don't export CKA_MODULUS on the private key, ++ * PK11_SignatureLen works around this if necessary */ ++ bitSize = PK11_SignatureLen((SECKEYPrivateKey *)privk) * PR_BITS_PER_BYTE; ++ if (bitSize == -1) { ++ bitSize = 0; ++ } ++ return bitSize; ++ case dsaKey: ++ case fortezzaKey: ++ case dhKey: ++ case keaKey: ++ attribute = CKA_PRIME; ++ break; ++ case ecKey: ++ rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID, ++ CKA_EC_PARAMS, NULL, ¶ms); ++ if ((rv != SECSuccess) || (params.data == NULL)) { ++ return 0; ++ } ++ bitSize = SECKEY_ECParamsToKeySize(¶ms); ++ PORT_Free(params.data); ++ return bitSize; ++ default: ++ PORT_SetError(SEC_ERROR_INVALID_KEY); ++ return 0; ++ } ++ PORT_Assert(attribute != CKT_INVALID_TYPE); ++ rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID, ++ attribute, NULL, ¶ms); ++ if ((rv != SECSuccess) || (params.data == NULL)) { ++ PORT_SetError(SEC_ERROR_INVALID_KEY); ++ return 0; ++ } ++ bitSize = SECKEY_BigIntegerBitLength(¶ms); ++ PORT_Free(params.data); ++ return bitSize; ++} ++ + /* returns signature length in bytes (not bits) */ + unsigned + SECKEY_SignatureLen(const SECKEYPublicKey *pubk) +@@ -1212,6 +1269,51 @@ SECKEY_CopyPublicKey(const SECKEYPublicK + } + + /* ++ * Check that a given key meets the policy limits for the given key ++ * size. ++ */ ++SECStatus ++seckey_EnforceKeySize(KeyType keyType, unsigned keyLength, SECErrorCodes error) ++{ ++ PRInt32 opt = -1; ++ PRInt32 optVal; ++ SECStatus rv; ++ ++ switch (keyType) { ++ case rsaKey: ++ case rsaPssKey: ++ case rsaOaepKey: ++ opt = NSS_RSA_MIN_KEY_SIZE; ++ break; ++ case dsaKey: ++ case fortezzaKey: ++ opt = NSS_DSA_MIN_KEY_SIZE; ++ break; ++ case dhKey: ++ case keaKey: ++ opt = NSS_DH_MIN_KEY_SIZE; ++ break; ++ case ecKey: ++ opt = NSS_ECC_MIN_KEY_SIZE; ++ break; ++ case nullKey: ++ default: ++ PORT_SetError(SEC_ERROR_INVALID_KEY); ++ return SECFailure; ++ } ++ PORT_Assert(opt != -1); ++ rv = NSS_OptionGet(opt, &optVal); ++ if (rv != SECSuccess) { ++ return rv; ++ } ++ if (optVal < keyLength) { ++ PORT_SetError(error); ++ return SECFailure; ++ } ++ return SECSuccess; ++} ++ ++/* + * Use the private key to find a public key handle. The handle will be on + * the same slot as the private key. + */ +diff -up ./lib/cryptohi/secsign.c.signature-policy ./lib/cryptohi/secsign.c +--- ./lib/cryptohi/secsign.c.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/cryptohi/secsign.c 2022-06-21 09:16:23.917905021 -0700 +@@ -15,6 +15,7 @@ + #include "pk11func.h" + #include "secerr.h" + #include "keyi.h" ++#include "nss.h" + + struct SGNContextStr { + SECOidTag signalg; +@@ -32,6 +33,7 @@ sgn_NewContext(SECOidTag alg, SECItem *p + SECOidTag hashalg, signalg; + KeyType keyType; + PRUint32 policyFlags; ++ PRInt32 optFlags; + SECStatus rv; + + /* OK, map a PKCS #7 hash and encrypt algorithm into +@@ -56,6 +58,16 @@ sgn_NewContext(SECOidTag alg, SECItem *p + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return NULL; + } ++ if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) != SECFailure) { ++ if (optFlags & NSS_KEY_SIZE_POLICY_SIGN_FLAG) { ++ rv = seckey_EnforceKeySize(key->keyType, ++ SECKEY_PrivateKeyStrengthInBits(key), ++ SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED); ++ if (rv != SECSuccess) { ++ return NULL; ++ } ++ } ++ } + /* check the policy on the hash algorithm */ + if ((NSS_GetAlgorithmPolicy(hashalg, &policyFlags) == SECFailure) || + !(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) { +@@ -467,9 +479,20 @@ SGN_Digest(SECKEYPrivateKey *privKey, + SGNDigestInfo *di = 0; + SECOidTag enctag; + PRUint32 policyFlags; ++ PRInt32 optFlags; + + result->data = 0; + ++ if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) != SECFailure) { ++ if (optFlags & NSS_KEY_SIZE_POLICY_SIGN_FLAG) { ++ rv = seckey_EnforceKeySize(privKey->keyType, ++ SECKEY_PrivateKeyStrengthInBits(privKey), ++ SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED); ++ if (rv != SECSuccess) { ++ return SECFailure; ++ } ++ } ++ } + /* check the policy on the hash algorithm */ + if ((NSS_GetAlgorithmPolicy(algtag, &policyFlags) == SECFailure) || + !(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) { +diff -up ./lib/cryptohi/secvfy.c.signature-policy ./lib/cryptohi/secvfy.c +--- ./lib/cryptohi/secvfy.c.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/cryptohi/secvfy.c 2022-06-21 09:16:23.918905028 -0700 +@@ -16,6 +16,7 @@ + #include "secdig.h" + #include "secerr.h" + #include "keyi.h" ++#include "nss.h" + + /* + ** Recover the DigestInfo from an RSA PKCS#1 signature. +@@ -467,6 +468,7 @@ vfy_CreateContext(const SECKEYPublicKey + unsigned int sigLen; + KeyType type; + PRUint32 policyFlags; ++ PRInt32 optFlags; + + /* make sure the encryption algorithm matches the key type */ + /* RSA-PSS algorithm can be used with both rsaKey and rsaPssKey */ +@@ -476,7 +478,16 @@ vfy_CreateContext(const SECKEYPublicKey + PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH); + return NULL; + } +- ++ if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) != SECFailure) { ++ if (optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) { ++ rv = seckey_EnforceKeySize(key->keyType, ++ SECKEY_PublicKeyStrengthInBits(key), ++ SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED); ++ if (rv != SECSuccess) { ++ return NULL; ++ } ++ } ++ } + /* check the policy on the encryption algorithm */ + if ((NSS_GetAlgorithmPolicy(encAlg, &policyFlags) == SECFailure) || + !(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) { +diff -up ./lib/freebl/blapit.h.signature-policy ./lib/freebl/blapit.h +--- ./lib/freebl/blapit.h.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/freebl/blapit.h 2022-06-21 09:16:23.918905028 -0700 +@@ -135,7 +135,7 @@ typedef int __BLAPI_DEPRECATED __attribu + * These values come from the initial key size limits from the PKCS #11 + * module. They may be arbitrarily adjusted to any value freebl supports. + */ +-#define RSA_MIN_MODULUS_BITS 128 ++#define RSA_MIN_MODULUS_BITS 1023 /* 128 */ + #define RSA_MAX_MODULUS_BITS 16384 + #define RSA_MAX_EXPONENT_BITS 64 + #define DH_MIN_P_BITS 128 +diff -up ./lib/nss/nss.h.signature-policy ./lib/nss/nss.h +--- ./lib/nss/nss.h.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/nss/nss.h 2022-06-21 09:16:23.918905028 -0700 +@@ -302,6 +302,28 @@ SECStatus NSS_UnregisterShutdown(NSS_Shu + #define NSS_DEFAULT_LOCKS 0x00d /* lock default values */ + #define NSS_DEFAULT_SSL_LOCK 1 /* lock the ssl default values */ + ++/* NSS_KEY_SIZE_POLICY controls what kinds of operations are subject to ++ * the NSS_XXX_MIN_KEY_SIZE values. ++ * NSS_KEY_SIZE_POLICY_FLAGS sets and clears all the flags to the input ++ * value ++ * On get it returns all the flags ++ * NSS_KEY_SIZE_POLICY_SET_FLAGS sets only the flags=1 in theinput value and ++ * does not affect the other flags ++ * On get it returns all the flags ++ * NSS_KEY_SIZE_POLICY_CLEAR_FLAGS clears only the flags=1 in the input ++ * value and does not affect the other flags ++ * On get it returns all the compliment of all the flags ++ * (cleared flags == 1) */ ++#define NSS_KEY_SIZE_POLICY_FLAGS 0x00e ++#define NSS_KEY_SIZE_POLICY_SET_FLAGS 0x00f ++#define NSS_KEY_SIZE_POLICY_CLEAR_FLAGS 0x010 ++/* currently defined flags */ ++#define NSS_KEY_SIZE_POLICY_SSL_FLAG 1 ++#define NSS_KEY_SIZE_POLICY_VERIFY_FLAG 2 ++#define NSS_KEY_SIZE_POLICY_SIGN_FLAG 4 ++ ++#define NSS_ECC_MIN_KEY_SIZE 0x011 ++ + /* + * Set and get global options for the NSS library. + */ +diff -up ./lib/nss/nssoptions.c.signature-policy ./lib/nss/nssoptions.c +--- ./lib/nss/nssoptions.c.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/nss/nssoptions.c 2022-06-21 09:16:23.918905028 -0700 +@@ -26,6 +26,8 @@ struct nssOps { + PRInt32 dtlsVersionMaxPolicy; + PRInt32 pkcs12DecodeForceUnicode; + PRInt32 defaultLocks; ++ PRInt32 keySizePolicyFlags; ++ PRInt32 eccMinKeySize; + }; + + static struct nssOps nss_ops = { +@@ -37,7 +39,9 @@ static struct nssOps nss_ops = { + 1, + 0xffff, + PR_FALSE, +- 0 ++ 0, ++ NSS_KEY_SIZE_POLICY_SSL_FLAG, ++ SSL_ECC_MIN_CURVE_BITS + }; + + SECStatus +@@ -78,6 +82,18 @@ NSS_OptionSet(PRInt32 which, PRInt32 val + case NSS_DEFAULT_LOCKS: + nss_ops.defaultLocks = value; + break; ++ case NSS_KEY_SIZE_POLICY_FLAGS: ++ nss_ops.keySizePolicyFlags = value; ++ break; ++ case NSS_KEY_SIZE_POLICY_SET_FLAGS: ++ nss_ops.keySizePolicyFlags |= value; ++ break; ++ case NSS_KEY_SIZE_POLICY_CLEAR_FLAGS: ++ nss_ops.keySizePolicyFlags &= ~value; ++ break; ++ case NSS_ECC_MIN_KEY_SIZE: ++ nss_ops.eccMinKeySize = value; ++ break; + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; +@@ -119,6 +135,16 @@ NSS_OptionGet(PRInt32 which, PRInt32 *va + case NSS_DEFAULT_LOCKS: + *value = nss_ops.defaultLocks; + break; ++ case NSS_KEY_SIZE_POLICY_FLAGS: ++ case NSS_KEY_SIZE_POLICY_SET_FLAGS: ++ *value = nss_ops.keySizePolicyFlags; ++ break; ++ case NSS_KEY_SIZE_POLICY_CLEAR_FLAGS: ++ *value = ~nss_ops.keySizePolicyFlags; ++ break; ++ case NSS_ECC_MIN_KEY_SIZE: ++ *value = nss_ops.eccMinKeySize; ++ break; + default: + rv = SECFailure; + } +diff -up ./lib/nss/nssoptions.h.signature-policy ./lib/nss/nssoptions.h +--- ./lib/nss/nssoptions.h.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/nss/nssoptions.h 2022-06-21 09:16:23.918905028 -0700 +@@ -18,3 +18,5 @@ + * happens because NSS used to count bit lengths incorrectly. */ + #define SSL_DH_MIN_P_BITS 1023 + #define SSL_DSA_MIN_P_BITS 1023 ++/* not really used by SSL, but define it here for consistency */ ++#define SSL_ECC_MIN_CURVE_BITS 256 +diff -up ./lib/pk11wrap/pk11kea.c.signature-policy ./lib/pk11wrap/pk11kea.c +--- ./lib/pk11wrap/pk11kea.c.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/pk11wrap/pk11kea.c 2022-06-21 09:16:23.918905028 -0700 +@@ -78,15 +78,14 @@ pk11_KeyExchange(PK11SlotInfo *slot, CK_ + if (privKeyHandle == CK_INVALID_HANDLE) { + PK11RSAGenParams rsaParams; + +- if (symKeyLength > 53) /* bytes */ { +- /* we'd have to generate an RSA key pair > 512 bits long, ++ if (symKeyLength > 120) /* bytes */ { ++ /* we'd have to generate an RSA key pair > 1024 bits long, + ** and that's too costly. Don't even try. + */ + PORT_SetError(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY); + goto rsa_failed; + } +- rsaParams.keySizeInBits = +- (symKeyLength > 21 || symKeyLength == 0) ? 512 : 256; ++ rsaParams.keySizeInBits = 1024; + rsaParams.pe = 0x10001; + privKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, + &rsaParams, &pubKey, PR_FALSE, PR_TRUE, symKey->cx); +diff -up ./lib/pk11wrap/pk11pars.c.signature-policy ./lib/pk11wrap/pk11pars.c +--- ./lib/pk11wrap/pk11pars.c.signature-policy 2022-06-21 09:16:23.898904900 -0700 ++++ ./lib/pk11wrap/pk11pars.c 2022-06-21 09:16:23.918905028 -0700 +@@ -430,12 +430,21 @@ static const optionFreeDef sslOptList[] + { CIPHER_NAME("DTLS1.3"), 0x304 }, + }; + ++static const optionFreeDef keySizeFlagsList[] = { ++ { CIPHER_NAME("KEY-SIZE-SSL"), NSS_KEY_SIZE_POLICY_SSL_FLAG }, ++ { CIPHER_NAME("KEY-SIZE-SIGN"), NSS_KEY_SIZE_POLICY_SIGN_FLAG }, ++ { CIPHER_NAME("KEY-SIZE-VERIFY"), NSS_KEY_SIZE_POLICY_VERIFY_FLAG }, ++}; ++ + static const optionFreeDef freeOptList[] = { + + /* Restrictions for asymetric keys */ + { CIPHER_NAME("RSA-MIN"), NSS_RSA_MIN_KEY_SIZE }, + { CIPHER_NAME("DH-MIN"), NSS_DH_MIN_KEY_SIZE }, + { CIPHER_NAME("DSA-MIN"), NSS_DSA_MIN_KEY_SIZE }, ++ { CIPHER_NAME("ECC-MIN"), NSS_ECC_MIN_KEY_SIZE }, ++ /* what operations doe the key size apply to */ ++ { CIPHER_NAME("KEY-SIZE-FLAGS"), NSS_KEY_SIZE_POLICY_FLAGS }, + /* constraints on SSL Protocols */ + { CIPHER_NAME("TLS-VERSION-MIN"), NSS_TLS_VERSION_MIN_POLICY }, + { CIPHER_NAME("TLS-VERSION-MAX"), NSS_TLS_VERSION_MAX_POLICY }, +@@ -543,6 +552,7 @@ secmod_getPolicyOptValue(const char *pol + *result = val; + return SECSuccess; + } ++ /* handle any ssl strings */ + for (i = 0; i < PR_ARRAY_SIZE(sslOptList); i++) { + if (policyValueLength == sslOptList[i].name_size && + PORT_Strncasecmp(sslOptList[i].name, policyValue, +@@ -551,7 +561,29 @@ secmod_getPolicyOptValue(const char *pol + return SECSuccess; + } + } +- return SECFailure; ++ /* handle key_size flags. Each flag represents a bit, which ++ * gets or'd together. They can be separated by , | or + */ ++ val = 0; ++ while (*policyValue) { ++ PRBool found = PR_FALSE; ++ for (i = 0; i < PR_ARRAY_SIZE(keySizeFlagsList); i++) { ++ if (PORT_Strncasecmp(keySizeFlagsList[i].name, policyValue, ++ keySizeFlagsList[i].name_size) == 0) { ++ val |= keySizeFlagsList[i].option; ++ found = PR_TRUE; ++ policyValue += keySizeFlagsList[i].name_size; ++ break; ++ } ++ } ++ if (!found) { ++ return SECFailure; ++ } ++ if (*policyValue == ',' || *policyValue == '|' || *policyValue == '+') { ++ policyValue++; ++ } ++ } ++ *result = val; ++ return SECSuccess; + } + + /* Policy operations: +diff -up ./lib/softoken/fips_algorithms.h.signature-policy ./lib/softoken/fips_algorithms.h +--- ./lib/softoken/fips_algorithms.h.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/softoken/fips_algorithms.h 2022-06-21 09:16:23.919905034 -0700 +@@ -54,7 +54,9 @@ SFTKFIPSAlgorithmList sftk_fips_mechs[] + /* mechanisms using the same key types share the same key type + * limits */ + #define RSA_FB_KEY 2048, 4096 /* min, max */ +-#define RSA_FB_STEP 1024 ++#define RSA_FB_STEP 1 ++#define RSA_LEGACY_FB_KEY 1024, 1792 /* min, max */ ++#define RSA_LEGACY_FB_STEP 256 + #define DSA_FB_KEY 2048, 4096 /* min, max */ + #define DSA_FB_STEP 1024 + #define DH_FB_KEY 2048, 4096 /* min, max */ +@@ -66,6 +68,7 @@ SFTKFIPSAlgorithmList sftk_fips_mechs[] + { CKM_RSA_PKCS_KEY_PAIR_GEN, { RSA_FB_KEY, CKF_KPG }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_RSA_PKCS_OAEP, { RSA_FB_KEY, CKF_ENC }, RSA_FB_STEP, SFTKFIPSNone }, ++ { CKM_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, + /* -------------- RSA Multipart Signing Operations -------------------- */ + { CKM_SHA224_RSA_PKCS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_SHA256_RSA_PKCS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, +@@ -75,6 +78,14 @@ SFTKFIPSAlgorithmList sftk_fips_mechs[] + { CKM_SHA256_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_SHA384_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, + { CKM_SHA512_RSA_PKCS_PSS, { RSA_FB_KEY, CKF_SGN }, RSA_FB_STEP, SFTKFIPSNone }, ++ { CKM_SHA224_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, ++ { CKM_SHA256_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, ++ { CKM_SHA384_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, ++ { CKM_SHA512_RSA_PKCS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, ++ { CKM_SHA224_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, ++ { CKM_SHA256_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, ++ { CKM_SHA384_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, ++ { CKM_SHA512_RSA_PKCS_PSS, { RSA_LEGACY_FB_KEY, CKF_VERIFY }, RSA_LEGACY_FB_STEP, SFTKFIPSNone }, + /* ------------------------- DSA Operations --------------------------- */ + { CKM_DSA_KEY_PAIR_GEN, { DSA_FB_KEY, CKF_KPG }, DSA_FB_STEP, SFTKFIPSNone }, + { CKM_DSA, { DSA_FB_KEY, CKF_SGN }, DSA_FB_STEP, SFTKFIPSNone }, +diff -up ./lib/ssl/ssl3con.c.signature-policy ./lib/ssl/ssl3con.c +--- ./lib/ssl/ssl3con.c.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./lib/ssl/ssl3con.c 2022-06-21 09:16:23.920905040 -0700 +@@ -7409,6 +7409,8 @@ ssl_HandleDHServerKeyExchange(sslSocket + unsigned dh_p_bits; + unsigned dh_g_bits; + PRInt32 minDH; ++ PRInt32 optval; ++ PRBool usePolicyLength = PR_FALSE; + + SSL3Hashes hashes; + SECItem signature = { siBuffer, NULL, 0 }; +@@ -7419,8 +7421,13 @@ ssl_HandleDHServerKeyExchange(sslSocket + if (rv != SECSuccess) { + goto loser; /* malformed. */ + } ++ rv = NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optval); ++ if (rv == SECSuccess) { ++ usePolicyLength = (PRBool)((optval & NSS_KEY_SIZE_POLICY_SSL_FLAG) == NSS_KEY_SIZE_POLICY_SSL_FLAG); ++ } + +- rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minDH); ++ rv = usePolicyLength ? NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minDH) ++ : SECFailure; + if (rv != SECSuccess || minDH <= 0) { + minDH = SSL_DH_MIN_P_BITS; + } +@@ -11411,13 +11418,20 @@ ssl_SetAuthKeyBits(sslSocket *ss, const + SECStatus rv; + PRUint32 minKey; + PRInt32 optval; ++ PRBool usePolicyLength = PR_TRUE; ++ ++ rv = NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optval); ++ if (rv == SECSuccess) { ++ usePolicyLength = (PRBool)((optval & NSS_KEY_SIZE_POLICY_SSL_FLAG) == NSS_KEY_SIZE_POLICY_SSL_FLAG); ++ } + + ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey); + switch (SECKEY_GetPublicKeyType(pubKey)) { + case rsaKey: + case rsaPssKey: + case rsaOaepKey: +- rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &optval); ++ rv = usePolicyLength ? NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &optval) ++ : SECFailure; + if (rv == SECSuccess && optval > 0) { + minKey = (PRUint32)optval; + } else { +@@ -11426,7 +11440,8 @@ ssl_SetAuthKeyBits(sslSocket *ss, const + break; + + case dsaKey: +- rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &optval); ++ rv = usePolicyLength ? NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &optval) ++ : SECFailure; + if (rv == SECSuccess && optval > 0) { + minKey = (PRUint32)optval; + } else { +@@ -11435,7 +11450,8 @@ ssl_SetAuthKeyBits(sslSocket *ss, const + break; + + case dhKey: +- rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &optval); ++ rv = usePolicyLength ? NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &optval) ++ : SECFailure; + if (rv == SECSuccess && optval > 0) { + minKey = (PRUint32)optval; + } else { +@@ -11444,9 +11460,15 @@ ssl_SetAuthKeyBits(sslSocket *ss, const + break; + + case ecKey: +- /* Don't check EC strength here on the understanding that we only +- * support curves we like. */ +- minKey = ss->sec.authKeyBits; ++ rv = usePolicyLength ? NSS_OptionGet(NSS_ECC_MIN_KEY_SIZE, &optval) ++ : SECFailure; ++ if (rv == SECSuccess && optval > 0) { ++ minKey = (PRUint32)optval; ++ } else { ++ /* Don't check EC strength here on the understanding that we ++ * only support curves we like. */ ++ minKey = ss->sec.authKeyBits; ++ } + break; + + default: +diff -up ./tests/policy/crypto-policy.txt.signature-policy ./tests/policy/crypto-policy.txt +--- ./tests/policy/crypto-policy.txt.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./tests/policy/crypto-policy.txt 2022-06-21 09:16:23.920905040 -0700 +@@ -6,6 +6,8 @@ + 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 ++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:KEY-SIZE-FLAGS=KEY-SIZE-SSL,KEY-SIZE-SIGN,KEY-SIZE-VERIFY NSS-POLICY-INFO.*LOADED-SUCCESSFULLY Valid key size ++2 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:KEY-SIZE-FLAGS=UNKNOWN,KEY-SIZE-SIGN,KEY-SIZE-VERIFY NSS-POLICY-FAIL.*unknown.* Invalid key size + 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 +diff -up ./tests/ssl/sslpolicy.txt.signature-policy ./tests/ssl/sslpolicy.txt +--- ./tests/ssl/sslpolicy.txt.signature-policy 2022-05-26 02:54:33.000000000 -0700 ++++ ./tests/ssl/sslpolicy.txt 2022-06-21 09:16:23.920905040 -0700 +@@ -194,6 +194,10 @@ + 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 ++ 1 noECC SSL3 d allow=rsa-min=16384:key-size-flags=key-size-verify Restrict RSA keys on signature verification ++ 1 noECC SSL3 d allow=rsa-min=16384:key-size-flags=key-size-sign Restrict RSA keys on signing ++ 1 noECC SSL3 d allow=rsa-min=16384:key-size-flags=key-size-ssl Restrict RSA keys when used in SSL ++ 0 noECC SSL3 d allow=rsa-min=1023 Restrict RSA keys when used in SSL + # test default settings + # NOTE: tstclient will attempt to overide the defaults, so we detect we + # were successful by locking in our settings diff --git a/nss.spec b/nss.spec index 5c0219b..3cd9cae 100644 --- a/nss.spec +++ b/nss.spec @@ -1,6 +1,6 @@ %global nss_version 3.79.0 %global nspr_version 4.34.0 -%global baserelease 4 +%global baserelease 5 %global nss_release %baserelease # NOTE: To avoid NVR clashes of nspr* packages: # use "%%global nspr_release %%[%%baserelease+n]" to handle offsets when @@ -158,15 +158,19 @@ Patch34: nss-3.71-fix-lto-gtests.patch Patch35: nss-3.71-camellia-pkcs12-doc.patch # patches that expect to be upstreamed -#Patch50: nss-3.79-remove-explicit-ipv4.patch +# https://bugzilla.mozilla.org/show_bug.cgi?id=1774659 Patch51: nss-3.79-dbtool.patch +# https://bugzilla.mozilla.org/show_bug.cgi?id=1774657 Patch52: nss-3.79-dont-verify-default.patch +# https://bugzilla.mozilla.org/show_bug.cgi?id=1774654 Patch53: nss-3.79-fix-client-cert-crash.patch - - +# https://bugzilla.mozilla.org/show_bug.cgi?id=1767883 +Patch54: nss-3.79-rhel-9-fips-signature-policy.patch +Patch55: nss-3.79-enable-POST-rerun.patch Patch100: nspr-config-pc.patch Patch101: nspr-gcc-atomics.patch +# https://bugzilla.mozilla.org/show_bug.cgi?id=1769293 Patch110: nspr-4.34-fix-coverity-loop-issue.patch Patch120: nspr-4.34-server-passive.patch @@ -1144,6 +1148,12 @@ update-crypto-policies &> /dev/null || : %changelog +* Mon Jun 20 2022 Bob Relyea - 3.79.0-5 +- FIPS 140-3 changes +- Reject Small RSA keys, 1024 bit keys are marked as FIP OK when verifying, reject + signature keys by policy +- Allow applications to retrigger selftests on demand. + * Tue Jun 14 2022 Bob Relyea - 3.79.0-4 - server passive fix