Resolves: RHEL-182305

- fix pkcs12 defaults
- fix pss issues
- remove crmf
This commit is contained in:
Robert Relyea 2026-06-17 12:41:09 -07:00
parent 7b1cb71cb7
commit d0f5c81f89
2 changed files with 404 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

@ -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 2
%global baserelease 4
%global nss_release %baserelease
# use "%%global nspr_release %%[%%baserelease+n]" to handle offsets when
# release number between nss and nspr are different. This typically
@ -162,8 +162,7 @@ Patch34: nss-3.71-fix-lto-gtests.patch
Patch35: 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
# build crmf for now
Patch37: nss-3.124-enable-crmf.patch
patch37: nss-3.124-allow-hash-override-pss.patch
Patch38: nss-3.79-revert-distrusted-certs.patch
# patches that expect to be upstreamed
@ -707,7 +706,7 @@ pushd nss/tests
# nss_cycles: standard pkix upgradedb sharedb
# the full list from all.sh is:
# "cipher lowhash libpkix cert dbtests tools fips sdr crmf smime ssl ocsp merge pkits chains ec gtests ssl_gtests"
%define nss_tests "libpkix cert dbtests tools fips sdr crmf smime ssl ocsp merge pkits chains ec gtests ssl_gtests"
%define nss_tests "libpkix cert dbtests tools fips sdr smime ssl ocsp merge pkits chains ec gtests ssl_gtests"
# nss_ssl_tests: crl bypass_normal normal_bypass normal_fips fips_normal iopr policy
# nss_ssl_run: cov auth stapling stress
#
@ -813,7 +812,7 @@ install -p -m 644 %{SOURCE14} $RPM_BUILD_ROOT/%{_sysconfdir}/pki/nssdb/key4.db
install -p -m 644 %{SOURCE15} $RPM_BUILD_ROOT/%{_sysconfdir}/pki/nssdb/pkcs11.txt
# Copy the development libraries we want
for file in libcrmf.a libnssb.a libnssckfw.a
for file in libnssb.a libnssckfw.a
do
install -p -m 644 dist/${LOBJDIR}/lib/$file $RPM_BUILD_ROOT/%{_libdir}
done
@ -983,7 +982,6 @@ fi
%doc %{_mandir}/man1/vfyserv.1*
%files devel
%{_libdir}/libcrmf.a
%{_libdir}/pkgconfig/nss.pc
%{_bindir}/nss-config
%doc %{_mandir}/man1/nss-config.1*
@ -992,13 +990,9 @@ fi
%{_includedir}/nss3/cert.h
%{_includedir}/nss3/certdb.h
%{_includedir}/nss3/certt.h
%{_includedir}/nss3/cmmf.h
%{_includedir}/nss3/cmmft.h
%{_includedir}/nss3/cms.h
%{_includedir}/nss3/cmsreclist.h
%{_includedir}/nss3/cmst.h
%{_includedir}/nss3/crmf.h
%{_includedir}/nss3/crmft.h
%{_includedir}/nss3/cryptohi.h
%{_includedir}/nss3/cryptoht.h
%{_includedir}/nss3/jar-ds.h
@ -1181,6 +1175,11 @@ fi
%changelog
* Tue Jun 16 2026 Bob Relyea <rrelyea@redhat.com> - 3.124.0-4
- fix pkcs12 defaults
- fix pss issues
- remove crmf
* Tue Jun 9 2026 Bob Relyea <rrelyea@redhat.com> - 3.124.0-2
- rebase fixes
- restore mlkem aliases