nss/nss-3.124-indicators-prf.patch
Robert Relyea 0b59ee7dde Resolves: RHEL-182305
- rebase to upstream NSS 3.124
- backport ml-dsa support that is not upstream yet.
- pick up in process patches upstream including eddsa
2026-06-04 14:34:43 -07:00

190 lines
7.2 KiB
Diff

# HG changeset patch
# User Robert Relyea <rrelyea@redhat.com>
# Date 1780434653 25200
# Tue Jun 02 14:10:53 2026 -0700
# Branch NSS_3_124_BRANCH
# Node ID 19e655733f3af71e3d517ada0d31ad0697d40f3f
# Parent 567ea70a139936a15e80b0c88104ea44936dfc30
nss-3.124-indicators-prf.patch
diff --git a/lib/softoken/pkcs11u.c b/lib/softoken/pkcs11u.c
--- a/lib/softoken/pkcs11u.c
+++ b/lib/softoken/pkcs11u.c
@@ -16,37 +16,47 @@
#include "secoid.h"
#include "softkver.h"
#if !defined(NSS_FIPS_DISABLED) && defined(NSS_ENABLE_FIPS_INDICATORS)
/* handle special cases. Classes require existing code to already be
* in place for that class */
typedef enum {
SFTKFIPSNone = 0,
- SFTKFIPSDH, /* allow only specific primes */
- SFTKFIPSECC, /* not just keys but specific curves */
- SFTKFIPSAEAD, /* single shot AEAD functions not allowed in FIPS mode */
- SFTKFIPSRSAPSS,
- SFTKFIPSTlsKeyCheck
+ SFTKFIPSDH, /* allow only specific primes */
+ SFTKFIPSECC, /* not just keys but specific curves */
+ SFTKFIPSAEAD, /* single shot AEAD functions not allowed in FIPS mode */
+ SFTKFIPSRSAPSS, /* make sure salt isn't too big */
+ SFTKFIPSPBKDF2, /* handle pbkdf2 FIPS restrictions */
+ SFTKFIPSTlsKeyCheck, /* check the output of TLS prf functions */
+ SFTKFIPSChkHash, /* make sure the base hash of KDF functions is FIPS */
+ SFTKFIPSChkHashTls, /* make sure the base hash of TLS KDF functions is FIPS */
+ SFTKFIPSChkHashSp800, /* make sure the base hash of SP-800-108 KDF functions is FIPS */
+ SFTKFIPSRSAOAEP, /* make sure that both hashes use the same FIPS compliant algorithm */
} SFTKFIPSSpecialClass;
typedef struct SFTKFIPSAlgorithmListStr SFTKFIPSAlgorithmList;
struct SFTKFIPSAlgorithmListStr {
CK_MECHANISM_TYPE type;
CK_MECHANISM_INFO info;
CK_ULONG step;
SFTKFIPSSpecialClass special;
+ size_t offset;
};
/* this file should be supplied by the vendor and include all the
* algorithms which have Algorithm certs and have been reviewed by
* the lab. A blank file is included for the base so that FIPS mode
* will still be compiled and run, but FIPS indicators will always
* return PR_FALSE
*/
#include "fips_algorithms.h"
+
+#ifndef SFTKFIPS_PBKDF2_MIN_PW_LEN /* allow fips_algorithms.h to override */
+#define SFTKFIPS_PBKDF2_MIN_PW_LEN 8
+#endif
#define NSS_HAS_FIPS_INDICATORS 1
#endif
/*
* ******************** Error mapping *******************************
*/
/*
* map all the SEC_ERROR_xxx error codes that may be returned by freebl
@@ -2566,25 +2576,49 @@ sftk_checkKeyLength(CK_ULONG keyLength,
return PR_TRUE;
}
if (((keyLength - min) % step) != 0) {
return PR_FALSE;
}
return PR_TRUE;
}
+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;
+}
+
/*
* 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,
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,
@@ -2644,18 +2678,72 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME
return PR_FALSE;
}
/* cap the salt based on the hash */
if (pss->sLen > hashObj->length) {
return PR_FALSE;
}
return PR_TRUE;
}
+ case SFTKFIPSPBKDF2: {
+ /* from NIST SP 800-132
+ * 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_PARAMS2 *pbkdf2 = (CK_PKCS5_PBKD2_PARAMS2 *)
+ 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_MECHANISM_TYPE *)(((char *)mech->pParameter) + mechInfo->offset), allowSmall, allowCMAC);
case SFTKFIPSTlsKeyCheck:
- return sftk_checkKeyLength(targetKeyLength, 112, 512, 1);
+ 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_MECHANISM_TYPE *)(((char *)mech->pParameter) + mechInfo->offset), PR_FALSE, PR_FALSE)) {
+ return PR_FALSE;
+ }
+ }
+ return PR_TRUE;
+ 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