Resolves: RHEL-103370

Rebase NSS to nss-3.112 for Firefox in RHEL 9
 - add ml-dsa support
 - add mlkem1024 support in ssl
This commit is contained in:
Robert Relyea 2025-07-15 09:18:36 -07:00
parent 7c9e7708b3
commit af5bf173e1
35 changed files with 121234 additions and 3731 deletions

3
.gitignore vendored
View File

@ -71,3 +71,6 @@ TestUser51.cert
/nss-3.90.tar.gz
/NameConstraints_Certs.tar
/nss-3.101.tar.gz
/nspr-4.36.tar.gz
/nss-3.112.tar.gz
/nss_compat_test_pkcs12.tar

View File

@ -1,51 +0,0 @@
diff --git a/pr/src/misc/prnetdb.c b/pr/src/misc/prnetdb.c
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -2209,28 +2209,38 @@ PR_GetPrefLoopbackAddrInfo(PRNetAddr *re
PRBool result_still_empty = PR_TRUE;
PRADDRINFO *ai = res;
do {
PRNetAddr aNetAddr;
while (ai && ai->ai_addrlen > sizeof(PRNetAddr))
ai = ai->ai_next;
- if (ai) {
- /* copy sockaddr to PRNetAddr */
- memcpy(&aNetAddr, ai->ai_addr, ai->ai_addrlen);
- aNetAddr.raw.family = ai->ai_addr->sa_family;
+ if (!ai) {
+ break;
+ }
+
+ /* copy sockaddr to PRNetAddr */
+ memcpy(&aNetAddr, ai->ai_addr, ai->ai_addrlen);
+ aNetAddr.raw.family = ai->ai_addr->sa_family;
#ifdef _PR_INET6
- if (AF_INET6 == aNetAddr.raw.family)
- aNetAddr.raw.family = PR_AF_INET6;
+ if (AF_INET6 == aNetAddr.raw.family)
+ aNetAddr.raw.family = PR_AF_INET6;
#endif
- if (ai->ai_addrlen < sizeof(PRNetAddr))
- memset(((char*)result)+ai->ai_addrlen, 0,
- sizeof(PRNetAddr) - ai->ai_addrlen);
+ if (ai->ai_addrlen < sizeof(PRNetAddr))
+ memset(((char*)&aNetAddr)+ai->ai_addrlen, 0,
+ sizeof(PRNetAddr) - ai->ai_addrlen);
+
+ if (result->raw.family == PR_AF_INET) {
+ aNetAddr.inet.port = htons(port);
}
+ else {
+ aNetAddr.ipv6.port = htons(port);
+ }
+
/* If we obtain more than one result, prefer IPv6. */
if (result_still_empty || aNetAddr.raw.family == PR_AF_INET6) {
memcpy(result, &aNetAddr, sizeof(PRNetAddr));
}
result_still_empty = PR_FALSE;
ai = ai->ai_next;
}

View File

@ -1,12 +0,0 @@
diff -r c75b4e36b7e8 pr/src/misc/prnetdb.c
--- a/pr/src/misc/prnetdb.c Wed May 25 23:39:48 2022 +0200
+++ b/pr/src/misc/prnetdb.c Tue Jun 14 18:48:03 2022 -0400
@@ -2204,6 +2204,7 @@
memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE;
rv = GETADDRINFO(NULL, tmpBuf, &hints, &res);
if (rv == 0) {
PRBool result_still_empty = PR_TRUE;

View File

@ -0,0 +1,53 @@
diff --git a/pr/src/misc/prnetdb.c b/pr/src/misc/prnetdb.c
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -2047,35 +2047,43 @@ PR_GetPrefLoopbackAddrInfo(PRNetAddr* re
return PR_FAILURE;
#else
PRADDRINFO *res, hints;
PRStatus rv;
memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE;
rv = GETADDRINFO(NULL, tmpBuf, &hints, &res);
if (rv == 0) {
PRBool result_still_empty = PR_TRUE;
PRADDRINFO* ai = res;
do {
PRNetAddr aNetAddr;
while (ai && ai->ai_addrlen > sizeof(PRNetAddr)) ai = ai->ai_next;
- if (ai) {
- /* copy sockaddr to PRNetAddr */
- memcpy(&aNetAddr, ai->ai_addr, ai->ai_addrlen);
- aNetAddr.raw.family = ai->ai_addr->sa_family;
+ if (!ai) {
+ break;
+ }
+
+ /* copy sockaddr to PRNetAddr */
+ memcpy(&aNetAddr, ai->ai_addr, ai->ai_addrlen);
+ aNetAddr.raw.family = ai->ai_addr->sa_family;
# ifdef _PR_INET6
- if (AF_INET6 == aNetAddr.raw.family) aNetAddr.raw.family = PR_AF_INET6;
+ if (AF_INET6 == aNetAddr.raw.family) aNetAddr.raw.family = PR_AF_INET6;
# endif
- if (ai->ai_addrlen < sizeof(PRNetAddr))
+ if (ai->ai_addrlen < sizeof(PRNetAddr))
memset(((char*)result) + ai->ai_addrlen, 0,
sizeof(PRNetAddr) - ai->ai_addrlen);
+ if (result->raw.family == PR_AF_INET) {
+ aNetAddr.inet.port = htons(port);
+ } else {
+ aNetAddr.ipv6.port = htons(port);
}
/* If we obtain more than one result, prefer IPv6. */
if (result_still_empty || aNetAddr.raw.family == PR_AF_INET6) {
memcpy(result, &aNetAddr, sizeof(PRNetAddr));
}
result_still_empty = PR_FALSE;
ai = ai->ai_next;

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +0,0 @@
diff -up ./lib/pk11wrap/pk11pars.c.ems ./lib/pk11wrap/pk11pars.c
--- ./lib/pk11wrap/pk11pars.c.ems 2024-06-11 13:09:25.956760476 -0700
+++ ./lib/pk11wrap/pk11pars.c 2024-06-11 13:09:52.837067481 -0700
@@ -433,6 +433,8 @@ static const oidValDef kxOptList[] = {
{ CIPHER_NAME("ECDHE-RSA"), SEC_OID_TLS_ECDHE_RSA, NSS_USE_ALG_IN_SSL_KX },
{ CIPHER_NAME("ECDH-ECDSA"), SEC_OID_TLS_ECDH_ECDSA, NSS_USE_ALG_IN_SSL_KX },
{ CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX },
+ { CIPHER_NAME("TLS-REQUIRE-EMS"), SEC_OID_TLS_REQUIRE_EMS, NSS_USE_ALG_IN_SSL_KX },
+
};
static const oidValDef smimeKxOptList[] = {
diff -up ./lib/pk11wrap/secmodti.h.add_ems_policy ./lib/pk11wrap/secmodti.h
--- ./lib/pk11wrap/secmodti.h.add_ems_policy 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/pk11wrap/secmodti.h 2023-06-12 17:18:35.129938514 -0700
@@ -202,4 +202,10 @@ struct PK11GenericObjectStr {
/* This mask includes all CK_FLAGs with an equivalent CKA_ attribute. */
#define CKF_KEY_OPERATION_FLAGS 0x000e7b00UL
+/* this oid value could change values if it's added after other new
+ * upstream oids. We protect applications by hiding the define in a private
+ * header file that only NSS sees. Currently it's only available through
+ * the policy code */
+#define SEC_OID_TLS_REQUIRE_EMS SEC_OID_PRIVATE_1
+
#endif /* _SECMODTI_H_ */
diff -up ./lib/ssl/ssl3con.c.add_ems_policy ./lib/ssl/ssl3con.c
--- ./lib/ssl/ssl3con.c.add_ems_policy 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/ssl/ssl3con.c 2023-06-12 17:18:35.130938525 -0700
@@ -36,6 +36,7 @@
#include "pk11func.h"
#include "secmod.h"
#include "blapi.h"
+#include "secmodti.h" /* until SEC_OID_TLS_REQUIRE_EMS is upstream */
#include <stdio.h>
@@ -3480,6 +3481,29 @@ ssl3_ComputeMasterSecretInt(sslSocket *s
CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params;
unsigned int master_params_len;
+ /* if we are using TLS and we aren't using the extended master secret,
+ * and SEC_OID_TLS_REQUIRE_EMS policy is true, fail. The caller will
+ * send and alert (eventually). In the RSA Server case, the alert
+ * won't happen until Finish time because the upper level code
+ * can't tell a difference between this failure and an RSA decrypt
+ * failure, so it will proceed with a faux key */
+ if (isTLS) {
+ PRUint32 policy;
+ SECStatus rv;
+
+ /* first fetch the policy for this algorithm */
+ rv = NSS_GetAlgorithmPolicy(SEC_OID_TLS_REQUIRE_EMS, &policy);
+ /* we only look at the policy if we can fetch it. */
+ if (rv == SECSuccess) {
+ if (policy & NSS_USE_ALG_IN_SSL_KX) {
+ /* just set the error, we don't want to map any errors
+ * set by NSS_GetAlgorithmPolicy here */
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
+ return SECFailure;
+ }
+ }
+ }
+
if (isTLS12) {
if (isDH)
master_derive = CKM_TLS12_MASTER_KEY_DERIVE_DH;
diff -up ./lib/util/secoid.c.ems ./lib/util/secoid.c
--- ./lib/util/secoid.c.ems 2024-06-11 13:11:28.078155282 -0700
+++ ./lib/util/secoid.c 2024-06-11 13:12:58.511188172 -0700
@@ -1890,6 +1890,12 @@ const static SECOidData oids[SEC_OID_TOT
ODE(SEC_OID_RC2_64_CBC, "RC2-64-CBC", CKM_RC2_CBC, INVALID_CERT_EXTENSION),
ODE(SEC_OID_RC2_128_CBC, "RC2-128-CBC", CKM_RC2_CBC, INVALID_CERT_EXTENSION),
ODE(SEC_OID_ECDH_KEA, "ECDH", CKM_ECDH1_DERIVE, INVALID_CERT_EXTENSION),
+
+ /* this will change upstream. for now apps shouldn't use it */
+ /* we need it for the policy code. */
+ ODE(SEC_OID_PRIVATE_1,
+ "TLS Require EMS", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
+
};
/* PRIVATE EXTENDED SECOID Table
@@ -2198,6 +2204,10 @@ SECOID_Init(void)
/* turn off NSS_USE_POLICY_IN_SSL by default */
xOids[SEC_OID_APPLY_SSL_POLICY].notPolicyFlags = NSS_USE_POLICY_IN_SSL;
+ /* turn off TLS REQUIRE EMS by default */
+ xOids[SEC_OID_PRIVATE_1].notPolicyFlags = ~0;
+
+
envVal = PR_GetEnvSecure("NSS_HASH_ALG_SUPPORT");
if (envVal)
diff -up ./lib/util/secoidt.h.ems ./lib/util/secoidt.h
--- ./lib/util/secoidt.h.ems 2024-06-11 13:16:13.212411967 -0700
+++ ./lib/util/secoidt.h 2024-06-11 13:16:48.098810434 -0700
@@ -530,6 +530,9 @@ typedef enum {
SEC_OID_RC2_64_CBC = 385,
SEC_OID_RC2_128_CBC = 386,
SEC_OID_ECDH_KEA = 387,
+ /* this will change upstream. for now apps shouldn't use it */
+ /* give it an obscure name here */
+ SEC_OID_PRIVATE_1 = 388,
SEC_OID_TOTAL
} SECOidTag;

View File

@ -1,20 +0,0 @@
diff -up ./lib/softoken/pkcs11u.c.fipsrsaoaep ./lib/softoken/pkcs11u.c
--- ./lib/softoken/pkcs11u.c.fipsrsaoaep 2024-10-24 09:27:17.971673855 +0200
+++ ./lib/softoken/pkcs11u.c 2024-10-24 09:23:35.006352872 +0200
@@ -2565,6 +2565,16 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
}
}
return sftk_checkKeyLength(targetKeyLength, 112, 512, 1);
+ case SFTKFIPSRSAOAEP:;
+ CK_RSA_PKCS_OAEP_PARAMS *rsaoaep = (CK_RSA_PKCS_OAEP_PARAMS *)
+ mech->pParameter;
+
+ HASH_HashType hash_msg = sftk_GetHashTypeFromMechanism(rsaoaep->hashAlg);
+ HASH_HashType hash_pad = sftk_GetHashTypeFromMechanism(rsaoaep->mgf);
+ /* message hash and mask generation function must be the same */
+ if (hash_pad != hash_msg) return PR_FALSE;
+
+ return sftk_checkFIPSHash(rsaoaep->hashAlg, PR_FALSE, PR_FALSE);
default:
break;
}

View File

@ -1,59 +0,0 @@
diff --git a/lib/freebl/chacha20poly1305.c b/lib/freebl/chacha20poly1305.c
--- a/lib/freebl/chacha20poly1305.c
+++ b/lib/freebl/chacha20poly1305.c
@@ -213,27 +213,31 @@
{
#ifdef NSS_X64
#ifndef NSS_DISABLE_AVX2
if (avx2_support()) {
Hacl_Chacha20_Vec256_chacha20_encrypt_256(len, output, block, k, nonce, ctr);
+ return;
}
#endif
#ifndef NSS_DISABLE_SSE3
if (ssse3_support() && sse4_1_support() && avx_support()) {
Hacl_Chacha20_Vec128_chacha20_encrypt_128(len, output, block, k, nonce, ctr);
+ return;
}
#endif
#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \
!defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX)
if (ppc_crypto_support()) {
chacha20vsx(len, output, block, k, nonce, ctr);
- } else
+ return;
+ }
#endif
{
Hacl_Chacha20_chacha20_encrypt(len, output, block, k, nonce, ctr);
+ return;
}
}
#endif /* NSS_DISABLE_CHACHAPOLY */
SECStatus
@@ -449,20 +453,18 @@
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, outTag);
goto finish;
}
#endif
-
- else
#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \
!defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX)
if (ppc_crypto_support()) {
Chacha20Poly1305_vsx_aead_encrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, outTag);
goto finish;
- } else
+ }
#endif
{
Hacl_Chacha20Poly1305_32_aead_encrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, outTag);

View File

@ -1,13 +0,0 @@
diff -up ./lib/pk11wrap/pk11pars.c.enable_kyber_policy ./lib/pk11wrap/pk11pars.c
--- ./lib/pk11wrap/pk11pars.c.enable_kyber_policy 2024-06-12 14:44:24.680338868 -0700
+++ ./lib/pk11wrap/pk11pars.c 2024-06-12 14:44:48.368609356 -0700
@@ -245,7 +245,8 @@ static const oidValDef curveOptList[] =
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("CURVE25519"), SEC_OID_CURVE25519,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
- { CIPHER_NAME("XYBER768D00"), SEC_OID_XYBER768D00, 0 },
+ { CIPHER_NAME("XYBER768D00"), SEC_OID_XYBER768D00,
+ NSS_USE_ALG_IN_SSL_KX },
/* ANSI X9.62 named elliptic curves (characteristic two field) */
{ CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },

View File

@ -1,63 +0,0 @@
diff -up ./tests/cert/cert.sh.no_dbm_tests ./tests/cert/cert.sh
--- ./tests/cert/cert.sh.no_dbm_tests 2024-06-20 17:08:03.146169243 -0700
+++ ./tests/cert/cert.sh 2024-06-20 17:08:23.282404259 -0700
@@ -2662,9 +2662,7 @@ cert_test_password
cert_test_distrust
cert_test_ocspresp
cert_test_rsapss
-if [ "${TEST_MODE}" = "SHARED_DB" ] ; then
- cert_test_rsapss_policy
-fi
+cert_test_rsapss_policy
cert_test_token_uri
if [ -z "$NSS_TEST_DISABLE_CRL" ] ; then
diff -up ./tests/smime/smime.sh.no_dbm_tests ./tests/smime/smime.sh
--- ./tests/smime/smime.sh.no_dbm_tests 2024-06-20 17:08:45.147659448 -0700
+++ ./tests/smime/smime.sh 2024-06-20 17:09:05.313894814 -0700
@@ -872,8 +872,6 @@ smime_init
smime_main
smime_data_tb
smime_p7
-if [ "${TEST_MODE}" = "SHARED_DB" ] ; then
- smime_policy
-fi
+smime_policy
smime_cleanup
diff -up ./tests/ssl/ssl.sh.no_dbm_tests ./tests/ssl/ssl.sh
--- ./tests/ssl/ssl.sh.no_dbm_tests 2024-06-20 17:09:28.588166454 -0700
+++ ./tests/ssl/ssl.sh 2024-06-20 17:09:54.351467232 -0700
@@ -1600,12 +1600,10 @@ ssl_run_tests()
do
case "${SSL_TEST}" in
"policy")
- if [ "${TEST_MODE}" = "SHARED_DB" ] ; then
- ssl_policy_listsuites
- ssl_policy_selfserv
- ssl_policy_pkix_ocsp
- ssl_policy
- fi
+ ssl_policy_listsuites
+ ssl_policy_selfserv
+ ssl_policy_pkix_ocsp
+ ssl_policy
;;
"crl")
ssl_crl_ssl
diff -up ./tests/tools/tools.sh.no_dbm_tests ./tests/tools/tools.sh
--- ./tests/tools/tools.sh.no_dbm_tests 2024-06-20 17:10:13.828694981 -0700
+++ ./tests/tools/tools.sh 2024-06-20 17:10:31.051896368 -0700
@@ -584,10 +584,8 @@ tools_p12()
tools_p12_export_with_invalid_ciphers
tools_p12_import_old_files
tools_p12_import_pbmac1_samples
- if [ "${TEST_MODE}" = "SHARED_DB" ] ; then
- tools_p12_import_rsa_pss_private_key
- tools_p12_policy
- fi
+ tools_p12_import_rsa_pss_private_key
+ tools_p12_policy
}
############################## tools_sign ##############################

View File

@ -1,12 +0,0 @@
diff -up ./lib/softoken/pkcs11u.c.fips_check_curver25519 ./lib/softoken/pkcs11u.c
--- ./lib/softoken/pkcs11u.c.fips_check_curver25519 2024-11-11 11:24:25.186654635 +0100
+++ ./lib/softoken/pkcs11u.c 2024-11-07 10:26:03.806562274 +0100
@@ -2356,7 +2356,7 @@ sftk_getKeyLength(SFTKObject *source)
* key length is CKA_VALUE, which is the default */
keyType = CKK_INVALID_KEY_TYPE;
}
- if (keyType == CKK_EC) {
+ if (keyType == CKK_EC || keyType == CKK_EC_EDWARDS || keyType == CKK_EC_MONTGOMERY) {
SECOidTag curve = sftk_quickGetECCCurveOid(source);
switch (curve) {
case SEC_OID_CURVE25519:

View File

@ -1,190 +0,0 @@
diff -up ./lib/softoken/pkcs11c.c.fips_indicators ./lib/softoken/pkcs11c.c
--- ./lib/softoken/pkcs11c.c.fips_indicators 2024-06-12 13:38:15.995811284 -0700
+++ ./lib/softoken/pkcs11c.c 2024-06-12 13:41:30.008188930 -0700
@@ -453,7 +453,7 @@ sftk_InitGeneric(SFTKSession *session, C
context->blockSize = 0;
context->maxLen = 0;
context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism,
- operation, key);
+ operation, key, 0);
*contextPtr = context;
return CKR_OK;
}
@@ -4885,7 +4885,7 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi
crv = sftk_handleObject(key, session);
/* we need to do this check at the end, so we can check the generated
* key length against fips requirements */
- key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE, key);
+ key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE, key, 0);
session->lastOpWasFIPS = key->isFIPS;
sftk_FreeSession(session);
if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) {
@@ -6020,7 +6020,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
return crv;
}
/* we need to do this check at the end to make sure the generated key meets the key length requirements */
- privateKey->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE_KEY_PAIR, privateKey);
+ privateKey->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE_KEY_PAIR, privateKey, 0);
publicKey->isFIPS = privateKey->isFIPS;
session->lastOpWasFIPS = privateKey->isFIPS;
sftk_FreeSession(session);
@@ -7220,6 +7220,10 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
return CKR_TEMPLATE_INCONSISTENT;
}
+ if (!params->bExpand) {
+ keySize = hashLen;
+ }
+
/* sourceKey is NULL if we are called from the POST, skip the
* sensitiveCheck */
if (sourceKey != NULL) {
@@ -7269,7 +7273,8 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
mech.pParameter = params;
mech.ulParameterLen = sizeof(*params);
key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech,
- CKA_DERIVE, saltKey);
+ CKA_DERIVE, saltKey,
+ keySize);
}
saltKeySource = saltKey->source;
saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
@@ -7336,7 +7341,7 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
/* HKDF-Expand */
if (!params->bExpand) {
okm = prk;
- keySize = genLen = hashLen;
+ genLen = hashLen;
} else {
/* T(1) = HMAC-Hash(prk, "" | info | 0x01)
* T(n) = HMAC-Hash(prk, T(n-1) | info | n
@@ -7583,7 +7588,8 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
return CKR_KEY_HANDLE_INVALID;
}
}
- key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey);
+ key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey,
+ keySize);
switch (mechanism) {
/* get a public key from a private key. nsslowkey_ConvertToPublickey()
diff -up ./lib/softoken/pkcs11i.h.fips_indicators ./lib/softoken/pkcs11i.h
--- ./lib/softoken/pkcs11i.h.fips_indicators 2024-06-12 13:38:15.988811198 -0700
+++ ./lib/softoken/pkcs11i.h 2024-06-12 13:38:15.996811296 -0700
@@ -979,7 +979,8 @@ CK_FLAGS sftk_AttributeToFlags(CK_ATTRIB
/* check the FIPS table to determine if this current operation is allowed by
* FIPS security policy */
PRBool sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech,
- CK_ATTRIBUTE_TYPE op, SFTKObject *source);
+ CK_ATTRIBUTE_TYPE op, SFTKObject *source,
+ CK_ULONG targetKeySize);
/* add validation objects to the slot */
CK_RV sftk_CreateValidationObjects(SFTKSlot *slot);
diff -up ./lib/softoken/pkcs11u.c.fips_indicators ./lib/softoken/pkcs11u.c
--- ./lib/softoken/pkcs11u.c.fips_indicators 2024-06-12 13:38:15.990811223 -0700
+++ ./lib/softoken/pkcs11u.c 2024-06-12 13:38:15.996811296 -0700
@@ -2336,7 +2336,7 @@ sftk_quickGetECCCurveOid(SFTKObject *sou
static CK_ULONG
sftk_getKeyLength(SFTKObject *source)
{
- CK_KEY_TYPE keyType = CK_INVALID_HANDLE;
+ CK_KEY_TYPE keyType = CKK_INVALID_KEY_TYPE;
CK_ATTRIBUTE_TYPE keyAttribute;
CK_ULONG keyLength = 0;
SFTKAttribute *attribute;
@@ -2398,13 +2398,29 @@ sftk_getKeyLength(SFTKObject *source)
return keyLength;
}
+PRBool
+sftk_CheckFIPSHash(CK_MECHANISM_TYPE hash)
+{
+ switch (hash) {
+ case CKM_SHA256:
+ case CKG_MGF1_SHA256:
+ case CKM_SHA384:
+ case CKG_MGF1_SHA384:
+ case CKM_SHA512:
+ case CKG_MGF1_SHA512:
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
/*
* handle specialized FIPS semantics that are too complicated to
* handle with just a table. NOTE: this means any additional semantics
* would have to be coded here before they can be added to the table */
static PRBool
sftk_handleSpecial(SFTKSlot *slot, CK_MECHANISM *mech,
- SFTKFIPSAlgorithmList *mechInfo, SFTKObject *source)
+ SFTKFIPSAlgorithmList *mechInfo, SFTKObject *source,
+ CK_ULONG keyLength, CK_ULONG targetKeyLength)
{
switch (mechInfo->special) {
case SFTKFIPSDH: {
@@ -2464,10 +2480,15 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
if (hashObj == NULL) {
return PR_FALSE;
}
+ /* cap the salt for legacy keys */
+ if ((keyLength <= 1024) && (pss->sLen > 63)) {
+ return PR_FALSE;
+ }
+ /* cap the salt for based on the hash */
if (pss->sLen > hashObj->length) {
return PR_FALSE;
}
- return PR_TRUE;
+ return sftk_CheckFIPSHash(pss->hashAlg);
}
case SFTKFIPSPBKDF2: {
/* PBKDF2 must have the following addition restrictions
@@ -2492,6 +2513,13 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
}
return PR_TRUE;
}
+ /* check the hash mechanisms to make sure they themselves are FIPS */
+ case SFTKFIPSChkHash:
+ if (mech->ulParameterLen < mechInfo->offset +sizeof(CK_ULONG)) {
+ return PR_FALSE;
+ }
+ return sftk_CheckFIPSHash(*(CK_ULONG *)(((char *)mech->pParameter)
+ + mechInfo->offset));
default:
break;
}
@@ -2502,7 +2530,7 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
PRBool
sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech, CK_ATTRIBUTE_TYPE op,
- SFTKObject *source)
+ SFTKObject *source, CK_ULONG targetKeyLength)
{
#ifndef NSS_HAS_FIPS_INDICATORS
return PR_FALSE;
@@ -2534,13 +2562,17 @@ sftk_operationIsFIPS(SFTKSlot *slot, CK_
SFTKFIPSAlgorithmList *mechs = &sftk_fips_mechs[i];
/* if we match the number of records exactly, then we are an
* approved algorithm in the approved mode with an approved key */
- if (((mech->mechanism == mechs->type) &&
- (opFlags == (mechs->info.flags & opFlags)) &&
- (keyLength <= mechs->info.ulMaxKeySize) &&
- (keyLength >= mechs->info.ulMinKeySize) &&
- ((keyLength - mechs->info.ulMinKeySize) % mechs->step) == 0) &&
+ if ((mech->mechanism == mechs->type) &&
+ (opFlags == (mechs->info.flags & opFlags)) &&
+ (keyLength <= mechs->info.ulMaxKeySize) &&
+ (keyLength >= mechs->info.ulMinKeySize) &&
+ (((keyLength - mechs->info.ulMinKeySize) % mechs->step) == 0) &&
+ ((targetKeyLength == 0) ||
+ ((targetKeyLength <= mechs->info.ulMaxKeySize) &&
+ (targetKeyLength >= mechs->info.ulMinKeySize) &&
+ ((targetKeyLength - mechs->info.ulMinKeySize) % mechs->step) == 0)) &&
((mechs->special == SFTKFIPSNone) ||
- sftk_handleSpecial(slot, mech, mechs, source))) {
+ sftk_handleSpecial(slot, mech, mechs, source, keyLength, targetKeyLength))) {
return PR_TRUE;
}
}

View File

@ -1,126 +0,0 @@
diff --git a/gtests/ssl_gtest/tls_subcerts_unittest.cc b/gtests/ssl_gtest/tls_subcerts_unittest.cc
--- a/gtests/ssl_gtest/tls_subcerts_unittest.cc
+++ b/gtests/ssl_gtest/tls_subcerts_unittest.cc
@@ -371,16 +371,21 @@ static void GenerateWeakRsaKey(ScopedSEC
// Fail to connect with a weak RSA key.
TEST_P(TlsConnectTls13, DCWeakKey) {
Reset(kPssDelegatorId);
EnsureTlsSetup();
static const SSLSignatureScheme kSchemes[] = {ssl_sig_rsa_pss_rsae_sha256,
ssl_sig_rsa_pss_pss_sha256};
client_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes));
server_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes));
+ PRInt32 keySizeFlags;
+ ASSERT_EQ(SECSuccess, NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &keySizeFlags));
+ // turn off the signing key sizes so we actually test the ssl tests
+ ASSERT_EQ(SECSuccess,
+ NSS_OptionSet(NSS_KEY_SIZE_POLICY_FLAGS, NSS_KEY_SIZE_POLICY_SSL_FLAG ));
#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));
@@ -408,16 +413,17 @@ TEST_P(TlsConnectTls13, DCWeakKey) {
client_->EnableDelegatedCredentials();
auto cfilter = MakeTlsFilter<TlsExtensionCapture>(
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
+ ASSERT_EQ(SECSuccess, NSS_OptionSet(NSS_KEY_SIZE_POLICY_FLAGS, keySizeFlags));
}
class ReplaceDCSigScheme : public TlsHandshakeFilter {
public:
ReplaceDCSigScheme(const std::shared_ptr<TlsAgent>& a)
: TlsHandshakeFilter(a, {ssl_hs_certificate_verify}) {}
protected:
diff --git a/lib/cryptohi/seckey.c b/lib/cryptohi/seckey.c
--- a/lib/cryptohi/seckey.c
+++ b/lib/cryptohi/seckey.c
@@ -1134,22 +1134,31 @@ SECKEY_PrivateKeyStrengthInBits(const SE
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;
+ rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
+ CKA_MODULUS, NULL, &params);
+ if ((rv != SECSuccess) || (params.data == NULL)) {
+ /* some tokens don't export CKA_MODULUS on the private key,
+ * PK11_SignatureLen works around this if necessary. This
+ * method is less percise because it returns bytes instead
+ * bits, so we only do it if we can't get the modulus */
+ bitSize = PK11_SignatureLen((SECKEYPrivateKey *)privk) * PR_BITS_PER_BYTE;
+ if (bitSize == -1) {
+ return 0;
+ }
+ return bitSize;
}
+ bitSize = SECKEY_BigIntegerBitLength(&params);
+ PORT_Free(params.data);
return bitSize;
case dsaKey:
case fortezzaKey:
case dhKey:
case keaKey:
rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
CKA_PRIME, NULL, &params);
if ((rv != SECSuccess) || (params.data == NULL)) {
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -1277,27 +1277,39 @@ ssl3_SignHashesWithPrivKey(SSL3Hashes *h
PORT_SetError(SEC_ERROR_INVALID_KEY);
goto done;
}
PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));
if (useRsaPss || hash->hashAlg == ssl_hash_none) {
CK_MECHANISM_TYPE mech = PK11_MapSignKeyType(key->keyType);
int signatureLen = PK11_SignatureLen(key);
+ PRInt32 optval;
SECItem *params = NULL;
CK_RSA_PKCS_PSS_PARAMS pssParams;
SECItem pssParamsItem = { siBuffer,
(unsigned char *)&pssParams,
sizeof(pssParams) };
if (signatureLen <= 0) {
PORT_SetError(SEC_ERROR_INVALID_KEY);
goto done;
}
+ /* since we are calling PK11_SignWithMechanism directly, we need to check the
+ * key policy ourselves (which is already checked in SGN_Digest */
+ rv = NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optval);
+ if ((rv == SECSuccess) &&
+ ((optval & NSS_KEY_SIZE_POLICY_SIGN_FLAG) == NSS_KEY_SIZE_POLICY_SIGN_FLAG)) {
+ rv = SECKEY_EnforceKeySize(key->keyType, SECKEY_PrivateKeyStrengthInBits(key),
+ SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
+ if (rv != SECSuccess) {
+ goto done; /* error code already set */
+ }
+ }
buf->len = (unsigned)signatureLen;
buf->data = (unsigned char *)PORT_Alloc(signatureLen);
if (!buf->data)
goto done; /* error code was set. */
if (useRsaPss) {
pssParams.hashAlg = ssl3_GetHashMechanismByHashType(hash->hashAlg);

View File

@ -1,43 +0,0 @@
diff --git a/lib/util/nsshash.c b/lib/util/nsshash.c
--- a/lib/util/nsshash.c
+++ b/lib/util/nsshash.c
@@ -102,16 +102,19 @@ HASH_GetHashOidTagByHashType(HASH_HashTy
SECOidTag
HASH_GetHashOidTagByHMACOidTag(SECOidTag hmacOid)
{
SECOidTag hashOid = SEC_OID_UNKNOWN;
switch (hmacOid) {
/* no oid exists for HMAC_MD2 */
/* NSS does not define a oid for HMAC_MD4 */
+ case SEC_OID_HMAC_MD5:
+ hashOid = SEC_OID_MD5;
+ break;
case SEC_OID_HMAC_SHA1:
hashOid = SEC_OID_SHA1;
break;
case SEC_OID_HMAC_SHA224:
hashOid = SEC_OID_SHA224;
break;
case SEC_OID_HMAC_SHA256:
hashOid = SEC_OID_SHA256;
@@ -145,16 +148,19 @@ HASH_GetHashOidTagByHMACOidTag(SECOidTag
SECOidTag
HASH_GetHMACOidTagByHashOidTag(SECOidTag hashOid)
{
SECOidTag hmacOid = SEC_OID_UNKNOWN;
switch (hashOid) {
/* no oid exists for HMAC_MD2 */
/* NSS does not define a oid for HMAC_MD4 */
+ case SEC_OID_MD5:
+ hmacOid = SEC_OID_HMAC_MD5;
+ break;
case SEC_OID_SHA1:
hmacOid = SEC_OID_HMAC_SHA1;
break;
case SEC_OID_SHA224:
hmacOid = SEC_OID_HMAC_SHA224;
break;
case SEC_OID_SHA256:
hmacOid = SEC_OID_HMAC_SHA256;

View File

@ -1,121 +0,0 @@
diff --git a/lib/pk11wrap/pk11mech.c b/lib/pk11wrap/pk11mech.c
--- a/lib/pk11wrap/pk11mech.c
+++ b/lib/pk11wrap/pk11mech.c
@@ -1710,20 +1710,26 @@ PK11_ParamToAlgid(SECOidTag algTag, SECI
case CKM_BATON_ECB96:
case CKM_BATON_CBC128:
case CKM_BATON_COUNTER:
case CKM_BATON_SHUFFLE:
case CKM_JUNIPER_ECB128:
case CKM_JUNIPER_CBC128:
case CKM_JUNIPER_COUNTER:
case CKM_JUNIPER_SHUFFLE:
- newParams = SEC_ASN1EncodeItem(NULL, NULL, param,
- SEC_ASN1_GET(SEC_OctetStringTemplate));
- if (newParams == NULL)
- break;
+ /* if no parameters have been supplied, then encode a NULL params
+ */
+ if (param && param->len > 0) {
+ newParams = SEC_ASN1EncodeItem(NULL, NULL, param,
+ SEC_ASN1_GET(SEC_OctetStringTemplate));
+ if (newParams == NULL)
+ break;
+ } else {
+ newParams = NULL;
+ }
rv = SECSuccess;
break;
}
if (rv != SECSuccess) {
if (newParams)
SECITEM_FreeItem(newParams, PR_TRUE);
return rv;
diff --git a/lib/pk11wrap/pk11pbe.c b/lib/pk11wrap/pk11pbe.c
--- a/lib/pk11wrap/pk11pbe.c
+++ b/lib/pk11wrap/pk11pbe.c
@@ -765,45 +765,53 @@ sec_pkcs5CreateAlgorithmID(SECOidTag alg
* algorithm is). We use choose this algorithm oid based on the
* cipherAlgorithm to determine what this should be (MAC1 or PBES2).
*/
if (algorithm == SEC_OID_PKCS5_PBKDF2) {
/* choose mac or pbes */
algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm);
}
+ SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
+
/* set the PKCS5v2 specific parameters */
if (keyLength == 0) {
- SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
if (hashAlg != SEC_OID_UNKNOWN) {
keyLength = HASH_ResultLenByOidTag(hashAlg);
} else {
keyLength = sec_pkcs5v2_default_key_length(cipherAlgorithm);
}
if (keyLength <= 0) {
goto loser;
}
}
/* currently SEC_OID_HMAC_SHA1 is the default */
if (prfAlg == SEC_OID_UNKNOWN) {
prfAlg = SEC_OID_HMAC_SHA1;
}
- /* build the PKCS5v2 cipher algorithm id */
- cipherParams = pk11_GenerateNewParamWithKeyLen(
- PK11_AlgtagToMechanism(cipherAlgorithm), keyLength);
- if (!cipherParams) {
- goto loser;
+ /* build the PKCS5v2 cipher algorithm id, if cipher
+ * is an HMAC, the cipherParams should be NULL */
+ if (hashAlg == SEC_OID_UNKNOWN) {
+ cipherParams = pk11_GenerateNewParamWithKeyLen(
+ PK11_AlgtagToMechanism(cipherAlgorithm), keyLength);
+ if (!cipherParams) {
+ goto loser;
+ }
+ } else {
+ cipherParams = NULL;
}
PORT_Memset(&pbeV2_param, 0, sizeof(pbeV2_param));
rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams,
poolp, &pbeV2_param.cipherAlgId);
- SECITEM_FreeItem(cipherParams, PR_TRUE);
+ if (cipherParams) {
+ SECITEM_FreeItem(cipherParams, PR_TRUE);
+ }
if (rv != SECSuccess) {
goto loser;
}
}
/* generate the parameter */
pbe_param = sec_pkcs5_create_pbe_parameter(pbeAlgorithm, salt, iteration,
keyLength, prfAlg);
diff --git a/lib/util/secalgid.c b/lib/util/secalgid.c
--- a/lib/util/secalgid.c
+++ b/lib/util/secalgid.c
@@ -50,17 +50,18 @@ SECOID_SetAlgorithmID(PLArenaPool *arena
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
if (SECITEM_CopyItem(arena, &id->algorithm, &oiddata->oid))
return SECFailure;
if ((secoid_IsRSAPKCS1(which)) ||
- (HASH_GetHashTypeByOidTag(which) != HASH_AlgNULL)) {
+ (HASH_GetHashTypeByOidTag(which) != HASH_AlgNULL) /* ||
+ (HASH_GetHashOidTagByHMACOidTag(which) != SEC_OID_UNKNOWN) */) {
add_null_param = PR_TRUE;
} else {
add_null_param = PR_FALSE;
}
if (params) {
/*
* I am specifically *not* enforcing the following assertion

View File

@ -1,12 +0,0 @@
diff -up ./tests/ssl/sslpolicy.txt.fix_rsa_policy ./tests/ssl/sslpolicy.txt
--- ./tests/ssl/sslpolicy.txt.fix_rsa_policy 2024-06-21 11:08:01.765937907 -0700
+++ ./tests/ssl/sslpolicy.txt 2024-06-21 11:08:55.598540079 -0700
@@ -195,7 +195,7 @@
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
+ 0 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

View File

@ -1,12 +0,0 @@
diff -up ./lib/pkcs12/p12local.c.long_pw_fix ./lib/pkcs12/p12local.c
--- ./lib/pkcs12/p12local.c.long_pw_fix 2024-09-06 17:58:39.905517185 -0700
+++ ./lib/pkcs12/p12local.c 2024-09-06 17:59:19.568985976 -0700
@@ -102,7 +102,7 @@ sec_pkcs12_integrity_key(PK11SlotInfo *s
*hmacMech = PK11_AlgtagToMechanism(hmacAlg);
/* pkcs12v2 hmac uses UTF8 rather than unicode */
if (!sec_pkcs12_convert_item_to_unicode(NULL, &utf8Pw, pwitem,
- PR_TRUE, PR_FALSE, PR_FALSE)) {
+ PR_FALSE, PR_FALSE, PR_FALSE)) {
return NULL;
}
symKey = PK11_PBEKeyGen(slot, prfAlgid, &utf8Pw, PR_FALSE, pwarg);

View File

@ -1,83 +0,0 @@
diff -up ./lib/pkcs12/p12plcy.c.no_p12_smime_policy ./lib/pkcs12/p12plcy.c
--- ./lib/pkcs12/p12plcy.c.no_p12_smime_policy 2024-06-07 09:26:03.000000000 -0700
+++ ./lib/pkcs12/p12plcy.c 2024-07-17 11:26:00.334836451 -0700
@@ -37,6 +37,7 @@ static pkcs12SuiteMap pkcs12SuiteMaps[]
static PRBool
sec_PKCS12Allowed(SECOidTag alg, PRUint32 needed)
{
+#ifdef notdef
PRUint32 policy;
SECStatus rv;
@@ -48,6 +49,9 @@ sec_PKCS12Allowed(SECOidTag alg, PRUint3
return PR_TRUE;
}
return PR_FALSE;
+#else
+ return PR_TRUE;
+#endif
}
PRBool
diff -up ./lib/smime/smimeutil.c.no_p12_smime_policy ./lib/smime/smimeutil.c
--- ./lib/smime/smimeutil.c.no_p12_smime_policy 2024-06-07 09:26:03.000000000 -0700
+++ ./lib/smime/smimeutil.c 2024-07-17 11:27:04.716617111 -0700
@@ -202,6 +202,7 @@ smime_get_policy_tag_from_key_length(SEC
PRBool
smime_allowed_by_policy(SECOidTag algtag, PRUint32 neededPolicy)
{
+#ifdef notdef
PRUint32 policyFlags;
/* some S/MIME algs map to the same underlying KEA mechanism,
@@ -221,6 +222,7 @@ smime_allowed_by_policy(SECOidTag algtag
PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
return PR_FALSE;
}
+#endif
return PR_TRUE;
}
@@ -485,6 +487,7 @@ smime_init_once(void *arg)
return PR_FAILURE;
}
+#ifdef notdef
/* At initialization time, we need to set up the defaults. We first
* look to see if the system or application has set up certain algorithms
* by policy. If they have set up values by policy we'll only allow those
@@ -497,6 +500,11 @@ smime_init_once(void *arg)
PORT_Free(tags);
tags = NULL;
}
+#else
+ /* just initialize the old maps */
+ rv = SECSuccess;
+ tagCount = 0;
+#endif
if ((rv != SECSuccess) || (tagCount == 0)) {
/* No algorithms have been enabled by policy (either by the system
* or by the application, we then will use the traditional default
diff -up ./tests/smime/smime.sh.no_p12_smime_policy ./tests/smime/smime.sh
--- ./tests/smime/smime.sh.no_p12_smime_policy 2024-07-17 11:26:00.303836075 -0700
+++ ./tests/smime/smime.sh 2024-07-17 11:26:00.334836451 -0700
@@ -872,6 +872,6 @@ smime_init
smime_main
smime_data_tb
smime_p7
-smime_policy
+#smime_policy
smime_cleanup
diff -up ./tests/tools/tools.sh.no_p12_smime_policy ./tests/tools/tools.sh
--- ./tests/tools/tools.sh.no_p12_smime_policy 2024-07-17 11:26:00.304836087 -0700
+++ ./tests/tools/tools.sh 2024-07-17 11:26:00.334836451 -0700
@@ -585,7 +585,7 @@ tools_p12()
tools_p12_import_old_files
tools_p12_import_pbmac1_samples
tools_p12_import_rsa_pss_private_key
- tools_p12_policy
+ #tools_p12_policy
}
############################## tools_sign ##############################

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,24 @@
diff -up ./gtests/ssl_gtest/manifest.mn.disable_ech ./gtests/ssl_gtest/manifest.mn
--- ./gtests/ssl_gtest/manifest.mn.disable_ech 2024-06-12 13:29:17.162207862 -0700
+++ ./gtests/ssl_gtest/manifest.mn 2024-06-12 13:30:25.699047788 -0700
@@ -59,7 +59,6 @@ CPPSRCS = \
diff --git a/gtests/ssl_gtest/manifest.mn b/gtests/ssl_gtest/manifest.mn
--- a/gtests/ssl_gtest/manifest.mn
+++ b/gtests/ssl_gtest/manifest.mn
@@ -50,17 +50,16 @@ CPPSRCS = \
ssl_staticrsa_unittest.cc \
ssl_tls13compat_unittest.cc \
ssl_v2_client_hello_unittest.cc \
ssl_version_unittest.cc \
ssl_versionpolicy_unittest.cc \
test_io.cc \
tls_agent.cc \
tls_connect.cc \
- tls_ech_unittest.cc \
tls_filter.cc \
tls_hkdf_unittest.cc \
tls_mlkem_unittest.cc \
tls_protect.cc \
tls_psk_unittest.cc \
tls_subcerts_unittest.cc \
- tls_ech_unittest.cc \
tls_xyber_unittest.cc \
$(SSLKEYLOGFILE_FILES) \
$(NULL)
diff -up ./lib/ssl/sslsock.c.disable_ech ./lib/ssl/sslsock.c
--- ./lib/ssl/sslsock.c.disable_ech 2024-06-07 09:26:03.000000000 -0700
+++ ./lib/ssl/sslsock.c 2024-06-12 13:29:17.162207862 -0700

View File

@ -43,11 +43,11 @@ diff -r 699541a7793b lib/util/secoid.c
if (oids[i].desc && strstr(arg, oids[i].desc)) {
xOids[i].notPolicyFlags = notEnable |
(xOids[i].notPolicyFlags & ~(DEF_FLAGS));
diff -up ./tests/tools/pkcs12policy.txt.disable_md5_test ./tests/tools/pkcs12policy.txt
--- ./tests/tools/pkcs12policy.txt.disable_md5_test 2024-06-07 09:26:03.000000000 -0700
+++ ./tests/tools/pkcs12policy.txt 2024-06-19 11:15:46.666728170 -0700
@@ -91,21 +91,21 @@
0 18 allow_all disallow=rc2 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC4 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC SHA-1 disallow rc2 (read), RC4 and RC2
diff -up ./tests/tools/pkcs12policy.txt.disable_md5 ./tests/tools/pkcs12policy.txt
--- ./tests/tools/pkcs12policy.txt.disable_md5 2025-05-23 06:07:49.000000000 -0700
+++ ./tests/tools/pkcs12policy.txt 2025-06-21 13:46:53.055812187 -0700
@@ -95,21 +95,12 @@
0 17 allow_all disallow=rc2 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC4 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC SHA-1 disallow rc2 (read), RC4 and RC2
# integrity policy check the various has based controls.
# NOTE: md4, md2, and md5 are turned off by policy by default for encrypting
-# (decrypting is fine). To be enabled, you must allow=all or allow=mdX on the
@ -58,24 +58,15 @@ diff -up ./tests/tools/pkcs12policy.txt.disable_md5_test ./tests/tools/pkcs12pol
- 0 0 allow=all allow=tls PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Allow all encrypt, use default decrypt with multiple hashes
- 0 0 allow=all allow=all PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Allow all with multiple hashes
- 28 x disallow=sha1_allow=md2 allow=all PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha1 on write
+ 0 0 allow=md2/pkcs12 allow=tls PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Allow all encrypt, use default decrypt with multiple hashes
+ 0 0 allow=md2/pkcs12 allow=all PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Allow all with multiple hashes
+ 28 x disallow=sha1_allow=md2/pkcs12 allow=all PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha1 on write
27 x disallow=md2 allow=all PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow md2 on write
- 29 x disallow=sha256_allow=md2 allow=all PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha256 on write
- 0 19 allow=all disallow=sha1 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha1 on read
- 0 18 allow=all disallow=md2 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow md2 on read
- 0 17 allow=all disallow=md2 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow md2 on read
- 0 17 allow=all disallow=sha256 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha256 on read
- 0 0 allow=all disallow=md2/pkcs12-encrypt PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow md2 on read
- 0 0 allow=all disallow=sha1/pkcs12-encrypt PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha1 on read
- 0 0 allow=all disallow=sha256/pkcs12-encrypt PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha256 on read
+ 29 x disallow=sha256_allow=md2/pkcs12 allow=all PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha256 on write
+ 0 19 allow=all:md2/pkcs12 disallow=sha1 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha1 on read
+ 0 18 allow=md2/pkcs12 disallow=md2 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow md2 on read
+ 0 17 allow=md2/pkcs12 disallow=sha256 PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha256 on read
+ 0 0 allow=md2/pkcs12 disallow=md2/pkcs12-encrypt PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow md2 on read
+ 0 0 allow=md2/pkcs12 disallow=sha1/pkcs12-encrypt PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha1 on read
+ 0 0 allow=md2/pkcs12 disallow=sha256/pkcs12-encrypt PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha256 on read
0 0 allow=all allow=all AES-128-CBC AES-128-CBC HMAC_SHA-256
29 x disallow=hmac-sha256 allow=all AES-128-CBC AES-128-CBC HMAC_SHA-256
0 18 allow=all disallow=hmac-sha256 AES-128-CBC AES-128-CBC HMAC_SHA-256
+ 27 x disallow=sha256_allow=md2 allow=all PKCS_#12_V2_PBE_With_SHA-1_And_128_Bit_RC2_CBC PKCS_#5_Password_Based_Encryption_with_MD2_and_DES-CBC SHA-256 Disallow sha256 on write
0 0 allow=all allow=all AES-128-CBC AES-128-CBC HMAC_SHA-256 Allow all with hmac
29 x disallow=hmac-sha256 allow=all AES-128-CBC AES-128-CBC HMAC_SHA-256 Disallow hmac on write
0 17 allow=all disallow=hmac-sha256 AES-128-CBC AES-128-CBC HMAC_SHA-256 Disallow hmac on read

888
nss-3.112-fips.patch Normal file
View File

@ -0,0 +1,888 @@
diff --git a/lib/freebl/stubs.c b/lib/freebl/stubs.c
--- a/lib/freebl/stubs.c
+++ b/lib/freebl/stubs.c
@@ -485,17 +485,17 @@ PR_GetLibraryFilePathname_stub(const cha
extern int
PORT_GetError_stub(void)
{
STUB_SAFE_CALL0(PORT_GetError_Util);
return errno;
}
extern void
-PORT_SafeZero(void *p, size_t n)
+PORT_SafeZero_stub(void *p, size_t n)
{
STUB_SAFE_CALL2(PORT_SafeZero, p, n);
/* just use a generic call in the case where we are running
* standalone freebl */
if (p != NULL) {
volatile unsigned char *__vl = (unsigned char *)p;
size_t __nl = n;
while (__nl--)
diff --git a/lib/freebl/stubs.h b/lib/freebl/stubs.h
--- a/lib/freebl/stubs.h
+++ b/lib/freebl/stubs.h
@@ -22,17 +22,17 @@
#define PORT_Alloc PORT_Alloc_stub
#define PORT_ArenaAlloc PORT_ArenaAlloc_stub
#define PORT_ArenaZAlloc PORT_ArenaZAlloc_stub
#define PORT_Free PORT_Free_stub
#define PORT_FreeArena PORT_FreeArena_stub
#define PORT_GetError PORT_GetError_stub
#define PORT_NewArena PORT_NewArena_stub
-#define PORT_SaveZero PORT_SaveZero_stub
+#define PORT_SafeZero PORT_SafeZero_stub
#define PORT_SetError PORT_SetError_stub
#define PORT_ZAlloc PORT_ZAlloc_stub
#define PORT_ZFree PORT_ZFree_stub
#define PORT_ZAllocAligned PORT_ZAllocAligned_stub
#define PORT_ZAllocAlignedOffset PORT_ZAllocAlignedOffset_stub
#define SECITEM_AllocItem SECITEM_AllocItem_stub
#define SECITEM_CompareItem SECITEM_CompareItem_stub
diff --git a/lib/freebl/unix_fips140_3.c b/lib/freebl/unix_fips140_3.c
--- a/lib/freebl/unix_fips140_3.c
+++ b/lib/freebl/unix_fips140_3.c
@@ -25,17 +25,17 @@ RNG_SystemInfoForRNG(void)
{
PRUint8 bytes[SYSTEM_RNG_SEED_COUNT];
size_t numBytes = RNG_SystemRNG(bytes, SYSTEM_RNG_SEED_COUNT);
if (!numBytes) {
/* error is set */
return;
}
RNG_RandomUpdate(bytes, numBytes);
- PORT_SaveZero(bytes, sizeof(bytes));
+ PORT_SafeZero(bytes, sizeof(bytes));
}
static unsigned int rng_grndFlags = 0;
static PRCallOnceType rng_KernelFips;
static PRStatus
rng_getKernelFips()
{
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
--- a/lib/softoken/pkcs11c.c
+++ b/lib/softoken/pkcs11c.c
@@ -535,17 +535,17 @@ sftk_InitGeneric(SFTKSession *session, C
context->cipherInfo = NULL;
context->hashInfo = NULL;
context->doPad = PR_FALSE;
context->padDataLength = 0;
context->key = key;
context->blockSize = 0;
context->maxLen = 0;
context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism,
- operation, key);
+ operation, key, 0);
*contextPtr = context;
return CKR_OK;
}
static int
sftk_aes_mode(CK_MECHANISM_TYPE mechanism)
{
switch (mechanism) {
@@ -4794,16 +4794,17 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi
goto loser;
}
/* make sure we don't have any class, key_type, or value fields */
sftk_DeleteAttributeType(key, CKA_CLASS);
sftk_DeleteAttributeType(key, CKA_KEY_TYPE);
sftk_DeleteAttributeType(key, CKA_VALUE);
+
/* Now Set up the parameters to generate the key (based on mechanism) */
key_gen_type = nsc_bulk; /* bulk key by default */
switch (pMechanism->mechanism) {
case CKM_CDMF_KEY_GEN:
case CKM_DES_KEY_GEN:
case CKM_DES2_KEY_GEN:
case CKM_DES3_KEY_GEN:
checkWeak = PR_TRUE;
@@ -4990,16 +4991,20 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi
crv = CKR_SESSION_HANDLE_INVALID;
goto loser;
}
/*
* handle the base object stuff
*/
crv = sftk_handleObject(key, session);
+ /* we need to do this check at the end, so we can check the generated key length against
+ * fips requirements */
+ key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE, key, 0);
+ session->lastOpWasFIPS = key->isFIPS;
sftk_FreeSession(session);
if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) {
crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL));
}
if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) {
crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL));
}
if (crv == CKR_OK) {
@@ -6077,18 +6082,18 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
}
/*
* handle the base object cleanup for the private Key
* If we have any problems, we destroy the public Key we've
* created and linked.
*/
crv = sftk_handleObject(publicKey, session);
- sftk_FreeSession(session);
if (crv != CKR_OK) {
+ sftk_FreeSession(session);
sftk_FreeObject(publicKey);
NSC_DestroyObject(hSession, privateKey->handle);
sftk_FreeObject(privateKey);
return crv;
}
if (sftk_isTrue(privateKey, CKA_SENSITIVE)) {
crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE,
&cktrue, sizeof(CK_BBOOL));
@@ -6120,22 +6125,29 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
(PRUint32)hSession, (PRUint32)pMechanism->mechanism,
(PRUint32)crv);
sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg);
}
}
}
if (crv != CKR_OK) {
+ sftk_FreeSession(session);
NSC_DestroyObject(hSession, publicKey->handle);
sftk_FreeObject(publicKey);
NSC_DestroyObject(hSession, privateKey->handle);
sftk_FreeObject(privateKey);
return crv;
}
+ /* we need to do this check at the end to make sure the generated key meets the key length requirements */
+ privateKey->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE_KEY_PAIR, privateKey, 0);
+ publicKey->isFIPS = privateKey->isFIPS;
+ session->lastOpWasFIPS = privateKey->isFIPS;
+
+ sftk_FreeSession(session);
*phPrivateKey = privateKey->handle;
*phPublicKey = publicKey->handle;
sftk_FreeObject(publicKey);
sftk_FreeObject(privateKey);
return CKR_OK;
}
@@ -7321,30 +7333,35 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
return CKR_MECHANISM_PARAM_INVALID;
}
if ((params->bExpand && keySize == 0) ||
(!params->bExpand && keySize > hashLen) ||
(params->bExpand && keySize > 255 * hashLen)) {
return CKR_TEMPLATE_INCONSISTENT;
}
+ if (!params->bExpand) {
+ keySize = hashLen;
+ }
+
/* sourceKey is NULL if we are called from the POST, skip the
* sensitiveCheck */
if (sourceKey != NULL) {
crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData);
if (crv != CKR_OK)
return crv;
}
/* HKDF-Extract(salt, base key value) */
if (params->bExtract) {
CK_BYTE *salt;
CK_ULONG saltLen;
HMACContext *hmac;
unsigned int bufLen;
+ SFTKSource saltKeySource = SFTK_SOURCE_DEFAULT;
switch (params->ulSaltType) {
case CKF_HKDF_SALT_NULL:
saltLen = hashLen;
salt = hashbuf;
memset(salt, 0, saltLen);
break;
case CKF_HKDF_SALT_DATA:
@@ -7369,31 +7386,57 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
/* if the base key is not fips, but the salt key is, the
* resulting key can be fips */
if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) {
CK_MECHANISM mech;
mech.mechanism = CKM_HKDF_DERIVE;
mech.pParameter = params;
mech.ulParameterLen = sizeof(*params);
key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech,
- CKA_DERIVE, saltKey);
+ CKA_DERIVE, saltKey,
+ keySize*PR_BITS_PER_BYTE);
}
+ saltKeySource = saltKey->source;
saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
if (saltKey_att == NULL) {
sftk_FreeObject(saltKey);
return CKR_KEY_HANDLE_INVALID;
}
/* save the resulting salt */
salt = saltKey_att->attrib.pValue;
saltLen = saltKey_att->attrib.ulValueLen;
break;
default:
return CKR_MECHANISM_PARAM_INVALID;
break;
}
+ /* only TLS style usage is FIPS approved,
+ * turn off the FIPS indicator for other usages */
+ if (isFIPS && key && sourceKey) {
+ PRBool fipsOK = PR_FALSE;
+ /* case one: mix the kea with a previous or default
+ * salt */
+ if ((sourceKey->source == SFTK_SOURCE_KEA) &&
+ (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) &&
+ (saltLen == rawHash->length)) {
+ fipsOK = PR_TRUE;
+ }
+ /* case two: restart, remix the previous secret as a salt */
+ if ((sourceKey->objclass == CKO_DATA) &&
+ (NSS_SecureMemcmpZero(sourceKeyBytes, sourceKeyLen) == 0) &&
+ (sourceKeyLen == rawHash->length) &&
+ (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) &&
+ (saltLen == rawHash->length)) {
+ fipsOK = PR_TRUE;
+ }
+ if (!fipsOK) {
+ key->isFIPS = PR_FALSE;
+ }
+ }
+ if (key) key->source = SFTK_SOURCE_HKDF_EXTRACT;
hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
if (saltKey_att) {
sftk_FreeAttribute(saltKey_att);
}
if (saltKey) {
sftk_FreeObject(saltKey);
}
@@ -7411,26 +7454,50 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
/* PRK = base key value */
prk = sourceKeyBytes;
prkLen = sourceKeyLen;
}
/* HKDF-Expand */
if (!params->bExpand) {
okm = prk;
- keySize = genLen = hashLen;
+ genLen = hashLen;
} else {
/* T(1) = HMAC-Hash(prk, "" | info | 0x01)
* T(n) = HMAC-Hash(prk, T(n-1) | info | n
* key material = T(1) | ... | T(n)
*/
HMACContext *hmac;
CK_BYTE bi;
unsigned iterations;
+ /* only TLS style usage is FIPS approved,
+ * turn off the FIPS indicator for other usages */
+ if (isFIPS && key && key->isFIPS && sourceKey) {
+ unsigned char *info=&params->pInfo[3];
+ /* only one case,
+ * 1) Expand only
+ * 2) with a key whose source was
+ * SFTK_SOURCE_HKDF_EXPAND or SFTK_SOURCE_HKDF_EXTRACT
+ * 3) source key length == rawHash->length
+ * 4) Info has tls or dtls
+ * If any of those conditions aren't met, then we turn
+ * off the fips indicator */
+ if (params->bExtract ||
+ ((sourceKey->source != SFTK_SOURCE_HKDF_EXTRACT) &&
+ (sourceKey->source != SFTK_SOURCE_HKDF_EXPAND)) ||
+ (sourceKeyLen != rawHash->length) ||
+ (params->ulInfoLen < 7) ||
+ ((PORT_Memcmp(info,"tls",3) != 0) &&
+ (PORT_Memcmp(info,"dtls",4) != 0))) {
+ key->isFIPS = PR_FALSE;
+ }
+ }
+ if (key) key->source = SFTK_SOURCE_HKDF_EXPAND;
+
genLen = PR_ROUNDUP(keySize, hashLen);
iterations = genLen / hashLen;
if (genLen > sizeof(keyBlock)) {
keyBlockAlloc = PORT_Alloc(genLen);
if (keyBlockAlloc == NULL) {
return CKR_HOST_MEMORY;
}
@@ -7635,17 +7702,18 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
/* get the value of the base key */
att = sftk_FindAttribute(sourceKey, CKA_VALUE);
if (att == NULL) {
sftk_FreeObject(key);
sftk_FreeObject(sourceKey);
return CKR_KEY_HANDLE_INVALID;
}
}
- key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey);
+ key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey,
+ keySize*PR_BITS_PER_BYTE);
switch (mechanism) {
/* get a public key from a private key. nsslowkey_ConvertToPublickey()
* will generate the public portion if it doesn't already exist. */
case CKM_NSS_PUB_FROM_PRIV: {
NSSLOWKEYPrivateKey *privKey;
NSSLOWKEYPublicKey *pubKey;
int error;
@@ -8797,16 +8865,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
/* calculate private value - oct */
rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
SECITEM_ZfreeItem(&dhValue, PR_FALSE);
if (rv == SECSuccess) {
+ key->source = SFTK_SOURCE_KEA;
sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
SECITEM_ZfreeItem(&derived, PR_FALSE);
crv = CKR_OK;
} else
crv = CKR_HOST_MEMORY;
break;
}
@@ -8894,16 +8963,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
* tmp is the raw data created by ECDH_Derive,
* secret and secretlen are the values we will
* eventually pass as our generated key.
*/
secret = tmp.data;
secretlen = tmp.len;
} else {
secretlen = keySize;
+ key->isFIPS = PR_FALSE;
crv = sftk_ANSI_X9_63_kdf(&secret, keySize,
&tmp, mechParams->pSharedData,
mechParams->ulSharedDataLen, mechParams->kdf);
PORT_ZFree(tmp.data, tmp.len);
if (crv != CKR_OK) {
break;
}
tmp.data = secret;
@@ -8927,16 +8997,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
}
PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen);
secret = keyData;
} else {
secret += (secretlen - keySize);
}
secretlen = keySize;
}
+ key->source = SFTK_SOURCE_KEA;
sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
PORT_ZFree(tmp.data, tmp.len);
if (keyData) {
PORT_ZFree(keyData, keySize);
}
break;
diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h
--- a/lib/softoken/pkcs11i.h
+++ b/lib/softoken/pkcs11i.h
@@ -147,16 +147,26 @@ typedef enum {
*/
typedef enum {
SFTK_DestroyFailure,
SFTK_Destroyed,
SFTK_Busy
} SFTKFreeStatus;
/*
+ * Source of various objects
+ */
+typedef enum {
+ SFTK_SOURCE_DEFAULT=0,
+ SFTK_SOURCE_KEA,
+ SFTK_SOURCE_HKDF_EXPAND,
+ SFTK_SOURCE_HKDF_EXTRACT
+} SFTKSource;
+
+/*
* attribute values of an object.
*/
struct SFTKAttributeStr {
SFTKAttribute *next;
SFTKAttribute *prev;
PRBool freeAttr;
PRBool freeData;
/*must be called handle to make sftkqueue_find work */
@@ -189,16 +199,17 @@ struct SFTKObjectStr {
CK_OBJECT_CLASS objclass;
CK_OBJECT_HANDLE handle;
int refCount;
PZLock *refLock;
SFTKSlot *slot;
void *objectInfo;
SFTKFree infoFree;
PRBool isFIPS;
+ SFTKSource source;
};
struct SFTKTokenObjectStr {
SFTKObject obj;
SECItem dbKey;
};
struct SFTKSessionObjectStr {
@@ -963,15 +974,16 @@ char **NSC_ModuleDBFunc(unsigned long fu
const SECItem *sftk_VerifyDH_Prime(SECItem *dhPrime, SECItem *generator, PRBool isFIPS);
/* check if dhSubPrime claims dhPrime is a safe prime. */
SECStatus sftk_IsSafePrime(SECItem *dhPrime, SECItem *dhSubPrime, PRBool *isSafe);
/* map an operation Attribute to a Mechanism flag */
CK_FLAGS sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE op);
/* check the FIPS table to determine if this current operation is allowed by
* FIPS security policy */
PRBool sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech,
- CK_ATTRIBUTE_TYPE op, SFTKObject *source);
+ CK_ATTRIBUTE_TYPE op, SFTKObject *source,
+ CK_ULONG targetKeySize);
/* add validation objects to the slot */
CK_RV sftk_CreateValidationObjects(SFTKSlot *slot);
SEC_END_PROTOS
#endif /* _PKCS11I_H_ */
diff --git a/lib/softoken/pkcs11u.c b/lib/softoken/pkcs11u.c
--- a/lib/softoken/pkcs11u.c
+++ b/lib/softoken/pkcs11u.c
@@ -1098,16 +1098,17 @@ sftk_NewObject(SFTKSlot *slot)
sessObject->attrList[i].freeData = PR_FALSE;
}
sessObject->optimizeSpace = slot->optimizeSpace;
object->handle = 0;
object->next = object->prev = NULL;
object->slot = slot;
object->isFIPS = sftk_isFIPS(slot->slotID);
+ object->source = SFTK_SOURCE_DEFAULT;
object->refCount = 1;
sessObject->sessionList.next = NULL;
sessObject->sessionList.prev = NULL;
sessObject->sessionList.parent = object;
sessObject->session = NULL;
sessObject->wasDerived = PR_FALSE;
if (!hasLocks)
@@ -1683,16 +1684,17 @@ fail:
CK_RV
sftk_CopyObject(SFTKObject *destObject, SFTKObject *srcObject)
{
SFTKAttribute *attribute;
SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject);
unsigned int i;
destObject->isFIPS = srcObject->isFIPS;
+ destObject->source = srcObject->source;
if (src_so == NULL) {
return sftk_CopyTokenObject(destObject, srcObject);
}
PZ_Lock(src_so->attributeLock);
for (i = 0; i < src_so->hashSize; i++) {
attribute = src_so->head[i];
do {
@@ -2068,16 +2070,17 @@ sftk_NewTokenObject(SFTKSlot *slot, SECI
/* every object must have a class, if we can't get it, the object
* doesn't exist */
crv = handleToClass(slot, handle, &object->objclass);
if (crv != CKR_OK) {
goto loser;
}
object->slot = slot;
object->isFIPS = sftk_isFIPS(slot->slotID);
+ object->source = SFTK_SOURCE_DEFAULT;
object->objectInfo = NULL;
object->infoFree = NULL;
if (!hasLocks) {
object->refLock = PZ_NewLock(nssILockRefLock);
}
if (object->refLock == NULL) {
goto loser;
}
@@ -2234,16 +2237,25 @@ sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE
break;
case CKA_DERIVE:
flags = CKF_DERIVE;
break;
/* fake attribute to select digesting */
case CKA_DIGEST:
flags = CKF_DIGEST;
break;
+ /* fake attribute to select key gen */
+ case CKA_NSS_GENERATE:
+ flags = CKF_GENERATE;
+ break;
+ /* fake attribute to select key pair gen */
+ case CKA_NSS_GENERATE_KEY_PAIR:
+ flags = CKF_GENERATE_KEY_PAIR;
+ break;
+ /* fake attributes to to handle MESSAGE* flags */
case CKA_NSS_MESSAGE | CKA_ENCRYPT:
flags = CKF_MESSAGE_ENCRYPT;
break;
case CKA_NSS_MESSAGE | CKA_DECRYPT:
flags = CKF_MESSAGE_DECRYPT;
break;
case CKA_NSS_MESSAGE | CKA_SIGN:
flags = CKF_MESSAGE_SIGN;
@@ -2319,20 +2331,20 @@ sftk_quickGetECCCurveOid(SFTKObject *sou
}
/* This function currently only returns valid lengths for
* FIPS approved ECC curves. If we want to make this generic
* in the future, that Curve determination can be done in
* the sftk_handleSpecial. Since it's currently only used
* in FIPS indicators, it's currently only compiled with
* the FIPS indicator code */
-static int
+static CK_ULONG
sftk_getKeyLength(SFTKObject *source)
{
- CK_KEY_TYPE keyType = CK_INVALID_HANDLE;
+ CK_KEY_TYPE keyType = CKK_INVALID_KEY_TYPE;
CK_ATTRIBUTE_TYPE keyAttribute;
CK_ULONG keyLength = 0;
SFTKAttribute *attribute;
CK_RV crv;
/* If we don't have a key, then it doesn't have a length.
* this may be OK (say we are hashing). The mech info will
* sort this out because algorithms which expect no keys
@@ -2342,17 +2354,17 @@ sftk_getKeyLength(SFTKObject *source)
}
crv = sftk_GetULongAttribute(source, CKA_KEY_TYPE, &keyType);
if (crv != CKR_OK) {
/* sometimes we're passed a data object, in that case the
* key length is CKA_VALUE, which is the default */
keyType = CKK_INVALID_KEY_TYPE;
}
- if (keyType == CKK_EC) {
+ if (keyType == CKK_EC || keyType == CKK_EC_EDWARDS || keyType == CKK_EC_MONTGOMERY) {
SECOidTag curve = sftk_quickGetECCCurveOid(source);
switch (curve) {
case SEC_OID_CURVE25519:
/* change when we start algorithm testing on curve25519 */
return 0;
case SEC_OID_SECG_EC_SECP256R1:
return 256;
case SEC_OID_SECG_EC_SECP384R1:
@@ -2384,24 +2396,65 @@ sftk_getKeyLength(SFTKObject *source)
attribute = sftk_FindAttribute(source, keyAttribute);
if (attribute) {
keyLength = attribute->attrib.ulValueLen * 8;
sftk_FreeAttribute(attribute);
}
return keyLength;
}
+PRBool
+sftk_checkFIPSHash(CK_MECHANISM_TYPE hash, PRBool allowSmall, PRBool allowCMAC)
+{
+ switch (hash) {
+ case CKM_AES_CMAC:
+ return allowCMAC;
+ case CKM_SHA_1:
+ case CKM_SHA_1_HMAC:
+ case CKM_SHA224:
+ case CKM_SHA224_HMAC:
+ return allowSmall;
+ case CKM_SHA256:
+ case CKM_SHA256_HMAC:
+ case CKM_SHA384:
+ case CKM_SHA384_HMAC:
+ case CKM_SHA512:
+ case CKM_SHA512_HMAC:
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+PRBool
+sftk_checkKeyLength(CK_ULONG keyLength, CK_ULONG min,
+ CK_ULONG max, CK_ULONG step)
+{
+ if (keyLength > max) {
+ return PR_FALSE;
+ }
+ if (keyLength < min ) {
+ return PR_FALSE;
+ }
+ if (((keyLength - min) % step) != 0) {
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
/*
* handle specialized FIPS semantics that are too complicated to
* handle with just a table. NOTE: this means any additional semantics
* would have to be coded here before they can be added to the table */
static PRBool
sftk_handleSpecial(SFTKSlot *slot, CK_MECHANISM *mech,
- SFTKFIPSAlgorithmList *mechInfo, SFTKObject *source)
+ SFTKFIPSAlgorithmList *mechInfo, SFTKObject *source,
+ CK_ULONG keyLength, CK_ULONG targetKeyLength)
{
+ PRBool allowSmall = PR_FALSE;
+ PRBool allowCMAC = PR_FALSE;
switch (mechInfo->special) {
case SFTKFIPSDH: {
SECItem dhPrime;
SECItem dhBase;
SECItem dhGenerator;
PRBool fipsOk = PR_FALSE;
const SECItem *dhSubPrime;
CK_RV crv = sftk_Attribute2SecItem(NULL, &dhPrime,
@@ -2451,32 +2504,97 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
}
/* we use the existing hash utilities to find the length of
* the hash */
hashObj = HASH_GetRawHashObject(sftk_GetHashTypeFromMechanism(
pss->hashAlg));
if (hashObj == NULL) {
return PR_FALSE;
}
+ /* cap the salt for legacy keys */
+ if ((keyLength <= 1024) && (pss->sLen > 63)) {
+ return PR_FALSE;
+ }
+ /* cap the salt for based on the hash */
if (pss->sLen > hashObj->length) {
return PR_FALSE;
}
+ /* Our code makes sure pss->hashAlg matches the explicit
+ * hash in the mechanism, and only mechanisms with approved
+ * hashes are included, so no need to check pss->hashAlg
+ * here */
+ return PR_TRUE;
+ }
+ case SFTKFIPSPBKDF2: {
+ /* PBKDF2 must have the following addition restrictions
+ * (independent of keysize).
+ * 1. iteration count must be at least 1000.
+ * 2. salt must be at least 128 bits (16 bytes).
+ * 3. password must match the length specified in the SP
+ */
+ CK_PKCS5_PBKD2_PARAMS *pbkdf2 = (CK_PKCS5_PBKD2_PARAMS *)
+ mech->pParameter;
+ if (mech->ulParameterLen != sizeof(*pbkdf2)) {
+ return PR_FALSE;
+ }
+ if (pbkdf2->iterations < 1000) {
+ return PR_FALSE;
+ }
+ if (pbkdf2->ulSaltSourceDataLen < 16) {
+ return PR_FALSE;
+ }
+ if (*(pbkdf2->ulPasswordLen) < SFTKFIPS_PBKDF2_MIN_PW_LEN) {
+ return PR_FALSE;
+ }
return PR_TRUE;
}
+ /* check the hash mechanisms to make sure they themselves are FIPS */
+ case SFTKFIPSChkHashSp800:
+ allowCMAC = PR_TRUE;
+ case SFTKFIPSChkHash:
+ allowSmall = PR_TRUE;
+ case SFTKFIPSChkHashTls:
+ if (mech->ulParameterLen < mechInfo->offset +sizeof(CK_ULONG)) {
+ return PR_FALSE;
+ }
+ return sftk_checkFIPSHash(*(CK_ULONG *)(((char *)mech->pParameter)
+ + mechInfo->offset), allowSmall, allowCMAC);
+ case SFTKFIPSTlsKeyCheck:
+ if (mech->mechanism != CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) {
+ /* unless the mechnism has a built-in hash, check the hash */
+ if (mech->ulParameterLen < mechInfo->offset +sizeof(CK_ULONG)) {
+ return PR_FALSE;
+ }
+ if (!sftk_checkFIPSHash(*(CK_ULONG *)(((char *)mech->pParameter)
+ + mechInfo->offset), PR_FALSE, PR_FALSE)) {
+ return PR_FALSE;
+ }
+ }
+ return sftk_checkKeyLength(targetKeyLength, 112, 512, 1);
+ case SFTKFIPSRSAOAEP:;
+ CK_RSA_PKCS_OAEP_PARAMS *rsaoaep = (CK_RSA_PKCS_OAEP_PARAMS *)
+ mech->pParameter;
+
+ HASH_HashType hash_msg = sftk_GetHashTypeFromMechanism(rsaoaep->hashAlg);
+ HASH_HashType hash_pad = sftk_GetHashTypeFromMechanism(rsaoaep->mgf);
+ /* message hash and mask generation function must be the same */
+ if (hash_pad != hash_msg) return PR_FALSE;
+
+ return sftk_checkFIPSHash(rsaoaep->hashAlg, PR_FALSE, PR_FALSE);
default:
break;
}
/* if we didn't understand the special processing, mark it non-fips */
return PR_FALSE;
}
#endif
PRBool
sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech, CK_ATTRIBUTE_TYPE op,
- SFTKObject *source)
+ SFTKObject *source, CK_ULONG targetKeyLength)
{
#ifndef NSS_HAS_FIPS_INDICATORS
return PR_FALSE;
#else
int i;
CK_FLAGS opFlags;
CK_ULONG keyLength;
@@ -2498,23 +2616,25 @@ sftk_operationIsFIPS(SFTKSlot *slot, CK_
}
keyLength = sftk_getKeyLength(source);
/* check against our algorithm array */
for (i = 0; i < SFTK_NUMBER_FIPS_ALGORITHMS; i++) {
SFTKFIPSAlgorithmList *mechs = &sftk_fips_mechs[i];
/* if we match the number of records exactly, then we are an
* approved algorithm in the approved mode with an approved key */
- if (((mech->mechanism == mechs->type) &&
- (opFlags == (mechs->info.flags & opFlags)) &&
- (keyLength <= mechs->info.ulMaxKeySize) &&
- (keyLength >= mechs->info.ulMinKeySize) &&
- ((keyLength - mechs->info.ulMinKeySize) % mechs->step) == 0) &&
- ((mechs->special == SFTKFIPSNone) ||
- sftk_handleSpecial(slot, mech, mechs, source))) {
+ if ((mech->mechanism == mechs->type) &&
+ (opFlags == (mechs->info.flags & opFlags)) &&
+ sftk_checkKeyLength(keyLength, mechs->info.ulMinKeySize,
+ mechs->info.ulMaxKeySize, mechs->step) &&
+ ((targetKeyLength == 0) || (mechs->special == SFTKFIPSTlsKeyCheck)
+ || sftk_checkKeyLength(targetKeyLength, mechs->info.ulMinKeySize,
+ mechs->info.ulMaxKeySize, mechs->step)) &&
+ ((mechs->special == SFTKFIPSNone) ||
+ sftk_handleSpecial(slot, mech, mechs, source, keyLength, targetKeyLength))) {
return PR_TRUE;
}
}
return PR_FALSE;
#endif
}
/*
diff --git a/lib/softoken/sftkike.c b/lib/softoken/sftkike.c
--- a/lib/softoken/sftkike.c
+++ b/lib/softoken/sftkike.c
@@ -511,16 +511,22 @@ sftk_ike_prf(CK_SESSION_HANDLE hSession,
}
/* key as the data */
crv = prf_update(&context, inKey->attrib.pValue,
inKey->attrib.ulValueLen);
if (crv != CKR_OK) {
goto fail;
}
} else {
+ /* ikev1 isn't validated, if we use this function in ikev1 mode,
+ * mark the resulting key as not FIPS */
+ if (!params->bRekey) {
+ outKey->isFIPS = PR_FALSE;
+ }
+
crv = prf_init(&context, inKey->attrib.pValue,
inKey->attrib.ulValueLen);
if (crv != CKR_OK) {
goto fail;
}
if (newKeyValue) {
crv = prf_update(&context, newKeyValue->attrib.pValue,
newKeyValue->attrib.ulValueLen);
diff --git a/lib/softoken/sftkmessage.c b/lib/softoken/sftkmessage.c
--- a/lib/softoken/sftkmessage.c
+++ b/lib/softoken/sftkmessage.c
@@ -178,16 +178,48 @@ sftk_CryptMessage(CK_SESSION_HANDLE hSes
CHECK_FORK();
/* make sure we're legal */
crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
if (crv != CKR_OK)
return crv;
+ if (context->isFIPS && (contextType == SFTK_MESSAGE_ENCRYPT)) {
+ if ((pParameter == NULL) || (ulParameterLen != sizeof(CK_GCM_MESSAGE_PARAMS))) {
+ context->isFIPS = PR_FALSE;
+ } else {
+ CK_GCM_MESSAGE_PARAMS *p = (CK_GCM_MESSAGE_PARAMS *)pParameter;
+ switch (p->ivGenerator) {
+ default:
+ case CKG_NO_GENERATE:
+ context->isFIPS = PR_FALSE;
+ break;
+ case CKG_GENERATE_RANDOM:
+ if ((p->ulIvLen < 96/PR_BITS_PER_BYTE) ||
+ (p->ulIvFixedBits != 0)) {
+ context->isFIPS = PR_FALSE;
+ }
+ break;
+ case CKG_GENERATE_COUNTER_XOR:
+ if ((p->ulIvLen != 96/PR_BITS_PER_BYTE) ||
+ (p->ulIvFixedBits != 32)) {
+ context->isFIPS = PR_FALSE;
+ }
+ break;
+ case CKG_GENERATE_COUNTER:
+ if ((p->ulIvFixedBits < 32) ||
+ ((p->ulIvLen*PR_BITS_PER_BYTE - p->ulIvFixedBits) < 32)) {
+ context->isFIPS = PR_FALSE;
+ }
+ break;
+ }
+ }
+ }
+
if (!pOuttext) {
*pulOuttextLen = ulIntextLen;
return CKR_OK;
}
rv = (*context->aeadUpdate)(context->cipherInfo, pOuttext, &outlen,
maxout, pIntext, ulIntextLen,
pParameter, ulParameterLen,
pAssociatedData, ulAssociatedDataLen);
diff --git a/lib/util/pkcs11n.h b/lib/util/pkcs11n.h
--- a/lib/util/pkcs11n.h
+++ b/lib/util/pkcs11n.h
@@ -148,16 +148,18 @@
/*
* NSS-defined certificate types
*
*/
#define CKC_NSS (CKC_VENDOR_DEFINED | NSSCK_VENDOR_NSS)
/* FAKE PKCS #11 defines */
#define CKA_DIGEST 0x81000000L
+#define CKA_NSS_GENERATE 0x81000001L
+#define CKA_NSS_GENERATE_KEY_PAIR 0x81000002L
#define CKA_NSS_MESSAGE 0x82000000L
#define CKA_NSS_MESSAGE_MASK 0xff000000L
#define CKA_FLAGS_ONLY 0 /* CKA_CLASS */
/*
* NSS-defined object attributes
*
*/

View File

@ -0,0 +1,151 @@
diff --git a/lib/pkcs12/p12plcy.c b/lib/pkcs12/p12plcy.c
--- a/lib/pkcs12/p12plcy.c
+++ b/lib/pkcs12/p12plcy.c
@@ -32,27 +32,31 @@ static pkcs12SuiteMap pkcs12SuiteMaps[]
{ SEC_OID_UNKNOWN, 0, PKCS12_NULL, PR_FALSE, PR_FALSE },
{ SEC_OID_UNKNOWN, 0, 0L, PR_FALSE, PR_FALSE }
};
/* determine if algid is an algorithm which is allowed */
static PRBool
sec_PKCS12Allowed(SECOidTag alg, PRUint32 needed)
{
+#ifdef notdef
PRUint32 policy;
SECStatus rv;
rv = NSS_GetAlgorithmPolicy(alg, &policy);
if (rv != SECSuccess) {
return PR_FALSE;
}
if ((policy & needed) == needed) {
return PR_TRUE;
}
return PR_FALSE;
+#else
+ return PR_TRUE;
+#endif
}
PRBool
SEC_PKCS12CipherAllowed(SECOidTag pbeAlg, SECOidTag hmacAlg)
{
SECOidTag cipherAlg = SEC_PKCS5GetCryptoFromAlgTag(pbeAlg);
SECOidTag hashAlg = SEC_PKCS5GetHashFromAlgTag(pbeAlg);
if (cipherAlg == SEC_OID_UNKNOWN) {
diff --git a/lib/smime/smimeutil.c b/lib/smime/smimeutil.c
--- a/lib/smime/smimeutil.c
+++ b/lib/smime/smimeutil.c
@@ -197,16 +197,17 @@ smime_get_policy_tag_from_key_length(SEC
return SEC_OID_UNKNOWN;
}
return algtag;
}
PRBool
smime_allowed_by_policy(SECOidTag algtag, PRUint32 neededPolicy)
{
+#ifdef notdef
PRUint32 policyFlags;
/* some S/MIME algs map to the same underlying KEA mechanism,
* collaps them here */
if ((neededPolicy & (NSS_USE_ALG_IN_SMIME_KX | NSS_USE_ALG_IN_SMIME_KX_LEGACY)) != 0) {
CK_MECHANISM_TYPE mechType = PK11_AlgtagToMechanism(algtag);
switch (mechType) {
case CKM_ECDH1_DERIVE:
@@ -216,16 +217,17 @@ smime_allowed_by_policy(SECOidTag algtag
}
}
if ((NSS_GetAlgorithmPolicy(algtag, &policyFlags) == SECFailure) ||
((policyFlags & neededPolicy) != neededPolicy)) {
PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM);
return PR_FALSE;
}
+#endif
return PR_TRUE;
}
/*
* We'll need this for the fake policy oids for RC2, but the
* rest of these should be moved to pk11wrap for generic
* algtag to key size values. We already need this for
* sec_pkcs5v2_key_length_by oid.
@@ -480,28 +482,34 @@ smime_init_once(void *arg)
return PR_FAILURE;
}
algorithm_list_lock = PZ_NewLock(nssILockCache);
if (algorithm_list_lock == NULL) {
*error = PORT_GetError();
return PR_FAILURE;
}
+#ifdef notdef
/* At initialization time, we need to set up the defaults. We first
* look to see if the system or application has set up certain algorithms
* by policy. If they have set up values by policy we'll only allow those
* algorithms. We'll then look to see if any algorithms are enabled by
* the application. */
rv = NSS_GetAlgorithmPolicyAll(NSS_USE_ALG_IN_SMIME_LEGACY,
NSS_USE_ALG_IN_SMIME_LEGACY,
&tags, &tagCount);
if (tags) {
PORT_Free(tags);
tags = NULL;
}
+#else
+ /* just initialize the old maps */
+ rv = SECSuccess;
+ tagCount = 0;
+#endif
if ((rv != SECSuccess) || (tagCount == 0)) {
/* No algorithms have been enabled by policy (either by the system
* or by the application, we then will use the traditional default
* algorithms from the policy map */
for (i = smime_legacy_map_count - 1; i >= 0; i--) {
SECOidTag policytag = smime_legacy_map[i].policytag;
/* this enables the algorithm by policy. We need this or
* the policy code will reject attempts to use it */
diff --git a/tests/smime/smime.sh b/tests/smime/smime.sh
--- a/tests/smime/smime.sh
+++ b/tests/smime/smime.sh
@@ -867,13 +867,13 @@ smime_cleanup()
}
################## main #################################################
smime_init
smime_main
smime_data_tb
smime_p7
-if using_sql ; then
- smime_policy
-fi
+#if using_sql ; then
+# smime_policy
+#fi
smime_cleanup
diff --git a/tests/tools/tools.sh b/tests/tools/tools.sh
--- a/tests/tools/tools.sh
+++ b/tests/tools/tools.sh
@@ -590,17 +590,17 @@ tools_p12()
tools_p12_export_list_import_most_ciphers
fi
tools_p12_export_with_none_ciphers
tools_p12_export_with_invalid_ciphers
tools_p12_import_old_files
tools_p12_import_pbmac1_samples
if using_sql; then
tools_p12_import_rsa_pss_private_key
- tools_p12_policy
+# tools_p12_policy
fi
}
############################## tools_sign ##############################
# local shell function pk12util uses a hardcoded tmp file, if this exists
# and is owned by another user we don't get reasonable errormessages
########################################################################
check_tmpfile()

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +0,0 @@
diff -up ./doc/pk12util.xml.camellia ./doc/pk12util.xml
--- ./doc/pk12util.xml.camellia 2022-01-26 09:46:39.794919455 -0800
+++ ./doc/pk12util.xml 2022-01-26 09:54:58.277019760 -0800
@@ -317,7 +317,7 @@ Certificate Friendly Name: Thawte Fre
<refsection id="encryption">
<title>Password Encryption</title>
- <para>PKCS #12 provides for not only the protection of the private keys but also the certificate and meta-data associated with the keys. Password-based encryption is used to protect private keys on export to a PKCS #12 file and, optionally, the associated certificates. If no algorithm is specified, the tool defaults to using PKCS #12 SHA-1 and 3-key triple DES for private key encryption. When not in FIPS mode, PKCS #12 SHA-1 and 40-bit RC4 is used for certificate encryption. When in FIPS mode, there is no certificate encryption. If certificate encryption is not wanted, specify <userinput>"NONE"</userinput> as the argument of the <option>-C</option> option.</para>
+ <para>PKCS #12 provides for not only the protection of the private keys but also the certificate and meta-data associated with the keys. Password-based encryption is used to protect private keys on export to a PKCS #12 file and, optionally, the associated certificates. If no algorithm is specified, the tool defaults to using AES-256-CBC for private key encryption and AES-128-CBC for certificate encryption. If certificate encryption is not wanted, specify <userinput>"NONE"</userinput> as the argument of the <option>-C</option> option.</para>
<para>The private key is always protected with strong encryption by default.</para>
<para>Several types of ciphers are supported.</para>
<variablelist>
@@ -327,6 +327,7 @@ Certificate Friendly Name: Thawte Fre
<listitem>
<itemizedlist>
<listitem><para>PBES2 with AES-CBC-Pad as underlying encryption scheme (<userinput>"AES-128-CBC"</userinput>, <userinput>"AES-192-CBC"</userinput>, and <userinput>"AES-256-CBC"</userinput>)</para></listitem>
+ <listitem><para>PBES2 with CAMELLIA-CBC-Pad as underlying encryption scheme (<userinput>"CAMELLIA-128-CBC"</userinput>, <userinput>"CAMELLIA-192-CBC"</userinput>, and <userinput>"CAMELLIA-256-CBC"</userinput>)</para></listitem>
</itemizedlist>
</listitem>
</varlistentry>

View File

@ -1,578 +0,0 @@
diff --git a/lib/freebl/config.mk b/lib/freebl/config.mk
--- a/lib/freebl/config.mk
+++ b/lib/freebl/config.mk
@@ -85,9 +85,13 @@ EXTRA_SHARED_LIBS += \
$(NULL)
endif
endif
ifeq ($(OS_ARCH), Darwin)
EXTRA_SHARED_LIBS += -dylib_file @executable_path/libplc4.dylib:$(DIST)/lib/libplc4.dylib -dylib_file @executable_path/libplds4.dylib:$(DIST)/lib/libplds4.dylib
endif
+ifdef NSS_FIPS_140_3
+DEFINES += -DNSS_FIPS_140_3
endif
+
+endif
diff --git a/lib/freebl/unix_urandom.c b/lib/freebl/unix_urandom.c
--- a/lib/freebl/unix_urandom.c
+++ b/lib/freebl/unix_urandom.c
@@ -20,53 +20,110 @@ RNG_SystemInfoForRNG(void)
if (!numBytes) {
/* error is set */
return;
}
RNG_RandomUpdate(bytes, numBytes);
PORT_Memset(bytes, 0, sizeof bytes);
}
+#ifdef NSS_FIPS_140_3
+#include <sys/random.h>
+#include "prinit.h"
+
+static int rng_grndFlags= 0;
+static PRCallOnceType rng_KernelFips;
+
+static PRStatus
+rng_getKernelFips()
+{
+#ifdef LINUX
+ FILE *f;
+ char d;
+ size_t size;
+
+ f = fopen("/proc/sys/crypto/fips_enabled", "r");
+ if (!f)
+ return PR_FAILURE;
+
+ size = fread(&d, 1, 1, f);
+ fclose(f);
+ if (size != 1)
+ return PR_SUCCESS;
+ if (d != '1')
+ return PR_SUCCESS;
+ /* if the kernel is in FIPS mode, set the GRND_RANDOM flag */
+ rng_grndFlags = GRND_RANDOM;
+#endif /* LINUX */
+ return PR_SUCCESS;
+}
+#endif
+
size_t
RNG_SystemRNG(void *dest, size_t maxLen)
{
+ size_t fileBytes = 0;
+ unsigned char *buffer = dest;
+#ifndef NSS_FIPS_140_3
int fd;
int bytes;
- size_t fileBytes = 0;
- unsigned char *buffer = dest;
+#else
+ PR_CallOnce(&rng_KernelFips, rng_getKernelFips);
+#endif
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))))
int result;
-
while (fileBytes < maxLen) {
size_t getBytes = maxLen - fileBytes;
if (getBytes > GETENTROPY_MAX_BYTES) {
getBytes = GETENTROPY_MAX_BYTES;
}
+#ifdef NSS_FIPS_140_3
+ /* FIP 140-3 requires full kernel reseeding for chained entropy sources
+ * so we need to use getrandom with GRND_RANDOM.
+ * getrandom returns -1 on failure, otherwise returns
+ * the number of bytes, which can be less than getBytes */
+ result = getrandom(buffer, getBytes, rng_grndFlags);
+ if (result < 0) {
+ break;
+ }
+ fileBytes += result;
+ buffer += result;
+#else
+ /* get entropy returns 0 on success and always return
+ * getBytes on success */
result = getentropy(buffer, getBytes);
if (result == 0) { /* success */
fileBytes += getBytes;
buffer += getBytes;
} else {
break;
}
+#endif
}
if (fileBytes == maxLen) { /* success */
return maxLen;
}
+#ifdef NSS_FIPS_140_3
+ /* in FIPS 104-3 we don't fallback, just fail */
+ PORT_SetError(SEC_ERROR_NEED_RANDOM);
+ return 0;
+#else
/* If we failed with an error other than ENOSYS, it means the destination
* buffer is not writeable. We don't need to try writing to it again. */
if (errno != ENOSYS) {
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return 0;
}
+#endif /*!NSS_FIPS_140_3 */
+#endif /* platorm has getentropy */
+#ifndef NSS_FIPS_140_3
/* ENOSYS means the kernel doesn't support getentropy()/getrandom().
* Reset the number of bytes to get and fall back to /dev/urandom. */
fileBytes = 0;
-#endif
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) {
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return 0;
}
while (fileBytes < maxLen) {
bytes = read(fd, buffer, maxLen - fileBytes);
if (bytes <= 0) {
@@ -76,9 +133,10 @@ RNG_SystemRNG(void *dest, size_t maxLen)
buffer += bytes;
}
(void)close(fd);
if (fileBytes != maxLen) {
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return 0;
}
return fileBytes;
+#endif
}
diff --git a/lib/softoken/config.mk b/lib/softoken/config.mk
--- a/lib/softoken/config.mk
+++ b/lib/softoken/config.mk
@@ -58,8 +58,12 @@ endif
ifdef NSS_ENABLE_FIPS_INDICATORS
DEFINES += -DNSS_ENABLE_FIPS_INDICATORS
endif
ifdef NSS_FIPS_MODULE_ID
DEFINES += -DNSS_FIPS_MODULE_ID=\"${NSS_FIPS_MODULE_ID}\"
endif
+ifdef NSS_FIPS_140_3
+DEFINES += -DNSS_FIPS_140_3
+endif
+
diff --git a/lib/softoken/lowpbe.c b/lib/softoken/lowpbe.c
--- a/lib/softoken/lowpbe.c
+++ b/lib/softoken/lowpbe.c
@@ -1766,16 +1766,20 @@ sftk_fips_pbkdf_PowerUpSelfTests(void)
unsigned char iteration_count = 5;
unsigned char keyLen = 64;
char *inKeyData = TEST_KEY;
- static const unsigned char saltData[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
+ static const unsigned char saltData[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
static const unsigned char pbkdf_known_answer[] = {
- 0x31, 0xf0, 0xe5, 0x39, 0x9f, 0x39, 0xb9, 0x29,
- 0x68, 0xac, 0xf2, 0xe9, 0x53, 0x9b, 0xb4, 0x9c,
- 0x28, 0x59, 0x8b, 0x5c, 0xd8, 0xd4, 0x02, 0x37,
- 0x18, 0x22, 0xc1, 0x92, 0xd0, 0xfa, 0x72, 0x90,
- 0x2c, 0x8d, 0x19, 0xd4, 0x56, 0xfb, 0x16, 0xfa,
- 0x8d, 0x5c, 0x06, 0x33, 0xd1, 0x5f, 0x17, 0xb1,
- 0x22, 0xd9, 0x9c, 0xaf, 0x5e, 0x3f, 0xf3, 0x66,
- 0xc6, 0x14, 0xfe, 0x83, 0xfa, 0x1a, 0x2a, 0xc5
+ 0x73, 0x8c, 0xfa, 0x02, 0xe8, 0xdb, 0x43, 0xe4,
+ 0x99, 0xc5, 0xfd, 0xd9, 0x4d, 0x8e, 0x3e, 0x7b,
+ 0xc4, 0xda, 0x22, 0x1b, 0xe1, 0xae, 0x23, 0x7a,
+ 0x21, 0x27, 0xbd, 0xcc, 0x78, 0xc4, 0xe6, 0xc5,
+ 0x33, 0x38, 0x35, 0xe0, 0x68, 0x1a, 0x1e, 0x06,
+ 0xad, 0xaf, 0x7f, 0xd7, 0x3f, 0x0e, 0xc0, 0x90,
+ 0x17, 0x97, 0x73, 0x75, 0x7b, 0x88, 0x49, 0xd8,
+ 0x6f, 0x78, 0x5a, 0xde, 0x50, 0x20, 0x55, 0x33
};
sftk_PBELockInit();
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
--- a/lib/softoken/pkcs11c.c
+++ b/lib/softoken/pkcs11c.c
@@ -4609,16 +4609,17 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi
goto loser;
}
/* make sure we don't have any class, key_type, or value fields */
sftk_DeleteAttributeType(key, CKA_CLASS);
sftk_DeleteAttributeType(key, CKA_KEY_TYPE);
sftk_DeleteAttributeType(key, CKA_VALUE);
+
/* Now Set up the parameters to generate the key (based on mechanism) */
key_gen_type = nsc_bulk; /* bulk key by default */
switch (pMechanism->mechanism) {
case CKM_CDMF_KEY_GEN:
case CKM_DES_KEY_GEN:
case CKM_DES2_KEY_GEN:
case CKM_DES3_KEY_GEN:
checkWeak = PR_TRUE;
@@ -4812,16 +4813,19 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi
crv = sftk_handleObject(key, session);
sftk_FreeSession(session);
if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) {
crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL));
}
if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) {
crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL));
}
+ /* we need to do this check at the end, so we can check the generated key length against
+ * fips requirements */
+ key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE, key);
if (crv == CKR_OK) {
*phKey = key->handle;
}
loser:
PORT_Memset(buf, 0, sizeof buf);
sftk_FreeObject(key);
return crv;
}
@@ -5780,16 +5784,19 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS
if (crv != CKR_OK) {
NSC_DestroyObject(hSession, publicKey->handle);
sftk_FreeObject(publicKey);
NSC_DestroyObject(hSession, privateKey->handle);
sftk_FreeObject(privateKey);
return crv;
}
+ /* we need to do this check at the end to make sure the generated key meets the key length requirements */
+ privateKey->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE_KEY_PAIR, privateKey);
+ publicKey->isFIPS = privateKey->isFIPS;
*phPrivateKey = privateKey->handle;
*phPublicKey = publicKey->handle;
sftk_FreeObject(publicKey);
sftk_FreeObject(privateKey);
return CKR_OK;
}
@@ -6990,16 +6997,17 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
}
/* HKDF-Extract(salt, base key value) */
if (params->bExtract) {
CK_BYTE *salt;
CK_ULONG saltLen;
HMACContext *hmac;
unsigned int bufLen;
+ SFTKSource saltKeySource = SFTK_SOURCE_DEFAULT;
switch (params->ulSaltType) {
case CKF_HKDF_SALT_NULL:
saltLen = hashLen;
salt = hashbuf;
memset(salt, 0, saltLen);
break;
case CKF_HKDF_SALT_DATA:
@@ -7026,29 +7034,54 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) {
CK_MECHANISM mech;
mech.mechanism = CKM_HKDF_DERIVE;
mech.pParameter = params;
mech.ulParameterLen = sizeof(*params);
key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech,
CKA_DERIVE, saltKey);
}
+ saltKeySource = saltKey->source;
saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
if (saltKey_att == NULL) {
sftk_FreeObject(saltKey);
return CKR_KEY_HANDLE_INVALID;
}
/* save the resulting salt */
salt = saltKey_att->attrib.pValue;
saltLen = saltKey_att->attrib.ulValueLen;
break;
default:
return CKR_MECHANISM_PARAM_INVALID;
break;
}
+ /* only TLS style usage is FIPS approved,
+ * turn off the FIPS indicator for other usages */
+ if (isFIPS && key && sourceKey) {
+ PRBool fipsOK = PR_FALSE;
+ /* case one: mix the kea with a previous or default
+ * salt */
+ if ((sourceKey->source == SFTK_SOURCE_KEA) &&
+ (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) &&
+ (saltLen == rawHash->length)) {
+ fipsOK = PR_TRUE;
+ }
+ /* case two: restart, remix the previous secret as a salt */
+ if ((sourceKey->objclass == CKO_DATA) &&
+ (NSS_SecureMemcmpZero(sourceKeyBytes, sourceKeyLen) == 0) &&
+ (sourceKeyLen == rawHash->length) &&
+ (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) &&
+ (saltLen == rawHash->length)) {
+ fipsOK = PR_TRUE;
+ }
+ if (!fipsOK) {
+ key->isFIPS = PR_FALSE;
+ }
+ }
+ if (key) key->source = SFTK_SOURCE_HKDF_EXTRACT;
hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
if (saltKey_att) {
sftk_FreeAttribute(saltKey_att);
}
if (saltKey) {
sftk_FreeObject(saltKey);
}
@@ -7076,16 +7109,40 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
/* T(1) = HMAC-Hash(prk, "" | info | 0x01)
* T(n) = HMAC-Hash(prk, T(n-1) | info | n
* key material = T(1) | ... | T(n)
*/
HMACContext *hmac;
CK_BYTE bi;
unsigned iterations;
+ /* only TLS style usage is FIPS approved,
+ * turn off the FIPS indicator for other usages */
+ if (isFIPS && key && key->isFIPS && sourceKey) {
+ unsigned char *info=&params->pInfo[3];
+ /* only one case,
+ * 1) Expand only
+ * 2) with a key whose source was
+ * SFTK_SOURCE_HKDF_EXPAND or SFTK_SOURCE_HKDF_EXTRACT
+ * 3) source key length == rawHash->length
+ * 4) Info has tls or dtls
+ * If any of those conditions aren't met, then we turn
+ * off the fips indicator */
+ if (params->bExtract ||
+ ((sourceKey->source != SFTK_SOURCE_HKDF_EXTRACT) &&
+ (sourceKey->source != SFTK_SOURCE_HKDF_EXPAND)) ||
+ (sourceKeyLen != rawHash->length) ||
+ (params->ulInfoLen < 7) ||
+ ((PORT_Memcmp(info,"tls",3) != 0) &&
+ (PORT_Memcmp(info,"dtls",4) != 0))) {
+ key->isFIPS = PR_FALSE;
+ }
+ }
+ if (key) key->source = SFTK_SOURCE_HKDF_EXPAND;
+
genLen = PR_ROUNDUP(keySize, hashLen);
iterations = genLen / hashLen;
if (genLen > sizeof(keyBlock)) {
keyBlockAlloc = PORT_Alloc(genLen);
if (keyBlockAlloc == NULL) {
return CKR_HOST_MEMORY;
}
@@ -8434,16 +8491,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
/* calculate private value - oct */
rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
SECITEM_ZfreeItem(&dhValue, PR_FALSE);
if (rv == SECSuccess) {
+ key->source = SFTK_SOURCE_KEA;
sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
SECITEM_ZfreeItem(&derived, PR_FALSE);
crv = CKR_OK;
} else
crv = CKR_HOST_MEMORY;
break;
}
@@ -8564,16 +8622,17 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
}
PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen);
secret = keyData;
} else {
secret += (secretlen - keySize);
}
secretlen = keySize;
}
+ key->source = SFTK_SOURCE_KEA;
sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
PORT_ZFree(tmp.data, tmp.len);
if (keyData) {
PORT_ZFree(keyData, keySize);
}
break;
diff --git a/lib/softoken/pkcs11i.h b/lib/softoken/pkcs11i.h
--- a/lib/softoken/pkcs11i.h
+++ b/lib/softoken/pkcs11i.h
@@ -147,16 +147,26 @@ typedef enum {
*/
typedef enum {
SFTK_DestroyFailure,
SFTK_Destroyed,
SFTK_Busy
} SFTKFreeStatus;
/*
+ * Source of various objects
+ */
+typedef enum {
+ SFTK_SOURCE_DEFAULT=0,
+ SFTK_SOURCE_KEA,
+ SFTK_SOURCE_HKDF_EXPAND,
+ SFTK_SOURCE_HKDF_EXTRACT
+} SFTKSource;
+
+/*
* attribute values of an object.
*/
struct SFTKAttributeStr {
SFTKAttribute *next;
SFTKAttribute *prev;
PRBool freeAttr;
PRBool freeData;
/*must be called handle to make sftkqueue_find work */
@@ -189,16 +199,17 @@ struct SFTKObjectStr {
CK_OBJECT_CLASS objclass;
CK_OBJECT_HANDLE handle;
int refCount;
PZLock *refLock;
SFTKSlot *slot;
void *objectInfo;
SFTKFree infoFree;
PRBool isFIPS;
+ SFTKSource source;
};
struct SFTKTokenObjectStr {
SFTKObject obj;
SECItem dbKey;
};
struct SFTKSessionObjectStr {
diff --git a/lib/softoken/pkcs11u.c b/lib/softoken/pkcs11u.c
--- a/lib/softoken/pkcs11u.c
+++ b/lib/softoken/pkcs11u.c
@@ -1090,16 +1090,17 @@ sftk_NewObject(SFTKSlot *slot)
sessObject->attrList[i].freeData = PR_FALSE;
}
sessObject->optimizeSpace = slot->optimizeSpace;
object->handle = 0;
object->next = object->prev = NULL;
object->slot = slot;
object->isFIPS = sftk_isFIPS(slot->slotID);
+ object->source = SFTK_SOURCE_DEFAULT;
object->refCount = 1;
sessObject->sessionList.next = NULL;
sessObject->sessionList.prev = NULL;
sessObject->sessionList.parent = object;
sessObject->session = NULL;
sessObject->wasDerived = PR_FALSE;
if (!hasLocks)
@@ -1674,16 +1675,17 @@ fail:
CK_RV
sftk_CopyObject(SFTKObject *destObject, SFTKObject *srcObject)
{
SFTKAttribute *attribute;
SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject);
unsigned int i;
destObject->isFIPS = srcObject->isFIPS;
+ destObject->source = srcObject->source;
if (src_so == NULL) {
return sftk_CopyTokenObject(destObject, srcObject);
}
PZ_Lock(src_so->attributeLock);
for (i = 0; i < src_so->hashSize; i++) {
attribute = src_so->head[i];
do {
@@ -2059,16 +2061,17 @@ sftk_NewTokenObject(SFTKSlot *slot, SECI
/* every object must have a class, if we can't get it, the object
* doesn't exist */
crv = handleToClass(slot, handle, &object->objclass);
if (crv != CKR_OK) {
goto loser;
}
object->slot = slot;
object->isFIPS = sftk_isFIPS(slot->slotID);
+ object->source = SFTK_SOURCE_DEFAULT;
object->objectInfo = NULL;
object->infoFree = NULL;
if (!hasLocks) {
object->refLock = PZ_NewLock(nssILockRefLock);
}
if (object->refLock == NULL) {
goto loser;
}
@@ -2225,16 +2228,25 @@ sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE
break;
case CKA_DERIVE:
flags = CKF_DERIVE;
break;
/* fake attribute to select digesting */
case CKA_DIGEST:
flags = CKF_DIGEST;
break;
+ /* fake attribute to select key gen */
+ case CKA_NSS_GENERATE:
+ flags = CKF_GENERATE;
+ break;
+ /* fake attribute to select key pair gen */
+ case CKA_NSS_GENERATE_KEY_PAIR:
+ flags = CKF_GENERATE_KEY_PAIR;
+ break;
+ /* fake attributes to to handle MESSAGE* flags */
case CKA_NSS_MESSAGE | CKA_ENCRYPT:
flags = CKF_MESSAGE_ENCRYPT;
break;
case CKA_NSS_MESSAGE | CKA_DECRYPT:
flags = CKF_MESSAGE_DECRYPT;
break;
case CKA_NSS_MESSAGE | CKA_SIGN:
flags = CKF_MESSAGE_SIGN;
@@ -2278,17 +2290,17 @@ sftk_quickGetECCCurveOid(SFTKObject *sou
}
/* This function currently only returns valid lengths for
* FIPS approved ECC curves. If we want to make this generic
* in the future, that Curve determination can be done in
* the sftk_handleSpecial. Since it's currently only used
* in FIPS indicators, it's currently only compiled with
* the FIPS indicator code */
-static int
+static CK_ULONG
sftk_getKeyLength(SFTKObject *source)
{
CK_KEY_TYPE keyType = CK_INVALID_HANDLE;
CK_ATTRIBUTE_TYPE keyAttribute;
CK_ULONG keyLength = 0;
SFTKAttribute *attribute;
CK_RV crv;
diff --git a/lib/util/pkcs11n.h b/lib/util/pkcs11n.h
--- a/lib/util/pkcs11n.h
+++ b/lib/util/pkcs11n.h
@@ -58,16 +58,18 @@
/*
* NSS-defined certificate types
*
*/
#define CKC_NSS (CKC_VENDOR_DEFINED | NSSCK_VENDOR_NSS)
/* FAKE PKCS #11 defines */
#define CKA_DIGEST 0x81000000L
+#define CKA_NSS_GENERATE 0x81000001L
+#define CKA_NSS_GENERATE_KEY_PAIR 0x81000002L
#define CKA_NSS_MESSAGE 0x82000000L
#define CKA_NSS_MESSAGE_MASK 0xff000000L
#define CKA_FLAGS_ONLY 0 /* CKA_CLASS */
/*
* NSS-defined object attributes
*
*/

View File

@ -1,42 +0,0 @@
diff --git a/lib/softoken/sftkmessage.c b/lib/softoken/sftkmessage.c
--- a/lib/softoken/sftkmessage.c
+++ b/lib/softoken/sftkmessage.c
@@ -146,16 +146,38 @@ sftk_CryptMessage(CK_SESSION_HANDLE hSes
CHECK_FORK();
/* make sure we're legal */
crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
if (crv != CKR_OK)
return crv;
+ if (context->isFIPS && (contextType == SFTK_MESSAGE_ENCRYPT)) {
+ if ((pParameter == NULL) || (ulParameterLen != sizeof(CK_GCM_MESSAGE_PARAMS))) {
+ context->isFIPS = PR_FALSE;
+ } else {
+ CK_GCM_MESSAGE_PARAMS *p = (CK_GCM_MESSAGE_PARAMS *)pParameter;
+ switch (p->ivGenerator) {
+ case CKG_NO_GENERATE:
+ context->isFIPS = PR_FALSE;
+ break;
+ case CKG_GENERATE_RANDOM:
+ if ((p->ulIvLen < 12) || (p->ulIvFixedBits != 0)) {
+ context->isFIPS = PR_FALSE;
+ }
+ break;
+ default:
+ if ((p->ulIvLen < 12) || (p->ulIvFixedBits < 32)) {
+ context->isFIPS = PR_FALSE;
+ }
+ }
+ }
+ }
+
if (!pOuttext) {
*pulOuttextLen = ulIntextLen;
return CKR_OK;
}
rv = (*context->aeadUpdate)(context->cipherInfo, pOuttext, &outlen,
maxout, pIntext, ulIntextLen,
pParameter, ulParameterLen,
pAssociatedData, ulAssociatedDataLen);

View File

@ -1,176 +0,0 @@
diff -up ./lib/softoken/pkcs11c.c.fips_2 ./lib/softoken/pkcs11c.c
--- ./lib/softoken/pkcs11c.c.fips_2 2024-01-19 09:21:19.632889660 -0800
+++ ./lib/softoken/pkcs11c.c 2024-01-19 09:22:18.541471306 -0800
@@ -7090,7 +7090,7 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
mech.ulParameterLen = sizeof(*params);
key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech,
CKA_DERIVE, saltKey,
- keySize);
+ keySize*PR_BITS_PER_BYTE);
}
saltKeySource = saltKey->source;
saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
@@ -7404,7 +7404,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
}
}
key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey,
- keySize);
+ keySize*PR_BITS_PER_BYTE);
switch (mechanism) {
/* get a public key from a private key. nsslowkey_ConvertToPublickey()
diff -up ./lib/softoken/pkcs11u.c.fips_2 ./lib/softoken/pkcs11u.c
--- ./lib/softoken/pkcs11u.c.fips_2 2024-01-19 09:21:19.633889670 -0800
+++ ./lib/softoken/pkcs11u.c 2024-01-19 09:28:00.082843565 -0800
@@ -2393,20 +2393,43 @@ sftk_getKeyLength(SFTKObject *source)
}
PRBool
-sftk_CheckFIPSHash(CK_MECHANISM_TYPE hash)
+sftk_checkFIPSHash(CK_MECHANISM_TYPE hash, PRBool allowSmall, PRBool allowCMAC)
{
switch (hash) {
+ case CKM_AES_CMAC:
+ return allowCMAC;
+ case CKM_SHA_1:
+ case CKM_SHA_1_HMAC:
+ case CKM_SHA224:
+ case CKM_SHA224_HMAC:
+ return allowSmall;
case CKM_SHA256:
- case CKG_MGF1_SHA256:
+ case CKM_SHA256_HMAC:
case CKM_SHA384:
- case CKG_MGF1_SHA384:
+ case CKM_SHA384_HMAC:
case CKM_SHA512:
- case CKG_MGF1_SHA512:
+ case CKM_SHA512_HMAC:
return PR_TRUE;
}
return PR_FALSE;
}
+PRBool
+sftk_checkKeyLength(CK_ULONG keyLength, CK_ULONG min,
+ CK_ULONG max, CK_ULONG step)
+{
+ if (keyLength > max) {
+ return PR_FALSE;
+ }
+ if (keyLength < min ) {
+ return PR_FALSE;
+ }
+ if (((keyLength - min) % step) != 0) {
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
/*
* handle specialized FIPS semantics that are too complicated to
* handle with just a table. NOTE: this means any additional semantics
@@ -2416,6 +2439,8 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
SFTKFIPSAlgorithmList *mechInfo, SFTKObject *source,
CK_ULONG keyLength, CK_ULONG targetKeyLength)
{
+ PRBool allowSmall = PR_FALSE;
+ PRBool allowCMAC = PR_FALSE;
switch (mechInfo->special) {
case SFTKFIPSDH: {
SECItem dhPrime;
@@ -2482,7 +2507,11 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
if (pss->sLen > hashObj->length) {
return PR_FALSE;
}
- return sftk_CheckFIPSHash(pss->hashAlg);
+ /* Our code makes sure pss->hashAlg matches the explicit
+ * hash in the mechanism, and only mechanisms with approved
+ * hashes are included, so no need to check pss->hashAlg
+ * here */
+ return PR_TRUE;
}
case SFTKFIPSPBKDF2: {
/* PBKDF2 must have the following addition restrictions
@@ -2508,12 +2537,28 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
return PR_TRUE;
}
/* check the hash mechanisms to make sure they themselves are FIPS */
+ case SFTKFIPSChkHashSp800:
+ allowCMAC = PR_TRUE;
case SFTKFIPSChkHash:
+ allowSmall = PR_TRUE;
+ case SFTKFIPSChkHashTls:
if (mech->ulParameterLen < mechInfo->offset +sizeof(CK_ULONG)) {
return PR_FALSE;
}
- return sftk_CheckFIPSHash(*(CK_ULONG *)(((char *)mech->pParameter)
- + mechInfo->offset));
+ return sftk_checkFIPSHash(*(CK_ULONG *)(((char *)mech->pParameter)
+ + mechInfo->offset), allowSmall, allowCMAC);
+ case SFTKFIPSTlsKeyCheck:
+ if (mech->mechanism != CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) {
+ /* unless the mechnism has a built-in hash, check the hash */
+ if (mech->ulParameterLen < mechInfo->offset +sizeof(CK_ULONG)) {
+ return PR_FALSE;
+ }
+ if (!sftk_checkFIPSHash(*(CK_ULONG *)(((char *)mech->pParameter)
+ + mechInfo->offset), PR_FALSE, PR_FALSE)) {
+ return PR_FALSE;
+ }
+ }
+ return sftk_checkKeyLength(targetKeyLength, 112, 512, 1);
default:
break;
}
@@ -2558,13 +2603,11 @@ sftk_operationIsFIPS(SFTKSlot *slot, CK_
* approved algorithm in the approved mode with an approved key */
if ((mech->mechanism == mechs->type) &&
(opFlags == (mechs->info.flags & opFlags)) &&
- (keyLength <= mechs->info.ulMaxKeySize) &&
- (keyLength >= mechs->info.ulMinKeySize) &&
- (((keyLength - mechs->info.ulMinKeySize) % mechs->step) == 0) &&
- ((targetKeyLength == 0) ||
- ((targetKeyLength <= mechs->info.ulMaxKeySize) &&
- (targetKeyLength >= mechs->info.ulMinKeySize) &&
- ((targetKeyLength - mechs->info.ulMinKeySize) % mechs->step) == 0)) &&
+ sftk_checkKeyLength(keyLength, mechs->info.ulMinKeySize,
+ mechs->info.ulMaxKeySize, mechs->step) &&
+ ((targetKeyLength == 0) || (mechs->special == SFTKFIPSTlsKeyCheck)
+ || sftk_checkKeyLength(targetKeyLength, mechs->info.ulMinKeySize,
+ mechs->info.ulMaxKeySize, mechs->step)) &&
((mechs->special == SFTKFIPSNone) ||
sftk_handleSpecial(slot, mech, mechs, source, keyLength, targetKeyLength))) {
return PR_TRUE;
diff -up ./lib/softoken/sftkmessage.c.fips_2 ./lib/softoken/sftkmessage.c
--- ./lib/softoken/sftkmessage.c.fips_2 2024-01-19 09:21:19.634889680 -0800
+++ ./lib/softoken/sftkmessage.c 2024-01-19 09:22:18.541471306 -0800
@@ -157,16 +157,25 @@ sftk_CryptMessage(CK_SESSION_HANDLE hSes
} else {
CK_GCM_MESSAGE_PARAMS *p = (CK_GCM_MESSAGE_PARAMS *)pParameter;
switch (p->ivGenerator) {
+ default:
case CKG_NO_GENERATE:
context->isFIPS = PR_FALSE;
break;
case CKG_GENERATE_RANDOM:
- if ((p->ulIvLen < 12) || (p->ulIvFixedBits != 0)) {
+ if ((p->ulIvLen < 96/PR_BITS_PER_BYTE) ||
+ (p->ulIvFixedBits != 0)) {
context->isFIPS = PR_FALSE;
}
break;
- default:
- if ((p->ulIvLen < 12) || (p->ulIvFixedBits < 32)) {
+ case CKG_GENERATE_COUNTER_XOR:
+ if ((p->ulIvLen != 96/PR_BITS_PER_BYTE) ||
+ (p->ulIvFixedBits != 32)) {
+ context->isFIPS = PR_FALSE;
+ }
+ break;
+ case CKG_GENERATE_COUNTER:
+ if ((p->ulIvFixedBits < 32) ||
+ ((p->ulIvLen*PR_BITS_PER_BYTE - p->ulIvFixedBits) < 32)) {
context->isFIPS = PR_FALSE;
}
}

View File

@ -1,506 +0,0 @@
diff -up ./lib/freebl/aeskeywrap.c.safe_zero ./lib/freebl/aeskeywrap.c
--- ./lib/freebl/aeskeywrap.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/aeskeywrap.c 2023-11-22 14:42:24.246388369 -0800
@@ -512,7 +512,7 @@ AESKeyWrap_EncryptKWP(AESKeyWrapContext
PORT_Memcpy(iv + AES_KEY_WRAP_BLOCK_SIZE, input, inputLen);
rv = AES_Encrypt(&cx->aescx, output, pOutputLen, maxOutputLen, iv,
outLen);
- PORT_Memset(iv, 0, sizeof(iv));
+ PORT_SafeZero(iv, sizeof(iv));
return rv;
}
@@ -528,7 +528,7 @@ AESKeyWrap_EncryptKWP(AESKeyWrapContext
PORT_ZFree(newBuf, paddedInputLen);
/* a little overkill, we only need to clear out the length, but this
* is easier to verify we got it all */
- PORT_Memset(iv, 0, sizeof(iv));
+ PORT_SafeZero(iv, sizeof(iv));
return rv;
}
@@ -631,12 +631,12 @@ AESKeyWrap_DecryptKWP(AESKeyWrapContext
loser:
/* if we failed, make sure we don't return any data to the user */
if ((rv != SECSuccess) && (output == newBuf)) {
- PORT_Memset(newBuf, 0, paddedLen);
+ PORT_SafeZero(newBuf, paddedLen);
}
/* clear out CSP sensitive data from the heap and stack */
if (allocBuf) {
PORT_ZFree(allocBuf, paddedLen);
}
- PORT_Memset(iv, 0, sizeof(iv));
+ PORT_SafeZero(iv, sizeof(iv));
return rv;
}
diff -up ./lib/freebl/blapii.h.safe_zero ./lib/freebl/blapii.h
--- ./lib/freebl/blapii.h.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/blapii.h 2023-11-22 14:42:24.246388369 -0800
@@ -101,10 +101,10 @@ PRBool ppc_crypto_support();
#ifdef NSS_FIPS_DISABLED
#define BLAPI_CLEAR_STACK(stack_size)
#else
-#define BLAPI_CLEAR_STACK(stack_size) \
- { \
- volatile char _stkclr[stack_size]; \
- PORT_Memset((void *)&_stkclr[0], 0, stack_size); \
+#define BLAPI_CLEAR_STACK(stack_size) \
+ { \
+ volatile char _stkclr[stack_size]; \
+ PORT_SafeZero((void *)&_stkclr[0], stack_size); \
}
#endif
diff -up ./lib/freebl/drbg.c.safe_zero ./lib/freebl/drbg.c
--- ./lib/freebl/drbg.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/drbg.c 2023-11-22 14:42:24.246388369 -0800
@@ -197,7 +197,7 @@ prng_initEntropy(void)
SHA256_Update(&ctx, block, sizeof(block));
SHA256_End(&ctx, globalrng->previousEntropyHash, NULL,
sizeof(globalrng->previousEntropyHash));
- PORT_Memset(block, 0, sizeof(block));
+ PORT_SafeZero(block, sizeof(block));
SHA256_DestroyContext(&ctx, PR_FALSE);
return PR_SUCCESS;
}
@@ -246,8 +246,8 @@ prng_getEntropy(PRUint8 *buffer, size_t
}
out:
- PORT_Memset(hash, 0, sizeof hash);
- PORT_Memset(block, 0, sizeof block);
+ PORT_SafeZero(hash, sizeof hash);
+ PORT_SafeZero(block, sizeof block);
return rv;
}
@@ -393,8 +393,8 @@ prng_Hashgen(RNGContext *rng, PRUint8 *r
PRNG_ADD_CARRY_ONLY(data, (sizeof data) - 1, carry);
SHA256_DestroyContext(&ctx, PR_FALSE);
}
- PORT_Memset(data, 0, sizeof data);
- PORT_Memset(thisHash, 0, sizeof thisHash);
+ PORT_SafeZero(data, sizeof data);
+ PORT_SafeZero(thisHash, sizeof thisHash);
}
/*
@@ -455,7 +455,7 @@ prng_generateNewBytes(RNGContext *rng,
PRNG_ADD_CARRY_ONLY(rng->reseed_counter, (sizeof rng->reseed_counter) - 1, carry);
/* if the prng failed, don't return any output, signal softoken */
- PORT_Memset(H, 0, sizeof H);
+ PORT_SafeZero(H, sizeof H);
if (!rng->isValid) {
PORT_Memset(returned_bytes, 0, no_of_returned_bytes);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
diff -up ./lib/freebl/dsa.c.safe_zero ./lib/freebl/dsa.c
--- ./lib/freebl/dsa.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/dsa.c 2023-11-22 14:42:24.246388369 -0800
@@ -471,7 +471,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECIt
err = MP_OKAY;
signature->len = dsa_signature_len;
cleanup:
- PORT_Memset(localDigestData, 0, DSA_MAX_SUBPRIME_LEN);
+ PORT_SafeZero(localDigestData, DSA_MAX_SUBPRIME_LEN);
mp_clear(&p);
mp_clear(&q);
mp_clear(&g);
@@ -532,7 +532,7 @@ DSA_SignDigest(DSAPrivateKey *key, SECIt
rv = dsa_SignDigest(key, signature, digest, kSeed);
} while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
--retries > 0);
- PORT_Memset(kSeed, 0, sizeof kSeed);
+ PORT_SafeZero(kSeed, sizeof kSeed);
return rv;
}
@@ -673,7 +673,7 @@ DSA_VerifyDigest(DSAPublicKey *key, cons
verified = SECSuccess; /* Signature verified. */
}
cleanup:
- PORT_Memset(localDigestData, 0, sizeof localDigestData);
+ PORT_SafeZero(localDigestData, sizeof localDigestData);
mp_clear(&p);
mp_clear(&q);
mp_clear(&g);
diff -up ./lib/freebl/gcm.c.safe_zero ./lib/freebl/gcm.c
--- ./lib/freebl/gcm.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/gcm.c 2023-11-22 14:42:24.246388369 -0800
@@ -480,7 +480,7 @@ gcmHash_Final(gcmHashContext *ghash, uns
rv = SECSuccess;
cleanup:
- PORT_Memset(T, 0, sizeof(T));
+ PORT_SafeZero(T, sizeof(T));
return rv;
}
@@ -596,15 +596,15 @@ GCM_CreateContext(void *context, freeblC
if (rv != SECSuccess) {
goto loser;
}
- PORT_Memset(H, 0, AES_BLOCK_SIZE);
+ PORT_SafeZero(H, AES_BLOCK_SIZE);
gcm->ctr_context_init = PR_TRUE;
return gcm;
loser:
- PORT_Memset(H, 0, AES_BLOCK_SIZE);
+ PORT_SafeZero(H, AES_BLOCK_SIZE);
if (ghash && ghash->mem) {
void *mem = ghash->mem;
- PORT_Memset(ghash, 0, sizeof(gcmHashContext));
+ PORT_SafeZero(ghash, sizeof(gcmHashContext));
PORT_Free(mem);
}
if (gcm) {
@@ -682,11 +682,11 @@ gcm_InitCounter(GCMContext *gcm, const u
goto loser;
}
- PORT_Memset(&ctrParams, 0, sizeof ctrParams);
+ PORT_SafeZero(&ctrParams, sizeof ctrParams);
return SECSuccess;
loser:
- PORT_Memset(&ctrParams, 0, sizeof ctrParams);
+ PORT_SafeZero(&ctrParams, sizeof ctrParams);
if (freeCtr) {
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
}
@@ -866,10 +866,10 @@ GCM_DecryptUpdate(GCMContext *gcm, unsig
if (NSS_SecureMemcmp(tag, intag, tagBytes) != 0) {
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
PORT_SetError(SEC_ERROR_BAD_DATA);
- PORT_Memset(tag, 0, sizeof(tag));
+ PORT_SafeZero(tag, sizeof(tag));
return SECFailure;
}
- PORT_Memset(tag, 0, sizeof(tag));
+ PORT_SafeZero(tag, sizeof(tag));
/* finish the decryption */
return CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
inbuf, inlen, AES_BLOCK_SIZE);
@@ -1159,10 +1159,10 @@ GCM_DecryptAEAD(GCMContext *gcm, unsigne
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
PORT_SetError(SEC_ERROR_BAD_DATA);
- PORT_Memset(tag, 0, sizeof(tag));
+ PORT_SafeZero(tag, sizeof(tag));
return SECFailure;
}
- PORT_Memset(tag, 0, sizeof(tag));
+ PORT_SafeZero(tag, sizeof(tag));
/* finish the decryption */
rv = CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
inbuf, inlen, AES_BLOCK_SIZE);
diff -up ./lib/freebl/hmacct.c.safe_zero ./lib/freebl/hmacct.c
--- ./lib/freebl/hmacct.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/hmacct.c 2023-11-22 14:42:24.246388369 -0800
@@ -274,10 +274,10 @@ MAC(unsigned char *mdOut,
hashObj->end(mdState, mdOut, mdOutLen, mdOutMax);
hashObj->destroy(mdState, PR_TRUE);
- PORT_Memset(lengthBytes, 0, sizeof lengthBytes);
- PORT_Memset(hmacPad, 0, sizeof hmacPad);
- PORT_Memset(firstBlock, 0, sizeof firstBlock);
- PORT_Memset(macOut, 0, sizeof macOut);
+ PORT_SafeZero(lengthBytes, sizeof lengthBytes);
+ PORT_SafeZero(hmacPad, sizeof hmacPad);
+ PORT_SafeZero(firstBlock, sizeof firstBlock);
+ PORT_SafeZero(macOut, sizeof macOut);
return SECSuccess;
}
diff -up ./lib/freebl/intel-gcm-wrap.c.safe_zero ./lib/freebl/intel-gcm-wrap.c
--- ./lib/freebl/intel-gcm-wrap.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/intel-gcm-wrap.c 2023-11-22 14:42:24.246388369 -0800
@@ -195,7 +195,7 @@ intel_aes_gcmInitCounter(intel_AES_GCMCo
void
intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
{
- PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext));
+ PORT_SafeZero(gcm, sizeof(intel_AES_GCMContext));
if (freeit) {
PORT_Free(gcm);
}
diff -up ./lib/freebl/ppc-gcm-wrap.c.safe_zero ./lib/freebl/ppc-gcm-wrap.c
--- ./lib/freebl/ppc-gcm-wrap.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/ppc-gcm-wrap.c 2023-11-22 14:42:24.246388369 -0800
@@ -169,7 +169,7 @@ ppc_aes_gcmInitCounter(ppc_AES_GCMContex
void
ppc_AES_GCM_DestroyContext(ppc_AES_GCMContext *gcm, PRBool freeit)
{
- PORT_Memset(gcm, 0, sizeof(ppc_AES_GCMContext));
+ PORT_SafeZero(gcm, sizeof(ppc_AES_GCMContext));
if (freeit) {
PORT_Free(gcm);
}
diff -up ./lib/freebl/pqg.c.safe_zero ./lib/freebl/pqg.c
--- ./lib/freebl/pqg.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/pqg.c 2023-11-22 14:42:24.246388369 -0800
@@ -703,7 +703,7 @@ cleanup:
mp_clear(&a);
mp_clear(&z);
mp_clear(&two_length_minus_1);
- PORT_Memset(x, 0, sizeof(x));
+ PORT_SafeZero(x, sizeof(x));
if (err) {
MP_TO_SEC_ERROR(err);
rv = SECFailure;
@@ -859,7 +859,7 @@ cleanup:
mp_clear(&c);
mp_clear(&c0);
mp_clear(&one);
- PORT_Memset(x, 0, sizeof(x));
+ PORT_SafeZero(x, sizeof(x));
if (err) {
MP_TO_SEC_ERROR(err);
rv = SECFailure;
@@ -1072,7 +1072,7 @@ makePfromQandSeed(
CHECK_MPI_OK(mp_sub_d(&c, 1, &c)); /* c -= 1 */
CHECK_MPI_OK(mp_sub(&X, &c, P)); /* P = X - c */
cleanup:
- PORT_Memset(V_j, 0, sizeof V_j);
+ PORT_SafeZero(V_j, sizeof V_j);
mp_clear(&W);
mp_clear(&X);
mp_clear(&c);
@@ -1221,7 +1221,7 @@ makeGfromIndex(HASH_HashType hashtype,
/* step 11.
* return valid G */
cleanup:
- PORT_Memset(data, 0, sizeof(data));
+ PORT_SafeZero(data, sizeof(data));
if (hashcx) {
hashobj->destroy(hashcx, PR_TRUE);
}
diff -up ./lib/freebl/rijndael.c.safe_zero ./lib/freebl/rijndael.c
--- ./lib/freebl/rijndael.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/rijndael.c 2023-11-22 14:42:24.247388378 -0800
@@ -1114,7 +1114,7 @@ AES_DestroyContext(AESContext *cx, PRBoo
cx->worker_cx = NULL;
cx->destroy = NULL;
}
- PORT_Memset(cx, 0, sizeof(AESContext));
+ PORT_SafeZero(cx, sizeof(AESContext));
if (freeit) {
PORT_Free(mem);
} else {
diff -up ./lib/freebl/rsa.c.safe_zero ./lib/freebl/rsa.c
--- ./lib/freebl/rsa.c.safe_zero 2023-11-22 14:41:24.066840894 -0800
+++ ./lib/freebl/rsa.c 2023-11-22 14:42:24.247388378 -0800
@@ -143,8 +143,8 @@ rsa_build_from_primes(const mp_int *p, c
/* 2. Compute phi = (p-1)*(q-1) */
CHECK_MPI_OK(mp_sub_d(p, 1, &psub1));
CHECK_MPI_OK(mp_sub_d(q, 1, &qsub1));
+ CHECK_MPI_OK(mp_lcm(&psub1, &qsub1, &phi));
if (needPublicExponent || needPrivateExponent) {
- CHECK_MPI_OK(mp_lcm(&psub1, &qsub1, &phi));
/* 3. Compute d = e**-1 mod(phi) */
/* or e = d**-1 mod(phi) as necessary */
if (needPublicExponent) {
@@ -165,6 +165,15 @@ rsa_build_from_primes(const mp_int *p, c
goto cleanup;
}
+ /* make sure we weren't passed in a d or e = 1 mod phi */
+ /* just need to check d, because if one is = 1 mod phi, they both are */
+ CHECK_MPI_OK(mp_mod(d, &phi, &tmp));
+ if (mp_cmp_d(&tmp, 2) <= 0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+ goto cleanup;
+ }
+
/* 4. Compute exponent1 = d mod (p-1) */
CHECK_MPI_OK(mp_mod(d, &psub1, &tmp));
MPINT_TO_SECITEM(&tmp, &key->exponent1, key->arena);
@@ -1152,6 +1161,8 @@ rsa_PrivateKeyOpCRTCheckedPubKey(RSAPriv
/* Perform a public key operation v = m ** e mod n */
CHECK_MPI_OK(mp_exptmod(m, &e, &n, &v));
if (mp_cmp(&v, c) != 0) {
+ /* this error triggers a fips fatal error lock */
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
rv = SECFailure;
}
cleanup:
diff -up ./lib/freebl/rsapkcs.c.safe_zero ./lib/freebl/rsapkcs.c
--- ./lib/freebl/rsapkcs.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/rsapkcs.c 2023-11-22 14:42:24.247388378 -0800
@@ -977,14 +977,14 @@ rsa_GetHMACContext(const SECHashObject *
/* now create the hmac key */
hmac = HMAC_Create(hash, keyHash, keyLen, PR_TRUE);
if (hmac == NULL) {
- PORT_Memset(keyHash, 0, sizeof(keyHash));
+ PORT_SafeZero(keyHash, sizeof(keyHash));
return NULL;
}
HMAC_Begin(hmac);
HMAC_Update(hmac, input, inputLen);
rv = HMAC_Finish(hmac, keyHash, &keyLen, sizeof(keyHash));
if (rv != SECSuccess) {
- PORT_Memset(keyHash, 0, sizeof(keyHash));
+ PORT_SafeZero(keyHash, sizeof(keyHash));
HMAC_Destroy(hmac, PR_TRUE);
return NULL;
}
@@ -992,7 +992,7 @@ rsa_GetHMACContext(const SECHashObject *
* reuse the original context allocated above so we don't
* need to allocate and free another one */
rv = HMAC_ReInit(hmac, hash, keyHash, keyLen, PR_TRUE);
- PORT_Memset(keyHash, 0, sizeof(keyHash));
+ PORT_SafeZero(keyHash, sizeof(keyHash));
if (rv != SECSuccess) {
HMAC_Destroy(hmac, PR_TRUE);
return NULL;
@@ -1042,7 +1042,7 @@ rsa_HMACPrf(HMACContext *hmac, const cha
return rv;
}
PORT_Memcpy(output, hmacLast, left);
- PORT_Memset(hmacLast, 0, sizeof(hmacLast));
+ PORT_SafeZero(hmacLast, sizeof(hmacLast));
}
return rv;
}
@@ -1087,7 +1087,7 @@ rsa_GetErrorLength(HMACContext *hmac, in
outLength = PORT_CT_SEL(PORT_CT_LT(candidate, maxLegalLen),
candidate, outLength);
}
- PORT_Memset(out, 0, sizeof(out));
+ PORT_SafeZero(out, sizeof(out));
return outLength;
}
diff -up ./lib/freebl/shvfy.c.safe_zero ./lib/freebl/shvfy.c
--- ./lib/freebl/shvfy.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/shvfy.c 2023-11-22 14:42:24.247388378 -0800
@@ -365,7 +365,7 @@ blapi_SHVerifyDSACheck(PRFileDesc *shFD,
/* verify the hash against the check file */
rv = DSA_VerifyDigest(key, signature, &hash);
- PORT_Memset(hashBuf, 0, sizeof hashBuf);
+ PORT_SafeZero(hashBuf, sizeof hashBuf);
return (rv == SECSuccess) ? PR_TRUE : PR_FALSE;
}
#endif
@@ -427,7 +427,7 @@ blapi_SHVerifyHMACCheck(PRFileDesc *shFD
if (rv == SECSuccess) {
result = SECITEM_ItemsAreEqual(signature, &hash);
}
- PORT_Memset(hashBuf, 0, sizeof hashBuf);
+ PORT_SafeZero(hashBuf, sizeof hashBuf);
return result;
}
@@ -451,7 +451,7 @@ blapi_SHVerifyFile(const char *shName, P
#ifndef NSS_STRICT_INTEGRITY
DSAPublicKey key;
- PORT_Memset(&key, 0, sizeof(key));
+ PORT_SafeZero(&key, sizeof(key));
#endif
/* If our integrity check was never ran or failed, fail any other
@@ -597,7 +597,7 @@ blapi_SHVerifyFile(const char *shName, P
shFD = NULL;
loser:
- PORT_Memset(&header, 0, sizeof header);
+ PORT_SafeZero(&header, sizeof header);
if (checkName != NULL) {
PORT_Free(checkName);
}
diff -up ./lib/freebl/tlsprfalg.c.safe_zero ./lib/freebl/tlsprfalg.c
--- ./lib/freebl/tlsprfalg.c.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/freebl/tlsprfalg.c 2023-11-22 14:42:24.247388378 -0800
@@ -82,8 +82,8 @@ loser:
/* clear out state so it's not left on the stack */
if (cx)
HMAC_Destroy(cx, PR_TRUE);
- PORT_Memset(state, 0, sizeof(state));
- PORT_Memset(outbuf, 0, sizeof(outbuf));
+ PORT_SafeZero(state, sizeof(state));
+ PORT_SafeZero(outbuf, sizeof(outbuf));
return rv;
}
diff -up ./lib/freebl/unix_urandom.c.safe_zero ./lib/freebl/unix_urandom.c
--- ./lib/freebl/unix_urandom.c.safe_zero 2023-11-22 14:42:24.247388378 -0800
+++ ./lib/freebl/unix_urandom.c 2023-11-22 14:44:15.519400684 -0800
@@ -22,7 +22,7 @@ RNG_SystemInfoForRNG(void)
return;
}
RNG_RandomUpdate(bytes, numBytes);
- PORT_Memset(bytes, 0, sizeof bytes);
+ PORT_SafeZero(bytes, sizeof bytes);
}
#ifdef NSS_FIPS_140_3
diff -up ./lib/softoken/pkcs11c.c.safe_zero ./lib/softoken/pkcs11c.c
--- ./lib/softoken/pkcs11c.c.safe_zero 2023-11-22 14:41:24.069840921 -0800
+++ ./lib/softoken/pkcs11c.c 2023-11-22 14:42:24.248388387 -0800
@@ -5092,7 +5092,7 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
if ((signature_length >= pairwise_digest_length) &&
(PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
PORT_Free(signature);
- return CKR_DEVICE_ERROR;
+ return CKR_GENERAL_ERROR;
}
/* Verify the known hash using the public key. */
diff -up ./lib/util/secport.h.safe_zero ./lib/util/secport.h
--- ./lib/util/secport.h.safe_zero 2023-06-04 01:42:53.000000000 -0700
+++ ./lib/util/secport.h 2023-11-22 14:42:24.248388387 -0800
@@ -36,6 +36,9 @@
#include <sys/types.h>
#include <ctype.h>
+/* ask for Annex K for memset_s. will set the appropriate #define
+ * if Annex K is supported */
+#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
@@ -182,6 +185,39 @@ SEC_END_PROTOS
#endif /*SUNOS4*/
#define PORT_Memset memset
+/* there are cases where the compiler optimizes away our attempt to clear
+ * out our stack variables. There are multiple solutions for this problem,
+ * but they aren't universally accepted on all platforms. This attempts
+ * to select the best solution available given our os, compilier, and libc */
+#ifdef __STDC_LIB_EXT1__
+/* if the os implements C11 annex K, use memset_s */
+#define PORT_SafeZero(p, n) memset_s(p, n, 0, n)
+#else
+#ifdef XP_WIN
+/* windows has a secure zero funtion */
+#define PORT_SafeZero(p, n) SecureZeroMemory(p, n)
+#else
+/* _DEFAULT_SORUCE == BSD source in GCC based environments
+ * if other environmens support explicit_bzero, their defines
+ * should be added here */
+#if defined(_DEFAULT_SOURCE) || defined(_BSD_SOURCE)
+#define PORT_SafeZero(p, n) explicit_bzero(p, n)
+#else
+/* if the os doesn't support one of the above, but does support
+ * memset_explicit, you can add the definition for memset with the
+ * appropriate define check here */
+/* define an explicitly implementated Safe zero if the OS
+ * doesn't provide one */
+#define PORT_SafeZero(p, n) \
+ if (p != NULL) { \
+ volatile unsigned char *__vl = (unsigned char *)p; \
+ size_t __nl = n; \
+ while (__nl--) *__vl++ = 0; \
+ }
+#endif /* no explicit_bzero */
+#endif /* no windows SecureZeroMemory */
+#endif /* no memset_s */
+
#define PORT_Strcasecmp PL_strcasecmp
#define PORT_Strcat strcat
#define PORT_Strchr strchr

View File

@ -1,42 +0,0 @@
diff -up ./lib/softoken/pkcs11u.c.pkcs12_indicator ./lib/softoken/pkcs11u.c
--- ./lib/softoken/pkcs11u.c.pkcs12_indicator 2023-08-03 10:50:37.067109367 -0700
+++ ./lib/softoken/pkcs11u.c 2023-08-03 11:41:55.641541953 -0700
@@ -2429,7 +2429,7 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
return PR_FALSE;
case SFTKFIPSECC:
/* we've already handled the curve selection in the 'getlength'
- * function */
+ * function */
return PR_TRUE;
case SFTKFIPSAEAD: {
if (mech->ulParameterLen == 0) {
@@ -2463,6 +2463,29 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
}
return PR_TRUE;
}
+ case SFTKFIPSPBKDF2: {
+ /* PBKDF2 must have the following addition restrictions
+ * (independent of keysize).
+ * 1. iteration count must be at least 1000.
+ * 2. salt must be at least 128 bits (16 bytes).
+ * 3. password must match the length specified in the SP
+ */
+ CK_PKCS5_PBKD2_PARAMS *pbkdf2 = (CK_PKCS5_PBKD2_PARAMS *)
+ mech->pParameter;
+ if (mech->ulParameterLen != sizeof(*pbkdf2)) {
+ return PR_FALSE;
+ }
+ if (pbkdf2->iterations < 1000) {
+ return PR_FALSE;
+ }
+ if (pbkdf2->ulSaltSourceDataLen < 16) {
+ return PR_FALSE;
+ }
+ if (*(pbkdf2->ulPasswordLen) < SFTKFIPS_PBKDF2_MIN_PW_LEN) {
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+ }
default:
break;
}

View File

@ -1,13 +1,14 @@
%global nss_version 3.101.0
%global nspr_version 4.35.0
%global baserelease 10
%global nss_version 3.112.0
%global nspr_version 4.36.0
%global baserelease 1
%global nss_release %baserelease
# NOTE: To avoid NVR clashes of nspr* packages:
# use "%%global nspr_release %%[%%baserelease+n]" to handle offsets when
# release number between nss and nspr are different.
# when a new nspr is released with nss, reset nspr_release to baserelease.
# for each new nss relase with the same nspr, change increment n by one.
%global nspr_release %[%baserelease+7]
#%%global nspr_release %%[%%baserelease+n]
%global nspr_release %baserelease
# only need to update this as we added new
# algorithms under nss policy control
%global crypto_policies_version 20210118
@ -126,6 +127,7 @@ Source22: pkcs11.txt.xml
Source24: cert9.db.xml
Source26: key4.db.xml
Source28: nss-p11-kit.config
Source29: nss_compat_test_pkcs12.tar
# fips algorithms are tied to the red hat validation, others
# will have their own validation
Source30: fips_algorithms.h
@ -149,11 +151,10 @@ Source101: nspr-config.xml
Patch4: iquote.patch
Patch12: nss-signtool-format.patch
Patch20: nss-3.101-extend-db-dump-time.patch
Patch21: nss-3.101-enable-sdb-tests.patch
# connect our shared library to the build root loader flags (needed for -relro)
Patch31: nss-dso-ldflags.patch
# keep RHEL 8 semantics of disabling md4 and md5 even if the env variable is set
Patch32: nss-3.101-disable-md5.patch
Patch32: nss-3.112-disable-md5.patch
# dbm is disabled on RHEL9, make the man pages reflect that
%if %{with dbm}
%else
@ -162,52 +163,35 @@ Patch33: nss-no-dbm-man-page.patch
# not upstreamable patch...
# WARNING: Need to make this patch work before checking!!! $$$$@@@
Patch34: nss-3.71-fix-lto-gtests.patch
# camellia pkcs12 docs.
Patch35: nss-3.71-camellia-pkcs12-doc.patch
# disable ech
Patch36: nss-3.101-disable-ech.patch
Patch36: nss-3.112-disable-ech.patch
# patches that expect to be upstreamed
# https://bugzilla.mozilla.org/show_bug.cgi?id=1767883
Patch50: nss-3.79-fips.patch
Patch50: nss-3.112-fips.patch
# https://bugzilla.mozilla.org/show_bug.cgi?id=1836781
# https://bugzilla.mozilla.org/show_bug.cgi?id=1836925
Patch51: nss-3.101-fips-review.patches
Patch52: nss-3.90-pbkdf2-indicator.patch
Patch53: nss-3.101-skip-ocsp-if-not-connected.patch
# dont upstream, must be after patch53 (sigh)
Patch54: nss-3.101-revert-libpkix-default.patch
# ems policy. needs to upstream
Patch60: nss-3.101-add-ems-policy.patch
Patch70: nss-3.90-fips-safe-memset.patch
Patch71: nss-3.101-fips-indicators.patch
Patch72: nss-3.90-aes-gmc-indicator.patch
Patch73: nss-3.90-fips-indicators2.patch
Patch74: nss-3.90-dh-test-update.patch
Patch75: nss-3.90-ppc_no_init.patch
Patch76: nss-3.101-enable-kyber-policy.patch
Patch77: nss-3.101-fix-rsa-policy-test.patch
Patch78: nss-3.101-fix-pkcs12-md5-decode.patch
Patch79: nss-3.101-el9-restore-old-pkcs12-default.patch
Patch80: nss-3.101-no-p12-smime-policy.patch
Patch81: nss-3.101-fix-missing-size-checks.patch
# https://bugzilla.mozilla.org/show_bug.cgi?id=1905691
Patch82: nss-3.101-chacha-timing-fix.patch
Patch83: nss-3.101-add-certificate-compression-test.patch
Patch84: nss-3.101-fix-pkcs12-pbkdf1-encoding.patch
Patch80: nss-3.112-no-p12-smime-policy.patch
# https://bugzilla.mozilla.org/show_bug.cgi?id=676100
Patch85: nss-3.101-fix-cms-abi-break.patch
Patch86: nss-3.101-long-pwd-fix.patch
Patch87: nss-3.101-fix-shlibsign-fips.patch
Patch88: nss-3.101-fips-check-ec25519-size.patch
Patch89: nss-3.101-allow-fips-rsa-oaep.patch
# Post Quantum specific
Patch91: nss-3.112-replace-xyber-with-mlkem-256.patch
Patch92: nss-3.112-add-sec384r1-mlkem-1024.patch
Patch93: nss-3.112-add-ml-dsa-base-dsa.patch
Patch94: nss-3.112-add-ml-dsa-gtests-dsa.patch
Patch95: nss-3.112-add-ml-dsa-ssl-support-dsa.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
Patch110: nspr-4.36-fix-coverity-loop-issue.patch
# NSS reverse patches
@ -377,6 +361,7 @@ pushd nspr
%autopatch -p 1 -m 101 -M 299
popd
tar xvf %{SOURCE29}
pushd nss
%autopatch -p1 -M 99
@ -467,6 +452,8 @@ export NSS_FIPS_MODULE_ID="${FIPS_MODULE_OS}\ ${NSS_FIPS_VERSION}"
# remove when the infrastructure is fixed
export NSS_FIPS_140_3=1
export NSS_ENABLE_FIPS_INDICATORS=1
export NSS_DISABLE_KYBER=1
export NSS_ENABLE_ML_DSA=1
# Enable compiler optimizations and disable debugging code
export BUILD_OPT=1
@ -653,6 +640,8 @@ popd
export FREEBL_NO_DEPEND=1
export BUILD_OPT=1
export NSS_DISABLE_KYBER=1
export NSS_ENABLE_ML_DSA=1
%ifnarch noarch
%if 0%{__isa_bits} == 64
@ -1094,6 +1083,7 @@ update-crypto-policies &> /dev/null || :
%{_includedir}/nss3/eccutil.h
%{_includedir}/nss3/hasht.h
%{_includedir}/nss3/kyber.h
%{_includedir}/nss3/ml_dsat.h
%{_includedir}/nss3/nssb64.h
%{_includedir}/nss3/nssb64t.h
%{_includedir}/nss3/nsshash.h
@ -1203,6 +1193,11 @@ update-crypto-policies &> /dev/null || :
%changelog
* Mon Jul 14 2025 Bob Relyea <rrelyea@redhat.com> - 3.112.0-1
- rebase to NSS 3.112
- add ml-kem-1024 support
- add ml-dsa support
* Mon Nov 11 2024 Frantisek Krenzelok <krenzelok.frantisek@gmail.com> - 3.101.0-10
- Allow RSA-OAEP in FIPS mode

View File

@ -1,4 +1,5 @@
SHA512 (blank-cert9.db) = 2f8eab4c0612210ee47db8a3a80c1b58a0b43849551af78c7da403fda3e3d4e7757838061ae56ccf5aac335cb54f254f0a9e6e9c0dd5920b4155a39264525b06
SHA512 (blank-key4.db) = 8fedae93af7163da23fe9492ea8e785a44c291604fa98e58438448efb69c85d3253fc22b926d5c3209c62e58a86038fd4d78a1c4c068bc00600a7f3e5382ebe7
SHA512 (nspr-4.35.tar.gz) = 502815833116e25f79ddf71d1526484908aa92fbc55f8a892729cb404a4daafcc0470a89854cd080d2d20299fdb7d9662507c5362c7ae661cbacf308ac56ef7f
SHA512 (nss-3.101.tar.gz) = b1596e7d74c654825eabbcc1f71b1410cf44d816c3044429576782bc800186073d43da9ad76de2fbd7de73c4460ebeb91aa244457da9d0d0cdc08a50a11a165f
SHA512 (nss_compat_test_pkcs12.tar) = 766af618ef02be5d54aff94651751ec68109a293c0b2782b0d7f6f2c844e41f4414eee5a9f46df2b1c22e0f24c4d85be00217cbcbc2632ac2f51bfa644abc2e6
SHA512 (nspr-4.36.tar.gz) = 55d21e196508ad29a179639fc8006f44b04dc2c0b5a85895e727f0a4f0ea37aeeceb936e37ac6b271b882a18e9f06d96133a60f19cee6345f8424c1c66e270ee
SHA512 (nss-3.112.tar.gz) = 564ae4ded323d7213f224673b0ddc584dcfae71bbdd139310854e547d9ba2877ba45462da49f71ea2fae72caea1cf10fa51d9dfef656a21957256cadc5fa4b35