Resolves: RHEL-182530

- fix pkcs12 defaults
- fix pss issues
This commit is contained in:
Robert Relyea 2026-06-17 12:53:56 -07:00
parent 32e2ff42ba
commit d5fc8658fe
3 changed files with 447 additions and 10 deletions

View File

@ -0,0 +1,395 @@
# HG changeset patch
# User Robert Relyea <rrelyea@redhat.com>
# Date 1781635239 25200
# Tue Jun 16 11:40:39 2026 -0700
# Branch NSS_3_124_BRANCH
# Node ID 7cc6c51cdb9e8deaf246b87856517e0c1a21ffb3
# Parent 4b0e3f33a2e76a77e36b435eb3cc1eb06f14249d
nss-3.124-allow-hash-override-pss.patch
diff --git a/gtests/cryptohi_gtest/cryptohi_unittest.cc b/gtests/cryptohi_gtest/cryptohi_unittest.cc
--- a/gtests/cryptohi_gtest/cryptohi_unittest.cc
+++ b/gtests/cryptohi_gtest/cryptohi_unittest.cc
@@ -105,17 +105,17 @@ class SignParamsTestF : public ::testing
SECItem *saltLengthItem =
SEC_ASN1EncodeInteger(arena_.get(), &params->saltLength, saltLength);
ASSERT_EQ(&params->saltLength, saltLengthItem);
}
void CheckHashAlg(SECKEYRSAPSSParams *params, SECOidTag hashAlgTag) {
// If hash algorithm is SHA-1, it must be omitted in the parameters
if (hashAlgTag == SEC_OID_SHA1) {
- EXPECT_EQ(nullptr, params->hashAlg);
+ EXPECT_EQ(nullptr, params->hashAlg) << "oid==" << SECOID_FindOIDTagDescription(SECOID_GetAlgorithmTag(params->hashAlg));
} else {
EXPECT_NE(nullptr, params->hashAlg);
EXPECT_EQ(hashAlgTag, SECOID_GetAlgorithmTag(params->hashAlg));
}
}
void CheckMaskAlg(SECKEYRSAPSSParams *params, SECOidTag hashAlgTag) {
SECStatus rv;
@@ -225,22 +225,16 @@ TEST_P(SignParamsTest, CreateRsaPss) {
} else {
srcParams = NULL;
}
SECItem *params = SEC_CreateSignatureAlgorithmParameters(
arena_.get(), nullptr, SEC_OID_PKCS1_RSA_PSS_SIGNATURE, hashAlg,
srcParams, privk_.get());
- if (hashAlg != SEC_OID_UNKNOWN && srcHashAlg != SEC_OID_UNKNOWN &&
- hashAlg != srcHashAlg) {
- EXPECT_EQ(nullptr, params);
- return;
- }
-
EXPECT_NE(nullptr, params);
SECKEYRSAPSSParams pssParams;
PORT_Memset(&pssParams, 0, sizeof(pssParams));
SECStatus rv =
SEC_QuickDERDecodeItem(arena_.get(), &pssParams,
SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate), params);
ASSERT_EQ(SECSuccess, rv);
@@ -294,83 +288,100 @@ TEST_P(SignParamsTest, CreateRsaPssWithE
TEST_P(SignParamsTest, CreateRsaPssWithInvalidHashAlg) {
SECOidTag srcHashAlg = std::get<1>(GetParam());
SECItem *srcParams;
if (srcHashAlg != SEC_OID_UNKNOWN) {
SECKEYRSAPSSParams pssParams;
ASSERT_NO_FATAL_FAILURE(
- CreatePssParams(&pssParams, srcHashAlg, srcHashAlg));
+ CreatePssParams(&pssParams, SEC_OID_MD5, SEC_OID_MD5));
srcParams = SEC_ASN1EncodeItem(arena_.get(), nullptr, &pssParams,
SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate));
ASSERT_NE(nullptr, srcParams);
} else {
srcParams = NULL;
}
SECItem *params = SEC_CreateSignatureAlgorithmParameters(
- arena_.get(), nullptr, SEC_OID_PKCS1_RSA_PSS_SIGNATURE, SEC_OID_MD5,
+ arena_.get(), nullptr, SEC_OID_PKCS1_RSA_PSS_SIGNATURE, srcHashAlg,
srcParams, privk_.get());
- EXPECT_EQ(nullptr, params);
+ /* override invalid hash with valid hash */
+ EXPECT_NE(nullptr, params);
+ /* assert params ->hashAlg != SEC_OID_MD5 */
}
TEST_P(SignParamsSourceTest, CreateRsaPssWithInvalidHashAlg) {
SECOidTag hashAlg = GetParam();
SECItem *srcParams;
SECKEYRSAPSSParams pssParams;
ASSERT_NO_FATAL_FAILURE(
- CreatePssParams(&pssParams, SEC_OID_MD5, SEC_OID_MD5));
+ CreatePssParams(&pssParams, hashAlg, hashAlg));
srcParams = SEC_ASN1EncodeItem(arena_.get(), nullptr, &pssParams,
SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate));
ASSERT_NE(nullptr, srcParams);
SECItem *params = SEC_CreateSignatureAlgorithmParameters(
- arena_.get(), nullptr, SEC_OID_PKCS1_RSA_PSS_SIGNATURE, hashAlg,
+ arena_.get(), nullptr, SEC_OID_PKCS1_RSA_PSS_SIGNATURE, SEC_OID_MD4,
srcParams, privk_.get());
EXPECT_EQ(nullptr, params);
}
TEST_P(SignParamsSourceTest, CreateRsaPssWithInvalidSaltLength) {
SECOidTag hashAlg = GetParam();
SECItem *srcParams;
SECKEYRSAPSSParams pssParams;
ASSERT_NO_FATAL_FAILURE(
- CreatePssParams(&pssParams, SEC_OID_SHA512, SEC_OID_SHA512, 100));
+ CreatePssParams(&pssParams, SEC_OID_SHA512, SEC_OID_SHA512, 110));
srcParams = SEC_ASN1EncodeItem(arena_.get(), nullptr, &pssParams,
SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate));
ASSERT_NE(nullptr, srcParams);
SECItem *params = SEC_CreateSignatureAlgorithmParameters(
arena_.get(), nullptr, SEC_OID_PKCS1_RSA_PSS_SIGNATURE, hashAlg,
srcParams, privk_.get());
EXPECT_EQ(nullptr, params);
}
TEST_P(SignParamsSourceTest, CreateRsaPssWithHashMismatch) {
SECOidTag hashAlg = GetParam();
SECItem *srcParams;
SECKEYRSAPSSParams pssParams;
+ if ((hashAlg == SEC_OID_UNKNOWN) || (hashAlg == SEC_OID_SHA512)) {
+ hashAlg = SEC_OID_SHA1;
+ }
ASSERT_NO_FATAL_FAILURE(
- CreatePssParams(&pssParams, SEC_OID_SHA256, SEC_OID_SHA512));
+ CreatePssParams(&pssParams, hashAlg, SEC_OID_SHA512));
srcParams = SEC_ASN1EncodeItem(arena_.get(), nullptr, &pssParams,
SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate));
ASSERT_NE(nullptr, srcParams);
SECItem *params = SEC_CreateSignatureAlgorithmParameters(
- arena_.get(), nullptr, SEC_OID_PKCS1_RSA_PSS_SIGNATURE, hashAlg,
+ arena_.get(), nullptr, SEC_OID_PKCS1_RSA_PSS_SIGNATURE, SEC_OID_UNKNOWN,
srcParams, privk_.get());
- EXPECT_EQ(nullptr, params);
+ EXPECT_NE(nullptr, params);
+
+ PORT_Memset(&pssParams, 0, sizeof(pssParams));
+ SECStatus rv =
+ SEC_QuickDERDecodeItem(arena_.get(), &pssParams,
+ SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate), params);
+ ASSERT_EQ(SECSuccess, rv);
+ ASSERT_NO_FATAL_FAILURE(CheckHashAlg(&pssParams, hashAlg));
+ ASSERT_NO_FATAL_FAILURE(CheckMaskAlg(&pssParams, hashAlg));
+ ASSERT_NO_FATAL_FAILURE(CheckSaltLength(&pssParams, hashAlg));
+
+ // The default trailer field (1) must be omitted
+ EXPECT_EQ(nullptr, pssParams.trailerField.data);
}
INSTANTIATE_TEST_SUITE_P(
SignParamsTestCases, SignParamsTest,
::testing::Combine(::testing::Values(SEC_OID_UNKNOWN, SEC_OID_SHA1,
SEC_OID_SHA224, SEC_OID_SHA256,
SEC_OID_SHA384, SEC_OID_SHA512),
::testing::Values(SEC_OID_UNKNOWN, SEC_OID_SHA1,
diff --git a/lib/cryptohi/secsign.c b/lib/cryptohi/secsign.c
--- a/lib/cryptohi/secsign.c
+++ b/lib/cryptohi/secsign.c
@@ -814,16 +814,18 @@ sec_CreateRSAPSSParameters(PLArenaPool *
SECOidTag hashAlgTag,
const SECItem *params,
int modBytes)
{
SECKEYRSAPSSParams pssParams;
int hashLength;
unsigned long saltLength;
PRBool defaultSHA1 = PR_FALSE;
+ PRBool overWriteHash = PR_TRUE;
+ PRBool overWriteMask = PR_TRUE;
SECStatus rv;
PORT_Memset(&pssParams, 0, sizeof(pssParams));
if (params && params->data) {
/* The parameters field should either be empty or contain
* valid RSA-PSS parameters */
PORT_Assert(!(params->len == 2 &&
@@ -831,16 +833,18 @@ sec_CreateRSAPSSParameters(PLArenaPool *
params->data[1] == 0));
rv = SEC_QuickDERDecodeItem(arena, &pssParams,
SECKEY_RSAPSSParamsTemplate,
params);
if (rv != SECSuccess) {
return NULL;
}
defaultSHA1 = PR_TRUE;
+ overWriteHash = PR_FALSE;
+ overWriteMask = PR_FALSE;
}
if (pssParams.trailerField.data) {
unsigned long trailerField;
rv = SEC_ASN1DecodeInteger((SECItem *)&pssParams.trailerField,
&trailerField);
if (rv != SECSuccess) {
@@ -851,19 +855,21 @@ sec_CreateRSAPSSParameters(PLArenaPool *
return NULL;
}
}
/* Determine the hash algorithm to use, based on hashAlgTag and
* pssParams.hashAlg; there are 6 cases.
* case:
* 1) We have params and params.hashAlg and we have a specified hashAlgTag,
- * make sure that hashAlgTag specified by the appication matches.
+ * make sure that hashAlgTag specified by the appication matches, othersize we
+ * overwrite params.hashAlg with hashAlgTag.
* 2) We have params, but no params.hashAlg and we have a specified
- * hashAlg, make sure the hashAlgTag matches SEC_OID_SHA1.
+ * hashAlg, make sure the hashAlgTag matches SEC_OID_SHA1, otherwise we
+ * overwrite params.hashAlg with hashAlgTag..
* 3) we did not specify any parameters but we did specified
* a hashAlgTag. Use the specified hash algtag.
* 4) We have params and params.hashAlg and we did not specify a
* hashAlgTag, use the hashAlg from the parameter.
* 5) We have params, but no params.hashAlg and we did not specify a
* hashAlgTag, use the SEC_OID_SHA1
* 6) We did not specify any parameters, nor did we specify a
* hashAlgTag, use the key size to select an appropriate hashAlg.
@@ -873,36 +879,42 @@ sec_CreateRSAPSSParameters(PLArenaPool *
if (pssParams.hashAlg) {
tag = SECOID_GetAlgorithmTag(pssParams.hashAlg);
} else if (defaultSHA1) {
tag = SEC_OID_SHA1;
}
if (tag != SEC_OID_UNKNOWN && tag != hashAlgTag) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return NULL;
+ overWriteHash = PR_TRUE;
}
} else if (hashAlgTag == SEC_OID_UNKNOWN) {
if (pssParams.hashAlg) {
hashAlgTag = SECOID_GetAlgorithmTag(pssParams.hashAlg);
} else if (defaultSHA1) {
hashAlgTag = SEC_OID_SHA1;
} else {
/* Find a suitable hash algorithm based on the NIST recommendation */
if (modBytes <= 384) { /* 128, in NIST 800-57, Part 1 */
hashAlgTag = SEC_OID_SHA256;
} else if (modBytes <= 960) { /* 192, NIST 800-57, Part 1 */
hashAlgTag = SEC_OID_SHA384;
} else {
hashAlgTag = SEC_OID_SHA512;
}
+ overWriteHash = PR_TRUE;
}
}
+ /* handle the case where the params invalidly encoded SEC_OID_SHA1. This
+ * will force the correct encoding */
+ if ((hashAlgTag == SEC_OID_SHA1) && pssParams.hashAlg) {
+ overWriteHash = PR_TRUE;
+ }
+
/* explicitly restrict hashAlg to SHA2 variants */
if (hashAlgTag != SEC_OID_SHA1 && hashAlgTag != SEC_OID_SHA224 &&
hashAlgTag != SEC_OID_SHA256 && hashAlgTag != SEC_OID_SHA384 &&
hashAlgTag != SEC_OID_SHA512) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return NULL;
}
@@ -927,23 +939,24 @@ sec_CreateRSAPSSParameters(PLArenaPool *
&pssParams.maskAlg->parameters);
if (rv != SECSuccess) {
return NULL;
}
/* Following the recommendation in RFC 4055, assume the hash
* algorithm identical to pssParam.hashAlg */
if (SECOID_GetAlgorithmTag(&maskHashAlg) != hashAlgTag) {
- PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
- return NULL;
+ overWriteMask = PR_TRUE;
+ }
+ if (hashAlgTag == SEC_OID_SHA1) {
+ overWriteMask = PR_TRUE;
}
} else if (defaultSHA1) {
if (hashAlgTag != SEC_OID_SHA1) {
- PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
- return NULL;
+ overWriteMask = PR_TRUE;
}
}
hashLength = HASH_ResultLenByOidTag(hashAlgTag);
if (modBytes < hashLength + 2) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
@@ -961,42 +974,38 @@ sec_CreateRSAPSSParameters(PLArenaPool *
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
} else if (defaultSHA1) {
saltLength = 20;
}
/* Fill in the parameters */
- if (pssParams.hashAlg) {
+ if (overWriteHash) {
if (hashAlgTag == SEC_OID_SHA1) {
/* Omit hashAlg if the the algorithm is SHA-1 (default) */
pssParams.hashAlg = NULL;
- }
- } else {
- if (hashAlgTag != SEC_OID_SHA1) {
+ } else {
pssParams.hashAlg = PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID));
if (!pssParams.hashAlg) {
return NULL;
}
rv = SECOID_SetAlgorithmID(arena, pssParams.hashAlg, hashAlgTag,
NULL);
if (rv != SECSuccess) {
return NULL;
}
}
}
- if (pssParams.maskAlg) {
+ if (overWriteMask) {
if (hashAlgTag == SEC_OID_SHA1) {
/* Omit maskAlg if the the algorithm is SHA-1 (default) */
pssParams.maskAlg = NULL;
- }
- } else {
- if (hashAlgTag != SEC_OID_SHA1) {
+ } else {
SECItem *hashAlgItem;
PORT_Assert(pssParams.hashAlg != NULL);
hashAlgItem = SEC_ASN1EncodeItem(arena, NULL, pssParams.hashAlg,
SEC_ASN1_GET(SECOID_AlgorithmIDTemplate));
if (!hashAlgItem) {
return NULL;
diff --git a/tests/cert/cert.sh b/tests/cert/cert.sh
--- a/tests/cert/cert.sh
+++ b/tests/cert/cert.sh
@@ -2234,20 +2234,18 @@ EOF
# Signature: RSA-PSS (with conflicting hash algorithm)
CERTNAME="TestUser-rsa-pss7"
CU_ACTION="Generate Cert Request for $CERTNAME"
CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US"
certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" --pss -o req 2>&1
CU_ACTION="Sign ${CERTNAME}'s Request"
- RETEXPECTED=255
certu -C -c "TestCA-rsa-pss" --pss-sign -Z SHA512 -m "${CERTSERIAL}" -v 60 -d "${P_R_CADIR}" \
-i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" "$1" 2>&1
- RETEXPECTED=0
CERTSERIAL=`expr $CERTSERIAL + 1`
# Subject certificate: RSA-PSS
# Issuer certificate: RSA-PSS
# Signature: RSA-PSS (with compatible hash algorithm)
CERTNAME="TestUser-rsa-pss8"
@@ -2345,20 +2343,18 @@ EOF
# Signature: RSA-PSS (with conflicting hash algorithm, default parameters)
CERTNAME="TestUser-rsa-pss11"
CU_ACTION="Generate Cert Request for $CERTNAME"
CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US"
certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" --pss -o req 2>&1
CU_ACTION="Sign ${CERTNAME}'s Request"
- RETEXPECTED=255
certu -C -c "TestCA-rsa-pss-sha1" --pss-sign -Z SHA256 -m "${CERTSERIAL}" -v 60 -d "${P_R_CADIR}" \
-i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" "$1" 2>&1
- RETEXPECTED=0
}
cert_test_orphan_key_delete()
{
CU_ACTION="Create orphan key in serverdir"
certu -G -k ec -q nistp256 -f "${R_PWFILE}" -z ${R_NOISE_FILE} -d ${PROFILEDIR}
# Let's get the key ID of the first orphan key.
# The output of certutil -K (list keys) isn't well formatted.

View File

@ -0,0 +1,36 @@
# HG changeset patch
# User Robert Relyea <rrelyea@redhat.com>
# Date 1781629595 25200
# Tue Jun 16 10:06:35 2026 -0700
# Branch NSS_3_124_BRANCH
# Node ID b38b82d220e288befed5176cd2ebb04df5fc3317
# Parent 07371c5f55e422e28311ef00131462bcf2058882
nss-3.124-revert-hmac-pkcs12-fips-default.patch
diff --git a/cmd/pk12util/pk12util.c b/cmd/pk12util/pk12util.c
--- a/cmd/pk12util/pk12util.c
+++ b/cmd/pk12util/pk12util.c
@@ -1159,20 +1159,23 @@ main(int argc, char **argv)
if (certCipher == SEC_OID_UNKNOWN) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString);
pk12uErrno = PK12UERR_INVALIDALGORITHM;
goto done;
}
}
}
+#ifdef nodef
+ /* default to old encodings on rhel-8 and rhel-9 */
/* in FIPS mode default to encoding with pkcs5v2 for the MAC */
if (PK11_IsFIPS()) {
hash = SEC_OID_HMAC_SHA256;
}
+#endif
if (pk12util.options[opt_Mac].activated) {
char *hashString = pk12util.options[opt_Mac].arg;
hash = PKCS12U_MapHashFromString(hashString);
/* We don't support creating Mac-less pkcs 12 files */
if (hash == SEC_OID_UNKNOWN) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
SECU_PrintError(progName, "Algorithm: \"%s\"", hashString);

View File

@ -3,7 +3,7 @@
# NOTE: To avoid NVR clashes of nspr* packages:
# - reset %%{nspr_release} to 1, when updating %%{nspr_version}
# - increment %%{nspr_version}, when updating the NSS part only
%global baserelease 3
%global baserelease 4
%global nss_release %baserelease
# release number between nss and nspr are different. This typically
# happens with a new version of nss was release, but nspr was not updated
@ -151,24 +151,26 @@ Patch4: iquote.patch
Patch12: nss-signtool-format.patch
Patch20: nss-3.101-extend-db-dump-time.patch
# connect our shared library to the build root loader flags (needed for -relro)
Patch31: nss-dso-ldflags.patch
Patch21: nss-dso-ldflags.patch
# keep RHEL 8 semantics of disabling md4 and md5 even if the env variable is set
Patch32: nss-3.112-disable-md5.patch
Patch22: nss-3.112-disable-md5.patch
# dbm is disabled on RHEL9, make the man pages reflect that
%if %{with dbm}
%else
Patch33: nss-no-dbm-man-page.patch
Patch23: nss-no-dbm-man-page.patch
%endif
# not upstreamable patch...
# WARNING: Need to make this patch work before checking!!! $$$$@@@
Patch34: nss-3.71-fix-lto-gtests.patch
Patch24: nss-3.71-fix-lto-gtests.patch
# disable ech
Patch35: nss-3.124-disable-ech.patch
Patch25: nss-3.124-disable-ech.patch
# don't fail if our build machine can't access the internet
Patch36: nss-3.101-skip-ocsp-if-not-connected.patch
# dont upstream, must be after patch36 (sigh)
Patch37: nss-3.124-revert-libpkix-default.patch
Patch38: nss-3.124-no-p12-smime-policy.patch
Patch26: nss-3.101-skip-ocsp-if-not-connected.patch
# dont upstream, must be after patch26 (sigh)
Patch27: nss-3.124-revert-libpkix-default.patch
Patch28: nss-3.124-no-p12-smime-policy.patch
Patch29: nss-3.124-revert-hmac-pkcs12-fips-default.patch
Patch37: nss-3.124-allow-hash-override-pss.patch
Patch39: nss-3.79-revert-distrusted-certs.patch
Patch40: nss-3.90-dh-test-update.patch
@ -1197,6 +1199,10 @@ update-crypto-policies &> /dev/null || :
%changelog
* Tue Jun 16 2026 Bob Relyea <rrelyea@redhat.com> - 3.124.0-4
- fix pkcs12 defaults
- fix pss issues
* Tue Jun 9 2026 Bob Relyea <rrelyea@redhat.com> - 3.124.0-3
- drop crmf