From 5fabc5f7a86de3634fb98fe8104c1b365eb27190 Mon Sep 17 00:00:00 2001 From: Robert Relyea Date: Thu, 11 Jul 2024 08:39:43 -0700 Subject: [PATCH] Resolves: RHEL-46839 Rebase nss to 3.101 for Firefox 128 --- .gitignore | 1 + STAGE2-nss | 68 - cert8.db.xml | 59 - key3.db.xml | 59 - nspr-4.34-fix-coverity-loop-issue.patch | 51 + nspr-4.34-server-passive.patch | 12 + nss-3.101-add-ems-policy.patch | 107 + nss-3.101-disable-ech.patch | 81 + nss-3.101-disable-md5.patch | 81 + nss-3.101-disable_dsa.patch | 1347 ++++++++ nss-3.101-enable-kyber-policy.patch | 13 + nss-3.101-enable-sdb-tests.patch | 63 + nss-3.101-extend-db-dump-time.patch | 12 + nss-3.101-fips-indicators.patch | 190 ++ nss-3.101-fips-review.patches | 490 +++ nss-3.101-fix-rsa-policy-test.patch | 12 + nss-3.101-skip-ocsp-if-not-connected.patch | 22 + nss-3.71-camellia-pkcs12-doc.patch | 20 + nss-3.71-fix-lto-gtests.patch | 26 + nss-3.79-dbtool.patch | 3411 -------------------- nss-3.79-distrusted-certs.patch | 375 +++ nss-3.79-fips.patch | 578 ++++ nss-3.89-dangling.patch | 78 - nss-3.90-aes-gmc-indicator.patch | 42 + nss-3.90-dh-test-update.patch | 90 + nss-3.90-fips-indicators2.patch | 176 + nss-3.90-fips-safe-memset.patch | 506 +++ nss-3.90-pbkdf2-indicator.patch | 42 + nss-3.90-ppc_no_init.patch | 36 + nss-dso-ldflags.patch | 13 + nss.spec | 80 +- secmod.db.xml | 63 - sources | 3 +- 33 files changed, 4454 insertions(+), 3753 deletions(-) delete mode 100644 STAGE2-nss delete mode 100644 cert8.db.xml delete mode 100644 key3.db.xml create mode 100644 nspr-4.34-fix-coverity-loop-issue.patch create mode 100644 nspr-4.34-server-passive.patch create mode 100644 nss-3.101-add-ems-policy.patch create mode 100644 nss-3.101-disable-ech.patch create mode 100644 nss-3.101-disable-md5.patch create mode 100644 nss-3.101-disable_dsa.patch create mode 100644 nss-3.101-enable-kyber-policy.patch create mode 100644 nss-3.101-enable-sdb-tests.patch create mode 100644 nss-3.101-extend-db-dump-time.patch create mode 100644 nss-3.101-fips-indicators.patch create mode 100644 nss-3.101-fips-review.patches create mode 100644 nss-3.101-fix-rsa-policy-test.patch create mode 100644 nss-3.101-skip-ocsp-if-not-connected.patch create mode 100644 nss-3.71-camellia-pkcs12-doc.patch create mode 100644 nss-3.71-fix-lto-gtests.patch delete mode 100644 nss-3.79-dbtool.patch create mode 100644 nss-3.79-distrusted-certs.patch create mode 100644 nss-3.79-fips.patch delete mode 100644 nss-3.89-dangling.patch create mode 100644 nss-3.90-aes-gmc-indicator.patch create mode 100644 nss-3.90-dh-test-update.patch create mode 100644 nss-3.90-fips-indicators2.patch create mode 100644 nss-3.90-fips-safe-memset.patch create mode 100644 nss-3.90-pbkdf2-indicator.patch create mode 100644 nss-3.90-ppc_no_init.patch create mode 100644 nss-dso-ldflags.patch delete mode 100644 secmod.db.xml diff --git a/.gitignore b/.gitignore index 06a3531..4e7c9bd 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,4 @@ TestUser51.cert /nss-3.96-with-nspr-4.35.tar.gz /nss-3.96.1-with-nspr-4.35.tar.gz /nss-3.97-with-nspr-4.35.tar.gz +/nss-3.101-with-nspr-4.35.tar.gz diff --git a/STAGE2-nss b/STAGE2-nss deleted file mode 100644 index 3d43b92..0000000 --- a/STAGE2-nss +++ /dev/null @@ -1,68 +0,0 @@ -#requires nspr -#requires perl -#requires nss-util -#requires nss-softokn - -mcd $BUILDDIR/nss - -export BUILD_OPT=1 -export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 -export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 -export NSPR_INCLUDE_DIR=/usr/include/nspr -export NSPR_LIB_DIR=/usr/lib${SUFFIX} -export NSS_USE_SYSTEM_SQLITE=1 -export NSS_BUILD_WITHOUT_SOFTOKEN=1 -export USE_SYSTEM_SOFTOKEN=1 -export SOFTOKEN_LIB_DIR=/usr/lib${SUFFIX} -export NSSUTIL_INCLUDE_DIR=/usr/include/nss3 -export NSSUTIL_LIB_DIR=/usr/lib${SUFFIX} -export USE_SYSTEM_NSSUTIL=1 -export FREEBL_INCLUDE_DIR=/usr/include/nss3 -export FREEBL_LIB_DIR=/usr/lib${SUFFIX} -export USE_SYSTEM_FREEBL=1 -export NSS_USE_SYSTEM_FREEBL=1 -export FREEBL_NO_DEPEND=1 -export IN_TREE_FREEBL_HEADERS_FIRST=1 -export NSS_BLTEST_NOT_AVAILABLE=1 -export NSS_NO_SSL2_NO_EXPORT=1 -export NSS_ECC_MORE_THAN_SUITE_B=1 -export NSS_NO_PKCS11_BYPASS=1 -#export NSDISTMODE="copy" - -if [ "$SUFFIX" = "64" ]; then - USE_64=1 - export USE_64 -fi - -(cd $SRC/nss-3.* && mkdir -p dist/private/nss && cp nss/lib/ckfw/nssck.api dist/private/nss/) - -make -C $SRC/nss-3.*/nss/coreconf -make -C $SRC/nss-3.*/nss/lib/dbm - -# nss/nssinit.c, ssl/sslcon.c, smime/smimeutil.c and ckfw/builtins/binst.c -# need nss/verref.h which is exported privately, move it to where it can be found. -(cd $SRC/nss-3.* && mkdir -p dist/private/nss && cp -a nss/verref.h dist/private/nss/) - -make -C $SRC/nss-3.*/nss -cd $SRC/nss-3.*/nss/coreconf -make install -cd $SRC/nss-3.*/nss/lib/dbm -make install -cd $SRC/nss-3.*/nss -make install -# Copy the binary libraries we want -NSSLIBS="libnss3.so libnssckbi.so libnsspem.so libnsssysinit.so libsmime3.so libssl3.so" -# BOZO: temporarily disable FIPS140 support -#NSSLIBCHKS="libnssdbm3.chk libfreebl3.chk libsoftokn3.chk" -NSSLIBCHKS="" -# END BOZO -cd $SRC/nss-3.* -for file in $NSSLIBS $NSSLIBCHKS -do - install -p -m 755 dist/*.OBJ/lib/$file /usr/lib${SUFFIX}/ -done -# Copy the include files we want -for file in $SRC/nss-*/dist/public/nss/*.h -do - install -p -m 644 $file /usr/include/nss3/ -done diff --git a/cert8.db.xml b/cert8.db.xml deleted file mode 100644 index e82948d..0000000 --- a/cert8.db.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - -]> - - - - - &date; - Network Security Services - nss - &version; - - - - cert8.db - 5 - - - - cert8.db - Legacy NSS certificate database - - - - Description - cert8.db is an NSS certificate database. - This certificate database is in the legacy database format. Consider migrating to cert9.db and key4.db which are the new sqlite-based shared database format with support for concurrent access. - - - - - Files - /etc/pki/nssdb/cert8.db - - - - See also - cert9.db(5), key4.db(5), pkcs11.txt(5), - - - - Authors - The nss libraries were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google. - Authors: Elio Maldonado <emaldona@redhat.com>. - - - - - LICENSE - Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - - - - - - diff --git a/key3.db.xml b/key3.db.xml deleted file mode 100644 index 444d7aa..0000000 --- a/key3.db.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - -]> - - - - - &date; - Network Security Services - nss - &version; - - - - key3.db - 5 - - - - key3.db - Legacy NSS certificate database - - - - Description - key3.db is an NSS certificate database. - This is a key database in the legacy database format. Consider migrating to cert9.db and key4.db which which are the new sqlite-based shared database format with support for concurrent access. - - - - - Files - /etc/pki/nssdb/key3.db - - - - See also - cert9.db(5), key4.db(5), pkcs11.txt(5), - - - - Authors - The nss libraries were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google. - Authors: Elio Maldonado <emaldona@redhat.com>. - - - - - LICENSE - Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - - - - - - diff --git a/nspr-4.34-fix-coverity-loop-issue.patch b/nspr-4.34-fix-coverity-loop-issue.patch new file mode 100644 index 0000000..c8c4149 --- /dev/null +++ b/nspr-4.34-fix-coverity-loop-issue.patch @@ -0,0 +1,51 @@ +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; + } diff --git a/nspr-4.34-server-passive.patch b/nspr-4.34-server-passive.patch new file mode 100644 index 0000000..ed8d713 --- /dev/null +++ b/nspr-4.34-server-passive.patch @@ -0,0 +1,12 @@ +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; + diff --git a/nss-3.101-add-ems-policy.patch b/nss-3.101-add-ems-policy.patch new file mode 100644 index 0000000..6464fbc --- /dev/null +++ b/nss-3.101-add-ems-policy.patch @@ -0,0 +1,107 @@ +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 + +@@ -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; diff --git a/nss-3.101-disable-ech.patch b/nss-3.101-disable-ech.patch new file mode 100644 index 0000000..3b6e399 --- /dev/null +++ b/nss-3.101-disable-ech.patch @@ -0,0 +1,81 @@ +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 = \ + 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 +@@ -4415,17 +4415,23 @@ ssl_ClearPRCList(PRCList *list, void (*f + SECStatus + SSLExp_EnableTls13GreaseEch(PRFileDesc *fd, PRBool enabled) + { ++#ifdef notdef + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + return SECFailure; + } + ss->opt.enableTls13GreaseEch = enabled; + return SECSuccess; ++#else ++ PORT_SetError(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API); ++ return SECFailure; ++#endif + } + + SECStatus + SSLExp_SetTls13GreaseEchSize(PRFileDesc *fd, PRUint8 size) + { ++#ifdef notdef + sslSocket *ss = ssl_FindSocket(fd); + if (!ss || size == 0) { + return SECFailure; +@@ -4439,28 +4445,42 @@ SSLExp_SetTls13GreaseEchSize(PRFileDesc + ssl_Release1stHandshakeLock(ss); + + return SECSuccess; ++#else ++ PORT_SetError(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API); ++ return SECFailure; ++#endif + } + + SECStatus + SSLExp_EnableTls13BackendEch(PRFileDesc *fd, PRBool enabled) + { ++#ifdef notdef + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + return SECFailure; + } + ss->opt.enableTls13BackendEch = enabled; + return SECSuccess; ++#else ++ PORT_SetError(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API); ++ return SECFailure; ++#endif + } + + SECStatus + SSLExp_CallExtensionWriterOnEchInner(PRFileDesc *fd, PRBool enabled) + { ++#ifdef notdef + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + return SECFailure; + } + ss->opt.callExtensionWriterOnEchInner = enabled; + return SECSuccess; ++#else ++ PORT_SetError(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API); ++ return SECFailure; ++#endif + } + + SECStatus diff --git a/nss-3.101-disable-md5.patch b/nss-3.101-disable-md5.patch new file mode 100644 index 0000000..56e1c58 --- /dev/null +++ b/nss-3.101-disable-md5.patch @@ -0,0 +1,81 @@ +diff -up ./lib/pk11wrap/pk11pars.c.no_md ./lib/pk11wrap/pk11pars.c +--- ./lib/pk11wrap/pk11pars.c.no_md 2024-06-11 12:41:35.054654990 -0700 ++++ ./lib/pk11wrap/pk11pars.c 2024-06-11 12:46:25.347979894 -0700 +@@ -329,14 +329,11 @@ static const oidValDef curveOptList[] = + static const oidValDef hashOptList[] = { + /* Hashes */ + { CIPHER_NAME("MD2"), SEC_OID_MD2, +- NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME | +- NSS_USE_ALG_IN_PKCS12 }, ++ NSS_USE_ALG_IN_SMIME_LEGACY | NSS_USE_ALG_IN_PKCS12_DECRYPT }, + { CIPHER_NAME("MD4"), SEC_OID_MD4, +- NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME | +- NSS_USE_ALG_IN_PKCS12 }, ++ NSS_USE_ALG_IN_SMIME_LEGACY | NSS_USE_ALG_IN_PKCS12_DECRYPT }, + { CIPHER_NAME("MD5"), SEC_OID_MD5, +- NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME | +- NSS_USE_ALG_IN_PKCS12 }, ++ NSS_USE_ALG_IN_SMIME_LEGACY | NSS_USE_ALG_IN_PKCS12_DECRYPT }, + { CIPHER_NAME("SHA1"), SEC_OID_SHA1, + NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_SIGNATURE | NSS_USE_ALG_IN_SMIME | + NSS_USE_ALG_IN_PKCS12 }, +diff -up ./lib/util/secoid.c.no_md ./lib/util/secoid.c +diff -r 699541a7793b lib/util/secoid.c +--- a/lib/util/secoid.c Tue Jun 16 23:03:22 2020 +0000 ++++ b/lib/util/secoid.c Thu Jun 25 14:33:09 2020 +0200 +@@ -2042,6 +2042,19 @@ + int i; + + for (i = 1; i < SEC_OID_TOTAL; i++) { ++ switch (i) { ++ case SEC_OID_MD2: ++ case SEC_OID_MD4: ++ case SEC_OID_MD5: ++ case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: ++ case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: ++ case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: ++ case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: ++ case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: ++ continue; ++ default: ++ break; ++ } + 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 + # 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 ++# (decrypting is fine). To be enabled, you must allow=mdX/pkcs12 on the + # encryption side. These tests purposefully tests that the default fails to encrypt + # but succeeds when decrypting. + 27 x allow=tls 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 Use default policy with multiple hashes +- 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=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 diff --git a/nss-3.101-disable_dsa.patch b/nss-3.101-disable_dsa.patch new file mode 100644 index 0000000..d51ad50 --- /dev/null +++ b/nss-3.101-disable_dsa.patch @@ -0,0 +1,1347 @@ +diff -up ./cmd/pk11mode/pk11mode.c.disable_dsa ./cmd/pk11mode/pk11mode.c +--- ./cmd/pk11mode/pk11mode.c.disable_dsa 2024-06-17 09:39:06.137190654 -0700 ++++ ./cmd/pk11mode/pk11mode.c 2024-06-17 09:39:12.265257501 -0700 +@@ -578,7 +578,7 @@ main(int argc, char **argv) + } + + /* +- * PKM_KeyTest creates RSA,DSA public keys ++ * PKM_KeyTest creates RSA,ECDSA public keys + * and AES, DES3 secret keys. + * then does digest, hmac, encrypt/decrypt, signing operations. + */ +@@ -793,19 +793,14 @@ PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunct + + CK_RV crv = CKR_OK; + +- /*** DSA Key ***/ +- CK_MECHANISM dsaParamGenMech; +- CK_ULONG primeBits = 1024; +- CK_ATTRIBUTE dsaParamGenTemplate[1]; +- CK_OBJECT_HANDLE hDsaParams = CK_INVALID_HANDLE; +- CK_BYTE DSA_P[128]; +- CK_BYTE DSA_Q[20]; +- CK_BYTE DSA_G[128]; +- CK_MECHANISM dsaKeyPairGenMech; +- CK_ATTRIBUTE dsaPubKeyTemplate[5]; +- CK_ATTRIBUTE dsaPrivKeyTemplate[5]; +- CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE; +- CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE; ++ /*** ECDSA Key ***/ ++ CK_BYTE ECDSA_P256_PARAMS[] = ++ { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 }; ++ CK_MECHANISM ecdsaKeyPairGenMech; ++ CK_ATTRIBUTE ecdsaPubKeyTemplate[3]; ++ CK_ATTRIBUTE ecdsaPrivKeyTemplate[5]; ++ CK_OBJECT_HANDLE hECDSApubKey = CK_INVALID_HANDLE; ++ CK_OBJECT_HANDLE hECDSAprivKey = CK_INVALID_HANDLE; + + /**** RSA Key ***/ + CK_KEY_TYPE rsatype = CKK_RSA; +@@ -840,8 +835,8 @@ PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunct + CK_ATTRIBUTE sDES3KeyTemplate[9]; + CK_OBJECT_HANDLE hDES3SecKey; + +- CK_MECHANISM dsaWithSha1Mech = { +- CKM_DSA_SHA1, NULL, 0 ++ CK_MECHANISM ecdsaWithSha256Mech = { ++ CKM_ECDSA_SHA256, NULL, 0 + }; + + CK_BYTE IV[16]; +@@ -888,45 +883,33 @@ PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunct + NUMTESTS++; /* increment NUMTESTS */ + + /* DSA key init */ +- dsaParamGenMech.mechanism = CKM_DSA_PARAMETER_GEN; +- dsaParamGenMech.pParameter = NULL_PTR; +- dsaParamGenMech.ulParameterLen = 0; +- dsaParamGenTemplate[0].type = CKA_PRIME_BITS; +- dsaParamGenTemplate[0].pValue = &primeBits; +- dsaParamGenTemplate[0].ulValueLen = sizeof(primeBits); +- dsaPubKeyTemplate[0].type = CKA_PRIME; +- dsaPubKeyTemplate[0].pValue = DSA_P; +- dsaPubKeyTemplate[0].ulValueLen = sizeof(DSA_P); +- dsaPubKeyTemplate[1].type = CKA_SUBPRIME; +- dsaPubKeyTemplate[1].pValue = DSA_Q; +- dsaPubKeyTemplate[1].ulValueLen = sizeof(DSA_Q); +- dsaPubKeyTemplate[2].type = CKA_BASE; +- dsaPubKeyTemplate[2].pValue = DSA_G; +- dsaPubKeyTemplate[2].ulValueLen = sizeof(DSA_G); +- dsaPubKeyTemplate[3].type = CKA_TOKEN; +- dsaPubKeyTemplate[3].pValue = &true; +- dsaPubKeyTemplate[3].ulValueLen = sizeof(true); +- dsaPubKeyTemplate[4].type = CKA_VERIFY; +- dsaPubKeyTemplate[4].pValue = &true; +- dsaPubKeyTemplate[4].ulValueLen = sizeof(true); +- dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN; +- dsaKeyPairGenMech.pParameter = NULL_PTR; +- dsaKeyPairGenMech.ulParameterLen = 0; +- dsaPrivKeyTemplate[0].type = CKA_TOKEN; +- dsaPrivKeyTemplate[0].pValue = &true; +- dsaPrivKeyTemplate[0].ulValueLen = sizeof(true); +- dsaPrivKeyTemplate[1].type = CKA_PRIVATE; +- dsaPrivKeyTemplate[1].pValue = &true; +- dsaPrivKeyTemplate[1].ulValueLen = sizeof(true); +- dsaPrivKeyTemplate[2].type = CKA_SENSITIVE; +- dsaPrivKeyTemplate[2].pValue = &true; +- dsaPrivKeyTemplate[2].ulValueLen = sizeof(true); +- dsaPrivKeyTemplate[3].type = CKA_SIGN, +- dsaPrivKeyTemplate[3].pValue = &true; +- dsaPrivKeyTemplate[3].ulValueLen = sizeof(true); +- dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE; +- dsaPrivKeyTemplate[4].pValue = &true; +- dsaPrivKeyTemplate[4].ulValueLen = sizeof(true); ++ ecdsaPubKeyTemplate[0].type = CKA_EC_PARAMS; ++ ecdsaPubKeyTemplate[0].pValue = ECDSA_P256_PARAMS; ++ ecdsaPubKeyTemplate[0].ulValueLen = sizeof(ECDSA_P256_PARAMS); ++ ecdsaPubKeyTemplate[1].type = CKA_TOKEN; ++ ecdsaPubKeyTemplate[1].pValue = &true; ++ ecdsaPubKeyTemplate[1].ulValueLen = sizeof(true); ++ ecdsaPubKeyTemplate[2].type = CKA_VERIFY; ++ ecdsaPubKeyTemplate[2].pValue = &true; ++ ecdsaPubKeyTemplate[2].ulValueLen = sizeof(true); ++ ecdsaKeyPairGenMech.mechanism = CKM_ECDSA_KEY_PAIR_GEN; ++ ecdsaKeyPairGenMech.pParameter = NULL_PTR; ++ ecdsaKeyPairGenMech.ulParameterLen = 0; ++ ecdsaPrivKeyTemplate[0].type = CKA_TOKEN; ++ ecdsaPrivKeyTemplate[0].pValue = &true; ++ ecdsaPrivKeyTemplate[0].ulValueLen = sizeof(true); ++ ecdsaPrivKeyTemplate[1].type = CKA_PRIVATE; ++ ecdsaPrivKeyTemplate[1].pValue = &true; ++ ecdsaPrivKeyTemplate[1].ulValueLen = sizeof(true); ++ ecdsaPrivKeyTemplate[2].type = CKA_SENSITIVE; ++ ecdsaPrivKeyTemplate[2].pValue = &true; ++ ecdsaPrivKeyTemplate[2].ulValueLen = sizeof(true); ++ ecdsaPrivKeyTemplate[3].type = CKA_SIGN, ++ ecdsaPrivKeyTemplate[3].pValue = &true; ++ ecdsaPrivKeyTemplate[3].ulValueLen = sizeof(true); ++ ecdsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE; ++ ecdsaPrivKeyTemplate[4].pValue = &true; ++ ecdsaPrivKeyTemplate[4].ulValueLen = sizeof(true); + + /* RSA key init */ + rsaKeyPairGenMech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; +@@ -1148,52 +1131,18 @@ PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunct + return crv; + } + +- PKM_LogIt("Generate DSA PQG domain parameters ... \n"); +- /* Generate DSA domain parameters PQG */ +- crv = pFunctionList->C_GenerateKey(hRwSession, &dsaParamGenMech, +- dsaParamGenTemplate, +- 1, +- &hDsaParams); ++ PKM_LogIt("Generate a ECDSA key pair ... \n"); ++ /* Generate a persistent ECDSA key pair */ ++ crv = pFunctionList->C_GenerateKeyPair(hRwSession, &ecdsaKeyPairGenMech, ++ ecdsaPubKeyTemplate, ++ NUM_ELEM(ecdsaPubKeyTemplate), ++ ecdsaPrivKeyTemplate, ++ NUM_ELEM(ecdsaPrivKeyTemplate), ++ &hECDSApubKey, &hECDSAprivKey); + if (crv == CKR_OK) { +- PKM_LogIt("DSA domain parameter generation succeeded\n"); ++ PKM_LogIt("ECDSA key pair generation succeeded\n"); + } else { +- PKM_Error("DSA domain parameter generation failed " +- "with 0x%08X, %-26s\n", +- crv, PKM_CK_RVtoStr(crv)); +- return crv; +- } +- crv = pFunctionList->C_GetAttributeValue(hRwSession, hDsaParams, +- dsaPubKeyTemplate, 3); +- if (crv == CKR_OK) { +- PKM_LogIt("Getting DSA domain parameters succeeded\n"); +- } else { +- PKM_Error("Getting DSA domain parameters failed " +- "with 0x%08X, %-26s\n", +- crv, PKM_CK_RVtoStr(crv)); +- return crv; +- } +- crv = pFunctionList->C_DestroyObject(hRwSession, hDsaParams); +- if (crv == CKR_OK) { +- PKM_LogIt("Destroying DSA domain parameters succeeded\n"); +- } else { +- PKM_Error("Destroying DSA domain parameters failed " +- "with 0x%08X, %-26s\n", +- crv, PKM_CK_RVtoStr(crv)); +- return crv; +- } +- +- PKM_LogIt("Generate a DSA key pair ... \n"); +- /* Generate a persistent DSA key pair */ +- crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech, +- dsaPubKeyTemplate, +- NUM_ELEM(dsaPubKeyTemplate), +- dsaPrivKeyTemplate, +- NUM_ELEM(dsaPrivKeyTemplate), +- &hDSApubKey, &hDSAprivKey); +- if (crv == CKR_OK) { +- PKM_LogIt("DSA key pair generation succeeded\n"); +- } else { +- PKM_Error("DSA key pair generation failed " ++ PKM_Error("ECDSA key pair generation failed " + "with 0x%08X, %-26s\n", + crv, PKM_CK_RVtoStr(crv)); + return crv; +@@ -1414,10 +1363,10 @@ PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunct + } /* end of RSA for loop */ + + crv = PKM_PubKeySign(pFunctionList, hRwSession, +- hDSApubKey, hDSAprivKey, +- &dsaWithSha1Mech, PLAINTEXT, sizeof(PLAINTEXT)); ++ hECDSApubKey, hECDSAprivKey, ++ &ecdsaWithSha256Mech, PLAINTEXT, sizeof(PLAINTEXT)); + if (crv == CKR_OK) { +- PKM_LogIt("PKM_PubKeySign for DSAwithSHA1 succeeded \n\n"); ++ PKM_LogIt("PKM_PubKeySign for ECDSAwithSHA256 succeeded \n\n"); + } else { + PKM_Error("PKM_PubKeySign failed " + "with 0x%08X, %-26s\n", +@@ -1425,8 +1374,8 @@ PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunct + return crv; + } + crv = PKM_DualFuncSign(pFunctionList, hRwSession, +- hDSApubKey, hDSAprivKey, +- &dsaWithSha1Mech, ++ hECDSApubKey, hECDSAprivKey, ++ &ecdsaWithSha256Mech, + hAESSecKey, &mech_AES_CBC, + PLAINTEXT, sizeof(PLAINTEXT)); + if (crv == CKR_OK) { +@@ -1439,44 +1388,44 @@ PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunct + return crv; + } + crv = PKM_DualFuncSign(pFunctionList, hRwSession, +- hDSApubKey, hDSAprivKey, +- &dsaWithSha1Mech, ++ hECDSApubKey, hECDSAprivKey, ++ &ecdsaWithSha256Mech, + hDES3SecKey, &mech_DES3_CBC, + PLAINTEXT, sizeof(PLAINTEXT)); + if (crv == CKR_OK) { + PKM_LogIt("PKM_DualFuncSign with DES3 secret key succeeded " +- "for DSAWithSHA1\n\n"); ++ "for ECDSAWithSHA256\n\n"); + } else { + PKM_Error("PKM_DualFuncSign with DES3 secret key failed " +- "for DSAWithSHA1 with 0x%08X, %-26s\n", ++ "for ECDSAWithSHA256 with 0x%08X, %-26s\n", + crv, PKM_CK_RVtoStr(crv)); + return crv; + } + crv = PKM_DualFuncSign(pFunctionList, hRwSession, +- hDSApubKey, hDSAprivKey, +- &dsaWithSha1Mech, ++ hECDSApubKey, hECDSAprivKey, ++ &ecdsaWithSha256Mech, + hAESSecKey, &mech_AES_CBC_PAD, + PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD)); + if (crv == CKR_OK) { + PKM_LogIt("PKM_DualFuncSign with AES secret key CBC_PAD succeeded " +- "for DSAWithSHA1\n\n"); ++ "for DSAWithSHA256\n\n"); + } else { + PKM_Error("PKM_DualFuncSign with AES secret key CBC_PAD failed " +- "for DSAWithSHA1 with 0x%08X, %-26s\n", ++ "for DSAWithSHA256 with 0x%08X, %-26s\n", + crv, PKM_CK_RVtoStr(crv)); + return crv; + } + crv = PKM_DualFuncSign(pFunctionList, hRwSession, +- hDSApubKey, hDSAprivKey, +- &dsaWithSha1Mech, ++ hECDSApubKey, hECDSAprivKey, ++ &ecdsaWithSha256Mech, + hDES3SecKey, &mech_DES3_CBC_PAD, + PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD)); + if (crv == CKR_OK) { + PKM_LogIt("PKM_DualFuncSign with DES3 secret key CBC_PAD succeeded " +- "for DSAWithSHA1\n\n"); ++ "for ECDSAWithSHA256\n\n"); + } else { + PKM_Error("PKM_DualFuncSign with DES3 secret key CBC_PAD failed " +- "for DSAWithSHA1 with 0x%08X, %-26s\n", ++ "for ECDSAWithSHA256 with 0x%08X, %-26s\n", + crv, PKM_CK_RVtoStr(crv)); + return crv; + } +@@ -3029,7 +2978,7 @@ PKM_PubKeySign(CK_FUNCTION_LIST_PTR pFun + } + + /* Check that the mechanism is Multi-part */ +- if (signMech->mechanism == CKM_DSA || ++ if (signMech->mechanism == CKM_ECDSA || + signMech->mechanism == CKM_RSA_PKCS) { + return crv; + } +@@ -3083,6 +3032,7 @@ PKM_PubKeySign(CK_FUNCTION_LIST_PTR pFun + return crv; + } + ++#define SHA256_LENGTH 32 + CK_RV + PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunctionList, + CK_SLOT_ID *pSlotList, +@@ -3092,19 +3042,14 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + CK_SESSION_HANDLE hSession; + CK_RV crv = CKR_OK; + +- /*** DSA Key ***/ +- CK_MECHANISM dsaParamGenMech; +- CK_ULONG primeBits = 1024; +- CK_ATTRIBUTE dsaParamGenTemplate[1]; +- CK_OBJECT_HANDLE hDsaParams = CK_INVALID_HANDLE; +- CK_BYTE DSA_P[128]; +- CK_BYTE DSA_Q[20]; +- CK_BYTE DSA_G[128]; +- CK_MECHANISM dsaKeyPairGenMech; +- CK_ATTRIBUTE dsaPubKeyTemplate[5]; +- CK_ATTRIBUTE dsaPrivKeyTemplate[5]; +- CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE; +- CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE; ++ /*** ECDSA Key ***/ ++ CK_MECHANISM ecdsaKeyPairGenMech; ++ CK_ATTRIBUTE ecdsaPubKeyTemplate[3]; ++ CK_ATTRIBUTE ecdsaPrivKeyTemplate[5]; ++ CK_OBJECT_HANDLE hECDSApubKey = CK_INVALID_HANDLE; ++ CK_OBJECT_HANDLE hECDSAprivKey = CK_INVALID_HANDLE; ++ CK_BYTE ECDSA_P256_PARAMS[] = ++ { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 }; + + /* From SHA1ShortMsg.req, Len = 136 */ + CK_BYTE MSG[] = { +@@ -3115,69 +3060,57 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + 0x44 + }; + CK_BYTE MD[] = { +- 0xf7, 0x5d, 0x92, 0xa4, +- 0xbb, 0x4d, 0xec, 0xc3, +- 0x7c, 0x5c, 0x72, 0xfa, +- 0x04, 0x75, 0x71, 0x0a, +- 0x06, 0x75, 0x8c, 0x1d ++ 0x88, 0x78, 0xe1, 0x1e, ++ 0x63, 0x74, 0xa9, 0xd9, ++ 0x90, 0xd0, 0xeb, 0x2c, ++ 0xeb, 0x62, 0x2b, 0x04, ++ 0x53, 0x9f, 0xa0, 0xfc + }; + +- CK_BYTE sha1Digest[20]; +- CK_ULONG sha1DigestLen; +- CK_BYTE dsaSig[40]; +- CK_ULONG dsaSigLen; +- CK_MECHANISM sha1Mech = { +- CKM_SHA_1, NULL, 0 ++ CK_BYTE sha256Digest[SHA256_LENGTH]; ++ CK_ULONG sha256DigestLen; ++ CK_BYTE ecdsaSig[SHA256_LENGTH*2+1]; ++ CK_ULONG ecdsaSigLen; ++ CK_MECHANISM sha256Mech = { ++ CKM_SHA256, NULL, 0 + }; +- CK_MECHANISM dsaMech = { +- CKM_DSA, NULL, 0 ++ CK_MECHANISM ecdsaMech = { ++ CKM_ECDSA, NULL, 0 + }; +- CK_MECHANISM dsaWithSha1Mech = { +- CKM_DSA_SHA1, NULL, 0 ++ CK_MECHANISM ecdsaWithSha256Mech = { ++ CKM_ECDSA_SHA256, NULL, 0 + }; + + NUMTESTS++; /* increment NUMTESTS */ + +- /* DSA key init */ +- dsaParamGenMech.mechanism = CKM_DSA_PARAMETER_GEN; +- dsaParamGenMech.pParameter = NULL_PTR; +- dsaParamGenMech.ulParameterLen = 0; +- dsaParamGenTemplate[0].type = CKA_PRIME_BITS; +- dsaParamGenTemplate[0].pValue = &primeBits; +- dsaParamGenTemplate[0].ulValueLen = sizeof(primeBits); +- dsaPubKeyTemplate[0].type = CKA_PRIME; +- dsaPubKeyTemplate[0].pValue = DSA_P; +- dsaPubKeyTemplate[0].ulValueLen = sizeof(DSA_P); +- dsaPubKeyTemplate[1].type = CKA_SUBPRIME; +- dsaPubKeyTemplate[1].pValue = DSA_Q; +- dsaPubKeyTemplate[1].ulValueLen = sizeof(DSA_Q); +- dsaPubKeyTemplate[2].type = CKA_BASE; +- dsaPubKeyTemplate[2].pValue = DSA_G; +- dsaPubKeyTemplate[2].ulValueLen = sizeof(DSA_G); +- dsaPubKeyTemplate[3].type = CKA_TOKEN; +- dsaPubKeyTemplate[3].pValue = &true; +- dsaPubKeyTemplate[3].ulValueLen = sizeof(true); +- dsaPubKeyTemplate[4].type = CKA_VERIFY; +- dsaPubKeyTemplate[4].pValue = &true; +- dsaPubKeyTemplate[4].ulValueLen = sizeof(true); +- dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN; +- dsaKeyPairGenMech.pParameter = NULL_PTR; +- dsaKeyPairGenMech.ulParameterLen = 0; +- dsaPrivKeyTemplate[0].type = CKA_TOKEN; +- dsaPrivKeyTemplate[0].pValue = &true; +- dsaPrivKeyTemplate[0].ulValueLen = sizeof(true); +- dsaPrivKeyTemplate[1].type = CKA_PRIVATE; +- dsaPrivKeyTemplate[1].pValue = &true; +- dsaPrivKeyTemplate[1].ulValueLen = sizeof(true); +- dsaPrivKeyTemplate[2].type = CKA_SENSITIVE; +- dsaPrivKeyTemplate[2].pValue = &true; +- dsaPrivKeyTemplate[2].ulValueLen = sizeof(true); +- dsaPrivKeyTemplate[3].type = CKA_SIGN, +- dsaPrivKeyTemplate[3].pValue = &true; +- dsaPrivKeyTemplate[3].ulValueLen = sizeof(true); +- dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE; +- dsaPrivKeyTemplate[4].pValue = &true; +- dsaPrivKeyTemplate[4].ulValueLen = sizeof(true); ++ /* ECDSA key init */ ++ ecdsaPubKeyTemplate[0].type = CKA_EC_PARAMS; ++ ecdsaPubKeyTemplate[0].pValue = ECDSA_P256_PARAMS; ++ ecdsaPubKeyTemplate[0].ulValueLen = sizeof(ECDSA_P256_PARAMS); ++ ecdsaPubKeyTemplate[1].type = CKA_TOKEN; ++ ecdsaPubKeyTemplate[1].pValue = &true; ++ ecdsaPubKeyTemplate[1].ulValueLen = sizeof(true); ++ ecdsaPubKeyTemplate[2].type = CKA_VERIFY; ++ ecdsaPubKeyTemplate[2].pValue = &true; ++ ecdsaPubKeyTemplate[2].ulValueLen = sizeof(true); ++ ecdsaKeyPairGenMech.mechanism = CKM_ECDSA_KEY_PAIR_GEN; ++ ecdsaKeyPairGenMech.pParameter = NULL_PTR; ++ ecdsaKeyPairGenMech.ulParameterLen = 0; ++ ecdsaPrivKeyTemplate[0].type = CKA_TOKEN; ++ ecdsaPrivKeyTemplate[0].pValue = &true; ++ ecdsaPrivKeyTemplate[0].ulValueLen = sizeof(true); ++ ecdsaPrivKeyTemplate[1].type = CKA_PRIVATE; ++ ecdsaPrivKeyTemplate[1].pValue = &true; ++ ecdsaPrivKeyTemplate[1].ulValueLen = sizeof(true); ++ ecdsaPrivKeyTemplate[2].type = CKA_SENSITIVE; ++ ecdsaPrivKeyTemplate[2].pValue = &true; ++ ecdsaPrivKeyTemplate[2].ulValueLen = sizeof(true); ++ ecdsaPrivKeyTemplate[3].type = CKA_SIGN, ++ ecdsaPrivKeyTemplate[3].pValue = &true; ++ ecdsaPrivKeyTemplate[3].ulValueLen = sizeof(true); ++ ecdsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE; ++ ecdsaPrivKeyTemplate[4].pValue = &true; ++ ecdsaPrivKeyTemplate[4].ulValueLen = sizeof(true); + + crv = pFunctionList->C_OpenSession(pSlotList[slotID], + CKF_RW_SESSION | CKF_SERIAL_SESSION, +@@ -3198,88 +3131,60 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + return crv; + } + +- PKM_LogIt("Generate DSA PQG domain parameters ... \n"); +- /* Generate DSA domain parameters PQG */ +- crv = pFunctionList->C_GenerateKey(hSession, &dsaParamGenMech, +- dsaParamGenTemplate, +- 1, +- &hDsaParams); +- if (crv == CKR_OK) { +- PKM_LogIt("DSA domain parameter generation succeeded\n"); +- } else { +- PKM_Error("DSA domain parameter generation failed " +- "with 0x%08X, %-26s\n", +- crv, PKM_CK_RVtoStr(crv)); +- return crv; +- } +- crv = pFunctionList->C_GetAttributeValue(hSession, hDsaParams, +- dsaPubKeyTemplate, 3); +- if (crv == CKR_OK) { +- PKM_LogIt("Getting DSA domain parameters succeeded\n"); +- } else { +- PKM_Error("Getting DSA domain parameters failed " +- "with 0x%08X, %-26s\n", +- crv, PKM_CK_RVtoStr(crv)); +- return crv; +- } +- crv = pFunctionList->C_DestroyObject(hSession, hDsaParams); +- if (crv == CKR_OK) { +- PKM_LogIt("Destroying DSA domain parameters succeeded\n"); +- } else { +- PKM_Error("Destroying DSA domain parameters failed " +- "with 0x%08X, %-26s\n", +- crv, PKM_CK_RVtoStr(crv)); +- return crv; +- } +- +- PKM_LogIt("Generate a DSA key pair ... \n"); +- /* Generate a persistent DSA key pair */ +- crv = pFunctionList->C_GenerateKeyPair(hSession, &dsaKeyPairGenMech, +- dsaPubKeyTemplate, +- NUM_ELEM(dsaPubKeyTemplate), +- dsaPrivKeyTemplate, +- NUM_ELEM(dsaPrivKeyTemplate), +- &hDSApubKey, &hDSAprivKey); ++ PKM_LogIt("Generate a ECDSA key pair ... \n"); ++ /* Generate a persistent ECDSA key pair */ ++ crv = pFunctionList->C_GenerateKeyPair(hSession, &ecdsaKeyPairGenMech, ++ ecdsaPubKeyTemplate, ++ NUM_ELEM(ecdsaPubKeyTemplate), ++ ecdsaPrivKeyTemplate, ++ NUM_ELEM(ecdsaPrivKeyTemplate), ++ &hECDSApubKey, &hECDSAprivKey); + if (crv == CKR_OK) { +- PKM_LogIt("DSA key pair generation succeeded\n"); ++ PKM_LogIt("ECDSA key pair generation succeeded\n"); + } else { +- PKM_Error("DSA key pair generation failed " ++ PKM_Error("ECDSA key pair generation failed " + "with 0x%08X, %-26s\n", + crv, PKM_CK_RVtoStr(crv)); + return crv; + } + + /* Compute SHA-1 digest */ +- crv = pFunctionList->C_DigestInit(hSession, &sha1Mech); ++ crv = pFunctionList->C_DigestInit(hSession, &sha256Mech); + if (crv != CKR_OK) { + PKM_Error("C_DigestInit failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); + return crv; + } +- sha1DigestLen = sizeof(sha1Digest); ++ sha256DigestLen = sizeof(sha256Digest); + crv = pFunctionList->C_Digest(hSession, MSG, sizeof(MSG), +- sha1Digest, &sha1DigestLen); ++ sha256Digest, &sha256DigestLen); + if (crv != CKR_OK) { + PKM_Error("C_Digest failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); + return crv; + } +- if (sha1DigestLen != sizeof(sha1Digest)) { +- PKM_Error("sha1DigestLen is %lu\n", sha1DigestLen); ++ if (sha256DigestLen != sizeof(sha256Digest)) { ++ PKM_Error("sha1DigestLen is %lu\n", sha256DigestLen); + return crv; + } + +- if (memcmp(sha1Digest, MD, sizeof(MD)) == 0) { +- PKM_LogIt("SHA-1 SHA1ShortMsg test case Len = 136 passed\n"); ++ if (memcmp(sha256Digest, MD, sizeof(MD)) == 0) { ++ PKM_LogIt("SHA-256 SHA256ShortMsg test case Len = 136 passed\n"); + } else { +- PKM_Error("SHA-1 SHA1ShortMsg test case Len = 136 failed\n"); ++ int i; ++ PKM_Error("SHA-256 SHA256ShortMsg test case Len = 136 failed\n"); ++ fprintf(stderr, "sha256Digest: "); ++ for (i=0; i < sizeof(MD); i++) fprintf(stderr, " 0x%02x", sha256Digest[i]); ++ fprintf(stderr, "\nMD: "); ++ for (i=0; i < sizeof(MD); i++) fprintf(stderr, " 0x%02x", MD[i]); ++ fprintf(stderr, "\n"); + } + + crv = PKM_PubKeySign(pFunctionList, hSession, +- hDSApubKey, hDSAprivKey, +- &dsaMech, sha1Digest, sizeof(sha1Digest)); ++ hECDSApubKey, hECDSAprivKey, ++ &ecdsaMech, sha256Digest, sizeof(sha256Digest)); + if (crv == CKR_OK) { +- PKM_LogIt("PKM_PubKeySign CKM_DSA succeeded \n"); ++ PKM_LogIt("PKM_PubKeySign CKM_ECDSA succeeded \n"); + } else { + PKM_Error("PKM_PubKeySign failed " + "with 0x%08X, %-26s\n", +@@ -3287,10 +3192,10 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + return crv; + } + crv = PKM_PubKeySign(pFunctionList, hSession, +- hDSApubKey, hDSAprivKey, +- &dsaWithSha1Mech, PLAINTEXT, sizeof(PLAINTEXT)); ++ hECDSApubKey, hECDSAprivKey, ++ &ecdsaWithSha256Mech, PLAINTEXT, sizeof(PLAINTEXT)); + if (crv == CKR_OK) { +- PKM_LogIt("PKM_PubKeySign CKM_DSA_SHA1 succeeded \n"); ++ PKM_LogIt("PKM_PubKeySign CKM_DSA_SHA256 succeeded \n"); + } else { + PKM_Error("PKM_PubKeySign failed " + "with 0x%08X, %-26s\n", +@@ -3298,16 +3203,16 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + return crv; + } + +- /* Sign with DSA */ +- crv = pFunctionList->C_SignInit(hSession, &dsaMech, hDSAprivKey); ++ /* Sign with ECDSA */ ++ crv = pFunctionList->C_SignInit(hSession, &ecdsaMech, hECDSAprivKey); + if (crv != CKR_OK) { + PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); + return crv; + } +- dsaSigLen = sizeof(dsaSig); +- crv = pFunctionList->C_Sign(hSession, sha1Digest, sha1DigestLen, +- dsaSig, &dsaSigLen); ++ ecdsaSigLen = sizeof(ecdsaSig); ++ crv = pFunctionList->C_Sign(hSession, sha256Digest, sha256DigestLen, ++ ecdsaSig, &ecdsaSigLen); + if (crv != CKR_OK) { + PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); +@@ -3315,14 +3220,14 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + } + + /* Verify the DSA signature */ +- crv = pFunctionList->C_VerifyInit(hSession, &dsaMech, hDSApubKey); ++ crv = pFunctionList->C_VerifyInit(hSession, &ecdsaMech, hECDSApubKey); + if (crv != CKR_OK) { + PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); + return crv; + } +- crv = pFunctionList->C_Verify(hSession, sha1Digest, sha1DigestLen, +- dsaSig, dsaSigLen); ++ crv = pFunctionList->C_Verify(hSession, sha256Digest, sha256DigestLen, ++ ecdsaSig, ecdsaSigLen); + if (crv == CKR_OK) { + PKM_LogIt("C_Verify succeeded\n"); + } else { +@@ -3332,8 +3237,8 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + } + + /* Verify the signature in a different way */ +- crv = pFunctionList->C_VerifyInit(hSession, &dsaWithSha1Mech, +- hDSApubKey); ++ crv = pFunctionList->C_VerifyInit(hSession, &ecdsaWithSha256Mech, ++ hECDSApubKey); + if (crv != CKR_OK) { + PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); +@@ -3351,7 +3256,7 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + PKM_CK_RVtoStr(crv)); + return crv; + } +- crv = pFunctionList->C_VerifyFinal(hSession, dsaSig, dsaSigLen); ++ crv = pFunctionList->C_VerifyFinal(hSession, ecdsaSig, ecdsaSigLen); + if (crv == CKR_OK) { + PKM_LogIt("C_VerifyFinal succeeded\n"); + } else { +@@ -3361,8 +3266,8 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + } + + /* Verify the signature in a different way */ +- crv = pFunctionList->C_VerifyInit(hSession, &dsaWithSha1Mech, +- hDSApubKey); ++ crv = pFunctionList->C_VerifyInit(hSession, &ecdsaWithSha256Mech, ++ hECDSApubKey); + if (crv != CKR_OK) { + PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", + crv, PKM_CK_RVtoStr(crv)); +@@ -3380,7 +3285,7 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + crv, PKM_CK_RVtoStr(crv)); + return crv; + } +- crv = pFunctionList->C_VerifyFinal(hSession, dsaSig, dsaSigLen); ++ crv = pFunctionList->C_VerifyFinal(hSession, ecdsaSig, ecdsaSigLen); + if (crv == CKR_OK) { + PKM_LogIt("C_VerifyFinal of multi update succeeded.\n"); + } else { +@@ -3391,28 +3296,28 @@ PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunc + /* Now modify the data */ + MSG[0] += 1; + /* Compute SHA-1 digest */ +- crv = pFunctionList->C_DigestInit(hSession, &sha1Mech); ++ crv = pFunctionList->C_DigestInit(hSession, &sha256Mech); + if (crv != CKR_OK) { + PKM_Error("C_DigestInit failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); + return crv; + } +- sha1DigestLen = sizeof(sha1Digest); ++ sha256DigestLen = sizeof(sha256Digest); + crv = pFunctionList->C_Digest(hSession, MSG, sizeof(MSG), +- sha1Digest, &sha1DigestLen); ++ sha256Digest, &sha256DigestLen); + if (crv != CKR_OK) { + PKM_Error("C_Digest failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); + return crv; + } +- crv = pFunctionList->C_VerifyInit(hSession, &dsaMech, hDSApubKey); ++ crv = pFunctionList->C_VerifyInit(hSession, &ecdsaMech, hECDSApubKey); + if (crv != CKR_OK) { + PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv, + PKM_CK_RVtoStr(crv)); + return crv; + } +- crv = pFunctionList->C_Verify(hSession, sha1Digest, sha1DigestLen, +- dsaSig, dsaSigLen); ++ crv = pFunctionList->C_Verify(hSession, sha256Digest, sha256DigestLen, ++ ecdsaSig, ecdsaSigLen); + if (crv != CKR_SIGNATURE_INVALID) { + PKM_Error("C_Verify of modified data succeeded\n"); + return crv; +@@ -5020,7 +4925,7 @@ PKM_DualFuncSign(CK_FUNCTION_LIST_PTR pF + NUMTESTS++; /* increment NUMTESTS */ + + /* Check that the mechanism is Multi-part */ +- if (sigMech->mechanism == CKM_DSA || sigMech->mechanism == CKM_RSA_PKCS) { ++ if (sigMech->mechanism == CKM_ECDSA || sigMech->mechanism == CKM_RSA_PKCS) { + PKM_Error("PKM_DualFuncSign must be called with a Multi-part " + "operation mechanism\n"); + return CKR_DEVICE_ERROR; +diff -up ./coreconf/config.mk.disable_dsa ./coreconf/config.mk +--- ./coreconf/config.mk.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./coreconf/config.mk 2024-06-17 09:38:50.438019407 -0700 +@@ -183,6 +183,10 @@ ifdef NSS_DISABLE_DBM + DEFINES += -DNSS_DISABLE_DBM + endif + ++ifdef NSS_DISABLE_DSA ++DEFINES += -DNSS_DISABLE_DSA ++endif ++ + ifdef NSS_DISABLE_AVX2 + DEFINES += -DNSS_DISABLE_AVX2 + endif +diff -up ./gtests/pk11_gtest/manifest.mn.disable_dsa ./gtests/pk11_gtest/manifest.mn +--- ./gtests/pk11_gtest/manifest.mn.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/pk11_gtest/manifest.mn 2024-06-17 09:38:50.438019407 -0700 +@@ -6,6 +6,10 @@ CORE_DEPTH = ../.. + DEPTH = ../.. + MODULE = nss + ++ifndef NSS_DISABLE_DSA ++ DSA_UNIT_TESTS=pk11_dsa_unittest.cc ++endif ++ + CPPSRCS = \ + json_reader.cc \ + pk11_aes_gcm_unittest.cc \ +@@ -17,7 +21,7 @@ CPPSRCS = \ + pk11_curve25519_unittest.cc \ + pk11_der_private_key_import_unittest.cc \ + pk11_des_unittest.cc \ +- pk11_dsa_unittest.cc \ ++ ${DSA_UNIT_TESTS} \ + pk11_ecdsa_unittest.cc \ + pk11_eddsa_unittest.cc \ + pk11_ecdh_unittest.cc \ +diff -up ./gtests/pk11_gtest/pk11_import_unittest.cc.disable_dsa ./gtests/pk11_gtest/pk11_import_unittest.cc +--- ./gtests/pk11_gtest/pk11_import_unittest.cc.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/pk11_gtest/pk11_import_unittest.cc 2024-06-17 09:38:50.438019407 -0700 +@@ -261,7 +261,9 @@ TEST_P(Pk11KeyImportTest, GenerateExport + + INSTANTIATE_TEST_SUITE_P(Pk11KeyImportTest, Pk11KeyImportTest, + ::testing::Values(CKM_RSA_PKCS_KEY_PAIR_GEN, ++#ifndef NSS_DISABLE_DSA + CKM_DSA_KEY_PAIR_GEN, ++#endif + CKM_DH_PKCS_KEY_PAIR_GEN)); + + class Pk11KeyImportTestEC : public Pk11KeyImportTestBase, +diff -up ./gtests/ssl_gtest/ssl_auth_unittest.cc.disable_dsa ./gtests/ssl_gtest/ssl_auth_unittest.cc +--- ./gtests/ssl_gtest/ssl_auth_unittest.cc.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_auth_unittest.cc 2024-06-17 09:38:50.438019407 -0700 +@@ -532,6 +532,7 @@ TEST_P(TlsConnectTls12, AutoClientSelect + EXPECT_TRUE(ecc.hookCalled); + } + ++#ifndef NSS_DISABLE_DSA + TEST_P(TlsConnectTls12, AutoClientSelectDsa) { + AutoClientResults dsa = {{SECFailure, TlsAgent::kClient}, + {SECFailure, TlsAgent::kClient}, +@@ -548,6 +549,7 @@ TEST_P(TlsConnectTls12, AutoClientSelect + Connect(); + EXPECT_TRUE(dsa.hookCalled); + } ++#endif + + TEST_P(TlsConnectClientAuthStream13, PostHandshakeAuthMultiple) { + client_->SetupClientAuth(std::get<2>(GetParam()), true); +@@ -1841,7 +1843,7 @@ TEST_F(TlsAgentStreamTestServer, Configu + // A server should refuse to even start a handshake with + // misconfigured certificate and signature scheme. + TEST_P(TlsConnectTls12Plus, MisconfiguredCertScheme) { +- Reset(TlsAgent::kServerDsa); ++ Reset(TlsAgent::kServerRsaSign); + static const SSLSignatureScheme kScheme[] = {ssl_sig_ecdsa_secp256r1_sha256}; + server_->SetSignatureSchemes(kScheme, PR_ARRAY_SIZE(kScheme)); + ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); +@@ -1882,6 +1884,9 @@ TEST_P(TlsConnectTls13, Tls13DsaOnlyClie + client_->CheckErrorCode(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM); + } + ++#ifndef NSS_DISABLE_DSA ++// can't test a dsa only server becasue we can't generate a server ++// DSA certificate + TEST_P(TlsConnectTls13, Tls13DsaOnlyServer) { + Reset(TlsAgent::kServerDsa); + static const SSLSignatureScheme kDsa[] = {ssl_sig_dsa_sha256}; +@@ -1890,6 +1895,7 @@ TEST_P(TlsConnectTls13, Tls13DsaOnlyServ + server_->CheckErrorCode(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM); + client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP); + } ++#endif + + TEST_P(TlsConnectTls13, Tls13Pkcs1OnlyClient) { + static const SSLSignatureScheme kPkcs1[] = {ssl_sig_rsa_pkcs1_sha256}; +diff -up ./gtests/ssl_gtest/ssl_ciphersuite_unittest.cc.disable_dsa ./gtests/ssl_gtest/ssl_ciphersuite_unittest.cc +--- ./gtests/ssl_gtest/ssl_ciphersuite_unittest.cc.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_ciphersuite_unittest.cc 2024-06-17 09:38:50.438019407 -0700 +@@ -383,8 +383,10 @@ INSTANTIATE_CIPHER_TEST_P(AEAD12, All, V + kDummySignatureSchemesParams, + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_256_GCM_SHA384, ++#ifndef NSS_DISABLE_DSA + TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, + TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, ++#endif + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384); + INSTANTIATE_CIPHER_TEST_P(AEAD, All, V12, kDummyNamedGroupParams, +@@ -395,16 +397,20 @@ INSTANTIATE_CIPHER_TEST_P(AEAD, All, V12 + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, ++ TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, +- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +- TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256); ++ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256); + INSTANTIATE_CIPHER_TEST_P( + CBC12, All, V12, kDummyNamedGroupParams, kDummySignatureSchemesParams, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, +- TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, +- TLS_DHE_DSS_WITH_AES_256_CBC_SHA256); ++ TLS_RSA_WITH_AES_128_CBC_SHA256 ++#ifndef NSS_DISABLE_DSA ++ , TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, ++ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 ++#endif ++ ); + INSTANTIATE_CIPHER_TEST_P( + CBCStream, Stream, V10ToV12, kDummyNamedGroupParams, + kDummySignatureSchemesParams, TLS_ECDH_ECDSA_WITH_NULL_SHA, +@@ -431,8 +437,12 @@ INSTANTIATE_CIPHER_TEST_P( + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, +- TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, +- TLS_DHE_DSS_WITH_AES_256_CBC_SHA256); ++ TLS_RSA_WITH_AES_128_CBC_SHA256 ++#ifndef NSS_DISABLE_DSA ++ , TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, ++ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 ++#endif ++ ); + #ifndef NSS_DISABLE_TLS_1_3 + INSTANTIATE_CIPHER_TEST_P(TLS13, All, V13, + ::testing::ValuesIn(kFasterDHEGroups), +diff -up ./gtests/ssl_gtest/ssl_dhe_unittest.cc.disable_dsa ./gtests/ssl_gtest/ssl_dhe_unittest.cc +--- ./gtests/ssl_gtest/ssl_dhe_unittest.cc.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_dhe_unittest.cc 2024-06-17 09:45:33.575416837 -0700 +@@ -622,6 +622,7 @@ class TlsDheSkeChangeSignature : public + size_t len_; + }; + ++#ifndef NSS_DISABLE_DSA + TEST_P(TlsConnectGenericPre13, InvalidDERSignatureFfdhe) { + const uint8_t kBogusDheSignature[] = { + 0x30, 0x69, 0x3c, 0x02, 0x1c, 0x7d, 0x0b, 0x2f, 0x64, 0x00, 0x27, +@@ -642,6 +643,7 @@ TEST_P(TlsConnectGenericPre13, InvalidDE + ConnectExpectAlert(client_, kTlsAlertDecryptError); + client_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); + } ++#endif + + TEST_P(TlsConnectTls12, ConnectInconsistentSigAlgDHE) { + EnableOnlyDheCiphers(); +diff -up ./gtests/ssl_gtest/ssl_extension_unittest.cc.disable_dsa ./gtests/ssl_gtest/ssl_extension_unittest.cc +--- ./gtests/ssl_gtest/ssl_extension_unittest.cc.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./gtests/ssl_gtest/ssl_extension_unittest.cc 2024-06-17 09:38:50.438019407 -0700 +@@ -651,7 +651,10 @@ TEST_P(TlsExtensionTest12, SignatureAlgo + } + } + ++#ifndef NSS_DISABLE_DSA + // This only works on TLS 1.2, since it relies on DSA. ++// and doesn't work if we've disabled DSA (Reset(TlsAgent:kServerDSA) fail ++// because we don't have a DSA certificate) + TEST_P(TlsExtensionTest12, SignatureAlgorithmDisableDSA) { + const std::vector schemes = { + ssl_sig_dsa_sha1, ssl_sig_dsa_sha256, ssl_sig_dsa_sha384, +@@ -700,6 +703,7 @@ TEST_P(TlsExtensionTest12, SignatureAlgo + EXPECT_TRUE(ext2.Read(2, 2, &v)); + EXPECT_EQ(ssl_sig_rsa_pss_rsae_sha256, v); + } ++#endif + + // Temporary test to verify that we choke on an empty ClientKeyShare. + // This test will fail when we implement HelloRetryRequest. +diff -up ./lib/softoken/pkcs11c.c.disable_dsa ./lib/softoken/pkcs11c.c +--- ./lib/softoken/pkcs11c.c.disable_dsa 2024-06-17 09:38:50.434019363 -0700 ++++ ./lib/softoken/pkcs11c.c 2024-06-17 09:38:50.439019418 -0700 +@@ -2665,6 +2665,7 @@ sftk_RSASignPSS(SFTKPSSSignInfo *info, u + return rv; + } + ++#ifndef NSS_DISABLE_DSA + static SECStatus + nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen, + void *dataBuf, unsigned int dataLen) +@@ -2690,6 +2691,7 @@ nsc_DSA_Sign_Stub(void *ctx, void *sigBu + *sigLen = signature.len; + return rv; + } ++#endif + + static SECStatus + nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen, +@@ -2905,6 +2907,7 @@ NSC_SignInit(CK_SESSION_HANDLE hSession, + context->maxLen = nsslowkey_PrivateModulusLen(pinfo->key); + break; + ++#ifndef NSS_DISABLE_DSA + #define INIT_DSA_SIG_MECH(mmm) \ + case CKM_DSA_##mmm: \ + context->multi = PR_TRUE; \ +@@ -2933,6 +2936,7 @@ NSC_SignInit(CK_SESSION_HANDLE hSession, + context->maxLen = DSA_MAX_SIGNATURE_LEN; + + break; ++#endif + + #define INIT_ECDSA_SIG_MECH(mmm) \ + case CKM_ECDSA_##mmm: \ +@@ -3717,6 +3721,7 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSessio + context->verify = (SFTKVerify)sftk_RSACheckSignPSS; + break; + ++#ifndef NSS_DISABLE_DSA + INIT_DSA_SIG_MECH(SHA1) + INIT_DSA_SIG_MECH(SHA224) + INIT_DSA_SIG_MECH(SHA256) +@@ -3736,6 +3741,7 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSessio + context->verify = (SFTKVerify)nsc_DSA_Verify_Stub; + context->destroy = sftk_Null; + break; ++#endif + + INIT_ECDSA_SIG_MECH(SHA1) + INIT_ECDSA_SIG_MECH(SHA224) +@@ -4753,12 +4759,16 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi + key_gen_type = nsc_pbe; + crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length); + break; ++/*#ifndef NSS_DISABLE_DSA */ ++/* some applications use CKM_DSA_PARAMTER_GEN for week DH keys... ++ * most notably tests... continue to allow it for now */ + case CKM_DSA_PARAMETER_GEN: + key_gen_type = nsc_param; + key_type = CKK_DSA; + objclass = CKO_DOMAIN_PARAMETERS; + crv = CKR_OK; + break; ++/* #endif */ + case CKM_NSS_JPAKE_ROUND1_SHA1: + hashType = HASH_AlgSHA1; + goto jpake1; +@@ -5121,11 +5131,13 @@ sftk_PairwiseConsistencyCheck(CK_SESSION + signature_length = modulusLen; + mech.mechanism = CKM_RSA_PKCS; + break; ++#ifndef NSS_DISABLE_DSA + case CKK_DSA: + signature_length = DSA_MAX_SIGNATURE_LEN; + pairwise_digest_length = subPrimeLen; + mech.mechanism = CKM_DSA; + break; ++#endif + case CKK_EC: + signature_length = MAX_ECKEY_LEN * 2; + mech.mechanism = CKM_ECDSA; +@@ -5373,10 +5385,12 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS + SECItem pubExp; + RSAPrivateKey *rsaPriv; + ++ DHParams dhParam; ++#ifndef NSS_DISABLE_DSA + /* DSA */ + PQGParams pqgParam; +- DHParams dhParam; + DSAPrivateKey *dsaPriv; ++#endif + + /* Diffie Hellman */ + DHPrivateKey *dhPriv; +@@ -5552,6 +5566,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS + /* Should zeroize the contents first, since this func doesn't. */ + PORT_FreeArena(rsaPriv->arena, PR_TRUE); + break; ++#ifndef NSS_DISABLE_DSA + case CKM_DSA_KEY_PAIR_GEN: + sftk_DeleteAttributeType(publicKey, CKA_VALUE); + sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); +@@ -5663,6 +5678,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS + /* should zeroize, since this function doesn't. */ + PORT_FreeArena(dsaPriv->params.arena, PR_TRUE); + break; ++#endif + + case CKM_DH_PKCS_KEY_PAIR_GEN: + sftk_DeleteAttributeType(privateKey, CKA_PRIME); +diff -up ./lib/softoken/pkcs11.c.disable_dsa ./lib/softoken/pkcs11.c +--- ./lib/softoken/pkcs11.c.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/softoken/pkcs11.c 2024-06-17 09:38:50.439019418 -0700 +@@ -359,6 +359,7 @@ static const struct mechanismList mechan + { CKM_SHA384_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, + { CKM_SHA512_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE }, + /* ------------------------- DSA Operations --------------------------- */ ++#ifndef NSS_DISABLE_DSA + { CKM_DSA_KEY_PAIR_GEN, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, + { CKM_DSA, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, + { CKM_DSA_PARAMETER_GEN, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_GENERATE }, PR_TRUE }, +@@ -367,6 +368,7 @@ static const struct mechanismList mechan + { CKM_DSA_SHA256, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, + { CKM_DSA_SHA384, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, + { CKM_DSA_SHA512, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE }, ++#endif + /* -------------------- Diffie Hellman Operations --------------------- */ + /* no diffie hellman yet */ + { CKM_DH_PKCS_KEY_PAIR_GEN, { DH_MIN_P_BITS, DH_MAX_P_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE }, +diff -up ./tests/cert/cert.sh.disable_dsa ./tests/cert/cert.sh +--- ./tests/cert/cert.sh.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./tests/cert/cert.sh 2024-06-17 09:38:50.440019429 -0700 +@@ -288,12 +288,14 @@ cert_create_cert() + return $RET + fi + ++ if [ -z "$NSS_DISABLE_DSA" ]; then + CU_ACTION="Import DSA Root CA for $CERTNAME" + certu -A -n "TestCA-dsa" -t "TC,TC,TC" -f "${R_PWFILE}" \ + -d "${PROFILEDIR}" -i "${R_CADIR}/TestCA-dsa.ca.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi ++ fi + + + CU_ACTION="Import EC Root CA for $CERTNAME" +@@ -342,6 +344,7 @@ cert_add_cert() + # + # Generate and add DSA cert + # ++ if [ -z "$NSS_DISABLE_DSA" ]; then + CU_ACTION="Generate DSA Cert Request for $CERTNAME" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsa@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -k dsa -d "${PROFILEDIR}" -f "${R_PWFILE}" \ +@@ -392,6 +395,7 @@ cert_add_cert() + return $RET + fi + cert_log "SUCCESS: $CERTNAME's mixed DSA Cert Created" ++ fi + + # + # Generate and add EC cert +@@ -504,6 +508,7 @@ cert_all_CA() + # in the chain + + ++ if [ -z "$NSS_DISABLE_DSA" ]; then + # + # Create DSA version of TestCA + ALL_CU_SUBJECT="CN=NSS Test CA (DSA), O=BOGUS NSS, L=Mountain View, ST=California, C=US" +@@ -527,6 +532,7 @@ cert_all_CA() + rm $CLIENT_CADIR/dsaroot.cert $SERVER_CADIR/dsaroot.cert + # dsaroot.cert in $CLIENT_CADIR and in $SERVER_CADIR is one of the last + # in the chain ++ fi + + # + # Create RSA-PSS version of TestCA +@@ -988,6 +994,7 @@ cert_extended_ssl() + certu -A -n "clientCA" -t "T,," -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CLIENT_CADIR}/clientCA.ca.cert" 2>&1 + ++ if [ -z "$NSS_DISABLE_DSA" ]; then + # + # Repeat the above for DSA certs + # +@@ -1031,6 +1038,7 @@ cert_extended_ssl() + # certu -A -n "clientCA-dsamixed" -t "T,," -f "${R_PWFILE}" \ + # -d "${PROFILEDIR}" -i "${CLIENT_CADIR}/clientCA-dsamixed.ca.cert" \ + # 2>&1 ++ fi + + # + # Repeat the above for EC certs +@@ -1084,18 +1092,18 @@ cert_extended_ssl() + # we'll use one of the longer nicknames for testing. + # (Because "grep -w hostname" matches "grep -w hostname-dsamixed") + MYDBPASS="-d ${PROFILEDIR} -f ${R_PWFILE}" +- TESTNAME="Ensure there's exactly one match for ${CERTNAME}-dsamixed" +- cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-dsamixed" 0 1 "${TESTNAME}" ++ TESTNAME="Ensure there's exactly one match for ${CERTNAME}-ecmixed" ++ cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-ecmixed" 0 1 "${TESTNAME}" + +- CU_ACTION="Repeated import of $CERTNAME's mixed DSA Cert with different nickname" +- certu -A -n "${CERTNAME}-repeated-dsamixed" -t "u,u,u" -d "${PROFILEDIR}" \ +- -f "${R_PWFILE}" -i "${CERTNAME}-dsamixed.cert" 2>&1 ++ CU_ACTION="Repeated import of $CERTNAME's mixed EC Cert with different nickname" ++ certu -A -n "${CERTNAME}-repeated-ecmixed" -t "u,u,u" -d "${PROFILEDIR}" \ ++ -f "${R_PWFILE}" -i "${CERTNAME}-ecmixed.cert" 2>&1 + +- TESTNAME="Ensure there's still exactly one match for ${CERTNAME}-dsamixed" +- cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-dsamixed" 0 1 "${TESTNAME}" ++ TESTNAME="Ensure there's still exactly one match for ${CERTNAME}-ecmixed" ++ cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-ecmixed" 0 1 "${TESTNAME}" + +- TESTNAME="Ensure there's zero matches for ${CERTNAME}-repeated-dsamixed" +- cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-repeated-dsamixed" 0 0 "${TESTNAME}" ++ TESTNAME="Ensure there's zero matches for ${CERTNAME}-repeated-ecmixed" ++ cert_check_nickname_exists "$MYDBPASS" "${CERTNAME}-repeated-ecmixed" 0 0 "${TESTNAME}" + + echo "Importing all the server's own CA chain into the servers DB" + for CA in `find ${SERVER_CADIR} -name "?*.ca.cert"` ; +@@ -1140,6 +1148,7 @@ cert_extended_ssl() + # + # Repeat the above for DSA certs + # ++ if [ -z "$NSS_DISABLE_DSA" ]; then + CU_ACTION="Generate DSA Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-dsa@example.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -k dsa -f "${R_PWFILE}" \ +@@ -1183,6 +1192,7 @@ cert_extended_ssl() + # + # done with mixed DSA certs + # ++ fi + + # + # Repeat the above for EC certs +@@ -1273,8 +1283,10 @@ cert_ssl() + CU_ACTION="Modify trust attributes of Root CA -t TC,TC,TC" + certu -M -n "TestCA" -t "TC,TC,TC" -d ${PROFILEDIR} -f "${R_PWFILE}" + ++ if [ -z "$NSS_DISABLE_DSA" ]; then + CU_ACTION="Modify trust attributes of DSA Root CA -t TC,TC,TC" + certu -M -n "TestCA-dsa" -t "TC,TC,TC" -d ${PROFILEDIR} -f "${R_PWFILE}" ++ fi + + CU_ACTION="Modify trust attributes of EC Root CA -t TC,TC,TC" + certu -M -n "TestCA-ec" -t "TC,TC,TC" -d ${PROFILEDIR} -f "${R_PWFILE}" +@@ -1383,9 +1395,14 @@ MODSCRIPT + certu -G -k rsa -g 2048 -y 17 -d "${PROFILEDIR}" -z ${R_NOISE_FILE} -f "${R_FIPSPWFILE}" + RETEXPECTED=0 + ++ if [ -z "$NSS_DISABLE_DSA" ]; then ++ FIPS_KEY="-k dsa" ++ else ++ FIPS_KEY="-k ec -q nistp256" ++ fi + CU_ACTION="Generate Certificate for ${CERTNAME}" + CU_SUBJECT="CN=${CERTNAME}, E=fips@example.com, O=BOGUS NSS, OU=FIPS PUB 140, L=Mountain View, ST=California, C=US" +- certu -S -n ${FIPSCERTNICK} -x -t "Cu,Cu,Cu" -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" -k dsa -v 600 -m 500 -z "${R_NOISE_FILE}" 2>&1 ++ certu -S -n ${FIPSCERTNICK} -x -t "Cu,Cu,Cu" -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" ${FIPS_KEY} -v 600 -m 500 -z "${R_NOISE_FILE}" 2>&1 + if [ "$RET" -eq 0 ]; then + cert_log "SUCCESS: FIPS passed" + fi +@@ -1817,6 +1834,7 @@ EOF_CRLINI + chmod 600 ${CRL_FILE_GRP_1}_or + + ++ if [ -z "$NSS_DISABLE_DSA" ]; then + CU_ACTION="Generating CRL (DSA) for range ${CRL_GRP_1_BEGIN}-${CRL_GRP_END} TestCA-dsa authority" + + # Until Bug 292285 is resolved, do not encode x400 Addresses. After +@@ -1831,6 +1849,7 @@ addext issuerAltNames 0 "rfc822Name:ca-d + EOF_CRLINI + CRL_GEN_RES=`expr $? + $CRL_GEN_RES` + chmod 600 ${CRL_FILE_GRP_1}_or-dsa ++ fi + + + +@@ -1867,6 +1886,7 @@ EOF_CRLINI + TEMPFILES="$TEMPFILES ${CRL_FILE_GRP_1}_or" + + ++ if [ -z "$NSS_DISABLE_DSA" ]; then + CU_ACTION="Modify CRL (DSA) by adding one more cert" + crlu -d $CADIR -M -n "TestCA-dsa" -f ${R_PWFILE} -o ${CRL_FILE_GRP_1}_or1-dsa \ + -i ${CRL_FILE_GRP_1}_or-dsa <
" >> ${PERFRESULTS} + fi + ++if [ -z "${NSS_DISABLE_DSA}" ]; then + if [ $TESTSET = "all" -o $TESTSET = "dsa" ]; then + + while read mode keysize bufsize reps cxreps +@@ -124,6 +125,7 @@ done < ${DSAPERFOUT} + + echo "
" >> ${PERFRESULTS} + fi ++fi + + if [ $TESTSET = "all" -o $TESTSET = "hash" ]; then + while read mode bufsize reps +diff -up ./tests/dbtests/dbtests.sh.disable_dsa ./tests/dbtests/dbtests.sh +--- ./tests/dbtests/dbtests.sh.disable_dsa 2024-06-17 09:38:50.412019123 -0700 ++++ ./tests/dbtests/dbtests.sh 2024-06-17 09:38:50.440019429 -0700 +@@ -257,7 +257,13 @@ dbtest_main() + fi + # import a token private key and make sure the corresponding public key is + # created +- ${BINDIR}/pk11importtest -d ${CONFLICT_DIR} -f ${R_PWFILE} ++ IMPORT_OPTIONS="" ++ if [ -n "$NSS_DISABLE_DSA" ]; then ++ IMPORT_OPTIONS="-D noDSA" ++ fi ++ Echo "Importing Token Private Key" ++ echo "pk11importtest ${IMPORT_OPTIONS} -d ${CONFLICT_DIR} -f ${R_PWFILE}" ++ ${BINDIR}/pk11importtest ${IMPORT_OPTIONS} -d ${CONFLICT_DIR} -f ${R_PWFILE} + ret=$? + if [ $ret -ne 0 ]; then + html_failed "Importing Token Private Key does not create the corrresponding Public Key" +diff -up ./tests/ssl_gtests/ssl_gtests.sh.disable_dsa ./tests/ssl_gtests/ssl_gtests.sh +--- ./tests/ssl_gtests/ssl_gtests.sh.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./tests/ssl_gtests/ssl_gtests.sh 2024-06-17 09:38:50.440019429 -0700 +@@ -56,7 +56,9 @@ ssl_gtest_certs() { + make_cert rsa_pss_chain rsapss_chain sign + make_cert rsa_ca_rsa_pss_chain rsa_ca_rsapss_chain sign + make_cert ecdh_rsa ecdh_rsa kex +- make_cert dsa dsa sign ++ if [ -z "${NSS_DISABLE_DSA}" ]; then ++ make_cert dsa dsa sign ++ fi + make_cert delegator_ecdsa256 delegator_p256 sign + make_cert delegator_rsae2048 delegator_rsae2048 sign + make_cert delegator_rsa_pss2048 delegator_rsa_pss2048 sign +diff -up ./tests/ssl/sslcov.txt.disable_dsa ./tests/ssl/sslcov.txt +--- ./tests/ssl/sslcov.txt.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./tests/ssl/sslcov.txt 2024-06-17 09:38:50.440019429 -0700 +@@ -16,7 +16,6 @@ + noECC SSL3 y SSL3_RSA_WITH_AES_256_CBC_SHA + noECC SSL3 z SSL3_RSA_WITH_NULL_SHA + noECC TLS12 :009F TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 +- noECC TLS12 :00A3 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 + noECC TLS12 :009D TLS_RSA_WITH_AES_256_GCM_SHA384 + # noECC SSL3 :0041 TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + # noECC SSL3 :0084 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA +@@ -51,20 +50,15 @@ + noECC TLS12 y TLS12_RSA_WITH_AES_256_CBC_SHA + noECC TLS12 z TLS12_RSA_WITH_NULL_SHA + noECC TLS12 :0016 TLS12_DHE_RSA_WITH_3DES_EDE_CBC_SHA +- noECC TLS12 :0032 TLS12_DHE_DSS_WITH_AES_128_CBC_SHA + noECC TLS12 :0033 TLS12_DHE_RSA_WITH_AES_128_CBC_SHA +- noECC TLS12 :0038 TLS12_DHE_DSS_WITH_AES_256_CBC_SHA + noECC TLS12 :0039 TLS12_DHE_RSA_WITH_AES_256_CBC_SHA + noECC TLS12 :003B TLS12_RSA_WITH_NULL_SHA256 + noECC TLS12 :003C TLS12_RSA_WITH_AES_128_CBC_SHA256 + noECC TLS12 :003D TLS12_RSA_WITH_AES_256_CBC_SHA256 +- noECC TLS12 :0040 TLS12_DHE_DSS_WITH_AES_128_CBC_SHA256 + noECC TLS12 :0067 TLS12_DHE_RSA_WITH_AES_128_CBC_SHA256 +- noECC TLS12 :006A TLS12_DHE_DSS_WITH_AES_256_CBC_SHA256 + noECC TLS12 :006B TLS12_DHE_RSA_WITH_AES_256_CBC_SHA256 + noECC TLS12 :009C TLS12_RSA_WITH_AES_128_GCM_SHA256 + noECC TLS12 :009E TLS12_DHE_RSA_WITH_AES_128_GCM_SHA256 +- noECC TLS12 :00A2 TLS12_DHE_DSS_WITH_AES_128_GCM_SHA256 + noECC TLS12 :CCAA TLS12_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + noECC TLS13 :1301 TLS13_DHE_WITH_AES_128_GCM_SHA256 + noECC TLS13 :1302 TLS13_DHE_WITH_AES_256_GCM_SHA384 +diff -up ./tests/ssl/ssl.sh.disable_dsa ./tests/ssl/ssl.sh +--- ./tests/ssl/ssl.sh.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./tests/ssl/ssl.sh 2024-06-17 09:38:50.440019429 -0700 +@@ -251,20 +251,26 @@ start_selfserv() + else + RSA_OPTIONS="-n ${HOSTADDR}-rsa-pss" + fi ++ if [ -z "$NSS_DISABLE_DSA" ]; then ++ DSA_OPTIONS="-S ${HOSTADDR}-dsa" ++ else ++ DSA_OPTIONS="" ++ fi ++ + SERVER_VMIN=${SERVER_VMIN-ssl3} + SERVER_VMAX=${SERVER_VMAX-tls1.2} + echo "selfserv starting at `date`" + echo "selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} ${RSA_OPTIONS} ${SERVER_OPTIONS} \\" +- echo " ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@" -i ${R_SERVERPID}\\" ++ echo " ${ECC_OPTIONS} ${DSA_OPTIONS} -w nss "$@" -i ${R_SERVERPID}\\" + echo " -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 &" + if [ ${fileout} -eq 1 ]; then + ${PROFTOOL} ${BINDIR}/selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} ${RSA_OPTIONS} ${SERVER_OPTIONS} \ +- ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@" -i ${R_SERVERPID} -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 \ ++ ${ECC_OPTIONS} ${DSA_OPTIONS} -w nss "$@" -i ${R_SERVERPID} -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 \ + > ${SERVEROUTFILE} 2>&1 & + RET=$? + else + ${PROFTOOL} ${BINDIR}/selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} ${RSA_OPTIONS} ${SERVER_OPTIONS} \ +- ${ECC_OPTIONS} -S ${HOSTADDR}-dsa -w nss "$@" -i ${R_SERVERPID} -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 & ++ ${ECC_OPTIONS} ${DSA_OPTIONS} -w nss "$@" -i ${R_SERVERPID} -V ${SERVER_VMIN}:${SERVER_VMAX} $verbose -H 1 & + RET=$? + fi + +diff -up ./tests/ssl/sslstress.txt.disable_dsa ./tests/ssl/sslstress.txt +--- ./tests/ssl/sslstress.txt.disable_dsa 2024-06-07 09:26:03.000000000 -0700 ++++ ./tests/ssl/sslstress.txt 2024-06-17 09:38:50.440019429 -0700 +@@ -55,15 +55,6 @@ + + + noECC 0 -c_:0039 -V_ssl3:tls1.2_-c_100_-C_:0039_-N Stress TLS DHE_RSA_WITH_AES_256_CBC_SHA (no reuse) +- noECC 0 -c_:0040 -V_ssl3:tls1.2_-c_100_-C_:0040_-N Stress TLS DHE_DSS_WITH_AES_128_CBC_SHA256 (no reuse) +- +-# noECC 0 -c_:0038_-u -V_ssl3:tls1.2_-c_1000_-C_:0038_-u Stress TLS DHE_DSS_WITH_AES_256_CBC_SHA (session ticket) +-# use the above session ticket test, once session tickets with DHE_DSS are working +- noECC 0 -c_:0038 -V_ssl3:tls1.2_-c_1000_-C_:0038_-N Stress TLS DHE_DSS_WITH_AES_256_CBC_SHA (no reuse) +- +-# noECC 0 -c_:006A -V_ssl3:tls1.2_-c_1000_-C_:006A Stress TLS DHE_DSS_WITH_AES_256_CBC_SHA256 +-# use the above reuse test, once the session cache with DHE_DSS is working +- noECC 0 -c_:006A -V_ssl3:tls1.2_-c_1000_-C_:006A_-N Stress TLS DHE_DSS_WITH_AES_256_CBC_SHA256 (no reuse + + noECC 0 -c_:006B -V_ssl3:tls1.2_-c_100_-C_:006B_-N Stress TLS DHE_RSA_WITH_AES_256_CBC_SHA256 (no reuse) + noECC 0 -c_:009E -V_ssl3:tls1.2_-c_100_-C_:009E_-N Stress TLS DHE_RSA_WITH_AES_128_GCM_SHA256 (no reuse) +@@ -71,11 +62,3 @@ + # + # add client auth versions here... + # +- noECC 0 -r_-r_-c_:0032 -V_ssl3:tls1.2_-c_100_-C_:0032_-N_-n_TestUser-dsa Stress TLS DHE_DSS_WITH_AES_128_CBC_SHA (no reuse, client auth) +- noECC 0 -r_-r_-c_:0067 -V_ssl3:tls1.2_-c_1000_-C_:0067_-n_TestUser-dsamixed Stress TLS DHE_RSA_WITH_AES_128_CBC_SHA256 (client auth) +- +-# noECC 0 -r_-r_-c_:00A2_-u -V_ssl3:tls1.2_-c_1000_-C_:00A2_-n_TestUser-dsa_-u Stress TLS DHE_DSS_WITH_AES_128_GCM_SHA256 (session ticket, client auth) +-# noECC 0 -r_-r_-c_:00A3_-u -V_ssl3:tls1.2_-c_1000_-C_:00A3_-n_TestUser-dsa_-u Stress TLS DHE_DSS_WITH_AES_256_GCM_SHA384 (session ticket, client auth) +-# use the above session ticket test, once session tickets with DHE_DSS are working +- noECC 0 -r_-r_-c_:00A2_-u -V_ssl3:tls1.2_-c_1000_-C_:00A2_-N_-n_TestUser-dsa Stress TLS DHE_DSS_WITH_AES_128_GCM_SHA256 (no reuse, client auth) +- noECC 0 -r_-r_-c_:00A3_-u -V_ssl3:tls1.2_-c_1000_-C_:00A3_-N_-n_TestUser-dsa Stress TLS DHE_DSS_WITH_AES_256_GCM_SHA384 (no reuse, client auth) diff --git a/nss-3.101-enable-kyber-policy.patch b/nss-3.101-enable-kyber-policy.patch new file mode 100644 index 0000000..374e4e6 --- /dev/null +++ b/nss-3.101-enable-kyber-policy.patch @@ -0,0 +1,13 @@ +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 }, diff --git a/nss-3.101-enable-sdb-tests.patch b/nss-3.101-enable-sdb-tests.patch new file mode 100644 index 0000000..6bf3484 --- /dev/null +++ b/nss-3.101-enable-sdb-tests.patch @@ -0,0 +1,63 @@ +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 ############################## diff --git a/nss-3.101-extend-db-dump-time.patch b/nss-3.101-extend-db-dump-time.patch new file mode 100644 index 0000000..88a608b --- /dev/null +++ b/nss-3.101-extend-db-dump-time.patch @@ -0,0 +1,12 @@ +diff -up ./tests/dbtests/dbtests.sh.extend ./tests/dbtests/dbtests.sh +--- ./tests/dbtests/dbtests.sh.extend 2023-11-15 13:17:50.651020458 -0800 ++++ ./tests/dbtests/dbtests.sh 2023-11-15 13:18:57.091608850 -0800 +@@ -366,7 +366,7 @@ dbtest_main() + RARRAY=($dtime) + TIMEARRAY=(${RARRAY[1]//./ }) + echo "${TIMEARRAY[0]} seconds" +- test ${TIMEARRAY[0]} -lt 5 ++ test ${TIMEARRAY[0]} -lt ${NSS_DB_DUMP_TIME-5} + ret=$? + html_msg ${ret} 0 "certutil dump keys with explicit default trust flags" + fi diff --git a/nss-3.101-fips-indicators.patch b/nss-3.101-fips-indicators.patch new file mode 100644 index 0000000..604d054 --- /dev/null +++ b/nss-3.101-fips-indicators.patch @@ -0,0 +1,190 @@ +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; + } + } diff --git a/nss-3.101-fips-review.patches b/nss-3.101-fips-review.patches new file mode 100644 index 0000000..755b087 --- /dev/null +++ b/nss-3.101-fips-review.patches @@ -0,0 +1,490 @@ +diff -up ./lib/freebl/dh.c.fips-review ./lib/freebl/dh.c +--- ./lib/freebl/dh.c.fips-review 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/freebl/dh.c 2024-06-12 12:04:10.639360404 -0700 +@@ -445,7 +445,7 @@ cleanup: + PRBool + KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime) + { +- mp_int p, q, y, r; ++ mp_int p, q, y, r, psub1; + mp_err err; + int cmp = 1; /* default is false */ + if (!Y || !prime || !subPrime) { +@@ -456,13 +456,30 @@ KEA_Verify(SECItem *Y, SECItem *prime, S + MP_DIGITS(&q) = 0; + MP_DIGITS(&y) = 0; + MP_DIGITS(&r) = 0; ++ MP_DIGITS(&psub1) = 0; + CHECK_MPI_OK(mp_init(&p)); + CHECK_MPI_OK(mp_init(&q)); + CHECK_MPI_OK(mp_init(&y)); + CHECK_MPI_OK(mp_init(&r)); ++ CHECK_MPI_OK(mp_init(&psub1)); + SECITEM_TO_MPINT(*prime, &p); + SECITEM_TO_MPINT(*subPrime, &q); + SECITEM_TO_MPINT(*Y, &y); ++ CHECK_MPI_OK(mp_sub_d(&p, 1, &psub1)); ++ /* ++ * We check that the public value isn't zero (which isn't in the ++ * group), one (subgroup of order one) or p-1 (subgroup of order 2). We ++ * also check that the public value is less than p, to avoid being fooled ++ * by values like p+1 or 2*p-1. ++ * This check is required by SP-800-56Ar3. It's also done in derive, ++ * but this is only called in various FIPS cases, so put it here to help ++ * reviewers find it. ++ */ ++ if (mp_cmp_d(&y, 1) <= 0 || ++ mp_cmp(&y, &psub1) >= 0) { ++ err = MP_BADARG; ++ goto cleanup; ++ } + /* compute r = y**q mod p */ + CHECK_MPI_OK(mp_exptmod(&y, &q, &p, &r)); + /* compare to 1 */ +@@ -472,6 +489,7 @@ cleanup: + mp_clear(&q); + mp_clear(&y); + mp_clear(&r); ++ mp_clear(&psub1); + if (err) { + MP_TO_SEC_ERROR(err); + return PR_FALSE; +diff -up ./lib/softoken/pkcs11c.c.fips-review ./lib/softoken/pkcs11c.c +--- ./lib/softoken/pkcs11c.c.fips-review 2024-06-12 12:04:10.638360392 -0700 ++++ ./lib/softoken/pkcs11c.c 2024-06-12 13:06:35.410551333 -0700 +@@ -43,6 +43,7 @@ + + #include "prprf.h" + #include "prenv.h" ++#include "prerror.h" + + #define __PASTE(x, y) x##y + #define BAD_PARAM_CAST(pMech, typeSize) (!pMech->pParameter || pMech->ulParameterLen < typeSize) +@@ -4882,6 +4883,10 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi + * 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); ++ 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)); +@@ -4889,9 +4894,6 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSessi + 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; + } +@@ -5199,60 +5201,68 @@ sftk_PairwiseConsistencyCheck(CK_SESSION + + if (isDerivable) { + SFTKAttribute *pubAttribute = NULL; +- CK_OBJECT_HANDLE newKey; + PRBool isFIPS = sftk_isFIPS(slot->slotID); +- CK_RV crv2; +- CK_OBJECT_CLASS secret = CKO_SECRET_KEY; +- CK_KEY_TYPE generic = CKK_GENERIC_SECRET; +- CK_ULONG keyLen = 128; +- CK_BBOOL ckTrue = CK_TRUE; +- CK_ATTRIBUTE template[] = { +- { CKA_CLASS, &secret, sizeof(secret) }, +- { CKA_KEY_TYPE, &generic, sizeof(generic) }, +- { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, +- { CKA_DERIVE, &ckTrue, sizeof(ckTrue) } +- }; +- CK_ULONG templateCount = PR_ARRAY_SIZE(template); +- CK_ECDH1_DERIVE_PARAMS ecParams; ++ NSSLOWKEYPrivateKey *lowPrivKey = NULL; ++ ECPrivateKey *ecPriv; ++ SECItem *lowPubValue = NULL; ++ SECItem item; ++ SECStatus rv; + + crv = CKR_OK; /*paranoia, already get's set before we drop to the end */ +- /* FIPS 140-2 requires we verify that the resulting key is a valid key. +- * The easiest way to do this is to do a derive operation, which checks +- * the validity of the key */ +- ++ /* FIPS 140-3 requires we verify that the resulting key is a valid key ++ * by recalculating the public can an compare it to our own public ++ * key. */ ++ lowPrivKey = sftk_GetPrivKey(privateKey, keyType, &crv); ++ if (lowPrivKey == NULL) { ++ return sftk_MapCryptError(PORT_GetError()); ++ } ++ /* recalculate the public key from the private key */ + switch (keyType) { +- case CKK_DH: +- mech.mechanism = CKM_DH_PKCS_DERIVE; +- pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE); +- if (pubAttribute == NULL) { +- return CKR_DEVICE_ERROR; +- } +- mech.pParameter = pubAttribute->attrib.pValue; +- mech.ulParameterLen = pubAttribute->attrib.ulValueLen; +- break; +- case CKK_EC: +- mech.mechanism = CKM_ECDH1_DERIVE; +- pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT); +- if (pubAttribute == NULL) { +- return CKR_DEVICE_ERROR; +- } +- ecParams.kdf = CKD_NULL; +- ecParams.ulSharedDataLen = 0; +- ecParams.pSharedData = NULL; +- ecParams.ulPublicDataLen = pubAttribute->attrib.ulValueLen; +- ecParams.pPublicData = pubAttribute->attrib.pValue; +- mech.pParameter = &ecParams; +- mech.ulParameterLen = sizeof(ecParams); +- break; +- default: +- return CKR_DEVICE_ERROR; ++ case CKK_DH: ++ rv = DH_Derive(&lowPrivKey->u.dh.base, &lowPrivKey->u.dh.prime, ++ &lowPrivKey->u.dh.privateValue, &item, 0); ++ if (rv != SECSuccess) { ++ return CKR_GENERAL_ERROR; ++ } ++ lowPubValue = SECITEM_DupItem(&item); ++ SECITEM_ZfreeItem(&item, PR_FALSE); ++ pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE); ++ break; ++ case CKK_EC: ++ rv = EC_NewKeyFromSeed(&lowPrivKey->u.ec.ecParams, &ecPriv, ++ lowPrivKey->u.ec.privateValue.data, ++ lowPrivKey->u.ec.privateValue.len); ++ if (rv != SECSuccess) { ++ return CKR_GENERAL_ERROR; ++ } ++ /* make sure it has the same encoding */ ++ if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") || ++ lowPrivKey->u.ec.ecParams.type != ec_params_named) { ++ lowPubValue = SECITEM_DupItem(&ecPriv->publicValue); ++ } else { ++ lowPubValue = SEC_ASN1EncodeItem(NULL, NULL, &ecPriv->publicValue, ++ SEC_ASN1_GET(SEC_OctetStringTemplate));; ++ } ++ pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT); ++ /* clear out our generated private key */ ++ PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); ++ break; ++ default: ++ return CKR_DEVICE_ERROR; + } + +- crv = NSC_DeriveKey(hSession, &mech, privateKey->handle, template, templateCount, &newKey); +- if (crv != CKR_OK) { +- sftk_FreeAttribute(pubAttribute); +- return crv; ++ /* now compare new public key with our already generated key */ ++ if ((pubAttribute == NULL) || (lowPubValue == NULL) || ++ (pubAttribute->attrib.ulValueLen != lowPubValue->len) || ++ (PORT_Memcmp(pubAttribute->attrib.pValue, lowPubValue->data, ++ lowPubValue->len) != 0)) { ++ if (pubAttribute) sftk_FreeAttribute(pubAttribute); ++ if (lowPubValue) SECITEM_ZfreeItem(lowPubValue, PR_TRUE); ++ PORT_SetError(SEC_ERROR_BAD_KEY); ++ return CKR_GENERAL_ERROR; + } ++ SECITEM_ZfreeItem(lowPubValue, PR_TRUE); ++ + /* FIPS requires full validation, but in fipx mode NSC_Derive + * only does partial validation with approved primes, now handle + * full validation */ +@@ -5260,44 +5270,78 @@ sftk_PairwiseConsistencyCheck(CK_SESSION + SECItem pubKey; + SECItem prime; + SECItem subPrime; ++ SECItem base; ++ SECItem generator; + const SECItem *subPrimePtr = &subPrime; + + pubKey.data = pubAttribute->attrib.pValue; + pubKey.len = pubAttribute->attrib.ulValueLen; +- prime.data = subPrime.data = NULL; +- prime.len = subPrime.len = 0; ++ base.data = prime.data = subPrime.data = NULL; ++ base.len = prime.len = subPrime.len = 0; + crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME); + if (crv != CKR_OK) { + goto done; + } +- crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME); ++ crv = sftk_Attribute2SecItem(NULL, &base, privateKey, CKA_BASE); ++ if (crv != CKR_OK) { ++ goto done; ++ } + /* we ignore the return code an only look at the length */ +- if (subPrime.len == 0) { +- /* subprime not supplied, In this case look it up. +- * This only works with approved primes, but in FIPS mode +- * that's the only kine of prime that will get here */ +- subPrimePtr = sftk_VerifyDH_Prime(&prime, isFIPS); +- if (subPrimePtr == NULL) { +- crv = CKR_GENERAL_ERROR; ++ /* do we have a known prime ? */ ++ subPrimePtr = sftk_VerifyDH_Prime(&prime, &generator, isFIPS); ++ if (subPrimePtr == NULL) { ++ if (subPrime.len == 0) { ++ /* if not a known prime, subprime must be supplied */ ++ crv = CKR_ATTRIBUTE_VALUE_INVALID; ++ goto done; ++ } else { ++ /* not a known prime, check for primality of prime ++ * and subPrime */ ++ if (!KEA_PrimeCheck(&prime)) { ++ crv = CKR_ATTRIBUTE_VALUE_INVALID; ++ goto done; ++ } ++ if (!KEA_PrimeCheck(&subPrime)) { ++ crv = CKR_ATTRIBUTE_VALUE_INVALID; ++ goto done; ++ } ++ /* if we aren't using a defined group, make sure base is in the ++ * subgroup. If it's not, then our key could fail or succeed sometimes. ++ * This makes the failure reliable */ ++ if (!KEA_Verify(&base, &prime, (SECItem *)subPrimePtr)) { ++ crv = CKR_ATTRIBUTE_VALUE_INVALID; ++ } ++ } ++ subPrimePtr = &subPrime; ++ } else { ++ /* we're using a known group, make sure we are using the known generator for that group */ ++ if (SECITEM_CompareItem(&generator, &base) != 0) { ++ crv = CKR_ATTRIBUTE_VALUE_INVALID; + goto done; + } ++ if (subPrime.len != 0) { ++ /* we have a known prime and a supplied subPrime, ++ * make sure the subPrime matches the subPrime for ++ * the known Prime */ ++ if (SECITEM_CompareItem(subPrimePtr, &subPrime) != 0) { ++ crv = CKR_ATTRIBUTE_VALUE_INVALID; ++ goto done; ++ } ++ } + } + if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) { +- crv = CKR_GENERAL_ERROR; ++ crv = CKR_ATTRIBUTE_VALUE_INVALID; + } + done: ++ SECITEM_ZfreeItem(&base, PR_FALSE); + SECITEM_ZfreeItem(&subPrime, PR_FALSE); + SECITEM_ZfreeItem(&prime, PR_FALSE); + } + /* clean up before we return */ + sftk_FreeAttribute(pubAttribute); +- crv2 = NSC_DestroyObject(hSession, newKey); + if (crv != CKR_OK) { + return crv; + } +- if (crv2 != CKR_OK) { +- return crv2; +- } + } + + return CKR_OK; +@@ -5925,8 +5969,8 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS + * 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); +@@ -5968,6 +6012,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS + } + + if (crv != CKR_OK) { ++ sftk_FreeSession(session); + NSC_DestroyObject(hSession, publicKey->handle); + sftk_FreeObject(publicKey); + NSC_DestroyObject(hSession, privateKey->handle); +@@ -5977,6 +6022,8 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hS + /* 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; ++ session->lastOpWasFIPS = privateKey->isFIPS; ++ sftk_FreeSession(session); + + *phPrivateKey = privateKey->handle; + *phPublicKey = publicKey->handle; +@@ -8610,7 +8657,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession + + /* if the prime is an approved prime, we can skip all the other + * checks. */ +- subPrime = sftk_VerifyDH_Prime(&dhPrime, isFIPS); ++ subPrime = sftk_VerifyDH_Prime(&dhPrime, NULL, isFIPS); + if (subPrime == NULL) { + SECItem dhSubPrime; + /* If the caller set the subprime value, it means that +@@ -8792,6 +8839,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession + 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); +diff -up ./lib/softoken/pkcs11i.h.fips-review ./lib/softoken/pkcs11i.h +--- ./lib/softoken/pkcs11i.h.fips-review 2024-06-12 12:04:10.638360392 -0700 ++++ ./lib/softoken/pkcs11i.h 2024-06-12 12:04:10.640360416 -0700 +@@ -971,7 +971,7 @@ char **NSC_ModuleDBFunc(unsigned long fu + /* dh verify functions */ + /* verify that dhPrime matches one of our known primes, and if so return + * it's subprime value */ +-const SECItem *sftk_VerifyDH_Prime(SECItem *dhPrime, PRBool isFIPS); ++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 */ +diff -up ./lib/softoken/pkcs11u.c.fips-review ./lib/softoken/pkcs11u.c +--- ./lib/softoken/pkcs11u.c.fips-review 2024-06-12 12:04:10.638360392 -0700 ++++ ./lib/softoken/pkcs11u.c 2024-06-12 12:04:10.640360416 -0700 +@@ -2409,15 +2409,27 @@ sftk_handleSpecial(SFTKSlot *slot, CK_ME + switch (mechInfo->special) { + case SFTKFIPSDH: { + SECItem dhPrime; ++ SECItem dhBase; ++ SECItem dhGenerator; ++ PRBool val = PR_FALSE; + const SECItem *dhSubPrime; + CK_RV crv = sftk_Attribute2SecItem(NULL, &dhPrime, + source, CKA_PRIME); + if (crv != CKR_OK) { + return PR_FALSE; + } +- dhSubPrime = sftk_VerifyDH_Prime(&dhPrime, PR_TRUE); ++ crv = sftk_Attribute2SecItem(NULL, &dhBase, source, CKA_BASE); ++ if (crv != CKR_OK) { ++ return PR_FALSE; ++ } ++ dhSubPrime = sftk_VerifyDH_Prime(&dhPrime, &dhGenerator, PR_TRUE); ++ val = (dhSubPrime) ? PR_TRUE : PR_FALSE; ++ if (val && (SECITEM_CompareItem(&dhBase, &dhGenerator) != 0)) { ++ val = PR_FALSE; ++ } + SECITEM_ZfreeItem(&dhPrime, PR_FALSE); +- return (dhSubPrime) ? PR_TRUE : PR_FALSE; ++ SECITEM_ZfreeItem(&dhBase, PR_FALSE); ++ return val; + } + case SFTKFIPSNone: + return PR_FALSE; +diff -up ./lib/softoken/sftkdhverify.c.fips-review ./lib/softoken/sftkdhverify.c +--- ./lib/softoken/sftkdhverify.c.fips-review 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/softoken/sftkdhverify.c 2024-06-12 12:04:10.641360427 -0700 +@@ -6726,11 +6726,20 @@ static const SECItem subprime_tls_8192 = + (unsigned char *)subprime_tls_8192_data, + sizeof(subprime_tls_8192_data) }; + ++/* generator for all the groups is 2 */ ++static const unsigned char generator_2_data[] = { 2 }; ++ ++ ++static const SECItem generator_2 = ++ { siBuffer, ++ (unsigned char *)generator_2_data, ++ sizeof(generator_2_data) }; ++ + /* + * verify that dhPrime matches one of our known primes + */ + const SECItem * +-sftk_VerifyDH_Prime(SECItem *dhPrime, PRBool isFIPS) ++sftk_VerifyDH_Prime(SECItem *dhPrime, SECItem *g, PRBool isFIPS) + { + /* use the length to decide which primes to check */ + switch (dhPrime->len) { +@@ -6741,56 +6750,67 @@ sftk_VerifyDH_Prime(SECItem *dhPrime, PR + } + if (PORT_Memcmp(dhPrime->data, prime_ike_1536, + sizeof(prime_ike_1536)) == 0) { ++ if (g) *g = generator_2; + return &subprime_ike_1536; + } + break; + case 2048 / PR_BITS_PER_BYTE: + if (PORT_Memcmp(dhPrime->data, prime_tls_2048, + sizeof(prime_tls_2048)) == 0) { ++ if (g) *g = generator_2; + return &subprime_tls_2048; + } + if (PORT_Memcmp(dhPrime->data, prime_ike_2048, + sizeof(prime_ike_2048)) == 0) { ++ if (g) *g = generator_2; + return &subprime_ike_2048; + } + break; + case 3072 / PR_BITS_PER_BYTE: + if (PORT_Memcmp(dhPrime->data, prime_tls_3072, + sizeof(prime_tls_3072)) == 0) { ++ if (g) *g = generator_2; + return &subprime_tls_3072; + } + if (PORT_Memcmp(dhPrime->data, prime_ike_3072, + sizeof(prime_ike_3072)) == 0) { ++ if (g) *g = generator_2; + return &subprime_ike_3072; + } + break; + case 4096 / PR_BITS_PER_BYTE: + if (PORT_Memcmp(dhPrime->data, prime_tls_4096, + sizeof(prime_tls_4096)) == 0) { ++ if (g) *g = generator_2; + return &subprime_tls_4096; + } + if (PORT_Memcmp(dhPrime->data, prime_ike_4096, + sizeof(prime_ike_4096)) == 0) { ++ if (g) *g = generator_2; + return &subprime_ike_4096; + } + break; + case 6144 / PR_BITS_PER_BYTE: + if (PORT_Memcmp(dhPrime->data, prime_tls_6144, + sizeof(prime_tls_6144)) == 0) { ++ if (g) *g = generator_2; + return &subprime_tls_6144; + } + if (PORT_Memcmp(dhPrime->data, prime_ike_6144, + sizeof(prime_ike_6144)) == 0) { ++ if (g) *g = generator_2; + return &subprime_ike_6144; + } + break; + case 8192 / PR_BITS_PER_BYTE: + if (PORT_Memcmp(dhPrime->data, prime_tls_8192, + sizeof(prime_tls_8192)) == 0) { ++ if (g) *g = generator_2; + return &subprime_tls_8192; + } + if (PORT_Memcmp(dhPrime->data, prime_ike_8192, + sizeof(prime_ike_8192)) == 0) { ++ if (g) *g = generator_2; + return &subprime_ike_8192; + } + break; +diff -up ./lib/softoken/sftkike.c.fips-review ./lib/softoken/sftkike.c +--- ./lib/softoken/sftkike.c.fips-review 2024-06-07 09:26:03.000000000 -0700 ++++ ./lib/softoken/sftkike.c 2024-06-12 12:04:10.641360427 -0700 +@@ -516,6 +516,11 @@ sftk_ike_prf(CK_SESSION_HANDLE hSession, + 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) { diff --git a/nss-3.101-fix-rsa-policy-test.patch b/nss-3.101-fix-rsa-policy-test.patch new file mode 100644 index 0000000..d198548 --- /dev/null +++ b/nss-3.101-fix-rsa-policy-test.patch @@ -0,0 +1,12 @@ +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 diff --git a/nss-3.101-skip-ocsp-if-not-connected.patch b/nss-3.101-skip-ocsp-if-not-connected.patch new file mode 100644 index 0000000..ac68afe --- /dev/null +++ b/nss-3.101-skip-ocsp-if-not-connected.patch @@ -0,0 +1,22 @@ +diff -up ./tests/ssl/ssl.sh.disable_ocsp_policy ./tests/ssl/ssl.sh +--- ./tests/ssl/ssl.sh.disable_ocsp_policy 2024-07-05 14:18:03.985453657 -0700 ++++ ./tests/ssl/ssl.sh 2024-07-05 14:21:59.308250122 -0700 +@@ -968,6 +968,18 @@ ssl_policy_pkix_ocsp() + #verbose="-v" + html_head "Check that OCSP doesn't break if we disable sha1 $NORM_EXT - server $SERVER_MODE/client $CLIENT_MODE" + ++ # if we are running on a build machine that can't tolerate external ++ # references don't run. ++ vfyserv -o wrong.host.badssl.com -d ${P_R_SERVERDIR} > ${P_R_SERVERDIR}/vfy2.out 2>&1 ++ RET=$? ; cat ${P_R_SERVERDIR}/vfy2.out" ++ # 5961 reset by peer ++ grep 5961 ${P_R_SERVERDIR}/vfy2.out ++ GRET=$? ; echo "OCSP: RET=$RET GRET=$GRET" ++ if [ $RET -ne 0 -o $GRET -eq 0 ]; then ++ echo "$SCRIPTNAME: skipping Check that OCSP doesn't break if we disable sha1 $NORM_EXT - server $SERVER_MODE/client $CLIENT_MODE - can't reach external servers" ++ return 0 ++ fi ++ + PKIX_SAVE=${NSS_DISABLE_LIBPKIX_VERIFY-"unset"} + unset NSS_DISABLE_LIBPKIX_VERIFY + diff --git a/nss-3.71-camellia-pkcs12-doc.patch b/nss-3.71-camellia-pkcs12-doc.patch new file mode 100644 index 0000000..f14b5a9 --- /dev/null +++ b/nss-3.71-camellia-pkcs12-doc.patch @@ -0,0 +1,20 @@ +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 + + + Password Encryption +- 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 "NONE" as the argument of the option. ++ 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 "NONE" as the argument of the option. + The private key is always protected with strong encryption by default. + Several types of ciphers are supported. + +@@ -327,6 +327,7 @@ Certificate Friendly Name: Thawte Fre + + + PBES2 with AES-CBC-Pad as underlying encryption scheme ("AES-128-CBC", "AES-192-CBC", and "AES-256-CBC") ++ PBES2 with CAMELLIA-CBC-Pad as underlying encryption scheme ("CAMELLIA-128-CBC", "CAMELLIA-192-CBC", and "CAMELLIA-256-CBC") + + + diff --git a/nss-3.71-fix-lto-gtests.patch b/nss-3.71-fix-lto-gtests.patch new file mode 100644 index 0000000..2699ca3 --- /dev/null +++ b/nss-3.71-fix-lto-gtests.patch @@ -0,0 +1,26 @@ +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 +@@ -15,13 +15,22 @@ + #include "gtest_utils.h" + #include "tls_agent.h" + #include "tls_connect.h" ++#define LTO + + namespace nss_test { + ++#ifndef LTO ++// sigh this construction breaks LTO + const std::string kEcdsaDelegatorId = TlsAgent::kDelegatorEcdsa256; + const std::string kRsaeDelegatorId = TlsAgent::kDelegatorRsae2048; + const std::string kPssDelegatorId = TlsAgent::kDelegatorRsaPss2048; + const std::string kDCId = TlsAgent::kServerEcdsa256; ++#else ++#define kEcdsaDelegatorId TlsAgent::kDelegatorEcdsa256 ++#define kRsaeDelegatorId TlsAgent::kDelegatorRsae2048 ++#define kPssDelegatorId TlsAgent::kDelegatorRsaPss2048 ++#define kDCId TlsAgent::kServerEcdsa256 ++#endif + const SSLSignatureScheme kDCScheme = ssl_sig_ecdsa_secp256r1_sha256; + const PRUint32 kDCValidFor = 60 * 60 * 24 * 7 /* 1 week (seconds) */; + diff --git a/nss-3.79-dbtool.patch b/nss-3.79-dbtool.patch deleted file mode 100644 index b61942b..0000000 --- a/nss-3.79-dbtool.patch +++ /dev/null @@ -1,3411 +0,0 @@ -diff --git a/cmd/dbtool/Makefile b/cmd/dbtool/Makefile -new file mode 100644 ---- /dev/null -+++ b/cmd/dbtool/Makefile -@@ -0,0 +1,46 @@ -+#! gmake -+# -+# This Source Code Form is subject to the terms of the Mozilla Public -+# License, v. 2.0. If a copy of the MPL was not distributed with this -+# file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ -+####################################################################### -+# (1) Include initial platform-independent assignments (MANDATORY). # -+####################################################################### -+ -+include manifest.mn -+ -+####################################################################### -+# (2) Include "global" configuration information. (OPTIONAL) # -+####################################################################### -+ -+include $(CORE_DEPTH)/coreconf/config.mk -+ -+####################################################################### -+# (3) Include "component" configuration information. (OPTIONAL) # -+####################################################################### -+ -+####################################################################### -+# (4) Include "local" platform-dependent assignments (OPTIONAL). # -+####################################################################### -+ -+include ../platlibs.mk -+ -+####################################################################### -+# (5) Execute "global" rules. (OPTIONAL) # -+####################################################################### -+ -+include $(CORE_DEPTH)/coreconf/rules.mk -+ -+####################################################################### -+# (6) Execute "component" rules. (OPTIONAL) # -+####################################################################### -+ -+#include ../platlibs.mk -+ -+####################################################################### -+# (7) Execute "local" rules. (OPTIONAL). # -+####################################################################### -+ -+include ../platrules.mk -+ -diff --git a/cmd/dbtool/dbtool.c b/cmd/dbtool/dbtool.c -new file mode 100644 ---- /dev/null -+++ b/cmd/dbtool/dbtool.c -@@ -0,0 +1,806 @@ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+/* -+** dbtool.c -+** -+** tool to dump the underlying encoding of a database. This tool duplicates -+** some private functions in softoken. It uses libsec and libutil, but no -+** other portions of NSS. It currently only works on sqlite databases. For -+** an even more primitive dump, use sqlite3 on the individual files. -+** -+** TODO: dump the meta data for the databases. -+** optionally dump more PKCS5 information (KDF/salt/iterations) -+** take a password and decode encrypted attributes/verify signed -+** attributes. -+*/ -+#include -+#include -+ -+#if defined(WIN32) -+#include "fcntl.h" -+#include "io.h" -+#endif -+ -+#include "secutil.h" -+#include "pk11pub.h" -+ -+#if defined(XP_UNIX) -+#include -+#endif -+ -+#include "nspr.h" -+#include "prtypes.h" -+#include "certdb.h" -+#include "nss.h" -+#include "../modutil/modutil.h" -+#include "pk11table.h" -+#include "sftkdbt.h" -+#include "sdb.h" -+#include "secoid.h" -+ -+#include "plgetopt.h" -+ -+static char *progName; -+ -+char *dbDir = NULL; -+ -+static void -+Usage() -+{ -+ printf("Usage: %s [-c certprefix] [-k keyprefix] " -+ "[-V certversion] [-v keyversion]\n" -+ " [-d dbdir]\n", -+ progName); -+ printf("%-20s Directory with cert database (default is .)\n", -+ "-d certdir"); -+ printf("%-20s prefix for the cert database (default is \"\")\n", -+ "-c certprefix"); -+ printf("%-20s prefix for the key database (default is \"\")\n", -+ "-k keyprefix"); -+ printf("%-20s version of the cert database (default is 9)\n", -+ "-V certversion"); -+ printf("%-20s version of the key database (default is 4)\n", -+ "-v keyversion"); -+ exit(1); -+} -+#define SFTK_KEYDB_TYPE 0x40000000 -+#define SFTK_TOKEN_TYPE 0x80000000 -+ -+/* -+ * known attributes -+ */ -+static const CK_ATTRIBUTE_TYPE known_attributes[] = { -+ CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_APPLICATION, -+ CKA_VALUE, CKA_OBJECT_ID, CKA_CERTIFICATE_TYPE, CKA_ISSUER, -+ CKA_SERIAL_NUMBER, CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES, CKA_TRUSTED, -+ CKA_CERTIFICATE_CATEGORY, CKA_JAVA_MIDP_SECURITY_DOMAIN, CKA_URL, -+ CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CKA_HASH_OF_ISSUER_PUBLIC_KEY, -+ CKA_CHECK_VALUE, CKA_KEY_TYPE, CKA_SUBJECT, CKA_ID, CKA_SENSITIVE, -+ CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SIGN, CKA_SIGN_RECOVER, -+ CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE, -+ CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, -+ CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT, -+ CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS, -+ CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE, -+ CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE, -+ CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS, -+ CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, -+ CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_WRAP_TEMPLATE, -+ CKA_UNWRAP_TEMPLATE, CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, -+ CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y, CKA_RESOLUTION, CKA_CHAR_ROWS, -+ CKA_CHAR_COLUMNS, CKA_COLOR, CKA_BITS_PER_PIXEL, CKA_CHAR_SETS, -+ CKA_ENCODING_METHODS, CKA_MIME_TYPES, CKA_MECHANISM_TYPE, -+ CKA_REQUIRED_CMS_ATTRIBUTES, CKA_DEFAULT_CMS_ATTRIBUTES, -+ CKA_SUPPORTED_CMS_ATTRIBUTES, CKA_NSS_URL, CKA_NSS_EMAIL, -+ CKA_NSS_SMIME_INFO, CKA_NSS_SMIME_TIMESTAMP, -+ CKA_NSS_PKCS8_SALT, CKA_NSS_PASSWORD_CHECK, CKA_NSS_EXPIRES, -+ CKA_NSS_KRL, CKA_NSS_PQG_COUNTER, CKA_NSS_PQG_SEED, -+ CKA_NSS_PQG_H, CKA_NSS_PQG_SEED_BITS, CKA_NSS_MODULE_SPEC, -+ CKA_TRUST_DIGITAL_SIGNATURE, CKA_TRUST_NON_REPUDIATION, -+ CKA_TRUST_KEY_ENCIPHERMENT, CKA_TRUST_DATA_ENCIPHERMENT, -+ CKA_TRUST_KEY_AGREEMENT, CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN, -+ CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING, -+ CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM, -+ CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING, -+ CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH, -+ CKA_NSS_DB, CKA_NSS_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS, -+ CKA_PUBLIC_KEY_INFO -+}; -+ -+static unsigned int known_attributes_size = sizeof(known_attributes) / -+ sizeof(known_attributes[0]); -+ -+PRBool -+isULONGAttribute(CK_ATTRIBUTE_TYPE type) -+{ -+ switch (type) { -+ case CKA_CERTIFICATE_CATEGORY: -+ case CKA_CERTIFICATE_TYPE: -+ case CKA_CLASS: -+ case CKA_JAVA_MIDP_SECURITY_DOMAIN: -+ case CKA_KEY_GEN_MECHANISM: -+ case CKA_KEY_TYPE: -+ case CKA_MECHANISM_TYPE: -+ case CKA_MODULUS_BITS: -+ case CKA_PRIME_BITS: -+ case CKA_SUBPRIME_BITS: -+ case CKA_VALUE_BITS: -+ case CKA_VALUE_LEN: -+ -+ case CKA_TRUST_DIGITAL_SIGNATURE: -+ case CKA_TRUST_NON_REPUDIATION: -+ case CKA_TRUST_KEY_ENCIPHERMENT: -+ case CKA_TRUST_DATA_ENCIPHERMENT: -+ case CKA_TRUST_KEY_AGREEMENT: -+ case CKA_TRUST_KEY_CERT_SIGN: -+ case CKA_TRUST_CRL_SIGN: -+ -+ case CKA_TRUST_SERVER_AUTH: -+ case CKA_TRUST_CLIENT_AUTH: -+ case CKA_TRUST_CODE_SIGNING: -+ case CKA_TRUST_EMAIL_PROTECTION: -+ case CKA_TRUST_IPSEC_END_SYSTEM: -+ case CKA_TRUST_IPSEC_TUNNEL: -+ case CKA_TRUST_IPSEC_USER: -+ case CKA_TRUST_TIME_STAMPING: -+ case CKA_TRUST_STEP_UP_APPROVED: -+ return PR_TRUE; -+ default: -+ break; -+ } -+ return PR_FALSE; -+} -+ -+/* are the attributes private? */ -+static PRBool -+isPrivateAttribute(CK_ATTRIBUTE_TYPE type) -+{ -+ switch (type) { -+ case CKA_VALUE: -+ case CKA_PRIVATE_EXPONENT: -+ case CKA_PRIME_1: -+ case CKA_PRIME_2: -+ case CKA_EXPONENT_1: -+ case CKA_EXPONENT_2: -+ case CKA_COEFFICIENT: -+ return PR_TRUE; -+ default: -+ break; -+ } -+ return PR_FALSE; -+} -+ -+/* These attributes must be authenticated with an hmac. */ -+static PRBool -+isAuthenticatedAttribute(CK_ATTRIBUTE_TYPE type) -+{ -+ switch (type) { -+ case CKA_MODULUS: -+ case CKA_PUBLIC_EXPONENT: -+ case CKA_CERT_SHA1_HASH: -+ case CKA_CERT_MD5_HASH: -+ case CKA_TRUST_SERVER_AUTH: -+ case CKA_TRUST_CLIENT_AUTH: -+ case CKA_TRUST_EMAIL_PROTECTION: -+ case CKA_TRUST_CODE_SIGNING: -+ case CKA_TRUST_STEP_UP_APPROVED: -+ case CKA_NSS_OVERRIDE_EXTENSIONS: -+ return PR_TRUE; -+ default: -+ break; -+ } -+ return PR_FALSE; -+} -+ -+/* -+ * convert a database ulong back to a native ULONG. (reverse of the above -+ * function. -+ */ -+static CK_ULONG -+sdbULong2ULong(unsigned char *data) -+{ -+ int i; -+ CK_ULONG value = 0; -+ -+ for (i = 0; i < SDB_ULONG_SIZE; i++) { -+ value |= (((CK_ULONG)data[i]) << (SDB_ULONG_SIZE - 1 - i) -+ * PR_BITS_PER_BYTE); -+ } -+ return value; -+} -+ -+/* PBE defines and functions */ -+ -+typedef struct EncryptedDataInfoStr { -+ SECAlgorithmID algorithm; -+ SECItem encryptedData; -+} EncryptedDataInfo; -+ -+static const SEC_ASN1Template encryptedDataInfoTemplate[] = { -+ { SEC_ASN1_SEQUENCE, -+ 0, NULL, sizeof(EncryptedDataInfo) }, -+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, -+ offsetof(EncryptedDataInfo, algorithm), -+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, -+ { SEC_ASN1_OCTET_STRING, -+ offsetof(EncryptedDataInfo, encryptedData) }, -+ { 0 } -+}; -+ -+typedef struct PBEParameterStr { -+ SECAlgorithmID prfAlg; -+ SECItem salt; -+ SECItem iteration; -+ SECItem keyLength; -+} PBEParameter; -+ -+static const SEC_ASN1Template pkcs5V1PBEParameterTemplate[] = -+ { -+ { SEC_ASN1_SEQUENCE, -+ 0, NULL, sizeof(PBEParameter) }, -+ { SEC_ASN1_OCTET_STRING, -+ offsetof(PBEParameter, salt) }, -+ { SEC_ASN1_INTEGER, -+ offsetof(PBEParameter, iteration) }, -+ { 0 } -+ }; -+ -+static const SEC_ASN1Template pkcs12V2PBEParameterTemplate[] = -+ { -+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PBEParameter) }, -+ { SEC_ASN1_OCTET_STRING, offsetof(PBEParameter, salt) }, -+ { SEC_ASN1_INTEGER, offsetof(PBEParameter, iteration) }, -+ { 0 } -+ }; -+ -+ -+static const SEC_ASN1Template pkcs5V2PBEParameterTemplate[] = -+ { -+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PBEParameter) }, -+ /* this is really a choice, but since we don't understand any other -+ * choice, just inline it. */ -+ { SEC_ASN1_OCTET_STRING, offsetof(PBEParameter, salt) }, -+ { SEC_ASN1_INTEGER, offsetof(PBEParameter, iteration) }, -+ { SEC_ASN1_INTEGER, offsetof(PBEParameter, keyLength) }, -+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, -+ offsetof(PBEParameter, prfAlg), -+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, -+ { 0 } -+ }; -+ -+typedef struct Pkcs5v2PBEParameterStr { -+ SECAlgorithmID keyParams; /* parameters of the key generation */ -+ SECAlgorithmID algParams; /* parameters for the encryption or mac op */ -+} Pkcs5v2PBEParameter; -+ -+static const SEC_ASN1Template pkcs5v2PBES2ParameterTemplate[] = { -+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(Pkcs5v2PBEParameter) }, -+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, -+ offsetof(Pkcs5v2PBEParameter, keyParams), -+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, -+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, -+ offsetof(Pkcs5v2PBEParameter, algParams), -+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, -+ { 0 } -+}; -+ -+static inline PRBool -+isPKCS12PBE(SECOidTag alg) { -+ switch (alg) { -+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: -+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: -+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: -+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: -+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: -+ case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: -+ return PR_TRUE; -+ default: -+ break; -+ } -+ return PR_FALSE; -+} -+ -+ -+/* helper functions */ -+ -+/* output an NSS specific attribute or name that wasn't found in our -+ * pkcs #11 table */ -+const char * -+makeNSSVendorName(CK_ATTRIBUTE_TYPE attribute, const char *nameType) -+{ -+ static char nss_name[256]; -+ const char *name = NULL; -+ if ((attribute >= CKA_NSS) && (attribute <= 0xffffffff)) { -+ sprintf(nss_name,"%s+%d", nameType, (int)(attribute-CKA_NSS)); -+ name = nss_name; -+ } -+ return name; -+} -+ -+/* turn and attribute into a name */ -+const char * -+AttributeName(CK_ATTRIBUTE_TYPE attribute) -+{ -+ const char *name = getNameFromAttribute(attribute); -+ if (!name) { -+ name = makeNSSVendorName(attribute, "CKA_NSS"); -+ } -+ -+ return name ? name : "UNKNOWN_ATTRIBUTE_TYPE"; -+} -+ -+/* turn and error code into a name */ -+const char * -+ErrorName(CK_RV crv) -+{ -+ const char *error = getName(crv, ConstResult); -+ if (!error) { -+ error = makeNSSVendorName(crv, "CKR_NSS"); -+ } -+ return error ? error : "UNKNOWN_ERROR"; -+} -+ -+/* turn an oud tag into a string */ -+const char * -+oid2string(SECOidTag alg) -+{ -+ const char *oidstring = SECOID_FindOIDTagDescription(alg); -+ const char *def="Invalid oid tag"; /* future build a dotted oid string value here */ -+ return oidstring ? oidstring : def; -+} -+ -+/* dump an arbitary data blob. Dump it has hex with ascii on the side */ -+#define ASCCHAR(val) ((val) >= ' ' && (val) <= 0x7e ? (val) : '.') -+#define LINE_LENGTH 16 -+void -+dumpValue(const unsigned char *v, int len) -+{ -+ int i, next = 0; -+ char string[LINE_LENGTH+1]; -+ char space[LINE_LENGTH*2+1]; -+ char *nl = ""; -+ char *sp = ""; -+ PORT_Memset(string, 0, sizeof(string)); -+ -+ for (i=0; i < len; i++) { -+ if ((i % LINE_LENGTH) == 0) { -+ printf("%s%s%s ", sp, string, nl); -+ PORT_Memset(string, 0, sizeof(string)); -+ next = 0; -+ nl = "\n"; -+ sp = " "; -+ } -+ printf("%02x", v[i]); -+ string[next++] = ASCCHAR(v[i]); -+ } -+ PORT_Memset(space, 0, sizeof(space)); -+ i = LINE_LENGTH - (len % LINE_LENGTH); -+ if (i != LINE_LENGTH) { -+ int j; -+ for (j=0 ; j < i; j++) { -+ space[j*2] = ' '; -+ space[j*2+1] = ' '; -+ } -+ } -+ printf("%s%s%s%s", space, sp, string, nl); -+} -+ -+/* dump a PKCS5/12 PBE blob */ -+void -+dumpPKCS(unsigned char *val, CK_ULONG len, PRBool *hasSig) -+{ -+ EncryptedDataInfo edi; -+ SECStatus rv; -+ SECItem data; -+ PLArenaPool *arena; -+ SECOidTag alg, prfAlg; -+ PBEParameter pbeParam; -+ unsigned char zero = 0; -+ const SEC_ASN1Template *template = pkcs5V1PBEParameterTemplate; -+ int iter, keyLen, i; -+ -+ if (hasSig) { *hasSig = PR_FALSE; } -+ -+ -+ data.data = val; -+ data.len = len; -+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); -+ if (arena == NULL) { -+ printf("Couldn't allocate arena\n"); -+ return; -+ } -+ -+ /* initialize default values */ -+ PORT_Memset(&pbeParam, 0, sizeof(pbeParam)); -+ pbeParam.keyLength.data = &zero; -+ pbeParam.keyLength.len = sizeof(zero); -+ SECOID_SetAlgorithmID(arena, &pbeParam.prfAlg, SEC_OID_SHA1, NULL); -+ -+ /* first crack the encrypted data from the PBE algorithm ID */ -+ rv = SEC_QuickDERDecodeItem(arena, &edi, encryptedDataInfoTemplate, &data); -+ if (rv != SECSuccess) { -+ printf("Encrypted Data, failed to decode\n"); -+ dumpValue(val,len); -+ PORT_FreeArena(arena, PR_FALSE); -+ return; -+ } -+ /* now use the pbe secalg to dump info on the pbe */ -+ alg = SECOID_GetAlgorithmTag(&edi.algorithm); -+ if ((alg == SEC_OID_PKCS5_PBES2) || (alg == SEC_OID_PKCS5_PBMAC1)){ -+ Pkcs5v2PBEParameter param; -+ SECOidTag palg; -+ const char *typeName = (alg == SEC_OID_PKCS5_PBES2) ? -+ "Encrypted Data PBES2" : -+ "Mac Data PBMAC1"; -+ -+ rv = SEC_QuickDERDecodeItem(arena, ¶m, -+ pkcs5v2PBES2ParameterTemplate, -+ &edi.algorithm.parameters); -+ if (rv != SECSuccess) { -+ printf("%s, failed to decode\n", typeName); -+ dumpValue(val,len); -+ PORT_FreeArena(arena, PR_FALSE); -+ return; -+ } -+ palg = SECOID_GetAlgorithmTag(¶m.algParams); -+ printf("%s alg=%s ", typeName, oid2string(palg)); -+ if (hasSig && palg == SEC_OID_AES_256_CBC) { -+ *hasSig = PR_TRUE; -+ } -+ template = pkcs5V2PBEParameterTemplate; -+ edi.algorithm.parameters = param.keyParams.parameters; -+ } else { -+ printf("Encrypted Data alg=%s ", oid2string(alg)); -+ if (alg == SEC_OID_PKCS5_PBKDF2) { -+ template = pkcs5V2PBEParameterTemplate; -+ } else if (isPKCS12PBE(alg)) { -+ template = pkcs12V2PBEParameterTemplate; -+ } else { -+ template = pkcs5V1PBEParameterTemplate; -+ } -+ } -+ rv = SEC_QuickDERDecodeItem(arena, &pbeParam, -+ template, -+ &edi.algorithm.parameters); -+ if (rv != SECSuccess) { -+ printf("( failed to decode params)\n"); -+ PORT_FreeArena(arena, PR_FALSE); -+ return; -+ } -+ /* dump the pbe parmeters */ -+ iter = DER_GetInteger(&pbeParam.iteration); -+ keyLen = DER_GetInteger(&pbeParam.keyLength); -+ prfAlg = SECOID_GetAlgorithmTag(&pbeParam.prfAlg); -+ printf("(prf=%s iter=%d keyLen=%d salt=0x", -+ oid2string(prfAlg), iter, keyLen); -+ for(i=0;i < pbeParam.salt.len; i++) printf("%02x",pbeParam.salt.data[i]); -+ printf(")\n"); -+ /* finally dump the raw encrypted data */ -+ dumpValue(edi.encryptedData.data, edi.encryptedData.len); -+ PORT_FreeArena(arena, PR_FALSE); -+} -+ -+/* dump a long attribute, convert to an unsigned long. PKCS #11 Longs are -+ * limited to 32 bits by the spec, even if the CK_ULONG is longer */ -+void -+dumpLongAttribute(CK_ATTRIBUTE_TYPE type, CK_ULONG value) -+{ -+ const char *nameType = "CK_NSS"; -+ ConstType constType = ConstNone; -+ const char *valueName = NULL; -+ -+ switch (type) { -+ case CKA_CLASS: -+ nameType = "CKO_NSS"; -+ constType = ConstObject; -+ break; -+ case CKA_CERTIFICATE_TYPE: -+ nameType = "CKC_NSS"; -+ constType = ConstCertType; -+ break; -+ case CKA_KEY_TYPE: -+ nameType = "CKK_NSS"; -+ constType = ConstKeyType; -+ break; -+ case CKA_MECHANISM_TYPE: -+ nameType = "CKM_NSS"; -+ constType = ConstMechanism; -+ break; -+ case CKA_TRUST_SERVER_AUTH: -+ case CKA_TRUST_CLIENT_AUTH: -+ case CKA_TRUST_CODE_SIGNING: -+ case CKA_TRUST_EMAIL_PROTECTION: -+ case CKA_TRUST_IPSEC_END_SYSTEM: -+ case CKA_TRUST_IPSEC_TUNNEL: -+ case CKA_TRUST_IPSEC_USER: -+ case CKA_TRUST_TIME_STAMPING: -+ nameType = "CKT_NSS"; -+ constType = ConstTrust; -+ break; -+ default: -+ break; -+ } -+ /* if value has a symbolic name, use it */ -+ if (constType != ConstNone) { -+ valueName = getName(value, constType); -+ } -+ if (!valueName) { -+ valueName = makeNSSVendorName(value, nameType); -+ } -+ if (!valueName) { -+ printf("%d (0x%08x)\n", (int) value, (int)value); -+ } else { -+ printf("%s (0x%08x)\n", valueName, (int)value); -+ } -+} -+ -+/* dump a signature for an object */ -+static const char META_SIG_TEMPLATE[] = "sig_%s_%08x_%08x"; -+void -+dumpSignature(CK_ATTRIBUTE_TYPE attribute, SDB *keydb, PRBool isKey, -+ CK_OBJECT_HANDLE objectID, PRBool force) -+{ -+ char id[30]; -+ CK_RV crv; -+ SECItem signText; -+ unsigned char signData[SDB_MAX_META_DATA_LEN]; -+ -+ if (!force && !isAuthenticatedAttribute(attribute)) { -+ return; -+ } -+ sprintf(id, META_SIG_TEMPLATE, -+ isKey ? "key" : "cert", -+ (unsigned int)objectID, (unsigned int)attribute); -+ printf(" Signature %s:",id); -+ signText.data = signData; -+ signText.len = sizeof(signData); -+ -+ -+ crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL); -+ if ((crv != CKR_OK) && isKey) { -+ sprintf(id, META_SIG_TEMPLATE, -+ isKey ? "key" : "cert", (unsigned int) -+ (objectID | SFTK_KEYDB_TYPE | SFTK_TOKEN_TYPE), -+ (unsigned int)attribute); -+ crv = (*keydb->sdb_GetMetaData)(keydb, id, &signText, NULL); -+ } -+ if (crv != CKR_OK) { -+ printf(" FAILED %s with %s (0x%08x)\n", id, ErrorName(crv), (int) crv); -+ return; -+ } -+ dumpPKCS(signText.data, signText.len, NULL); -+ return; -+} -+ -+/* dump an attribute. use the helper functions above */ -+void -+dumpAttribute(CK_ATTRIBUTE *template, SDB *keydb, PRBool isKey, -+ CK_OBJECT_HANDLE id) -+{ -+ CK_ATTRIBUTE_TYPE attribute = template->type; -+ printf(" %s(0x%08x): ", AttributeName(attribute), (int)attribute); -+ if (template->pValue == NULL) { -+ printf("NULL (%d)\n", (int)template->ulValueLen); -+ return; -+ } -+ if (template->ulValueLen == SDB_ULONG_SIZE -+ && isULONGAttribute(attribute)) { -+ CK_ULONG value=sdbULong2ULong(template->pValue); -+ dumpLongAttribute(attribute, value); -+ return; -+ } -+ if (template->ulValueLen == 1) { -+ unsigned char val = *(unsigned char *)template->pValue; -+ switch (val) { -+ case 0: -+ printf("CK_FALSE\n"); -+ break; -+ case 1: -+ printf("CK_TRUE\n"); -+ break; -+ default: -+ printf("%d 0x%02x %c\n", val, val, ASCCHAR(val)); -+ break; -+ } -+ return; -+ } -+ if (isKey && isPrivateAttribute(attribute)) { -+ PRBool hasSig = PR_FALSE; -+ dumpPKCS(template->pValue, template->ulValueLen, &hasSig); -+ if (hasSig) { -+ dumpSignature(attribute, keydb, isKey, id, PR_TRUE); -+ } -+ return; -+ } -+ if (template->ulValueLen == 0) { printf("empty"); } -+ printf("\n"); -+ dumpValue(template->pValue, template->ulValueLen); -+} -+ -+/* dump all the attributes in an object */ -+void -+dumpObject(CK_OBJECT_HANDLE id, SDB *db, SDB *keydb, PRBool isKey) -+{ -+ CK_RV crv; -+ int i; -+ CK_ATTRIBUTE template; -+ char buffer[2048]; -+ char * alloc = NULL; -+ -+ printf(" Object 0x%08x:\n", (int)id); -+ for (i = 0; i < known_attributes_size; i++) { -+ CK_ATTRIBUTE_TYPE attribute = known_attributes[i]; -+ template.type = attribute; -+ template.pValue = NULL; -+ template.ulValueLen = 0; -+ crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1); -+ -+ if (crv != CKR_OK) { -+ if (crv != CKR_ATTRIBUTE_TYPE_INVALID) { -+ PR_fprintf(PR_STDERR, " " -+ "Get Attribute %s (0x%08x):FAILED\"%s\"(0x%08x)\n", -+ AttributeName(attribute), (int)attribute, -+ ErrorName(crv), (int)crv); -+ } -+ continue; -+ } -+ -+ if (template.ulValueLen < sizeof(buffer)) { -+ template.pValue = buffer; -+ } else { -+ alloc = PORT_Alloc(template.ulValueLen); -+ template.pValue = alloc; -+ } -+ if (template.pValue == NULL) { -+ PR_fprintf(PR_STDERR, " " -+ "Could allocate %d bytes for Attribute %s (0x%08x)\n", -+ (int) template.ulValueLen, -+ AttributeName(attribute), (int)attribute); -+ continue; -+ } -+ crv = (*db->sdb_GetAttributeValue)(db, id, &template, 1); -+ -+ if (crv != CKR_OK) { -+ if (crv != CKR_ATTRIBUTE_TYPE_INVALID) { -+ PR_fprintf(PR_STDERR, " " -+ "Get Attribute %s (0x%08x):FAILED\"%s\"(0x%08x)\n", -+ AttributeName(attribute), (int)attribute, -+ ErrorName(crv), (int)crv); -+ } -+ if (alloc) { -+ PORT_Free(alloc); -+ alloc = NULL; -+ } -+ continue; -+ } -+ -+ dumpAttribute(&template, keydb, isKey, id); -+ dumpSignature(template.type, keydb, isKey, id, PR_FALSE); -+ if (alloc) { -+ PORT_Free(alloc); -+ alloc = NULL; -+ } -+ } -+} -+ -+/* dump all the objects in a database */ -+void -+dumpDB(SDB *db, const char *name, SDB *keydb, PRBool isKey) -+{ -+ SDBFind *findHandle= NULL; -+ CK_BBOOL isTrue = 1; -+ CK_ATTRIBUTE allObjectTemplate = {CKA_TOKEN, NULL, 1 }; -+ CK_ULONG allObjectTemplateCount = 1; -+ PRBool recordFound = PR_FALSE; -+ CK_RV crv = CKR_OK; -+ CK_ULONG objectCount = 0; -+ printf("%s:\n",name); -+ -+ allObjectTemplate.pValue = &isTrue; -+ crv = (*db->sdb_FindObjectsInit)(db, &allObjectTemplate, -+ allObjectTemplateCount, &findHandle); -+ do { -+ CK_OBJECT_HANDLE id; -+ recordFound = PR_FALSE; -+ crv =(*db->sdb_FindObjects)(db, findHandle, &id, 1, &objectCount); -+ if ((crv == CKR_OK) && (objectCount == 1)) { -+ recordFound = PR_TRUE; -+ dumpObject(id, db, keydb, isKey); -+ } -+ } while (recordFound); -+ if (crv != CKR_OK) { -+ PR_fprintf(PR_STDERR, -+ "Last record return PKCS #11 error = %s (0x%08x)\n", -+ ErrorName(crv), (int)crv); -+ } -+ (*db->sdb_FindObjectsFinal)(db,findHandle); -+} -+ -+int -+main(int argc, char **argv) -+{ -+ PLOptState *optstate; -+ PLOptStatus optstatus; -+ char *certPrefix="", *keyPrefix=""; -+ int cert_version = 9; -+ int key_version = 4; -+ SDB *certdb = NULL; -+ SDB *keydb = NULL; -+ PRBool isNew = PR_FALSE; -+ -+ CK_RV crv; -+ -+ progName = strrchr(argv[0], '/'); -+ if (!progName) -+ progName = strrchr(argv[0], '\\'); -+ progName = progName ? progName + 1 : argv[0]; -+ -+ optstate = PL_CreateOptState(argc, argv, "d:c:k:v:V:h"); -+ -+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { -+ switch (optstate->option) { -+ case 'h': -+ default: -+ Usage(); -+ break; -+ -+ case 'd': -+ dbDir = PORT_Strdup(optstate->value); -+ break; -+ -+ case 'c': -+ certPrefix = PORT_Strdup(optstate->value); -+ break; -+ -+ case 'k': -+ keyPrefix = PORT_Strdup(optstate->value); -+ break; -+ -+ case 'v': -+ key_version = atoi(optstate->value); -+ break; -+ -+ case 'V': -+ cert_version = atoi(optstate->value); -+ break; -+ -+ } -+ } -+ PL_DestroyOptState(optstate); -+ if (optstatus == PL_OPT_BAD) -+ Usage(); -+ -+ if (dbDir) { -+ char *tmp = dbDir; -+ dbDir = SECU_ConfigDirectory(tmp); -+ PORT_Free(tmp); -+ } else { -+ /* Look in $SSL_DIR */ -+ dbDir = SECU_ConfigDirectory(SECU_DefaultSSLDir()); -+ } -+ PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir); -+ -+ if (dbDir[0] == '\0') { -+ PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir); -+ return 1; -+ } -+ -+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); -+ SECOID_Init(); -+ -+ crv = s_open(dbDir, certPrefix, keyPrefix, cert_version, key_version, -+ SDB_RDONLY, &certdb, &keydb, &isNew); -+ if (crv != CKR_OK) { -+ PR_fprintf(PR_STDERR, -+ "Couldn't open databased in %s, error=%s (0x%08x)\n", -+ dbDir, ErrorName(crv), (int)crv); -+ return 1; -+ } -+ -+ /* now dump the objects in the cert database */ -+ dumpDB(certdb, "CertDB", keydb, PR_FALSE); -+ dumpDB(keydb, "KeyDB", keydb, PR_TRUE); -+ return 0; -+} -diff --git a/cmd/dbtool/dbtool.gyp b/cmd/dbtool/dbtool.gyp -new file mode 100644 ---- /dev/null -+++ b/cmd/dbtool/dbtool.gyp -@@ -0,0 +1,25 @@ -+# This Source Code Form is subject to the terms of the Mozilla Public -+# License, v. 2.0. If a copy of the MPL was not distributed with this -+# file, You can obtain one at http://mozilla.org/MPL/2.0/. -+{ -+ 'includes': [ -+ '../../coreconf/config.gypi', -+ '../../cmd/platlibs.gypi' -+ ], -+ 'targets': [ -+ { -+ 'target_name': 'dbtest', -+ 'type': 'executable', -+ 'sources': [ -+ 'dbtest.c' -+ ], -+ 'dependencies': [ -+ '<(DEPTH)/exports.gyp:dbm_exports', -+ '<(DEPTH)/exports.gyp:nss_exports' -+ ] -+ } -+ ], -+ 'variables': { -+ 'module': 'nss' -+ } -+} -\ No newline at end of file -diff --git a/cmd/dbtool/manifest.mn b/cmd/dbtool/manifest.mn -new file mode 100644 ---- /dev/null -+++ b/cmd/dbtool/manifest.mn -@@ -0,0 +1,18 @@ -+# -+# This Source Code Form is subject to the terms of the Mozilla Public -+# License, v. 2.0. If a copy of the MPL was not distributed with this -+# file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ -+CORE_DEPTH = ../.. -+ -+# MODULE public and private header directories are implicitly REQUIRED. -+MODULE = nss -+ -+USE_STATIC_LIBS = 1 -+ -+# DIRS = -+ -+CSRCS = dbtool.c sdb.c -+ -+PROGRAM = dbtool -+ -diff --git a/cmd/dbtool/sdb.c b/cmd/dbtool/sdb.c -new file mode 100644 ---- /dev/null -+++ b/cmd/dbtool/sdb.c -@@ -0,0 +1,2469 @@ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+/* -+ * This file implements PKCS 11 on top of our existing security modules -+ * -+ * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. -+ * This implementation has two slots: -+ * slot 1 is our generic crypto support. It does not require login. -+ * It supports Public Key ops, and all they bulk ciphers and hashes. -+ * It can also support Private Key ops for imported Private keys. It does -+ * not have any token storage. -+ * slot 2 is our private key support. It requires a login before use. It -+ * can store Private Keys and Certs as token objects. Currently only private -+ * keys and their associated Certificates are saved on the token. -+ * -+ * In this implementation, session objects are only visible to the session -+ * that created or generated them. -+ */ -+ -+#include "sdb.h" -+#include "pkcs11t.h" -+#include "seccomon.h" -+#include -+#include "prthread.h" -+#include "prio.h" -+#include -+#include "secport.h" -+#include "prmon.h" -+#include "prenv.h" -+#include "prprf.h" -+#include "prsystem.h" /* for PR_GetDirectorySeparator() */ -+#include -+#if defined(_WIN32) -+#include -+#include -+#elif defined(XP_UNIX) -+#include -+#endif -+#if defined(LINUX) && !defined(ANDROID) -+#include -+#include -+#endif -+#include "utilpars.h" -+ -+#ifdef SQLITE_UNSAFE_THREADS -+#include "prlock.h" -+/* -+ * SQLite can be compiled to be thread safe or not. -+ * turn on SQLITE_UNSAFE_THREADS if the OS does not support -+ * a thread safe version of sqlite. -+ */ -+static PRLock *sqlite_lock = NULL; -+ -+#define LOCK_SQLITE() PR_Lock(sqlite_lock); -+#define UNLOCK_SQLITE() PR_Unlock(sqlite_lock); -+#else -+#define LOCK_SQLITE() -+#define UNLOCK_SQLITE() -+#endif -+ -+typedef enum { -+ SDB_CERT = 1, -+ SDB_KEY = 2 -+} sdbDataType; -+ -+/* -+ * defines controlling how long we wait to acquire locks. -+ * -+ * SDB_SQLITE_BUSY_TIMEOUT specifies how long (in milliseconds) -+ * sqlite will wait on lock. If that timeout expires, sqlite will -+ * return SQLITE_BUSY. -+ * SDB_BUSY_RETRY_TIME specifies how many seconds the sdb_ code waits -+ * after receiving a busy before retrying. -+ * SDB_MAX_BUSY_RETRIES specifies how many times the sdb_ will retry on -+ * a busy condition. -+ * -+ * SDB_SQLITE_BUSY_TIMEOUT affects all opertions, both manual -+ * (prepare/step/reset/finalize) and automatic (sqlite3_exec()). -+ * SDB_BUSY_RETRY_TIME and SDB_MAX_BUSY_RETRIES only affect manual operations -+ * -+ * total wait time for automatic operations: -+ * 1 second (SDB_SQLITE_BUSY_TIMEOUT/1000). -+ * total wait time for manual operations: -+ * (1 second + SDB_BUSY_RETRY_TIME) * 30 = 30 seconds. -+ * (SDB_SQLITE_BUSY_TIMEOUT/1000 + SDB_BUSY_RETRY_TIME)*SDB_MAX_BUSY_RETRIES -+ */ -+#define SDB_SQLITE_BUSY_TIMEOUT 1000 /* milliseconds */ -+#define SDB_BUSY_RETRY_TIME 5 /* 'ticks', varies by platforms */ -+#define SDB_MAX_BUSY_RETRIES 30 -+ -+/* -+ * known attributes -+ */ -+static const CK_ATTRIBUTE_TYPE known_attributes[] = { -+ CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_APPLICATION, -+ CKA_VALUE, CKA_OBJECT_ID, CKA_CERTIFICATE_TYPE, CKA_ISSUER, -+ CKA_SERIAL_NUMBER, CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES, CKA_TRUSTED, -+ CKA_CERTIFICATE_CATEGORY, CKA_JAVA_MIDP_SECURITY_DOMAIN, CKA_URL, -+ CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CKA_HASH_OF_ISSUER_PUBLIC_KEY, -+ CKA_CHECK_VALUE, CKA_KEY_TYPE, CKA_SUBJECT, CKA_ID, CKA_SENSITIVE, -+ CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SIGN, CKA_SIGN_RECOVER, -+ CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE, -+ CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, -+ CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT, -+ CKA_PUBLIC_KEY_INFO, CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS, -+ CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE, -+ CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE, -+ CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS, -+ CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, -+ CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_HW_FEATURE_TYPE, -+ CKA_RESET_ON_INIT, CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y, -+ CKA_RESOLUTION, CKA_CHAR_ROWS, CKA_CHAR_COLUMNS, CKA_COLOR, -+ CKA_BITS_PER_PIXEL, CKA_CHAR_SETS, CKA_ENCODING_METHODS, CKA_MIME_TYPES, -+ CKA_MECHANISM_TYPE, CKA_REQUIRED_CMS_ATTRIBUTES, -+ CKA_DEFAULT_CMS_ATTRIBUTES, CKA_SUPPORTED_CMS_ATTRIBUTES, -+ CKA_WRAP_TEMPLATE, CKA_UNWRAP_TEMPLATE, CKA_NSS_TRUST, CKA_NSS_URL, -+ CKA_NSS_EMAIL, CKA_NSS_SMIME_INFO, CKA_NSS_SMIME_TIMESTAMP, -+ CKA_NSS_PKCS8_SALT, CKA_NSS_PASSWORD_CHECK, CKA_NSS_EXPIRES, -+ CKA_NSS_KRL, CKA_NSS_PQG_COUNTER, CKA_NSS_PQG_SEED, -+ CKA_NSS_PQG_H, CKA_NSS_PQG_SEED_BITS, CKA_NSS_MODULE_SPEC, -+ CKA_NSS_OVERRIDE_EXTENSIONS, CKA_NSS_SERVER_DISTRUST_AFTER, -+ CKA_NSS_EMAIL_DISTRUST_AFTER, CKA_TRUST_DIGITAL_SIGNATURE, -+ CKA_TRUST_NON_REPUDIATION, CKA_TRUST_KEY_ENCIPHERMENT, -+ CKA_TRUST_DATA_ENCIPHERMENT, CKA_TRUST_KEY_AGREEMENT, -+ CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN, CKA_TRUST_SERVER_AUTH, -+ CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING, CKA_TRUST_EMAIL_PROTECTION, -+ CKA_TRUST_IPSEC_END_SYSTEM, CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, -+ CKA_TRUST_TIME_STAMPING, CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, -+ CKA_CERT_MD5_HASH, CKA_NSS_DB -+}; -+ -+static const int known_attributes_size = PR_ARRAY_SIZE(known_attributes); -+ -+/* -+ * Note on use of sqlReadDB: Only one thread at a time may have an actual -+ * operation going on given sqlite3 * database. An operation is defined as -+ * the time from a sqlite3_prepare() until the sqlite3_finalize(). -+ * Multiple sqlite3 * databases can be open and have simultaneous operations -+ * going. We use the sqlXactDB for all write operations. This database -+ * is only opened when we first create a transaction and closed when the -+ * transaction is complete. sqlReadDB is open when we first opened the database -+ * and is used for all read operation. It's use is protected by a monitor. This -+ * is because an operation can span the use of FindObjectsInit() through the -+ * call to FindObjectsFinal(). In the intermediate time it is possible to call -+ * other operations like NSC_GetAttributeValue */ -+ -+struct SDBPrivateStr { -+ char *sqlDBName; /* invariant, path to this database */ -+ sqlite3 *sqlXactDB; /* access protected by dbMon, use protected -+ * by the transaction. Current transaction db*/ -+ PRThread *sqlXactThread; /* protected by dbMon, -+ * current transaction thread */ -+ sqlite3 *sqlReadDB; /* use protected by dbMon, value invariant */ -+ PRIntervalTime lastUpdateTime; /* last time the cache was updated */ -+ PRIntervalTime updateInterval; /* how long the cache can go before it -+ * must be updated again */ -+ sdbDataType type; /* invariant, database type */ -+ char *table; /* invariant, SQL table which contains the db */ -+ char *cacheTable; /* invariant, SQL table cache of db */ -+ PRMonitor *dbMon; /* invariant, monitor to protect -+ * sqlXact* fields, and use of the sqlReadDB */ -+ CK_ATTRIBUTE_TYPE *schemaAttrs; /* Attribute columns that exist in the table. */ -+ unsigned int numSchemaAttrs; -+}; -+ -+typedef struct SDBPrivateStr SDBPrivate; -+ -+/* Magic for an explicit NULL. NOTE: ideally this should be -+ * out of band data. Since it's not completely out of band, pick -+ * a value that has no meaning to any existing PKCS #11 attributes. -+ * This value is 1) not a valid string (imbedded '\0'). 2) not a U_LONG -+ * or a normal key (too short). 3) not a bool (too long). 4) not an RSA -+ * public exponent (too many bits). -+ */ -+const unsigned char SQLITE_EXPLICIT_NULL[] = { 0xa5, 0x0, 0x5a }; -+#define SQLITE_EXPLICIT_NULL_LEN 3 -+ -+/* -+ * determine when we've completed our tasks -+ */ -+static int -+sdb_done(int err, int *count) -+{ -+ /* allow as many rows as the database wants to give */ -+ if (err == SQLITE_ROW) { -+ *count = 0; -+ return 0; -+ } -+ if (err != SQLITE_BUSY) { -+ return 1; -+ } -+ /* err == SQLITE_BUSY, Dont' retry forever in this case */ -+ if (++(*count) >= SDB_MAX_BUSY_RETRIES) { -+ return 1; -+ } -+ return 0; -+} -+ -+#if defined(_WIN32) -+/* -+ * NSPR functions and narrow CRT functions do not handle UTF-8 file paths that -+ * sqlite3 expects. -+ */ -+ -+static int -+sdb_chmod(const char *filename, int pmode) -+{ -+ int result; -+ -+ if (!filename) { -+ return -1; -+ } -+ -+ wchar_t *filenameWide = _NSSUTIL_UTF8ToWide(filename); -+ if (!filenameWide) { -+ return -1; -+ } -+ result = _wchmod(filenameWide, pmode); -+ PORT_Free(filenameWide); -+ -+ return result; -+} -+#else -+#define sdb_chmod(filename, pmode) chmod((filename), (pmode)) -+#endif -+ -+/* -+ * find out where sqlite stores the temp tables. We do this by replicating -+ * the logic from sqlite. -+ */ -+#if defined(_WIN32) -+static char * -+sdb_getFallbackTempDir(void) -+{ -+ /* sqlite uses sqlite3_temp_directory if it is not NULL. We don't have -+ * access to sqlite3_temp_directory because it is not exported from -+ * sqlite3.dll. Assume sqlite3_win32_set_directory isn't called and -+ * sqlite3_temp_directory is NULL. -+ */ -+ char path[MAX_PATH]; -+ DWORD rv; -+ size_t len; -+ -+ rv = GetTempPathA(MAX_PATH, path); -+ if (rv > MAX_PATH || rv == 0) -+ return NULL; -+ len = strlen(path); -+ if (len == 0) -+ return NULL; -+ /* The returned string ends with a backslash, for example, "C:\TEMP\". */ -+ if (path[len - 1] == '\\') -+ path[len - 1] = '\0'; -+ return PORT_Strdup(path); -+} -+#elif defined(XP_UNIX) -+static char * -+sdb_getFallbackTempDir(void) -+{ -+ const char *azDirs[] = { -+ NULL, -+ NULL, -+ "/var/tmp", -+ "/usr/tmp", -+ "/tmp", -+ NULL /* List terminator */ -+ }; -+ unsigned int i; -+ struct stat buf; -+ const char *zDir = NULL; -+ -+ azDirs[0] = sqlite3_temp_directory; -+ azDirs[1] = PR_GetEnvSecure("TMPDIR"); -+ -+ for (i = 0; i < PR_ARRAY_SIZE(azDirs); i++) { -+ zDir = azDirs[i]; -+ if (zDir == NULL) -+ continue; -+ if (stat(zDir, &buf)) -+ continue; -+ if (!S_ISDIR(buf.st_mode)) -+ continue; -+ if (access(zDir, 07)) -+ continue; -+ break; -+ } -+ -+ if (zDir == NULL) -+ return NULL; -+ return PORT_Strdup(zDir); -+} -+#else -+#error "sdb_getFallbackTempDir not implemented" -+#endif -+ -+#ifndef SQLITE_FCNTL_TEMPFILENAME -+/* SQLITE_FCNTL_TEMPFILENAME was added in SQLite 3.7.15 */ -+#define SQLITE_FCNTL_TEMPFILENAME 16 -+#endif -+ -+static char * -+sdb_getTempDir(sqlite3 *sqlDB) -+{ -+ int sqlrv; -+ char *result = NULL; -+ char *tempName = NULL; -+ char *foundSeparator = NULL; -+ -+ /* Obtain temporary filename in sqlite's directory for temporary tables */ -+ sqlrv = sqlite3_file_control(sqlDB, 0, SQLITE_FCNTL_TEMPFILENAME, -+ (void *)&tempName); -+ if (sqlrv == SQLITE_NOTFOUND) { -+ /* SQLITE_FCNTL_TEMPFILENAME not implemented because we are using -+ * an older SQLite. */ -+ return sdb_getFallbackTempDir(); -+ } -+ if (sqlrv != SQLITE_OK) { -+ return NULL; -+ } -+ -+ /* We'll extract the temporary directory from tempName */ -+ foundSeparator = PORT_Strrchr(tempName, PR_GetDirectorySeparator()); -+ if (foundSeparator) { -+ /* We shorten the temp filename string to contain only -+ * the directory name (including the trailing separator). -+ * We know the byte after the foundSeparator position is -+ * safe to use, in the shortest scenario it contains the -+ * end-of-string byte. -+ * By keeping the separator at the found position, it will -+ * even work if tempDir consists of the separator, only. -+ * (In this case the toplevel directory will be used for -+ * access speed testing). */ -+ ++foundSeparator; -+ *foundSeparator = 0; -+ -+ /* Now we copy the directory name for our caller */ -+ result = PORT_Strdup(tempName); -+ } -+ -+ sqlite3_free(tempName); -+ return result; -+} -+ -+/* -+ * Map SQL_LITE errors to PKCS #11 errors as best we can. -+ */ -+static CK_RV -+sdb_mapSQLError(sdbDataType type, int sqlerr) -+{ -+ switch (sqlerr) { -+ /* good matches */ -+ case SQLITE_OK: -+ case SQLITE_DONE: -+ return CKR_OK; -+ case SQLITE_NOMEM: -+ return CKR_HOST_MEMORY; -+ case SQLITE_READONLY: -+ return CKR_TOKEN_WRITE_PROTECTED; -+ /* close matches */ -+ case SQLITE_AUTH: -+ case SQLITE_PERM: -+ /*return CKR_USER_NOT_LOGGED_IN; */ -+ case SQLITE_CANTOPEN: -+ case SQLITE_NOTFOUND: -+ /* NSS distiguishes between failure to open the cert and the key db */ -+ return type == SDB_CERT ? CKR_NSS_CERTDB_FAILED : CKR_NSS_KEYDB_FAILED; -+ case SQLITE_IOERR: -+ return CKR_DEVICE_ERROR; -+ default: -+ break; -+ } -+ return CKR_GENERAL_ERROR; -+} -+ -+/* -+ * build up database name from a directory, prefix, name, version and flags. -+ */ -+static char * -+sdb_BuildFileName(const char *directory, -+ const char *prefix, const char *type, -+ int version) -+{ -+ char *dbname = NULL; -+ /* build the full dbname */ -+ dbname = sqlite3_mprintf("%s%c%s%s%d.db", directory, -+ (int)(unsigned char)PR_GetDirectorySeparator(), -+ prefix, type, version); -+ return dbname; -+} -+ -+/* -+ * find out how expensive the access system call is for non-existant files -+ * in the given directory. Return the number of operations done in 33 ms. -+ */ -+static PRUint32 -+sdb_measureAccess(const char *directory) -+{ -+ PRUint32 i; -+ PRIntervalTime time; -+ PRIntervalTime delta; -+ PRIntervalTime duration = PR_MillisecondsToInterval(33); -+ const char *doesntExistName = "_dOeSnotExist_.db"; -+ char *temp, *tempStartOfFilename; -+ size_t maxTempLen, maxFileNameLen, directoryLength, tmpdirLength = 0; -+#ifdef SDB_MEASURE_USE_TEMP_DIR -+ /* -+ * on some OS's and Filesystems, creating a bunch of files and deleting -+ * them messes up the systems's caching, but if we create the files in -+ * a temp directory which we later delete, then the cache gets cleared -+ * up. This code uses several OS dependent calls, and it's not clear -+ * that temp directory use won't mess up other filesystems and OS caching, -+ * so if you need this for your OS, you can turn on the -+ * 'SDB_MEASURE_USE_TEMP_DIR' define in coreconf -+ */ -+ const char template[] = "dbTemp.XXXXXX"; -+ tmpdirLength = sizeof(template); -+#endif -+ /* no directory, just return one */ -+ if (directory == NULL) { -+ return 1; -+ } -+ -+ /* our calculation assumes time is a 4 bytes == 32 bit integer */ -+ PORT_Assert(sizeof(time) == 4); -+ -+ directoryLength = strlen(directory); -+ -+ maxTempLen = directoryLength + 1 /* dirname + / */ -+ + tmpdirLength /* tmpdirname includes / */ -+ + strlen(doesntExistName) /* filename base */ -+ + 11 /* max chars for 32 bit int plus potential sign */ -+ + 1; /* zero terminator */ -+ -+ temp = PORT_ZAlloc(maxTempLen); -+ if (!temp) { -+ return 1; -+ } -+ -+ /* We'll copy directory into temp just once, then ensure it ends -+ * with the directory separator. */ -+ -+ strcpy(temp, directory); -+ if (directory[directoryLength - 1] != PR_GetDirectorySeparator()) { -+ temp[directoryLength++] = PR_GetDirectorySeparator(); -+ } -+ -+#ifdef SDB_MEASURE_USE_TEMP_DIR -+ /* add the template for a temporary subdir, and create it */ -+ strcat(temp, template); -+ if (!mkdtemp(temp)) { -+ PORT_Free(temp); -+ return 1; -+ } -+ /* and terminate that tmp subdir with a / */ -+ strcat(temp, "/"); -+#endif -+ -+ /* Remember the position after the last separator, and calculate the -+ * number of remaining bytes. */ -+ tempStartOfFilename = temp + directoryLength + tmpdirLength; -+ maxFileNameLen = maxTempLen - directoryLength; -+ -+ /* measure number of Access operations that can be done in 33 milliseconds -+ * (1/30'th of a second), or 10000 operations, which ever comes first. -+ */ -+ time = PR_IntervalNow(); -+ for (i = 0; i < 10000u; i++) { -+ PRIntervalTime next; -+ -+ /* We'll use the variable part first in the filename string, just in -+ * case it's longer than assumed, so if anything gets cut off, it -+ * will be cut off from the constant part. -+ * This code assumes the directory name at the beginning of -+ * temp remains unchanged during our loop. */ -+ PR_snprintf(tempStartOfFilename, maxFileNameLen, -+ ".%lu%s", (PRUint32)(time + i), doesntExistName); -+ PR_Access(temp, PR_ACCESS_EXISTS); -+ next = PR_IntervalNow(); -+ delta = next - time; -+ if (delta >= duration) -+ break; -+ } -+ -+#ifdef SDB_MEASURE_USE_TEMP_DIR -+ /* turn temp back into our tmpdir path by removing doesntExistName, and -+ * remove the tmp dir */ -+ *tempStartOfFilename = '\0'; -+ (void)rmdir(temp); -+#endif -+ PORT_Free(temp); -+ -+ /* always return 1 or greater */ -+ return i ? i : 1u; -+} -+ -+/* -+ * some file sytems are very slow to run sqlite3 on, particularly if the -+ * access count is pretty high. On these filesystems is faster to create -+ * a temporary database on the local filesystem and access that. This -+ * code uses a temporary table to create that cache. Temp tables are -+ * automatically cleared when the database handle it was created on -+ * Is freed. -+ */ -+static const char DROP_CACHE_CMD[] = "DROP TABLE %s"; -+static const char CREATE_CACHE_CMD[] = -+ "CREATE TEMPORARY TABLE %s AS SELECT * FROM %s"; -+static const char CREATE_ISSUER_INDEX_CMD[] = -+ "CREATE INDEX issuer ON %s (a81)"; -+static const char CREATE_SUBJECT_INDEX_CMD[] = -+ "CREATE INDEX subject ON %s (a101)"; -+static const char CREATE_LABEL_INDEX_CMD[] = "CREATE INDEX label ON %s (a3)"; -+static const char CREATE_ID_INDEX_CMD[] = "CREATE INDEX ckaid ON %s (a102)"; -+ -+static CK_RV -+sdb_buildCache(sqlite3 *sqlDB, sdbDataType type, -+ const char *cacheTable, const char *table) -+{ -+ char *newStr; -+ int sqlerr = SQLITE_OK; -+ -+ newStr = sqlite3_mprintf(CREATE_CACHE_CMD, cacheTable, table); -+ if (newStr == NULL) { -+ return CKR_HOST_MEMORY; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ if (sqlerr != SQLITE_OK) { -+ return sdb_mapSQLError(type, sqlerr); -+ } -+ /* failure to create the indexes is not an issue */ -+ newStr = sqlite3_mprintf(CREATE_ISSUER_INDEX_CMD, cacheTable); -+ if (newStr == NULL) { -+ return CKR_OK; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ newStr = sqlite3_mprintf(CREATE_SUBJECT_INDEX_CMD, cacheTable); -+ if (newStr == NULL) { -+ return CKR_OK; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ newStr = sqlite3_mprintf(CREATE_LABEL_INDEX_CMD, cacheTable); -+ if (newStr == NULL) { -+ return CKR_OK; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ newStr = sqlite3_mprintf(CREATE_ID_INDEX_CMD, cacheTable); -+ if (newStr == NULL) { -+ return CKR_OK; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ return CKR_OK; -+} -+ -+/* -+ * update the cache and the data records describing it. -+ * The cache is updated by dropping the temp database and recreating it. -+ */ -+static CK_RV -+sdb_updateCache(SDBPrivate *sdb_p) -+{ -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ char *newStr; -+ -+ /* drop the old table */ -+ newStr = sqlite3_mprintf(DROP_CACHE_CMD, sdb_p->cacheTable); -+ if (newStr == NULL) { -+ return CKR_HOST_MEMORY; -+ } -+ sqlerr = sqlite3_exec(sdb_p->sqlReadDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ if ((sqlerr != SQLITE_OK) && (sqlerr != SQLITE_ERROR)) { -+ /* something went wrong with the drop, don't try to refresh... -+ * NOTE: SQLITE_ERROR is returned if the table doesn't exist. In -+ * that case, we just continue on and try to reload it */ -+ return sdb_mapSQLError(sdb_p->type, sqlerr); -+ } -+ -+ /* set up the new table */ -+ error = sdb_buildCache(sdb_p->sqlReadDB, sdb_p->type, -+ sdb_p->cacheTable, sdb_p->table); -+ if (error == CKR_OK) { -+ /* we have a new cache! */ -+ sdb_p->lastUpdateTime = PR_IntervalNow(); -+ } -+ return error; -+} -+ -+/* -+ * The sharing of sqlite3 handles across threads is tricky. Older versions -+ * couldn't at all, but newer ones can under strict conditions. Basically -+ * no 2 threads can use the same handle while another thread has an open -+ * stmt running. Once the sqlite3_stmt is finalized, another thread can then -+ * use the database handle. -+ * -+ * We use monitors to protect against trying to use a database before -+ * it's sqlite3_stmt is finalized. This is preferable to the opening and -+ * closing the database each operation because there is significant overhead -+ * in the open and close. Also continually opening and closing the database -+ * defeats the cache code as the cache table is lost on close (thus -+ * requiring us to have to reinitialize the cache every operation). -+ * -+ * An execption to the shared handle is transations. All writes happen -+ * through a transaction. When we are in a transaction, we must use the -+ * same database pointer for that entire transation. In this case we save -+ * the transaction database and use it for all accesses on the transaction -+ * thread. Other threads use the common database. -+ * -+ * There can only be once active transaction on the database at a time. -+ * -+ * sdb_openDBLocal() provides us with a valid database handle for whatever -+ * state we are in (reading or in a transaction), and acquires any locks -+ * appropriate to that state. It also decides when it's time to refresh -+ * the cache before we start an operation. Any database handle returned -+ * just eventually be closed with sdb_closeDBLocal(). -+ * -+ * The table returned either points to the database's physical table, or -+ * to the cached shadow. Tranactions always return the physical table -+ * and read operations return either the physical table or the cache -+ * depending on whether or not the cache exists. -+ */ -+static CK_RV -+sdb_openDBLocal(SDBPrivate *sdb_p, sqlite3 **sqlDB, const char **table) -+{ -+ *sqlDB = NULL; -+ -+ PR_EnterMonitor(sdb_p->dbMon); -+ -+ if (table) { -+ *table = sdb_p->table; -+ } -+ -+ /* We're in a transaction, use the transaction DB */ -+ if ((sdb_p->sqlXactDB) && (sdb_p->sqlXactThread == PR_GetCurrentThread())) { -+ *sqlDB = sdb_p->sqlXactDB; -+ /* only one thread can get here, safe to unlock */ -+ PR_ExitMonitor(sdb_p->dbMon); -+ return CKR_OK; -+ } -+ -+ /* -+ * if we are just reading from the table, we may have the table -+ * cached in a temporary table (especially if it's on a shared FS). -+ * In that case we want to see updates to the table, the the granularity -+ * is on order of human scale, not computer scale. -+ */ -+ if (table && sdb_p->cacheTable) { -+ PRIntervalTime now = PR_IntervalNow(); -+ if ((now - sdb_p->lastUpdateTime) > sdb_p->updateInterval) { -+ sdb_updateCache(sdb_p); -+ } -+ *table = sdb_p->cacheTable; -+ } -+ -+ *sqlDB = sdb_p->sqlReadDB; -+ -+ /* leave holding the lock. only one thread can actually use a given -+ * database connection at once */ -+ -+ return CKR_OK; -+} -+ -+/* closing the local database currenly means unlocking the monitor */ -+static CK_RV -+sdb_closeDBLocal(SDBPrivate *sdb_p, sqlite3 *sqlDB) -+{ -+ if (sdb_p->sqlXactDB != sqlDB) { -+ /* if we weren't in a transaction, we got a lock */ -+ PR_ExitMonitor(sdb_p->dbMon); -+ } -+ return CKR_OK; -+} -+ -+/* -+ * wrapper to sqlite3_open which also sets the busy_timeout -+ */ -+static int -+sdb_openDB(const char *name, sqlite3 **sqlDB, int flags) -+{ -+ int sqlerr; -+ int openFlags; -+ -+ *sqlDB = NULL; -+ -+ if (flags & SDB_RDONLY) { -+ openFlags = SQLITE_OPEN_READONLY; -+ } else { -+ openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; -+ /* sqlite 3.34 seem to incorrectly open readwrite. -+ * when the file is readonly. Explicitly reject that issue here */ -+ if ((_NSSUTIL_Access(name, PR_ACCESS_EXISTS) == PR_SUCCESS) && (_NSSUTIL_Access(name, PR_ACCESS_WRITE_OK) != PR_SUCCESS)) { -+ return SQLITE_READONLY; -+ } -+ } -+ -+ /* Requires SQLite 3.5.0 or newer. */ -+ sqlerr = sqlite3_open_v2(name, sqlDB, openFlags, NULL); -+ if (sqlerr != SQLITE_OK) { -+ return sqlerr; -+ } -+ -+ sqlerr = sqlite3_busy_timeout(*sqlDB, SDB_SQLITE_BUSY_TIMEOUT); -+ if (sqlerr != SQLITE_OK) { -+ sqlite3_close(*sqlDB); -+ *sqlDB = NULL; -+ return sqlerr; -+ } -+ return SQLITE_OK; -+} -+ -+/* Sigh, if we created a new table since we opened the database, -+ * the database handle will not see the new table, we need to close this -+ * database and reopen it. Caller must be in a transaction or holding -+ * the dbMon. sqlDB is changed on success. */ -+static int -+sdb_reopenDBLocal(SDBPrivate *sdb_p, sqlite3 **sqlDB) -+{ -+ sqlite3 *newDB; -+ int sqlerr; -+ -+ /* open a new database */ -+ sqlerr = sdb_openDB(sdb_p->sqlDBName, &newDB, SDB_RDONLY); -+ if (sqlerr != SQLITE_OK) { -+ return sqlerr; -+ } -+ -+ /* if we are in a transaction, we may not be holding the monitor. -+ * grab it before we update the transaction database. This is -+ * safe since are using monitors. */ -+ PR_EnterMonitor(sdb_p->dbMon); -+ /* update our view of the database */ -+ if (sdb_p->sqlReadDB == *sqlDB) { -+ sdb_p->sqlReadDB = newDB; -+ } else if (sdb_p->sqlXactDB == *sqlDB) { -+ sdb_p->sqlXactDB = newDB; -+ } -+ PR_ExitMonitor(sdb_p->dbMon); -+ -+ /* close the old one */ -+ sqlite3_close(*sqlDB); -+ -+ *sqlDB = newDB; -+ return SQLITE_OK; -+} -+ -+struct SDBFindStr { -+ sqlite3 *sqlDB; -+ sqlite3_stmt *findstmt; -+}; -+ -+static const char FIND_OBJECTS_CMD[] = "SELECT ALL id FROM %s WHERE %s;"; -+static const char FIND_OBJECTS_ALL_CMD[] = "SELECT ALL id FROM %s;"; -+CK_RV -+sdb_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *template, CK_ULONG count, -+ SDBFind **find) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3 *sqlDB = NULL; -+ const char *table; -+ char *newStr, *findStr = NULL; -+ sqlite3_stmt *findstmt = NULL; -+ char *join = ""; -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ unsigned int i; -+ -+ LOCK_SQLITE() -+ *find = NULL; -+ error = sdb_openDBLocal(sdb_p, &sqlDB, &table); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ -+ findStr = sqlite3_mprintf(""); -+ for (i = 0; findStr && i < count; i++) { -+ newStr = sqlite3_mprintf("%s%sa%x=$DATA%d", findStr, join, -+ template[i].type, i); -+ join = " AND "; -+ sqlite3_free(findStr); -+ findStr = newStr; -+ } -+ -+ if (findStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ -+ if (count == 0) { -+ newStr = sqlite3_mprintf(FIND_OBJECTS_ALL_CMD, table); -+ } else { -+ newStr = sqlite3_mprintf(FIND_OBJECTS_CMD, table, findStr); -+ } -+ sqlite3_free(findStr); -+ if (newStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &findstmt, NULL); -+ sqlite3_free(newStr); -+ for (i = 0; sqlerr == SQLITE_OK && i < count; i++) { -+ const void *blobData = template[i].pValue; -+ unsigned int blobSize = template[i].ulValueLen; -+ if (blobSize == 0) { -+ blobSize = SQLITE_EXPLICIT_NULL_LEN; -+ blobData = SQLITE_EXPLICIT_NULL; -+ } -+ sqlerr = sqlite3_bind_blob(findstmt, i + 1, blobData, blobSize, -+ SQLITE_TRANSIENT); -+ } -+ if (sqlerr == SQLITE_OK) { -+ *find = PORT_New(SDBFind); -+ if (*find == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ (*find)->findstmt = findstmt; -+ (*find)->sqlDB = sqlDB; -+ UNLOCK_SQLITE() -+ return CKR_OK; -+ } -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ -+loser: -+ if (findstmt) { -+ sqlite3_reset(findstmt); -+ sqlite3_finalize(findstmt); -+ } -+ if (sqlDB) { -+ sdb_closeDBLocal(sdb_p, sqlDB); -+ } -+ UNLOCK_SQLITE() -+ return error; -+} -+ -+CK_RV -+sdb_FindObjects(SDB *sdb, SDBFind *sdbFind, CK_OBJECT_HANDLE *object, -+ CK_ULONG arraySize, CK_ULONG *count) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3_stmt *stmt = sdbFind->findstmt; -+ int sqlerr = SQLITE_OK; -+ int retry = 0; -+ -+ *count = 0; -+ -+ if (arraySize == 0) { -+ return CKR_OK; -+ } -+ LOCK_SQLITE() -+ -+ do { -+ sqlerr = sqlite3_step(stmt); -+ if (sqlerr == SQLITE_BUSY) { -+ PR_Sleep(SDB_BUSY_RETRY_TIME); -+ } -+ if (sqlerr == SQLITE_ROW) { -+ /* only care about the id */ -+ *object++ = sqlite3_column_int(stmt, 0); -+ arraySize--; -+ (*count)++; -+ } -+ } while (!sdb_done(sqlerr, &retry) && (arraySize > 0)); -+ -+ /* we only have some of the objects, there is probably more, -+ * set the sqlerr to an OK value so we return CKR_OK */ -+ if (sqlerr == SQLITE_ROW && arraySize == 0) { -+ sqlerr = SQLITE_DONE; -+ } -+ UNLOCK_SQLITE() -+ -+ return sdb_mapSQLError(sdb_p->type, sqlerr); -+} -+ -+CK_RV -+sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3_stmt *stmt = sdbFind->findstmt; -+ sqlite3 *sqlDB = sdbFind->sqlDB; -+ int sqlerr = SQLITE_OK; -+ -+ LOCK_SQLITE() -+ if (stmt) { -+ sqlite3_reset(stmt); -+ sqlerr = sqlite3_finalize(stmt); -+ } -+ if (sqlDB) { -+ sdb_closeDBLocal(sdb_p, sqlDB); -+ } -+ PORT_Free(sdbFind); -+ -+ UNLOCK_SQLITE() -+ return sdb_mapSQLError(sdb_p->type, sqlerr); -+} -+ -+static CK_RV -+sdb_GetValidAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id, -+ CK_ATTRIBUTE *template, CK_ULONG count) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3 *sqlDB = NULL; -+ sqlite3_stmt *stmt = NULL; -+ const char *table = NULL; -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ int found = 0; -+ int retry = 0; -+ unsigned int i; -+ -+ if (count == 0) { -+ error = CKR_OBJECT_HANDLE_INVALID; -+ goto loser; -+ } -+ -+ /* open a new db if necessary */ -+ error = sdb_openDBLocal(sdb_p, &sqlDB, &table); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ -+ char *columns = NULL; -+ for (i = 0; i < count; i++) { -+ char *newColumns; -+ if (columns) { -+ newColumns = sqlite3_mprintf("%s, a%x", columns, template[i].type); -+ sqlite3_free(columns); -+ columns = NULL; -+ } else { -+ newColumns = sqlite3_mprintf("a%x", template[i].type); -+ } -+ if (!newColumns) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ columns = newColumns; -+ } -+ -+ PORT_Assert(columns); -+ -+ char *statement = sqlite3_mprintf("SELECT DISTINCT %s FROM %s where id=$ID LIMIT 1;", -+ columns, table); -+ sqlite3_free(columns); -+ columns = NULL; -+ if (!statement) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ -+ sqlerr = sqlite3_prepare_v2(sqlDB, statement, -1, &stmt, NULL); -+ sqlite3_free(statement); -+ statement = NULL; -+ if (sqlerr != SQLITE_OK) { -+ goto loser; -+ } -+ -+ // NB: indices in sqlite3_bind_int are 1-indexed -+ sqlerr = sqlite3_bind_int(stmt, 1, object_id); -+ if (sqlerr != SQLITE_OK) { -+ goto loser; -+ } -+ -+ do { -+ sqlerr = sqlite3_step(stmt); -+ if (sqlerr == SQLITE_BUSY) { -+ PR_Sleep(SDB_BUSY_RETRY_TIME); -+ } -+ if (sqlerr == SQLITE_ROW) { -+ PORT_Assert(!found); -+ for (i = 0; i < count; i++) { -+ unsigned int blobSize; -+ const char *blobData; -+ -+ // NB: indices in sqlite_column_{bytes,blob} are 0-indexed -+ blobSize = sqlite3_column_bytes(stmt, i); -+ blobData = sqlite3_column_blob(stmt, i); -+ if (blobData == NULL) { -+ /* PKCS 11 requires that get attributes process all the -+ * attributes in the template, marking the attributes with -+ * issues with -1. Mark the error but continue */ -+ template[i].ulValueLen = -1; -+ error = CKR_ATTRIBUTE_TYPE_INVALID; -+ continue; -+ } -+ /* If the blob equals our explicit NULL value, then the -+ * attribute is a NULL. */ -+ if ((blobSize == SQLITE_EXPLICIT_NULL_LEN) && -+ (PORT_Memcmp(blobData, SQLITE_EXPLICIT_NULL, -+ SQLITE_EXPLICIT_NULL_LEN) == 0)) { -+ blobSize = 0; -+ } -+ if (template[i].pValue) { -+ if (template[i].ulValueLen < blobSize) { -+ /* like CKR_ATTRIBUTE_TYPE_INVALID, continue processing */ -+ template[i].ulValueLen = -1; -+ error = CKR_BUFFER_TOO_SMALL; -+ continue; -+ } -+ PORT_Memcpy(template[i].pValue, blobData, blobSize); -+ } -+ template[i].ulValueLen = blobSize; -+ } -+ found = 1; -+ } -+ } while (!sdb_done(sqlerr, &retry)); -+ -+ sqlite3_reset(stmt); -+ sqlite3_finalize(stmt); -+ stmt = NULL; -+ -+loser: -+ /* fix up the error if necessary */ -+ if (error == CKR_OK) { -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ if (!found && error == CKR_OK) { -+ error = CKR_OBJECT_HANDLE_INVALID; -+ } -+ } -+ -+ if (stmt) { -+ sqlite3_reset(stmt); -+ sqlite3_finalize(stmt); -+ } -+ -+ /* if we had to open a new database, free it now */ -+ if (sqlDB) { -+ sdb_closeDBLocal(sdb_p, sqlDB); -+ } -+ return error; -+} -+ -+/* NOTE: requires sdb_p->schemaAttrs to be sorted asc. */ -+inline static PRBool -+sdb_attributeExists(SDB *sdb, CK_ATTRIBUTE_TYPE attr) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ int first = 0; -+ int last = (int)sdb_p->numSchemaAttrs - 1; -+ while (last >= first) { -+ int mid = first + (last - first) / 2; -+ if (sdb_p->schemaAttrs[mid] == attr) { -+ return PR_TRUE; -+ } -+ if (attr > sdb_p->schemaAttrs[mid]) { -+ first = mid + 1; -+ } else { -+ last = mid - 1; -+ } -+ } -+ -+ return PR_FALSE; -+} -+ -+CK_RV -+sdb_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id, -+ CK_ATTRIBUTE *template, CK_ULONG count) -+{ -+ CK_RV crv = CKR_OK; -+ unsigned int tmplIdx; -+ unsigned int resIdx = 0; -+ unsigned int validCount = 0; -+ unsigned int i; -+ -+ if (count == 0) { -+ return crv; -+ } -+ -+ CK_ATTRIBUTE *validTemplate; -+ PRBool invalidExists = PR_FALSE; -+ for (tmplIdx = 0; tmplIdx < count; tmplIdx++) { -+ if (!sdb_attributeExists(sdb, template[tmplIdx].type)) { -+ template[tmplIdx].ulValueLen = -1; -+ crv = CKR_ATTRIBUTE_TYPE_INVALID; -+ invalidExists = PR_TRUE; -+ break; -+ } -+ } -+ -+ if (!invalidExists) { -+ validTemplate = template; -+ validCount = count; -+ } else { -+ /* Create a new template containing only the valid subset of -+ * input |template|, and query with that. */ -+ validCount = tmplIdx; -+ validTemplate = malloc(sizeof(CK_ATTRIBUTE) * count); -+ if (!validTemplate) { -+ return CKR_HOST_MEMORY; -+ } -+ /* Copy in what we already know is valid. */ -+ for (i = 0; i < validCount; i++) { -+ validTemplate[i] = template[i]; -+ } -+ -+ /* tmplIdx was left at the index of the first invalid -+ * attribute, which has been handled. We only need to -+ * deal with the remainder. */ -+ tmplIdx++; -+ for (; tmplIdx < count; tmplIdx++) { -+ if (sdb_attributeExists(sdb, template[tmplIdx].type)) { -+ validTemplate[validCount++] = template[tmplIdx]; -+ } else { -+ template[tmplIdx].ulValueLen = -1; -+ } -+ } -+ } -+ -+ if (validCount) { -+ LOCK_SQLITE() -+ CK_RV crv2 = sdb_GetValidAttributeValueNoLock(sdb, object_id, validTemplate, validCount); -+ UNLOCK_SQLITE() -+ -+ /* If an invalid attribute was removed above, let -+ * the caller know. Any other error from the actual -+ * query should propogate. */ -+ crv = (crv2 == CKR_OK) ? crv : crv2; -+ } -+ -+ if (invalidExists) { -+ /* Copy out valid lengths. */ -+ tmplIdx = 0; -+ for (resIdx = 0; resIdx < validCount; resIdx++) { -+ for (; tmplIdx < count; tmplIdx++) { -+ if (template[tmplIdx].type != validTemplate[resIdx].type) { -+ continue; -+ } -+ template[tmplIdx].ulValueLen = validTemplate[resIdx].ulValueLen; -+ tmplIdx++; -+ break; -+ } -+ } -+ free(validTemplate); -+ } -+ -+ return crv; -+} -+ -+static const char SET_ATTRIBUTE_CMD[] = "UPDATE %s SET %s WHERE id=$ID;"; -+CK_RV -+sdb_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id, -+ const CK_ATTRIBUTE *template, CK_ULONG count) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3 *sqlDB = NULL; -+ sqlite3_stmt *stmt = NULL; -+ char *setStr = NULL; -+ char *newStr = NULL; -+ int sqlerr = SQLITE_OK; -+ int retry = 0; -+ CK_RV error = CKR_OK; -+ unsigned int i; -+ -+ if ((sdb->sdb_flags & SDB_RDONLY) != 0) { -+ return CKR_TOKEN_WRITE_PROTECTED; -+ } -+ -+ if (count == 0) { -+ return CKR_OK; -+ } -+ -+ LOCK_SQLITE() -+ setStr = sqlite3_mprintf(""); -+ for (i = 0; setStr && i < count; i++) { -+ if (i == 0) { -+ sqlite3_free(setStr); -+ setStr = sqlite3_mprintf("a%x=$VALUE%d", -+ template[i].type, i); -+ continue; -+ } -+ newStr = sqlite3_mprintf("%s,a%x=$VALUE%d", setStr, -+ template[i].type, i); -+ sqlite3_free(setStr); -+ setStr = newStr; -+ } -+ newStr = NULL; -+ -+ if (setStr == NULL) { -+ return CKR_HOST_MEMORY; -+ } -+ newStr = sqlite3_mprintf(SET_ATTRIBUTE_CMD, sdb_p->table, setStr); -+ sqlite3_free(setStr); -+ if (newStr == NULL) { -+ UNLOCK_SQLITE() -+ return CKR_HOST_MEMORY; -+ } -+ error = sdb_openDBLocal(sdb_p, &sqlDB, NULL); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL); -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ for (i = 0; i < count; i++) { -+ if (template[i].ulValueLen != 0) { -+ sqlerr = sqlite3_bind_blob(stmt, i + 1, template[i].pValue, -+ template[i].ulValueLen, SQLITE_STATIC); -+ } else { -+ sqlerr = sqlite3_bind_blob(stmt, i + 1, SQLITE_EXPLICIT_NULL, -+ SQLITE_EXPLICIT_NULL_LEN, SQLITE_STATIC); -+ } -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ } -+ sqlerr = sqlite3_bind_int(stmt, i + 1, object_id); -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ -+ do { -+ sqlerr = sqlite3_step(stmt); -+ if (sqlerr == SQLITE_BUSY) { -+ PR_Sleep(SDB_BUSY_RETRY_TIME); -+ } -+ } while (!sdb_done(sqlerr, &retry)); -+ -+loser: -+ if (newStr) { -+ sqlite3_free(newStr); -+ } -+ if (error == CKR_OK) { -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ } -+ -+ if (stmt) { -+ sqlite3_reset(stmt); -+ sqlite3_finalize(stmt); -+ } -+ -+ if (sqlDB) { -+ sdb_closeDBLocal(sdb_p, sqlDB); -+ } -+ -+ UNLOCK_SQLITE() -+ return error; -+} -+ -+/* -+ * check to see if a candidate object handle already exists. -+ */ -+static PRBool -+sdb_objectExists(SDB *sdb, CK_OBJECT_HANDLE candidate) -+{ -+ CK_RV crv; -+ CK_ATTRIBUTE template = { CKA_LABEL, NULL, 0 }; -+ -+ crv = sdb_GetValidAttributeValueNoLock(sdb, candidate, &template, 1); -+ if (crv == CKR_OBJECT_HANDLE_INVALID) { -+ return PR_FALSE; -+ } -+ return PR_TRUE; -+} -+ -+/* -+ * if we're here, we are in a transaction, so it's safe -+ * to examine the current state of the database -+ */ -+static CK_OBJECT_HANDLE -+sdb_getObjectId(SDB *sdb) -+{ -+ CK_OBJECT_HANDLE candidate; -+ static CK_OBJECT_HANDLE next_obj = CK_INVALID_HANDLE; -+ int count; -+ /* -+ * get an initial object handle to use -+ */ -+ if (next_obj == CK_INVALID_HANDLE) { -+ PRTime time; -+ time = PR_Now(); -+ -+ next_obj = (CK_OBJECT_HANDLE)(time & 0x3fffffffL); -+ } -+ candidate = next_obj++; -+ /* detect that we've looped through all the handles... */ -+ for (count = 0; count < 0x40000000; count++, candidate = next_obj++) { -+ /* mask off excess bits */ -+ candidate &= 0x3fffffff; -+ /* if we hit zero, go to the next entry */ -+ if (candidate == CK_INVALID_HANDLE) { -+ continue; -+ } -+ /* make sure we aren't already using */ -+ if (!sdb_objectExists(sdb, candidate)) { -+ /* this one is free */ -+ return candidate; -+ } -+ } -+ -+ /* no handle is free, fail */ -+ return CK_INVALID_HANDLE; -+} -+ -+CK_RV -+sdb_GetNewObjectID(SDB *sdb, CK_OBJECT_HANDLE *object) -+{ -+ CK_OBJECT_HANDLE id; -+ -+ id = sdb_getObjectId(sdb); -+ if (id == CK_INVALID_HANDLE) { -+ return CKR_DEVICE_MEMORY; /* basically we ran out of resources */ -+ } -+ *object = id; -+ return CKR_OK; -+} -+ -+static const char CREATE_CMD[] = "INSERT INTO %s (id%s) VALUES($ID%s);"; -+CK_RV -+sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id, -+ const CK_ATTRIBUTE *template, CK_ULONG count) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3 *sqlDB = NULL; -+ sqlite3_stmt *stmt = NULL; -+ char *columnStr = NULL; -+ char *valueStr = NULL; -+ char *newStr = NULL; -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ CK_OBJECT_HANDLE this_object = CK_INVALID_HANDLE; -+ int retry = 0; -+ unsigned int i; -+ -+ if ((sdb->sdb_flags & SDB_RDONLY) != 0) { -+ return CKR_TOKEN_WRITE_PROTECTED; -+ } -+ -+ LOCK_SQLITE() -+ if ((*object_id != CK_INVALID_HANDLE) && -+ !sdb_objectExists(sdb, *object_id)) { -+ this_object = *object_id; -+ } else { -+ this_object = sdb_getObjectId(sdb); -+ } -+ if (this_object == CK_INVALID_HANDLE) { -+ UNLOCK_SQLITE(); -+ return CKR_HOST_MEMORY; -+ } -+ columnStr = sqlite3_mprintf(""); -+ valueStr = sqlite3_mprintf(""); -+ *object_id = this_object; -+ for (i = 0; columnStr && valueStr && i < count; i++) { -+ newStr = sqlite3_mprintf("%s,a%x", columnStr, template[i].type); -+ sqlite3_free(columnStr); -+ columnStr = newStr; -+ newStr = sqlite3_mprintf("%s,$VALUE%d", valueStr, i); -+ sqlite3_free(valueStr); -+ valueStr = newStr; -+ } -+ newStr = NULL; -+ if ((columnStr == NULL) || (valueStr == NULL)) { -+ if (columnStr) { -+ sqlite3_free(columnStr); -+ } -+ if (valueStr) { -+ sqlite3_free(valueStr); -+ } -+ UNLOCK_SQLITE() -+ return CKR_HOST_MEMORY; -+ } -+ newStr = sqlite3_mprintf(CREATE_CMD, sdb_p->table, columnStr, valueStr); -+ sqlite3_free(columnStr); -+ sqlite3_free(valueStr); -+ error = sdb_openDBLocal(sdb_p, &sqlDB, NULL); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL); -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ sqlerr = sqlite3_bind_int(stmt, 1, *object_id); -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ for (i = 0; i < count; i++) { -+ if (template[i].ulValueLen) { -+ sqlerr = sqlite3_bind_blob(stmt, i + 2, template[i].pValue, -+ template[i].ulValueLen, SQLITE_STATIC); -+ } else { -+ sqlerr = sqlite3_bind_blob(stmt, i + 2, SQLITE_EXPLICIT_NULL, -+ SQLITE_EXPLICIT_NULL_LEN, SQLITE_STATIC); -+ } -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ } -+ -+ do { -+ sqlerr = sqlite3_step(stmt); -+ if (sqlerr == SQLITE_BUSY) { -+ PR_Sleep(SDB_BUSY_RETRY_TIME); -+ } -+ } while (!sdb_done(sqlerr, &retry)); -+ -+loser: -+ if (newStr) { -+ sqlite3_free(newStr); -+ } -+ if (error == CKR_OK) { -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ } -+ -+ if (stmt) { -+ sqlite3_reset(stmt); -+ sqlite3_finalize(stmt); -+ } -+ -+ if (sqlDB) { -+ sdb_closeDBLocal(sdb_p, sqlDB); -+ } -+ UNLOCK_SQLITE() -+ -+ return error; -+} -+ -+/* -+ * Generic destroy that can destroy metadata or objects -+ */ -+static const char DESTROY_CMD[] = "DELETE FROM %s WHERE (id=$ID);"; -+CK_RV -+sdb_destroyAnyObject(SDB *sdb, const char *table, -+ CK_OBJECT_HANDLE object_id, const char *string_id) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3 *sqlDB = NULL; -+ sqlite3_stmt *stmt = NULL; -+ char *newStr = NULL; -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ int retry = 0; -+ -+ if ((sdb->sdb_flags & SDB_RDONLY) != 0) { -+ return CKR_TOKEN_WRITE_PROTECTED; -+ } -+ -+ LOCK_SQLITE() -+ error = sdb_openDBLocal(sdb_p, &sqlDB, NULL); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ newStr = sqlite3_mprintf(DESTROY_CMD, table); -+ if (newStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ sqlerr = sqlite3_prepare_v2(sqlDB, newStr, -1, &stmt, NULL); -+ sqlite3_free(newStr); -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ if (string_id == NULL) { -+ sqlerr = sqlite3_bind_int(stmt, 1, object_id); -+ } else { -+ sqlerr = sqlite3_bind_text(stmt, 1, string_id, -+ PORT_Strlen(string_id), SQLITE_STATIC); -+ } -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ -+ do { -+ sqlerr = sqlite3_step(stmt); -+ if (sqlerr == SQLITE_BUSY) { -+ PR_Sleep(SDB_BUSY_RETRY_TIME); -+ } -+ } while (!sdb_done(sqlerr, &retry)); -+ -+loser: -+ if (error == CKR_OK) { -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ } -+ -+ if (stmt) { -+ sqlite3_reset(stmt); -+ sqlite3_finalize(stmt); -+ } -+ -+ if (sqlDB) { -+ sdb_closeDBLocal(sdb_p, sqlDB); -+ } -+ -+ UNLOCK_SQLITE() -+ return error; -+} -+ -+CK_RV -+sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ return sdb_destroyAnyObject(sdb, sdb_p->table, object_id, NULL); -+} -+ -+CK_RV -+sdb_DestroyMetaData(SDB *sdb, const char *id) -+{ -+ return sdb_destroyAnyObject(sdb, "metaData", 0, id); -+} -+ -+static const char BEGIN_CMD[] = "BEGIN IMMEDIATE TRANSACTION;"; -+ -+/* -+ * start a transaction. -+ * -+ * We need to open a new database, then store that new database into -+ * the private data structure. We open the database first, then use locks -+ * to protect storing the data to prevent deadlocks. -+ */ -+CK_RV -+sdb_Begin(SDB *sdb) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3 *sqlDB = NULL; -+ sqlite3_stmt *stmt = NULL; -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ int retry = 0; -+ -+ if ((sdb->sdb_flags & SDB_RDONLY) != 0) { -+ return CKR_TOKEN_WRITE_PROTECTED; -+ } -+ -+ LOCK_SQLITE() -+ -+ /* get a new version that we will use for the entire transaction */ -+ sqlerr = sdb_openDB(sdb_p->sqlDBName, &sqlDB, SDB_RDWR); -+ if (sqlerr != SQLITE_OK) { -+ goto loser; -+ } -+ -+ sqlerr = sqlite3_prepare_v2(sqlDB, BEGIN_CMD, -1, &stmt, NULL); -+ -+ do { -+ sqlerr = sqlite3_step(stmt); -+ if (sqlerr == SQLITE_BUSY) { -+ PR_Sleep(SDB_BUSY_RETRY_TIME); -+ } -+ /* don't retry BEGIN transaction*/ -+ retry = 0; -+ } while (!sdb_done(sqlerr, &retry)); -+ -+ if (stmt) { -+ sqlite3_reset(stmt); -+ sqlite3_finalize(stmt); -+ } -+ -+loser: -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ -+ /* we are starting a new transaction, -+ * and if we succeeded, then save this database for the rest of -+ * our transaction */ -+ if (error == CKR_OK) { -+ /* we hold a 'BEGIN TRANSACTION' and a sdb_p->lock. At this point -+ * sdb_p->sqlXactDB MUST be null */ -+ PR_EnterMonitor(sdb_p->dbMon); -+ PORT_Assert(sdb_p->sqlXactDB == NULL); -+ sdb_p->sqlXactDB = sqlDB; -+ sdb_p->sqlXactThread = PR_GetCurrentThread(); -+ PR_ExitMonitor(sdb_p->dbMon); -+ } else { -+ /* we failed to start our transaction, -+ * free any databases we opened. */ -+ if (sqlDB) { -+ sqlite3_close(sqlDB); -+ } -+ } -+ -+ UNLOCK_SQLITE() -+ return error; -+} -+ -+/* -+ * Complete a transaction. Basically undo everything we did in begin. -+ * There are 2 flavors Abort and Commit. Basically the only differerence between -+ * these 2 are what the database will show. (no change in to former, change in -+ * the latter). -+ */ -+static CK_RV -+sdb_complete(SDB *sdb, const char *cmd) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3 *sqlDB = NULL; -+ sqlite3_stmt *stmt = NULL; -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ int retry = 0; -+ -+ if ((sdb->sdb_flags & SDB_RDONLY) != 0) { -+ return CKR_TOKEN_WRITE_PROTECTED; -+ } -+ -+ /* We must have a transation database, or we shouldn't have arrived here */ -+ PR_EnterMonitor(sdb_p->dbMon); -+ PORT_Assert(sdb_p->sqlXactDB); -+ if (sdb_p->sqlXactDB == NULL) { -+ PR_ExitMonitor(sdb_p->dbMon); -+ return CKR_GENERAL_ERROR; /* shouldn't happen */ -+ } -+ PORT_Assert(sdb_p->sqlXactThread == PR_GetCurrentThread()); -+ if (sdb_p->sqlXactThread != PR_GetCurrentThread()) { -+ PR_ExitMonitor(sdb_p->dbMon); -+ return CKR_GENERAL_ERROR; /* shouldn't happen */ -+ } -+ sqlDB = sdb_p->sqlXactDB; -+ sdb_p->sqlXactDB = NULL; /* no one else can get to this DB, -+ * safe to unlock */ -+ sdb_p->sqlXactThread = NULL; -+ PR_ExitMonitor(sdb_p->dbMon); -+ -+ sqlerr = sqlite3_prepare_v2(sqlDB, cmd, -1, &stmt, NULL); -+ -+ do { -+ sqlerr = sqlite3_step(stmt); -+ if (sqlerr == SQLITE_BUSY) { -+ PR_Sleep(SDB_BUSY_RETRY_TIME); -+ } -+ } while (!sdb_done(sqlerr, &retry)); -+ -+ /* Pending BEGIN TRANSACTIONS Can move forward at this point. */ -+ -+ if (stmt) { -+ sqlite3_reset(stmt); -+ sqlite3_finalize(stmt); -+ } -+ -+ /* we we have a cached DB image, update it as well */ -+ if (sdb_p->cacheTable) { -+ PR_EnterMonitor(sdb_p->dbMon); -+ sdb_updateCache(sdb_p); -+ PR_ExitMonitor(sdb_p->dbMon); -+ } -+ -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ -+ /* We just finished a transaction. -+ * Free the database, and remove it from the list */ -+ sqlite3_close(sqlDB); -+ -+ return error; -+} -+ -+static const char COMMIT_CMD[] = "COMMIT TRANSACTION;"; -+CK_RV -+sdb_Commit(SDB *sdb) -+{ -+ CK_RV crv; -+ LOCK_SQLITE() -+ crv = sdb_complete(sdb, COMMIT_CMD); -+ UNLOCK_SQLITE() -+ return crv; -+} -+ -+static const char ROLLBACK_CMD[] = "ROLLBACK TRANSACTION;"; -+CK_RV -+sdb_Abort(SDB *sdb) -+{ -+ CK_RV crv; -+ LOCK_SQLITE() -+ crv = sdb_complete(sdb, ROLLBACK_CMD); -+ UNLOCK_SQLITE() -+ return crv; -+} -+ -+static int tableExists(sqlite3 *sqlDB, const char *tableName); -+ -+static const char GET_PW_CMD[] = "SELECT ALL * FROM metaData WHERE id=$ID;"; -+CK_RV -+sdb_GetMetaData(SDB *sdb, const char *id, SECItem *item1, SECItem *item2) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3 *sqlDB = sdb_p->sqlXactDB; -+ sqlite3_stmt *stmt = NULL; -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ int found = 0; -+ int retry = 0; -+ -+ LOCK_SQLITE() -+ error = sdb_openDBLocal(sdb_p, &sqlDB, NULL); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ -+ /* handle 'test' versions of the sqlite db */ -+ sqlerr = sqlite3_prepare_v2(sqlDB, GET_PW_CMD, -1, &stmt, NULL); -+ /* Sigh, if we created a new table since we opened the database, -+ * the database handle will not see the new table, we need to close this -+ * database and reopen it. This is safe because we are holding the lock -+ * still. */ -+ if (sqlerr == SQLITE_SCHEMA) { -+ sqlerr = sdb_reopenDBLocal(sdb_p, &sqlDB); -+ if (sqlerr != SQLITE_OK) { -+ goto loser; -+ } -+ sqlerr = sqlite3_prepare_v2(sqlDB, GET_PW_CMD, -1, &stmt, NULL); -+ } -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ sqlerr = sqlite3_bind_text(stmt, 1, id, PORT_Strlen(id), SQLITE_STATIC); -+ do { -+ sqlerr = sqlite3_step(stmt); -+ if (sqlerr == SQLITE_BUSY) { -+ PR_Sleep(SDB_BUSY_RETRY_TIME); -+ } -+ if (sqlerr == SQLITE_ROW) { -+ const char *blobData; -+ unsigned int len = item1->len; -+ item1->len = sqlite3_column_bytes(stmt, 1); -+ if (item1->len > len) { -+ error = CKR_BUFFER_TOO_SMALL; -+ continue; -+ } -+ blobData = sqlite3_column_blob(stmt, 1); -+ PORT_Memcpy(item1->data, blobData, item1->len); -+ if (item2) { -+ len = item2->len; -+ item2->len = sqlite3_column_bytes(stmt, 2); -+ if (item2->len > len) { -+ error = CKR_BUFFER_TOO_SMALL; -+ continue; -+ } -+ blobData = sqlite3_column_blob(stmt, 2); -+ PORT_Memcpy(item2->data, blobData, item2->len); -+ } -+ found = 1; -+ } -+ } while (!sdb_done(sqlerr, &retry)); -+ -+loser: -+ /* fix up the error if necessary */ -+ if (error == CKR_OK) { -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ if (!found && error == CKR_OK) { -+ error = CKR_OBJECT_HANDLE_INVALID; -+ } -+ } -+ -+ if (stmt) { -+ sqlite3_reset(stmt); -+ sqlite3_finalize(stmt); -+ } -+ -+ if (sqlDB) { -+ sdb_closeDBLocal(sdb_p, sqlDB); -+ } -+ UNLOCK_SQLITE() -+ -+ return error; -+} -+ -+static const char PW_CREATE_TABLE_CMD[] = -+ "CREATE TABLE metaData (id PRIMARY KEY UNIQUE ON CONFLICT REPLACE, item1, item2);"; -+static const char PW_CREATE_CMD[] = -+ "INSERT INTO metaData (id,item1,item2) VALUES($ID,$ITEM1,$ITEM2);"; -+static const char MD_CREATE_CMD[] = -+ "INSERT INTO metaData (id,item1) VALUES($ID,$ITEM1);"; -+ -+CK_RV -+sdb_PutMetaData(SDB *sdb, const char *id, const SECItem *item1, -+ const SECItem *item2) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3 *sqlDB = sdb_p->sqlXactDB; -+ sqlite3_stmt *stmt = NULL; -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ int retry = 0; -+ const char *cmd = PW_CREATE_CMD; -+ -+ if ((sdb->sdb_flags & SDB_RDONLY) != 0) { -+ return CKR_TOKEN_WRITE_PROTECTED; -+ } -+ -+ LOCK_SQLITE() -+ error = sdb_openDBLocal(sdb_p, &sqlDB, NULL); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ -+ if (!tableExists(sqlDB, "metaData")) { -+ sqlerr = sqlite3_exec(sqlDB, PW_CREATE_TABLE_CMD, NULL, 0, NULL); -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ } -+ if (item2 == NULL) { -+ cmd = MD_CREATE_CMD; -+ } -+ sqlerr = sqlite3_prepare_v2(sqlDB, cmd, -1, &stmt, NULL); -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ sqlerr = sqlite3_bind_text(stmt, 1, id, PORT_Strlen(id), SQLITE_STATIC); -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ sqlerr = sqlite3_bind_blob(stmt, 2, item1->data, item1->len, SQLITE_STATIC); -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ if (item2) { -+ sqlerr = sqlite3_bind_blob(stmt, 3, item2->data, -+ item2->len, SQLITE_STATIC); -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ } -+ -+ do { -+ sqlerr = sqlite3_step(stmt); -+ if (sqlerr == SQLITE_BUSY) { -+ PR_Sleep(SDB_BUSY_RETRY_TIME); -+ } -+ } while (!sdb_done(sqlerr, &retry)); -+ -+loser: -+ /* fix up the error if necessary */ -+ if (error == CKR_OK) { -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ } -+ -+ if (stmt) { -+ sqlite3_reset(stmt); -+ sqlite3_finalize(stmt); -+ } -+ -+ if (sqlDB) { -+ sdb_closeDBLocal(sdb_p, sqlDB); -+ } -+ UNLOCK_SQLITE() -+ -+ return error; -+} -+ -+static const char RESET_CMD[] = "DELETE FROM %s;"; -+CK_RV -+sdb_Reset(SDB *sdb) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ sqlite3 *sqlDB = NULL; -+ char *newStr; -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ -+ /* only Key databases can be reset */ -+ if (sdb_p->type != SDB_KEY) { -+ return CKR_OBJECT_HANDLE_INVALID; -+ } -+ -+ LOCK_SQLITE() -+ error = sdb_openDBLocal(sdb_p, &sqlDB, NULL); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ -+ if (tableExists(sqlDB, sdb_p->table)) { -+ /* delete the contents of the key table */ -+ newStr = sqlite3_mprintf(RESET_CMD, sdb_p->table); -+ if (newStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ -+ if (sqlerr != SQLITE_OK) -+ goto loser; -+ } -+ -+ /* delete the password entry table */ -+ sqlerr = sqlite3_exec(sqlDB, "DROP TABLE IF EXISTS metaData;", -+ NULL, 0, NULL); -+ -+loser: -+ /* fix up the error if necessary */ -+ if (error == CKR_OK) { -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ } -+ -+ if (sqlDB) { -+ sdb_closeDBLocal(sdb_p, sqlDB); -+ } -+ -+ UNLOCK_SQLITE() -+ return error; -+} -+ -+CK_RV -+sdb_Close(SDB *sdb) -+{ -+ SDBPrivate *sdb_p = sdb->private; -+ int sqlerr = SQLITE_OK; -+ sdbDataType type = sdb_p->type; -+ -+ sqlerr = sqlite3_close(sdb_p->sqlReadDB); -+ PORT_Free(sdb_p->sqlDBName); -+ if (sdb_p->cacheTable) { -+ sqlite3_free(sdb_p->cacheTable); -+ } -+ if (sdb_p->dbMon) { -+ PR_DestroyMonitor(sdb_p->dbMon); -+ } -+ free(sdb_p->schemaAttrs); -+ free(sdb_p); -+ free(sdb); -+ return sdb_mapSQLError(type, sqlerr); -+} -+ -+/* -+ * functions to support open -+ */ -+ -+static const char CHECK_TABLE_CMD[] = "SELECT ALL * FROM %s LIMIT 0;"; -+ -+/* return 1 if sqlDB contains table 'tableName */ -+static int -+tableExists(sqlite3 *sqlDB, const char *tableName) -+{ -+ char *cmd = sqlite3_mprintf(CHECK_TABLE_CMD, tableName); -+ int sqlerr = SQLITE_OK; -+ -+ if (cmd == NULL) { -+ return 0; -+ } -+ -+ sqlerr = sqlite3_exec(sqlDB, cmd, NULL, 0, 0); -+ sqlite3_free(cmd); -+ -+ return (sqlerr == SQLITE_OK) ? 1 : 0; -+} -+ -+void -+sdb_SetForkState(PRBool forked) -+{ -+ /* XXXright now this is a no-op. The global fork state in the softokn3 -+ * shared library is already taken care of at the PKCS#11 level. -+ * If and when we add fork state to the sqlite shared library and extern -+ * interface, we will need to set it and reset it from here */ -+} -+ -+static int -+sdb_attributeComparator(const void *a, const void *b) -+{ -+ if (*(CK_ATTRIBUTE_TYPE *)a < *(CK_ATTRIBUTE_TYPE *)b) { -+ return -1; -+ } -+ if (*(CK_ATTRIBUTE_TYPE *)a > *(CK_ATTRIBUTE_TYPE *)b) { -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * initialize a single database -+ */ -+static const char INIT_CMD[] = -+ "CREATE TABLE %s (id PRIMARY KEY UNIQUE ON CONFLICT ABORT%s)"; -+ -+CK_RV -+sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate, -+ int *newInit, int inFlags, PRUint32 accessOps, SDB **pSdb) -+{ -+ int i; -+ char *initStr = NULL; -+ char *newStr; -+ char *queryStr = NULL; -+ int inTransaction = 0; -+ SDB *sdb = NULL; -+ SDBPrivate *sdb_p = NULL; -+ sqlite3 *sqlDB = NULL; -+ int sqlerr = SQLITE_OK; -+ CK_RV error = CKR_OK; -+ char *cacheTable = NULL; -+ PRIntervalTime now = 0; -+ char *env; -+ PRBool enableCache = PR_FALSE; -+ PRBool checkFSType = PR_FALSE; -+ PRBool measureSpeed = PR_FALSE; -+ PRBool create; -+ int flags = inFlags & 0x7; -+ -+ *pSdb = NULL; -+ *inUpdate = 0; -+ -+ /* sqlite3 doesn't have a flag to specify that we want to -+ * open the database read only. If the db doesn't exist, -+ * sqlite3 will always create it. -+ */ -+ LOCK_SQLITE(); -+ create = (_NSSUTIL_Access(dbname, PR_ACCESS_EXISTS) != PR_SUCCESS); -+ if ((flags == SDB_RDONLY) && create) { -+ error = sdb_mapSQLError(type, SQLITE_CANTOPEN); -+ goto loser; -+ } -+ sqlerr = sdb_openDB(dbname, &sqlDB, flags); -+ if (sqlerr != SQLITE_OK) { -+ error = sdb_mapSQLError(type, sqlerr); -+ goto loser; -+ } -+ -+ /* -+ * SQL created the file, but it doesn't set appropriate modes for -+ * a database. -+ * -+ * NO NSPR call for chmod? :( -+ */ -+ if (create && sdb_chmod(dbname, 0600) != 0) { -+ error = sdb_mapSQLError(type, SQLITE_CANTOPEN); -+ goto loser; -+ } -+ -+ if (flags != SDB_RDONLY) { -+ sqlerr = sqlite3_exec(sqlDB, BEGIN_CMD, NULL, 0, NULL); -+ if (sqlerr != SQLITE_OK) { -+ error = sdb_mapSQLError(type, sqlerr); -+ goto loser; -+ } -+ inTransaction = 1; -+ } -+ if (!tableExists(sqlDB, table)) { -+ *newInit = 1; -+ if (flags != SDB_CREATE) { -+ error = sdb_mapSQLError(type, SQLITE_CANTOPEN); -+ goto loser; -+ } -+ initStr = sqlite3_mprintf(""); -+ for (i = 0; initStr && i < known_attributes_size; i++) { -+ newStr = sqlite3_mprintf("%s, a%x", initStr, known_attributes[i]); -+ sqlite3_free(initStr); -+ initStr = newStr; -+ } -+ if (initStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ -+ newStr = sqlite3_mprintf(INIT_CMD, table, initStr); -+ sqlite3_free(initStr); -+ if (newStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ if (sqlerr != SQLITE_OK) { -+ error = sdb_mapSQLError(type, sqlerr); -+ goto loser; -+ } -+ -+ newStr = sqlite3_mprintf(CREATE_ISSUER_INDEX_CMD, table); -+ if (newStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ if (sqlerr != SQLITE_OK) { -+ error = sdb_mapSQLError(type, sqlerr); -+ goto loser; -+ } -+ -+ newStr = sqlite3_mprintf(CREATE_SUBJECT_INDEX_CMD, table); -+ if (newStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ if (sqlerr != SQLITE_OK) { -+ error = sdb_mapSQLError(type, sqlerr); -+ goto loser; -+ } -+ -+ newStr = sqlite3_mprintf(CREATE_LABEL_INDEX_CMD, table); -+ if (newStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ if (sqlerr != SQLITE_OK) { -+ error = sdb_mapSQLError(type, sqlerr); -+ goto loser; -+ } -+ -+ newStr = sqlite3_mprintf(CREATE_ID_INDEX_CMD, table); -+ if (newStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ sqlerr = sqlite3_exec(sqlDB, newStr, NULL, 0, NULL); -+ sqlite3_free(newStr); -+ if (sqlerr != SQLITE_OK) { -+ error = sdb_mapSQLError(type, sqlerr); -+ goto loser; -+ } -+ } -+ /* -+ * detect the case where we have created the database, but have -+ * not yet updated it. -+ * -+ * We only check the Key database because only the key database has -+ * a metaData table. The metaData table is created when a password -+ * is set, or in the case of update, when a password is supplied. -+ * If no key database exists, then the update would have happened immediately -+ * on noticing that the cert database didn't exist (see newInit set above). -+ */ -+ if (type == SDB_KEY && !tableExists(sqlDB, "metaData")) { -+ *newInit = 1; -+ } -+ -+ /* access to network filesystems are significantly slower than local ones -+ * for database operations. In those cases we need to create a cached copy -+ * of the database in a temporary location on the local disk. SQLITE -+ * already provides a way to create a temporary table and initialize it, -+ * so we use it for the cache (see sdb_buildCache for how it's done).*/ -+ -+ /* -+ * we decide whether or not to use the cache based on the following input. -+ * -+ * NSS_SDB_USE_CACHE environment variable is set to anything other than -+ * "yes" or "no" (for instance, "auto"): NSS will measure the performance -+ * of access to the temp database versus the access to the user's -+ * passed-in database location. If the temp database location is -+ * "significantly" faster we will use the cache. -+ * -+ * NSS_SDB_USE_CACHE environment variable is nonexistent or set to "no": -+ * cache will not be used. -+ * -+ * NSS_SDB_USE_CACHE environment variable is set to "yes": cache will -+ * always be used. -+ * -+ * It is expected that most applications will not need this feature, and -+ * thus it is disabled by default. -+ */ -+ -+ env = PR_GetEnvSecure("NSS_SDB_USE_CACHE"); -+ -+ /* Variables enableCache, checkFSType, measureSpeed are PR_FALSE by default, -+ * which is the expected behavior for NSS_SDB_USE_CACHE="no". -+ * We don't need to check for "no" here. */ -+ if (!env) { -+ /* By default, with no variable set, we avoid expensive measuring for -+ * most FS types. We start with inexpensive FS type checking, and -+ * might perform measuring for some types. */ -+ checkFSType = PR_TRUE; -+ } else if (PORT_Strcasecmp(env, "yes") == 0) { -+ enableCache = PR_TRUE; -+ } else if (PORT_Strcasecmp(env, "no") != 0) { /* not "no" => "auto" */ -+ measureSpeed = PR_TRUE; -+ } -+ -+ if (checkFSType) { -+#if defined(LINUX) && !defined(ANDROID) -+ struct statfs statfs_s; -+ if (statfs(dbname, &statfs_s) == 0) { -+ switch (statfs_s.f_type) { -+ case SMB_SUPER_MAGIC: -+ case 0xff534d42: /* CIFS_MAGIC_NUMBER */ -+ case NFS_SUPER_MAGIC: -+ /* We assume these are slow. */ -+ enableCache = PR_TRUE; -+ break; -+ case CODA_SUPER_MAGIC: -+ case 0x65735546: /* FUSE_SUPER_MAGIC */ -+ case NCP_SUPER_MAGIC: -+ /* It's uncertain if this FS is fast or slow. -+ * It seems reasonable to perform slow measuring for users -+ * with questionable FS speed. */ -+ measureSpeed = PR_TRUE; -+ break; -+ case AFS_SUPER_MAGIC: /* Already implements caching. */ -+ default: -+ break; -+ } -+ } -+#endif -+ } -+ -+ if (measureSpeed) { -+ char *tempDir = NULL; -+ PRUint32 tempOps = 0; -+ /* -+ * Use PR_Access to determine how expensive it -+ * is to check for the existance of a local file compared to the same -+ * check in the temp directory. If the temp directory is faster, cache -+ * the database there. */ -+ tempDir = sdb_getTempDir(sqlDB); -+ if (tempDir) { -+ tempOps = sdb_measureAccess(tempDir); -+ PORT_Free(tempDir); -+ -+ /* There is a cost to continually copying the database. -+ * Account for that cost with the arbitrary factor of 10 */ -+ enableCache = (PRBool)(tempOps > accessOps * 10); -+ } -+ } -+ -+ if (enableCache) { -+ /* try to set the temp store to memory.*/ -+ sqlite3_exec(sqlDB, "PRAGMA temp_store=MEMORY", NULL, 0, NULL); -+ /* Failure to set the temp store to memory is not fatal, -+ * ignore the error */ -+ -+ cacheTable = sqlite3_mprintf("%sCache", table); -+ if (cacheTable == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ /* build the cache table */ -+ error = sdb_buildCache(sqlDB, type, cacheTable, table); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ /* initialize the last cache build time */ -+ now = PR_IntervalNow(); -+ } -+ -+ sdb = (SDB *)malloc(sizeof(SDB)); -+ if (!sdb) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ sdb_p = (SDBPrivate *)malloc(sizeof(SDBPrivate)); -+ if (!sdb_p) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ -+ /* Cache the attributes that are held in the table, so we can later check -+ * that queried attributes actually exist. We don't assume the schema -+ * to be exactly |known_attributes|, as it may change over time. */ -+ sdb_p->schemaAttrs = NULL; -+ if (!PORT_Strcmp("nssPublic", table) || -+ !PORT_Strcmp("nssPrivate", table)) { -+ sqlite3_stmt *stmt = NULL; -+ int retry = 0; -+ unsigned int backedAttrs = 0; -+ -+ /* Can't bind parameters to a PRAGMA. */ -+ queryStr = sqlite3_mprintf("PRAGMA table_info(%s);", table); -+ if (queryStr == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ sqlerr = sqlite3_prepare_v2(sqlDB, queryStr, -1, &stmt, NULL); -+ sqlite3_free(queryStr); -+ queryStr = NULL; -+ if (sqlerr != SQLITE_OK) { -+ goto loser; -+ } -+ unsigned int schemaAttrsCapacity = known_attributes_size; -+ sdb_p->schemaAttrs = malloc(schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE)); -+ if (!sdb_p->schemaAttrs) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ do { -+ sqlerr = sqlite3_step(stmt); -+ if (sqlerr == SQLITE_BUSY) { -+ PR_Sleep(SDB_BUSY_RETRY_TIME); -+ } -+ if (sqlerr == SQLITE_ROW) { -+ if (backedAttrs == schemaAttrsCapacity) { -+ schemaAttrsCapacity += known_attributes_size; -+ sdb_p->schemaAttrs = realloc(sdb_p->schemaAttrs, -+ schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE)); -+ if (!sdb_p->schemaAttrs) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ } -+ /* Record the ULONG attribute value. */ -+ char *val = (char *)sqlite3_column_text(stmt, 1); -+ if (val && val[0] == 'a') { -+ CK_ATTRIBUTE_TYPE attr = strtoul(&val[1], NULL, 16); -+ sdb_p->schemaAttrs[backedAttrs++] = attr; -+ } -+ } -+ } while (!sdb_done(sqlerr, &retry)); -+ -+ if (sqlerr != SQLITE_DONE) { -+ goto loser; -+ } -+ sqlerr = sqlite3_reset(stmt); -+ if (sqlerr != SQLITE_OK) { -+ goto loser; -+ } -+ sqlerr = sqlite3_finalize(stmt); -+ if (sqlerr != SQLITE_OK) { -+ goto loser; -+ } -+ -+ sdb_p->numSchemaAttrs = backedAttrs; -+ -+ /* Sort these once so we can shortcut invalid attribute searches. */ -+ qsort(sdb_p->schemaAttrs, sdb_p->numSchemaAttrs, -+ sizeof(CK_ATTRIBUTE_TYPE), sdb_attributeComparator); -+ } -+ -+ /* invariant fields */ -+ sdb_p->sqlDBName = PORT_Strdup(dbname); -+ sdb_p->type = type; -+ sdb_p->table = table; -+ sdb_p->cacheTable = cacheTable; -+ sdb_p->lastUpdateTime = now; -+ /* set the cache delay time. This is how long we will wait before we -+ * decide the existing cache is stale. Currently set to 10 sec */ -+ sdb_p->updateInterval = PR_SecondsToInterval(10); -+ sdb_p->dbMon = PR_NewMonitor(); -+ /* these fields are protected by the lock */ -+ sdb_p->sqlXactDB = NULL; -+ sdb_p->sqlXactThread = NULL; -+ sdb->private = sdb_p; -+ sdb->version = 1; -+ sdb->sdb_flags = inFlags | SDB_HAS_META; -+ sdb->app_private = NULL; -+ sdb->sdb_FindObjectsInit = sdb_FindObjectsInit; -+ sdb->sdb_FindObjects = sdb_FindObjects; -+ sdb->sdb_FindObjectsFinal = sdb_FindObjectsFinal; -+ sdb->sdb_GetAttributeValue = sdb_GetAttributeValue; -+ sdb->sdb_SetAttributeValue = sdb_SetAttributeValue; -+ sdb->sdb_CreateObject = sdb_CreateObject; -+ sdb->sdb_DestroyObject = sdb_DestroyObject; -+ sdb->sdb_GetMetaData = sdb_GetMetaData; -+ sdb->sdb_PutMetaData = sdb_PutMetaData; -+ sdb->sdb_DestroyMetaData = sdb_DestroyMetaData; -+ sdb->sdb_Begin = sdb_Begin; -+ sdb->sdb_Commit = sdb_Commit; -+ sdb->sdb_Abort = sdb_Abort; -+ sdb->sdb_Reset = sdb_Reset; -+ sdb->sdb_Close = sdb_Close; -+ sdb->sdb_SetForkState = sdb_SetForkState; -+ sdb->sdb_GetNewObjectID = sdb_GetNewObjectID; -+ -+ if (inTransaction) { -+ sqlerr = sqlite3_exec(sqlDB, COMMIT_CMD, NULL, 0, NULL); -+ if (sqlerr != SQLITE_OK) { -+ error = sdb_mapSQLError(sdb_p->type, sqlerr); -+ goto loser; -+ } -+ inTransaction = 0; -+ } -+ -+ sdb_p->sqlReadDB = sqlDB; -+ -+ *pSdb = sdb; -+ UNLOCK_SQLITE(); -+ return CKR_OK; -+ -+loser: -+ /* lots of stuff to do */ -+ if (inTransaction) { -+ sqlite3_exec(sqlDB, ROLLBACK_CMD, NULL, 0, NULL); -+ } -+ if (sdb) { -+ free(sdb); -+ } -+ if (sdb_p) { -+ if (sdb_p->schemaAttrs) { -+ free(sdb_p->schemaAttrs); -+ } -+ free(sdb_p); -+ } -+ if (sqlDB) { -+ sqlite3_close(sqlDB); -+ } -+ UNLOCK_SQLITE(); -+ return error; -+} -+ -+/* sdbopen */ -+CK_RV -+s_open(const char *directory, const char *certPrefix, const char *keyPrefix, -+ int cert_version, int key_version, int flags, -+ SDB **certdb, SDB **keydb, int *newInit) -+{ -+ char *cert = sdb_BuildFileName(directory, certPrefix, -+ "cert", cert_version); -+ char *key = sdb_BuildFileName(directory, keyPrefix, -+ "key", key_version); -+ CK_RV error = CKR_OK; -+ int inUpdate; -+ PRUint32 accessOps; -+ -+ if (certdb) -+ *certdb = NULL; -+ if (keydb) -+ *keydb = NULL; -+ *newInit = 0; -+ -+#ifdef SQLITE_UNSAFE_THREADS -+ if (sqlite_lock == NULL) { -+ sqlite_lock = PR_NewLock(); -+ if (sqlite_lock == NULL) { -+ error = CKR_HOST_MEMORY; -+ goto loser; -+ } -+ } -+#endif -+ -+ /* how long does it take to test for a non-existant file in our working -+ * directory? Allows us to test if we may be on a network file system */ -+ accessOps = 1; -+ { -+ char *env; -+ env = PR_GetEnvSecure("NSS_SDB_USE_CACHE"); -+ /* If the environment variable is undefined or set to yes or no, -+ * sdb_init() will ignore the value of accessOps, and we can skip the -+ * measuring.*/ -+ if (env && PORT_Strcasecmp(env, "no") != 0 && -+ PORT_Strcasecmp(env, "yes") != 0) { -+ accessOps = sdb_measureAccess(directory); -+ } -+ } -+ -+ /* -+ * open the cert data base -+ */ -+ if (certdb) { -+ /* initialize Certificate database */ -+ error = sdb_init(cert, "nssPublic", SDB_CERT, &inUpdate, -+ newInit, flags, accessOps, certdb); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ } -+ -+ /* -+ * open the key data base: -+ * NOTE:if we want to implement a single database, we open -+ * the same database file as the certificate here. -+ * -+ * cert an key db's have different tables, so they will not -+ * conflict. -+ */ -+ if (keydb) { -+ /* initialize the Key database */ -+ error = sdb_init(key, "nssPrivate", SDB_KEY, &inUpdate, -+ newInit, flags, accessOps, keydb); -+ if (error != CKR_OK) { -+ goto loser; -+ } -+ } -+ -+loser: -+ if (cert) { -+ sqlite3_free(cert); -+ } -+ if (key) { -+ sqlite3_free(key); -+ } -+ -+ if (error != CKR_OK) { -+ /* currently redundant, but could be necessary if more code is added -+ * just before loser */ -+ if (keydb && *keydb) { -+ sdb_Close(*keydb); -+ } -+ if (certdb && *certdb) { -+ sdb_Close(*certdb); -+ } -+ } -+ -+ return error; -+} -+ -+CK_RV -+s_shutdown() -+{ -+#ifdef SQLITE_UNSAFE_THREADS -+ if (sqlite_lock) { -+ PR_DestroyLock(sqlite_lock); -+ sqlite_lock = NULL; -+ } -+#endif -+ return CKR_OK; -+} -diff --git a/cmd/manifest.mn b/cmd/manifest.mn ---- a/cmd/manifest.mn -+++ b/cmd/manifest.mn -@@ -36,16 +36,17 @@ NSS_SRCDIRS = \ - addbuiltin \ - atob \ - btoa \ - certutil \ - chktest \ - crlutil \ - crmftest \ - dbtest \ -+ dbtool \ - derdump \ - digest \ - httpserv \ - listsuites \ - makepqg \ - multinit \ - nss-policy-check \ - ocspclnt \ diff --git a/nss-3.79-distrusted-certs.patch b/nss-3.79-distrusted-certs.patch new file mode 100644 index 0000000..14a5b0c --- /dev/null +++ b/nss-3.79-distrusted-certs.patch @@ -0,0 +1,375 @@ +# HG changeset patch +# User John M. Schanck +# Date 1648094761 0 +# Thu Mar 24 04:06:01 2022 +0000 +# Node ID b722e523d66297fe4bc1fac0ebb06203138eccbb +# Parent 853b64626b19a46f41f4ba9c684490dc15923c94 +Bug 1751305 - Remove expired explicitly distrusted certificates from certdata.txt. r=KathleenWilson + +Differential Revision: https://phabricator.services.mozilla.com/D141919 + +diff --git a/lib/ckfw/builtins/certdata.txt b/lib/ckfw/builtins/certdata.txt +--- a/lib/ckfw/builtins/certdata.txt ++++ b/lib/ckfw/builtins/certdata.txt +@@ -7663,197 +7663,16 @@ CKA_SERIAL_NUMBER MULTILINE_OCTAL + \377\377 + END + CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_NOT_TRUSTED + CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_NOT_TRUSTED + CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_NOT_TRUSTED + CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + + # +-# Certificate "Explicitly Distrusted DigiNotar PKIoverheid G2" +-# +-# Issuer: CN=DigiNotar PKIoverheid CA Organisatie - G2,O=DigiNotar B.V.,C=NL +-# Serial Number: 268435455 (0xfffffff) +-# Subject: CN=DigiNotar PKIoverheid CA Organisatie - G2,O=DigiNotar B.V.,C=NL +-# Not Valid Before: Wed May 12 08:51:39 2010 +-# Not Valid After : Mon Mar 23 09:50:05 2020 +-# Fingerprint (MD5): 2E:61:A2:D1:78:CE:EE:BF:59:33:B0:23:14:0F:94:1C +-# Fingerprint (SHA1): D5:F2:57:A9:BF:2D:D0:3F:8B:46:57:F9:2B:C9:A4:C6:92:E1:42:42 +-CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE +-CKA_TOKEN CK_BBOOL CK_TRUE +-CKA_PRIVATE CK_BBOOL CK_FALSE +-CKA_MODIFIABLE CK_BBOOL CK_FALSE +-CKA_LABEL UTF8 "Explicitly Distrusted DigiNotar PKIoverheid G2" +-CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 +-CKA_SUBJECT MULTILINE_OCTAL +-\060\132\061\013\060\011\006\003\125\004\006\023\002\116\114\061 +-\027\060\025\006\003\125\004\012\014\016\104\151\147\151\116\157 +-\164\141\162\040\102\056\126\056\061\062\060\060\006\003\125\004 +-\003\014\051\104\151\147\151\116\157\164\141\162\040\120\113\111 +-\157\166\145\162\150\145\151\144\040\103\101\040\117\162\147\141 +-\156\151\163\141\164\151\145\040\055\040\107\062 +-END +-CKA_ID UTF8 "0" +-CKA_ISSUER MULTILINE_OCTAL +-\060\132\061\013\060\011\006\003\125\004\006\023\002\116\114\061 +-\027\060\025\006\003\125\004\012\014\016\104\151\147\151\116\157 +-\164\141\162\040\102\056\126\056\061\062\060\060\006\003\125\004 +-\003\014\051\104\151\147\151\116\157\164\141\162\040\120\113\111 +-\157\166\145\162\150\145\151\144\040\103\101\040\117\162\147\141 +-\156\151\163\141\164\151\145\040\055\040\107\062 +-END +-CKA_SERIAL_NUMBER MULTILINE_OCTAL +-\002\004\017\377\377\377 +-END +-CKA_VALUE MULTILINE_OCTAL +-\060\202\006\225\060\202\004\175\240\003\002\001\002\002\004\017 +-\377\377\377\060\015\006\011\052\206\110\206\367\015\001\001\013 +-\005\000\060\132\061\013\060\011\006\003\125\004\006\023\002\116 +-\114\061\027\060\025\006\003\125\004\012\014\016\104\151\147\151 +-\116\157\164\141\162\040\102\056\126\056\061\062\060\060\006\003 +-\125\004\003\014\051\104\151\147\151\116\157\164\141\162\040\120 +-\113\111\157\166\145\162\150\145\151\144\040\103\101\040\117\162 +-\147\141\156\151\163\141\164\151\145\040\055\040\107\062\060\036 +-\027\015\061\060\060\065\061\062\060\070\065\061\063\071\132\027 +-\015\062\060\060\063\062\063\060\071\065\060\060\065\132\060\132 +-\061\013\060\011\006\003\125\004\006\023\002\116\114\061\027\060 +-\025\006\003\125\004\012\014\016\104\151\147\151\116\157\164\141 +-\162\040\102\056\126\056\061\062\060\060\006\003\125\004\003\014 +-\051\104\151\147\151\116\157\164\141\162\040\120\113\111\157\166 +-\145\162\150\145\151\144\040\103\101\040\117\162\147\141\156\151 +-\163\141\164\151\145\040\055\040\107\062\060\202\002\042\060\015 +-\006\011\052\206\110\206\367\015\001\001\001\005\000\003\202\002 +-\017\000\060\202\002\012\002\202\002\001\000\261\023\031\017\047 +-\346\154\324\125\206\113\320\354\211\212\105\221\170\254\107\275 +-\107\053\344\374\105\353\117\264\046\163\133\067\323\303\177\366 +-\343\336\327\243\370\055\150\305\010\076\113\224\326\344\207\045 +-\066\153\204\265\030\164\363\050\130\163\057\233\152\317\274\004 +-\036\366\336\335\257\374\113\252\365\333\146\142\045\001\045\202 +-\336\362\227\132\020\156\335\135\251\042\261\004\251\043\163\072 +-\370\161\255\035\317\204\104\353\107\321\257\155\310\174\050\253 +-\307\362\067\172\164\137\137\305\002\024\212\243\132\343\033\154 +-\001\343\135\216\331\150\326\364\011\033\062\334\221\265\054\365 +-\040\353\214\003\155\046\111\270\223\304\205\135\330\322\233\257 +-\126\152\314\005\063\314\240\102\236\064\125\104\234\153\240\324 +-\022\320\053\124\315\267\211\015\345\366\353\350\373\205\001\063 +-\117\172\153\361\235\162\063\226\016\367\262\204\245\245\047\304 +-\047\361\121\163\051\167\272\147\156\376\114\334\264\342\241\241 +-\201\057\071\111\215\103\070\023\316\320\245\134\302\207\072\000 +-\147\145\102\043\361\066\131\012\035\243\121\310\274\243\224\052 +-\061\337\343\074\362\235\032\074\004\260\357\261\012\060\023\163 +-\266\327\363\243\114\001\165\024\205\170\300\327\212\071\130\205 +-\120\372\056\346\305\276\317\213\077\257\217\066\324\045\011\055 +-\322\017\254\162\223\362\277\213\324\120\263\371\025\120\233\231 +-\365\024\331\373\213\221\243\062\046\046\240\370\337\073\140\201 +-\206\203\171\133\053\353\023\075\051\072\301\155\335\275\236\216 +-\207\326\112\256\064\227\005\356\024\246\366\334\070\176\112\351 +-\044\124\007\075\227\150\067\106\153\015\307\250\041\257\023\124 +-\344\011\152\361\115\106\012\311\135\373\233\117\275\336\373\267 +-\124\313\270\070\234\247\071\373\152\055\300\173\215\253\245\247 +-\127\354\112\222\212\063\305\341\040\134\163\330\220\222\053\200 +-\325\017\206\030\151\174\071\117\204\206\274\367\114\133\363\325 +-\264\312\240\302\360\067\042\312\171\122\037\123\346\252\363\220 +-\260\073\335\362\050\375\254\353\305\006\044\240\311\324\057\017 +-\130\375\265\236\354\017\317\262\131\320\242\004\172\070\152\256 +-\162\373\275\360\045\142\224\011\247\005\013\002\003\001\000\001 +-\243\202\001\141\060\202\001\135\060\110\006\003\125\035\040\004 +-\101\060\077\060\075\006\004\125\035\040\000\060\065\060\063\006 +-\010\053\006\001\005\005\007\002\001\026\047\150\164\164\160\072 +-\057\057\167\167\167\056\144\151\147\151\156\157\164\141\162\056 +-\156\154\057\143\160\163\057\160\153\151\157\166\145\162\150\145 +-\151\144\060\017\006\003\125\035\023\001\001\377\004\005\060\003 +-\001\001\377\060\016\006\003\125\035\017\001\001\377\004\004\003 +-\002\001\006\060\201\205\006\003\125\035\043\004\176\060\174\200 +-\024\071\020\213\111\222\134\333\141\022\040\315\111\235\032\216 +-\332\234\147\100\271\241\136\244\134\060\132\061\013\060\011\006 +-\003\125\004\006\023\002\116\114\061\036\060\034\006\003\125\004 +-\012\014\025\123\164\141\141\164\040\144\145\162\040\116\145\144 +-\145\162\154\141\156\144\145\156\061\053\060\051\006\003\125\004 +-\003\014\042\123\164\141\141\164\040\144\145\162\040\116\145\144 +-\145\162\154\141\156\144\145\156\040\122\157\157\164\040\103\101 +-\040\055\040\107\062\202\004\000\230\226\364\060\111\006\003\125 +-\035\037\004\102\060\100\060\076\240\074\240\072\206\070\150\164 +-\164\160\072\057\057\143\162\154\056\160\153\151\157\166\145\162 +-\150\145\151\144\056\156\154\057\104\157\155\117\162\147\141\156 +-\151\163\141\164\151\145\114\141\164\145\163\164\103\122\114\055 +-\107\062\056\143\162\154\060\035\006\003\125\035\016\004\026\004 +-\024\274\135\224\073\331\253\173\003\045\163\141\302\333\055\356 +-\374\253\217\145\241\060\015\006\011\052\206\110\206\367\015\001 +-\001\013\005\000\003\202\002\001\000\217\374\055\114\267\331\055 +-\325\037\275\357\313\364\267\150\027\165\235\116\325\367\335\234 +-\361\052\046\355\237\242\266\034\003\325\123\263\354\010\317\064 +-\342\343\303\364\265\026\057\310\303\276\327\323\163\253\000\066 +-\371\032\112\176\326\143\351\136\106\272\245\266\216\025\267\243 +-\052\330\103\035\357\135\310\037\201\205\263\213\367\377\074\364 +-\331\364\106\010\077\234\274\035\240\331\250\114\315\045\122\116 +-\012\261\040\367\037\351\103\331\124\106\201\023\232\300\136\164 +-\154\052\230\062\352\374\167\273\015\245\242\061\230\042\176\174 +-\174\347\332\244\255\354\267\056\032\031\161\370\110\120\332\103 +-\217\054\204\335\301\100\047\343\265\360\025\116\226\324\370\134 +-\343\206\051\106\053\327\073\007\353\070\177\310\206\127\227\323 +-\357\052\063\304\027\120\325\144\151\153\053\153\105\136\135\057 +-\027\312\132\116\317\303\327\071\074\365\073\237\106\271\233\347 +-\016\111\227\235\326\325\343\033\017\352\217\001\116\232\023\224 +-\131\012\002\007\110\113\032\140\253\177\117\355\013\330\125\015 +-\150\157\125\234\151\145\025\102\354\300\334\335\154\254\303\026 +-\316\013\035\126\233\244\304\304\322\056\340\017\342\104\047\053 +-\120\151\244\334\142\350\212\041\051\102\154\314\000\072\226\166 +-\233\357\100\300\244\136\167\204\062\154\046\052\071\146\256\135 +-\343\271\271\262\054\150\037\036\232\220\003\071\360\252\263\244 +-\314\111\213\030\064\351\067\311\173\051\307\204\174\157\104\025 +-\057\354\141\131\004\311\105\313\242\326\122\242\174\177\051\222 +-\326\112\305\213\102\250\324\376\352\330\307\207\043\030\344\235 +-\172\175\163\100\122\230\240\256\156\343\005\077\005\017\340\245 +-\306\155\115\355\203\067\210\234\307\363\334\102\232\152\266\327 +-\041\111\066\167\362\357\030\117\305\160\331\236\351\336\267\053 +-\213\364\274\176\050\337\015\100\311\205\134\256\235\305\061\377 +-\320\134\016\265\250\176\360\351\057\272\257\210\256\345\265\321 +-\130\245\257\234\161\247\051\001\220\203\151\067\202\005\272\374 +-\011\301\010\156\214\170\073\303\063\002\200\077\104\205\010\035 +-\337\125\126\010\255\054\205\055\135\261\003\341\256\252\164\305 +-\244\363\116\272\067\230\173\202\271 +-END +- +-# Trust for Certificate "Explicitly Distrusted DigiNotar PKIoverheid G2" +-# Issuer: CN=DigiNotar PKIoverheid CA Organisatie - G2,O=DigiNotar B.V.,C=NL +-# Serial Number: 268435455 (0xfffffff) +-# Subject: CN=DigiNotar PKIoverheid CA Organisatie - G2,O=DigiNotar B.V.,C=NL +-# Not Valid Before: Wed May 12 08:51:39 2010 +-# Not Valid After : Mon Mar 23 09:50:05 2020 +-# Fingerprint (MD5): 2E:61:A2:D1:78:CE:EE:BF:59:33:B0:23:14:0F:94:1C +-# Fingerprint (SHA1): D5:F2:57:A9:BF:2D:D0:3F:8B:46:57:F9:2B:C9:A4:C6:92:E1:42:42 +-CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +-CKA_TOKEN CK_BBOOL CK_TRUE +-CKA_PRIVATE CK_BBOOL CK_FALSE +-CKA_MODIFIABLE CK_BBOOL CK_FALSE +-CKA_LABEL UTF8 "Explicitly Distrusted DigiNotar PKIoverheid G2" +-CKA_CERT_SHA1_HASH MULTILINE_OCTAL +-\325\362\127\251\277\055\320\077\213\106\127\371\053\311\244\306 +-\222\341\102\102 +-END +-CKA_CERT_MD5_HASH MULTILINE_OCTAL +-\056\141\242\321\170\316\356\277\131\063\260\043\024\017\224\034 +-END +-CKA_ISSUER MULTILINE_OCTAL +-\060\132\061\013\060\011\006\003\125\004\006\023\002\116\114\061 +-\027\060\025\006\003\125\004\012\014\016\104\151\147\151\116\157 +-\164\141\162\040\102\056\126\056\061\062\060\060\006\003\125\004 +-\003\014\051\104\151\147\151\116\157\164\141\162\040\120\113\111 +-\157\166\145\162\150\145\151\144\040\103\101\040\117\162\147\141 +-\156\151\163\141\164\151\145\040\055\040\107\062 +-END +-CKA_SERIAL_NUMBER MULTILINE_OCTAL +-\002\004\017\377\377\377 +-END +-CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE +- +-# + # Certificate "Security Communication RootCA2" + # + # Issuer: OU=Security Communication RootCA2,O="SECOM Trust Systems CO.,LTD.",C=JP + # Serial Number: 0 (0x0) + # Subject: OU=Security Communication RootCA2,O="SECOM Trust Systems CO.,LTD.",C=JP + # Not Valid Before: Fri May 29 05:00:39 2009 + # Not Valid After : Tue May 29 05:00:39 2029 + # Fingerprint (SHA-256): 51:3B:2C:EC:B8:10:D4:CD:E5:DD:85:39:1A:DF:C6:C2:DD:60:D8:7B:B7:36:D2:B5:21:48:4A:A4:7A:0E:BE:F6 +@@ -8337,78 +8156,16 @@ END + CKA_SERIAL_NUMBER MULTILINE_OCTAL + \002\001\000 + END + CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR + CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR + CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST + CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +-# Explicitly Distrust "MITM subCA 1 issued by Trustwave", Bug 724929 +-# Issuer: E=ca@trustwave.com,CN="Trustwave Organization Issuing CA, Level 2",O="Trustwave Holdings, Inc.",L=Chicago,ST=Illinois,C=US +-# Serial Number: 1800000005 (0x6b49d205) +-# Not Before: Apr 7 15:37:15 2011 GMT +-# Not After : Apr 4 15:37:15 2021 GMT +-CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +-CKA_TOKEN CK_BBOOL CK_TRUE +-CKA_PRIVATE CK_BBOOL CK_FALSE +-CKA_MODIFIABLE CK_BBOOL CK_FALSE +-CKA_LABEL UTF8 "MITM subCA 1 issued by Trustwave" +-CKA_ISSUER MULTILINE_OCTAL +-\060\201\253\061\013\060\011\006\003\125\004\006\023\002\125\123 +-\061\021\060\017\006\003\125\004\010\023\010\111\154\154\151\156 +-\157\151\163\061\020\060\016\006\003\125\004\007\023\007\103\150 +-\151\143\141\147\157\061\041\060\037\006\003\125\004\012\023\030 +-\124\162\165\163\164\167\141\166\145\040\110\157\154\144\151\156 +-\147\163\054\040\111\156\143\056\061\063\060\061\006\003\125\004 +-\003\023\052\124\162\165\163\164\167\141\166\145\040\117\162\147 +-\141\156\151\172\141\164\151\157\156\040\111\163\163\165\151\156 +-\147\040\103\101\054\040\114\145\166\145\154\040\062\061\037\060 +-\035\006\011\052\206\110\206\367\015\001\011\001\026\020\143\141 +-\100\164\162\165\163\164\167\141\166\145\056\143\157\155 +-END +-CKA_SERIAL_NUMBER MULTILINE_OCTAL +-\002\004\153\111\322\005 +-END +-CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE +- +-# Explicitly Distrust "MITM subCA 2 issued by Trustwave", Bug 724929 +-# Issuer: E=ca@trustwave.com,CN="Trustwave Organization Issuing CA, Level 2",O="Trustwave Holdings, Inc.",L=Chicago,ST=Illinois,C=US +-# Serial Number: 1800000006 (0x6b49d206) +-# Not Before: Apr 18 21:09:30 2011 GMT +-# Not After : Apr 15 21:09:30 2021 GMT +-CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +-CKA_TOKEN CK_BBOOL CK_TRUE +-CKA_PRIVATE CK_BBOOL CK_FALSE +-CKA_MODIFIABLE CK_BBOOL CK_FALSE +-CKA_LABEL UTF8 "MITM subCA 2 issued by Trustwave" +-CKA_ISSUER MULTILINE_OCTAL +-\060\201\253\061\013\060\011\006\003\125\004\006\023\002\125\123 +-\061\021\060\017\006\003\125\004\010\023\010\111\154\154\151\156 +-\157\151\163\061\020\060\016\006\003\125\004\007\023\007\103\150 +-\151\143\141\147\157\061\041\060\037\006\003\125\004\012\023\030 +-\124\162\165\163\164\167\141\166\145\040\110\157\154\144\151\156 +-\147\163\054\040\111\156\143\056\061\063\060\061\006\003\125\004 +-\003\023\052\124\162\165\163\164\167\141\166\145\040\117\162\147 +-\141\156\151\172\141\164\151\157\156\040\111\163\163\165\151\156 +-\147\040\103\101\054\040\114\145\166\145\154\040\062\061\037\060 +-\035\006\011\052\206\110\206\367\015\001\011\001\026\020\143\141 +-\100\164\162\165\163\164\167\141\166\145\056\143\157\155 +-END +-CKA_SERIAL_NUMBER MULTILINE_OCTAL +-\002\004\153\111\322\006 +-END +-CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE +- + # + # Certificate "Actalis Authentication Root CA" + # + # Issuer: CN=Actalis Authentication Root CA,O=Actalis S.p.A./03358520967,L=Milan,C=IT + # Serial Number:57:0a:11:97:42:c4:e3:cc + # Subject: CN=Actalis Authentication Root CA,O=Actalis S.p.A./03358520967,L=Milan,C=IT + # Not Valid Before: Thu Sep 22 11:22:02 2011 + # Not Valid After : Sun Sep 22 11:22:02 2030 +@@ -9042,84 +8799,16 @@ END + CKA_SERIAL_NUMBER MULTILINE_OCTAL + \002\001\001 + END + CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR + CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST + CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST + CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE + +-# Explicitly Distrust "TURKTRUST Mis-issued Intermediate CA 1", Bug 825022 +-# Issuer: O=T..RKTRUST Bilgi ..leti..im ve Bili..im G..venli..i Hizmetleri A...,C=TR,CN=T..RKTRUST Elektronik Sunucu Sertifikas.. Hizmetleri +-# Serial Number: 2087 (0x827) +-# Subject: CN=*.EGO.GOV.TR,OU=EGO BILGI ISLEM,O=EGO,L=ANKARA,ST=ANKARA,C=TR +-# Not Valid Before: Mon Aug 08 07:07:51 2011 +-# Not Valid After : Tue Jul 06 07:07:51 2021 +-# Fingerprint (MD5): F8:F5:25:FF:0C:31:CF:85:E1:0C:86:17:C1:CE:1F:8E +-# Fingerprint (SHA1): C6:9F:28:C8:25:13:9E:65:A6:46:C4:34:AC:A5:A1:D2:00:29:5D:B1 +-CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +-CKA_TOKEN CK_BBOOL CK_TRUE +-CKA_PRIVATE CK_BBOOL CK_FALSE +-CKA_MODIFIABLE CK_BBOOL CK_FALSE +-CKA_LABEL UTF8 "TURKTRUST Mis-issued Intermediate CA 1" +-CKA_ISSUER MULTILINE_OCTAL +-\060\201\254\061\075\060\073\006\003\125\004\003\014\064\124\303 +-\234\122\113\124\122\125\123\124\040\105\154\145\153\164\162\157 +-\156\151\153\040\123\165\156\165\143\165\040\123\145\162\164\151 +-\146\151\153\141\163\304\261\040\110\151\172\155\145\164\154\145 +-\162\151\061\013\060\011\006\003\125\004\006\023\002\124\122\061 +-\136\060\134\006\003\125\004\012\014\125\124\303\234\122\113\124 +-\122\125\123\124\040\102\151\154\147\151\040\304\260\154\145\164 +-\151\305\237\151\155\040\166\145\040\102\151\154\151\305\237\151 +-\155\040\107\303\274\166\145\156\154\151\304\237\151\040\110\151 +-\172\155\145\164\154\145\162\151\040\101\056\305\236\056\040\050 +-\143\051\040\113\141\163\304\261\155\040\040\062\060\060\065 +-END +-CKA_SERIAL_NUMBER MULTILINE_OCTAL +-\002\002\010\047 +-END +-CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE +- +-# Explicitly Distrust "TURKTRUST Mis-issued Intermediate CA 2", Bug 825022 +-# Issuer: O=T..RKTRUST Bilgi ..leti..im ve Bili..im G..venli..i Hizmetleri A...,C=TR,CN=T..RKTRUST Elektronik Sunucu Sertifikas.. Hizmetleri +-# Serial Number: 2148 (0x864) +-# Subject: E=ileti@kktcmerkezbankasi.org,CN=e-islem.kktcmerkezbankasi.org,O=KKTC Merkez Bankasi,L=Lefkosa,ST=Lefkosa,C=TR +-# Not Valid Before: Mon Aug 08 07:07:51 2011 +-# Not Valid After : Thu Aug 05 07:07:51 2021 +-# Fingerprint (MD5): BF:C3:EC:AD:0F:42:4F:B4:B5:38:DB:35:BF:AD:84:A2 +-# Fingerprint (SHA1): F9:2B:E5:26:6C:C0:5D:B2:DC:0D:C3:F2:DC:74:E0:2D:EF:D9:49:CB +-CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST +-CKA_TOKEN CK_BBOOL CK_TRUE +-CKA_PRIVATE CK_BBOOL CK_FALSE +-CKA_MODIFIABLE CK_BBOOL CK_FALSE +-CKA_LABEL UTF8 "TURKTRUST Mis-issued Intermediate CA 2" +-CKA_ISSUER MULTILINE_OCTAL +-\060\201\254\061\075\060\073\006\003\125\004\003\014\064\124\303 +-\234\122\113\124\122\125\123\124\040\105\154\145\153\164\162\157 +-\156\151\153\040\123\165\156\165\143\165\040\123\145\162\164\151 +-\146\151\153\141\163\304\261\040\110\151\172\155\145\164\154\145 +-\162\151\061\013\060\011\006\003\125\004\006\023\002\124\122\061 +-\136\060\134\006\003\125\004\012\014\125\124\303\234\122\113\124 +-\122\125\123\124\040\102\151\154\147\151\040\304\260\154\145\164 +-\151\305\237\151\155\040\166\145\040\102\151\154\151\305\237\151 +-\155\040\107\303\274\166\145\156\154\151\304\237\151\040\110\151 +-\172\155\145\164\154\145\162\151\040\101\056\305\236\056\040\050 +-\143\051\040\113\141\163\304\261\155\040\040\062\060\060\065 +-END +-CKA_SERIAL_NUMBER MULTILINE_OCTAL +-\002\002\010\144 +-END +-CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_NOT_TRUSTED +-CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE +- + # + # Certificate "D-TRUST Root Class 3 CA 2 2009" + # + # Issuer: CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE + # Serial Number: 623603 (0x983f3) + # Subject: CN=D-TRUST Root Class 3 CA 2 2009,O=D-Trust GmbH,C=DE + # Not Valid Before: Thu Nov 05 08:35:58 2009 + # Not Valid After : Mon Nov 05 08:35:58 2029 diff --git a/nss-3.79-fips.patch b/nss-3.79-fips.patch new file mode 100644 index 0000000..07c500f --- /dev/null +++ b/nss-3.79-fips.patch @@ -0,0 +1,578 @@ +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 ++#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=¶ms->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 + * + */ diff --git a/nss-3.89-dangling.patch b/nss-3.89-dangling.patch deleted file mode 100644 index ea4690c..0000000 --- a/nss-3.89-dangling.patch +++ /dev/null @@ -1,78 +0,0 @@ -diff --git a/cmd/ecperf/ecperf.c b/cmd/ecperf/ecperf.c ---- a/cmd/ecperf/ecperf.c -+++ b/cmd/ecperf/ecperf.c -@@ -51,10 +51,11 @@ - int iters = threadData->iters; - unsigned char sigData[256]; - SECItem sig; - CK_SESSION_HANDLE session; - CK_RV crv; -+ void *tmp = NULL; - - threadData->status = SECSuccess; - threadData->count = 0; - - /* get our thread's session */ -@@ -66,10 +67,11 @@ - } - - if (threadData->isSign) { - sig.data = sigData; - sig.len = sizeof(sigData); -+ tmp = threadData->p2; - threadData->p2 = (void *)&sig; - } - - while (iters--) { - threadData->status = (*op)(session, threadData->p1, -@@ -77,27 +79,33 @@ - if (threadData->status != SECSuccess) { - break; - } - threadData->count++; - } -+ -+ if (threadData->isSign) { -+ threadData->p2 = tmp; -+ } - return; - } - - void - genericThread(void *data) - { - ThreadData *threadData = (ThreadData *)data; - int iters = threadData->iters; - unsigned char sigData[256]; - SECItem sig; -+ void *tmp = NULL; - - threadData->status = SECSuccess; - threadData->count = 0; - - if (threadData->isSign) { - sig.data = sigData; - sig.len = sizeof(sigData); -+ tmp = threadData->p2; - threadData->p2 = (void *)&sig; - } - - while (iters--) { - threadData->status = (*threadData->op)(threadData->p1, -@@ -105,10 +113,14 @@ - if (threadData->status != SECSuccess) { - break; - } - threadData->count++; - } -+ -+ if (threadData->isSign) { -+ threadData->p2 = tmp; -+ } - return; - } - - /* Time iter repetitions of operation op. */ - SECStatus - - diff --git a/nss-3.90-aes-gmc-indicator.patch b/nss-3.90-aes-gmc-indicator.patch new file mode 100644 index 0000000..8a91208 --- /dev/null +++ b/nss-3.90-aes-gmc-indicator.patch @@ -0,0 +1,42 @@ +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); diff --git a/nss-3.90-dh-test-update.patch b/nss-3.90-dh-test-update.patch new file mode 100644 index 0000000..fcbeae5 --- /dev/null +++ b/nss-3.90-dh-test-update.patch @@ -0,0 +1,90 @@ +diff -up ./lib/freebl/fipsfreebl.c.dh_test ./lib/freebl/fipsfreebl.c +--- ./lib/freebl/fipsfreebl.c.dh_test 2024-01-18 08:34:45.936944401 -0800 ++++ ./lib/freebl/fipsfreebl.c 2024-01-18 09:20:57.555980326 -0800 +@@ -1816,38 +1816,39 @@ freebl_fips_DH_PowerUpSelfTest(void) + { + /* DH Known P (2048-bits) */ + static const PRUint8 dh_known_P[] = { +- 0xc2, 0x79, 0xbb, 0x76, 0x32, 0x0d, 0x43, 0xfd, +- 0x1b, 0x8c, 0xa2, 0x3c, 0x00, 0xdd, 0x6d, 0xef, +- 0xf8, 0x1a, 0xd9, 0xc1, 0xa2, 0xf5, 0x73, 0x2b, +- 0xdb, 0x1a, 0x3e, 0x84, 0x90, 0xeb, 0xe7, 0x8e, +- 0x5f, 0x5c, 0x6b, 0xb6, 0x61, 0x89, 0xd1, 0x03, +- 0xb0, 0x5f, 0x91, 0xe4, 0xd2, 0x82, 0x90, 0xfc, +- 0x3c, 0x49, 0x69, 0x59, 0xc1, 0x51, 0x6a, 0x85, +- 0x71, 0xe7, 0x5d, 0x72, 0x5a, 0x45, 0xad, 0x01, +- 0x6f, 0x82, 0xae, 0xec, 0x91, 0x08, 0x2e, 0x7c, +- 0x64, 0x93, 0x46, 0x1c, 0x68, 0xef, 0xc2, 0x03, +- 0x28, 0x1d, 0x75, 0x3a, 0xeb, 0x9c, 0x46, 0xf0, +- 0xc9, 0xdb, 0x99, 0x95, 0x13, 0x66, 0x4d, 0xd5, +- 0x1a, 0x78, 0x92, 0x51, 0x89, 0x72, 0x28, 0x7f, +- 0x20, 0x70, 0x41, 0x49, 0xa2, 0x86, 0xe9, 0xf9, +- 0x78, 0x5f, 0x8d, 0x2e, 0x5d, 0xfa, 0xdb, 0x57, +- 0xd4, 0x71, 0xdf, 0x66, 0xe3, 0x9e, 0x88, 0x70, +- 0xa4, 0x21, 0x44, 0x6a, 0xc7, 0xae, 0x30, 0x2c, +- 0x9c, 0x1f, 0x91, 0x57, 0xc8, 0x24, 0x34, 0x2d, +- 0x7a, 0x4a, 0x43, 0xc2, 0x5f, 0xab, 0x64, 0x2e, +- 0xaa, 0x28, 0x32, 0x95, 0x42, 0x7b, 0xa0, 0xcc, +- 0xdf, 0xfd, 0x22, 0xc8, 0x56, 0x84, 0xc1, 0x62, +- 0x15, 0xb2, 0x77, 0x86, 0x81, 0xfc, 0xa5, 0x12, +- 0x3c, 0xca, 0x28, 0x17, 0x8f, 0x03, 0x16, 0x6e, +- 0xb8, 0x24, 0xfa, 0x1b, 0x15, 0x02, 0xfd, 0x8b, +- 0xb6, 0x0a, 0x1a, 0xf7, 0x47, 0x41, 0xc5, 0x2b, +- 0x37, 0x3e, 0xa1, 0xbf, 0x68, 0xda, 0x1c, 0x55, +- 0x44, 0xc3, 0xee, 0xa1, 0x63, 0x07, 0x11, 0x3b, +- 0x5f, 0x00, 0x84, 0xb4, 0xc4, 0xe4, 0xa7, 0x97, +- 0x29, 0xf8, 0xce, 0xab, 0xfc, 0x27, 0x3e, 0x34, +- 0xe4, 0xc7, 0x81, 0x52, 0x32, 0x0e, 0x27, 0x3c, +- 0xa6, 0x70, 0x3f, 0x4a, 0x54, 0xda, 0xdd, 0x60, +- 0x26, 0xb3, 0x6e, 0x45, 0x26, 0x19, 0x41, 0x6f ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, ++ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, ++ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, ++ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, ++ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, ++ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, ++ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, ++ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, ++ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, ++ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, ++ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, ++ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, ++ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, ++ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, ++ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, ++ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, ++ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, ++ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, ++ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, ++ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, ++ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, ++ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, ++ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, ++ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, ++ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, ++ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, ++ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, ++ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, ++ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, ++ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ++ + }; + + static const PRUint8 dh_known_Y_1[] = { +@@ -1893,10 +1894,10 @@ freebl_fips_DH_PowerUpSelfTest(void) + }; + + static const PRUint8 dh_known_hash_result[] = { +- 0x93, 0xa2, 0x89, 0x1c, 0x8a, 0xc3, 0x70, 0xbf, +- 0xa7, 0xdf, 0xb6, 0xd7, 0x82, 0xfb, 0x87, 0x81, +- 0x09, 0x47, 0xf3, 0x9f, 0x5a, 0xbf, 0x4f, 0x3f, +- 0x8e, 0x5e, 0x06, 0xca, 0x30, 0xa7, 0xaf, 0x10 ++ 0x40, 0xe3, 0x7a, 0x34, 0x83, 0x2d, 0x94, 0x57, ++ 0x99, 0x3d, 0x66, 0xec, 0x54, 0xdf, 0x82, 0x4a, ++ 0x37, 0x0d, 0xf9, 0x01, 0xb3, 0xbc, 0x54, 0xe5, ++ 0x5e, 0x63, 0xd3, 0x46, 0x4e, 0xa3, 0xe2, 0x8a + }; + + /* DH variables. */ diff --git a/nss-3.90-fips-indicators2.patch b/nss-3.90-fips-indicators2.patch new file mode 100644 index 0000000..e02d8bf --- /dev/null +++ b/nss-3.90-fips-indicators2.patch @@ -0,0 +1,176 @@ +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; + } + } diff --git a/nss-3.90-fips-safe-memset.patch b/nss-3.90-fips-safe-memset.patch new file mode 100644 index 0000000..1503bd9 --- /dev/null +++ b/nss-3.90-fips-safe-memset.patch @@ -0,0 +1,506 @@ +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 + + #include ++/* ask for Annex K for memset_s. will set the appropriate #define ++ * if Annex K is supported */ ++#define __STDC_WANT_LIB_EXT1__ 1 + #include + #include + #include +@@ -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 diff --git a/nss-3.90-pbkdf2-indicator.patch b/nss-3.90-pbkdf2-indicator.patch new file mode 100644 index 0000000..dbb7765 --- /dev/null +++ b/nss-3.90-pbkdf2-indicator.patch @@ -0,0 +1,42 @@ +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; + } diff --git a/nss-3.90-ppc_no_init.patch b/nss-3.90-ppc_no_init.patch new file mode 100644 index 0000000..134955a --- /dev/null +++ b/nss-3.90-ppc_no_init.patch @@ -0,0 +1,36 @@ +diff -up ./lib/freebl/Makefile.ppc_no_init ./lib/freebl/Makefile +--- ./lib/freebl/Makefile.ppc_no_init 2024-06-03 14:12:24.216755903 -0700 ++++ ./lib/freebl/Makefile 2024-06-03 14:11:36.464234903 -0700 +@@ -303,7 +303,7 @@ endif + ifeq ($(CPU_ARCH),ppc) + EXTRA_SRCS += gcm-ppc.c + ifdef USE_64 +- DEFINES += -DNSS_NO_INIT_SUPPORT ++# DEFINES += -DNSS_NO_INIT_SUPPORT + PPC_ABI := $(shell $(CC) -dM -E - < /dev/null | awk '$$2 == "_CALL_ELF" {print $$3}') + ifeq ($(PPC_ABI),2) + ASFILES += sha512-p8.s +diff -up ./lib/softoken/Makefile.ppc_no_init ./lib/softoken/Makefile +--- ./lib/softoken/Makefile.ppc_no_init 2024-06-03 14:12:44.664979003 -0700 ++++ ./lib/softoken/Makefile 2024-06-03 14:10:26.703473806 -0700 +@@ -23,13 +23,13 @@ include $(CORE_DEPTH)/coreconf/config.mk + ifdef NSS_NO_INIT_SUPPORT + DEFINES += -DNSS_NO_INIT_SUPPORT + endif +-ifeq ($(OS_TARGET),Linux) +-ifeq ($(CPU_ARCH),ppc) +-ifdef USE_64 +- DEFINES += -DNSS_NO_INIT_SUPPORT +-endif # USE_64 +-endif # ppc +-endif # Linux ++#ifeq ($(OS_TARGET),Linux) ++#ifeq ($(CPU_ARCH),ppc) ++#ifdef USE_64 ++# DEFINES += -DNSS_NO_INIT_SUPPORT ++#endif # USE_64 ++#endif # ppc ++#endif # Linux + + + ####################################################################### diff --git a/nss-dso-ldflags.patch b/nss-dso-ldflags.patch new file mode 100644 index 0000000..d5485ae --- /dev/null +++ b/nss-dso-ldflags.patch @@ -0,0 +1,13 @@ +Index: nss/coreconf/Linux.mk +=================================================================== +--- nss.orig/coreconf/Linux.mk ++++ nss/coreconf/Linux.mk +@@ -144,7 +144,7 @@ ifdef USE_PTHREADS + endif + + DSO_CFLAGS = -fPIC +-DSO_LDOPTS = -shared $(ARCHFLAG) -Wl,--gc-sections ++DSO_LDOPTS = -shared $(ARCHFLAG) -Wl,--gc-sections $(DSO_LDFLAGS) + # The linker on Red Hat Linux 7.2 and RHEL 2.1 (GNU ld version 2.11.90.0.8) + # incorrectly reports undefined references in the libraries we link with, so + # we don't use -z defs there. diff --git a/nss.spec b/nss.spec index c5412d9..8875897 100644 --- a/nss.spec +++ b/nss.spec @@ -1,13 +1,13 @@ +%global nss_version 3.101.0 %global nspr_version 4.35.0 -%global nss_version 3.97.0 # 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 1 %global nss_release %baserelease # use "%%global nspr_release %%[%%baserelease+n]" to handle offsets when # release number between nss and nspr are different. -%global nspr_release %[%baserelease+19] +%global nspr_release %[%baserelease+21] # only need to update this as we added new # algorithms under nss policy control %global crypto_policies_version 20210118 @@ -129,11 +129,53 @@ Source101: nspr-config.xml # but it doesn't hurt to keep it. Patch4: iquote.patch Patch12: nss-signtool-format.patch -# fedora disabled dbm by default -Patch40: nss-no-dbm-man-page.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 +Patch32: nss-3.101-disable-md5.patch +# rhel10 disabled dbm by default +Patch33: nss-no-dbm-man-page.patch + +# not upstreamable patch... +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 + +# patches that expect to be upstreamed +# https://bugzilla.mozilla.org/show_bug.cgi?id=1767883 +Patch50: nss-3.79-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 + +# 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 + +# RHEL-10 specific +Patch90: nss-3.101-disable_dsa.patch + +# NSS reverse patches +Patch300: nss-3.79-distrusted-certs.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 %description Network Security Services (NSS) is a set of libraries designed to @@ -289,13 +331,15 @@ Header files for doing development with the Netscape Portable Runtime. %setup -q -T -b 0 -n %{name}-%{nss_archive_version} cp ./nspr/config/nspr-config.in ./nspr/config/nspr-config-pc.in -%patch 100 -p0 -b .flags +%patch -P 100 -p0 -b .flags pushd nspr -%patch 101 -p1 -b .gcc-atomics +%autopatch -p 1 -m 101 -M 299 popd pushd nss %autopatch -p1 -M 99 +# sigh it would be nice if autopatch supported -R +%patch -P 300 -R -p 1 popd # https://bugzilla.redhat.com/show_bug.cgi?id=1247353 @@ -360,6 +404,8 @@ popd export IN_TREE_FREEBL_HEADERS_FIRST=1 export NSS_FORCE_FIPS=1 +export NSS_DISABLE_DEPRECATED_SEED=1 +export NSS_DISABLE_DSA=1 # Enable compiler optimizations and disable debugging code export BUILD_OPT=1 @@ -548,6 +594,8 @@ export FREEBL_NO_DEPEND=1 export BUILD_OPT=1 export NSS_DISABLE_PPC_GHASH=1 +export NSS_DISABLE_DEPRECATED_SEED=1 +export NSS_DISABLE_DSA=1 %ifnarch noarch %if 0%{__isa_bits} == 64 @@ -907,7 +955,6 @@ update-crypto-policies &> /dev/null || : %{_includedir}/nss3/crmft.h %{_includedir}/nss3/cryptohi.h %{_includedir}/nss3/cryptoht.h -%{_includedir}/nss3/sechash.h %{_includedir}/nss3/jar-ds.h %{_includedir}/nss3/jar.h %{_includedir}/nss3/jarfile.h @@ -932,6 +979,7 @@ update-crypto-policies &> /dev/null || : %{_includedir}/nss3/pkcs12t.h %{_includedir}/nss3/pkcs7t.h %{_includedir}/nss3/preenc.h +%{_includedir}/nss3/sechash.h %{_includedir}/nss3/secmime.h %{_includedir}/nss3/secmod.h %{_includedir}/nss3/secmodt.h @@ -975,16 +1023,17 @@ update-crypto-policies &> /dev/null || : %{_includedir}/nss3/base64.h %{_includedir}/nss3/ciferfam.h %{_includedir}/nss3/eccutil.h +%{_includedir}/nss3/kyber.h %{_includedir}/nss3/hasht.h %{_includedir}/nss3/nssb64.h %{_includedir}/nss3/nssb64t.h -%{_includedir}/nss3/nsslocks.h +%{_includedir}/nss3/nsshash.h %{_includedir}/nss3/nssilock.h %{_includedir}/nss3/nssilckt.h +%{_includedir}/nss3/nsslocks.h %{_includedir}/nss3/nssrwlk.h %{_includedir}/nss3/nssrwlkt.h %{_includedir}/nss3/nssutil.h -%{_includedir}/nss3/pkcs1sig.h %{_includedir}/nss3/pkcs11.h %{_includedir}/nss3/pkcs11f.h %{_includedir}/nss3/pkcs11n.h @@ -992,6 +1041,7 @@ update-crypto-policies &> /dev/null || : %{_includedir}/nss3/pkcs11t.h %{_includedir}/nss3/pkcs11u.h %{_includedir}/nss3/pkcs11uri.h +%{_includedir}/nss3/pkcs1sig.h %{_includedir}/nss3/portreg.h %{_includedir}/nss3/secasn1.h %{_includedir}/nss3/secasn1t.h @@ -1009,7 +1059,6 @@ update-crypto-policies &> /dev/null || : %{_includedir}/nss3/utilpars.h %{_includedir}/nss3/utilparst.h %{_includedir}/nss3/utilrename.h -%{_includedir}/nss3/kyber.h %{_includedir}/nss3/templates/templates.c %files softokn @@ -1044,9 +1093,9 @@ update-crypto-policies &> /dev/null || : %files softokn-freebl-devel %{_libdir}/libfreebl.a +%{_includedir}/nss3/alghmac.h %{_includedir}/nss3/blapi.h %{_includedir}/nss3/blapit.h -%{_includedir}/nss3/alghmac.h %{_includedir}/nss3/cmac.h %{_includedir}/nss3/lowkeyi.h %{_includedir}/nss3/lowkeyti.h @@ -1085,10 +1134,15 @@ update-crypto-policies &> /dev/null || : %changelog +* Tue Jun 25 2024 Bob Relyea - 3.101.0-1 +- Update NSS to 3.101.0 +- Pick up RHEL FIPS and other patches +- Turn off SEED and DSA + * Mon Jun 24 2024 Troy Dawson - 3.97.0-2 - Bump release for June 2024 mass rebuild -* Sun Jan 27 2024 Frantisek Krenzelok - 3.97.0-1 +* Sun Jan 28 2024 Frantisek Krenzelok - 3.97.0-1 - Update NSS to 3.97.0 * Thu Jan 25 2024 Fedora Release Engineering - 3.96.1-3 diff --git a/secmod.db.xml b/secmod.db.xml deleted file mode 100644 index afc9dce..0000000 --- a/secmod.db.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - -]> - - - - - &date; - Network Security Services - nss - &version; - - - - secmod.db - 5 - - - - secmod.db - Legacy NSS security modules database - - - - Description - secmod.db is an NSS security modules database. - The security modules database is used to keep track of the NSS security modules. The NSS security modules export their services via the PKCS #11 API which NSS uses as its Services Provider Interface. - - The command line utility modutil is used for managing PKCS #11 module information both within secmod.db files and within hardware tokens. - - For new applications the recommended way of tracking security modules is via the pkcs11.txt configuration file used in conjunction the new sqlite-based shared database format for certificate and key databases. - - - - - Files - /etc/pki/nssdb/secmod.db - - - - See also - modutil(1), cert8.db(5), cert9.db(5), key3.db(5), key4.db(5), pkcs11.txt(5) - - - - Authors - The nss libraries were written and maintained by developers with Netscape, Red Hat, Sun, Oracle, Mozilla, and Google. - Authors: Elio Maldonado <emaldona@redhat.com>. - - - - - LICENSE - Licensed under the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. - - - - - - diff --git a/sources b/sources index e731429..82834cf 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ SHA512 (blank-cert9.db) = 2f8eab4c0612210ee47db8a3a80c1b58a0b43849551af78c7da403fda3e3d4e7757838061ae56ccf5aac335cb54f254f0a9e6e9c0dd5920b4155a39264525b06 SHA512 (blank-key4.db) = 8fedae93af7163da23fe9492ea8e785a44c291604fa98e58438448efb69c85d3253fc22b926d5c3209c62e58a86038fd4d78a1c4c068bc00600a7f3e5382ebe7 -SHA512 (nss-3.96.1-with-nspr-4.35.tar.gz) = 7831835936748adb7fdb050f06caea09ddcbf48e9c401bba9df1e405b05658204e1cea7800c565aae742551779ff0d4c9834b686b484055ee569ed3f4546f428 -SHA512 (nss-3.97-with-nspr-4.35.tar.gz) = 5153eb99ca3a372dfa89671d2c589675d99755c04760d65280ce694ff5761b2a0502416cb9f0950bb5156c71a5c68491582dcb7a970e65ea0b1082fff0ba0153 +SHA512 (nss-3.101-with-nspr-4.35.tar.gz) = 95c8ef1c12e1de7da4d918cebd1d5464b0ff4932083f6d395733345bd9f8598069028793fd1c08f974efcb31129cd84718487fd5326e45a878fba0d8c309bd39