Hello community, here is the log from the commit of package mozilla-nss for openSUSE:Factory checked in at 2020-06-30 21:52:57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mozilla-nss (Old) and /work/SRC/openSUSE:Factory/.mozilla-nss.new.3060 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mozilla-nss" Tue Jun 30 21:52:57 2020 rev:159 rq:817441 version:3.53.1 Changes: -------- --- /work/SRC/openSUSE:Factory/mozilla-nss/mozilla-nss.changes 2020-06-05 20:02:36.828412875 +0200 +++ /work/SRC/openSUSE:Factory/.mozilla-nss.new.3060/mozilla-nss.changes 2020-06-30 21:52:58.474110783 +0200 @@ -1,0 +2,59 @@ +Sat Jun 27 21:16:07 UTC 2020 - Wolfgang Rosenauer <[email protected]> + +- add FIPS mode patches from SLE stream + nss-fips-aes-keywrap-post.patch + nss-fips-approved-crypto-non-ec.patch + nss-fips-cavs-dsa-fixes.patch + nss-fips-cavs-general.patch + nss-fips-cavs-kas-ecc.patch + nss-fips-cavs-kas-ffc.patch + nss-fips-cavs-keywrap.patch + nss-fips-cavs-rsa-fixes.patch + nss-fips-combined-hash-sign-dsa-ecdsa.patch + nss-fips-constructor-self-tests.patch + nss-fips-detect-fips-mode-fixes.patch + nss-fips-dsa-kat.patch + nss-fips-gcm-ctr.patch + nss-fips-pairwise-consistency-check.patch + nss-fips-rsa-keygen-strictness.patch + nss-fips-tls-allow-md5-prf.patch + nss-fips-use-getrandom.patch + nss-fips-use-strong-random-pool.patch + nss-fips-zeroization.patch + nss-fix-dh-pkcs-derive-inverted-logic.patch + +------------------------------------------------------------------- +Tue Jun 23 05:40:12 UTC 2020 - Wolfgang Rosenauer <[email protected]> + +- update to NSS 3.53.1 + * required for Firefox 78 + * CVE-2020-12402 - Use constant-time GCD and modular inversion in MPI. + (bmo#1631597, bsc#1173032) + +------------------------------------------------------------------- +Sun Jun 21 04:44:40 UTC 2020 - Michel Normand <[email protected]> + +- Add ppc-old-abi-v3.patch as per upstream bug + https://bugzilla.mozilla.org/show_bug.cgi?id=1642174 + +------------------------------------------------------------------- +Thu Jun 11 20:09:44 UTC 2020 - Wolfgang Rosenauer <[email protected]> + +- update to NSS 3.53 + Notable changes + * SEED is now moved into a new freebl directory freebl/deprecated + bmo#1636389 + * SEED will be disabled by default in a future release of NSS. At + that time, users will need to set the compile-time flag + (bmo#1622033) to disable that deprecation in order to use the + algorithm. + * Algorithms marked as deprecated will ultimately be removed + * Several root certificates in the Mozilla program now set the + CKA_NSS_SERVER_DISTRUST_AFTER attribute, which NSS consumers + can query to further refine trust decisions. (bmo#1618404, + bmo#1621159). If a builtin certificate has a + CKA_NSS_SERVER_DISTRUST_AFTER timestamp before the SCT or + NotBefore date of a certificate that builtin issued, then clients + can elect not to trust it. + +------------------------------------------------------------------- Old: ---- nss-3.52.1.tar.gz New: ---- nss-3.53.1.tar.gz nss-fips-aes-keywrap-post.patch nss-fips-approved-crypto-non-ec.patch nss-fips-cavs-dsa-fixes.patch nss-fips-cavs-general.patch nss-fips-cavs-kas-ecc.patch nss-fips-cavs-kas-ffc.patch nss-fips-cavs-keywrap.patch nss-fips-cavs-rsa-fixes.patch nss-fips-combined-hash-sign-dsa-ecdsa.patch nss-fips-constructor-self-tests.patch nss-fips-detect-fips-mode-fixes.patch nss-fips-dsa-kat.patch nss-fips-gcm-ctr.patch nss-fips-pairwise-consistency-check.patch nss-fips-rsa-keygen-strictness.patch nss-fips-tls-allow-md5-prf.patch nss-fips-use-getrandom.patch nss-fips-use-strong-random-pool.patch nss-fips-zeroization.patch nss-fix-dh-pkcs-derive-inverted-logic.patch ppc-old-abi-v3.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mozilla-nss.spec ++++++ --- /var/tmp/diff_new_pack.toDILa/_old 2020-06-30 21:53:07.798139636 +0200 +++ /var/tmp/diff_new_pack.toDILa/_new 2020-06-30 21:53:07.798139636 +0200 @@ -17,14 +17,14 @@ # -%global nss_softokn_fips_version 3.52 +%global nss_softokn_fips_version 3.53 %define NSPR_min_version 4.25 %define nspr_ver %(rpm -q --queryformat '%%{VERSION}' mozilla-nspr) %define nssdbdir %{_sysconfdir}/pki/nssdb Name: mozilla-nss -Version: 3.52.1 +Version: 3.53.1 Release: 0 -%define underscore_version 3_52_1 +%define underscore_version 3_53_1 Summary: Network Security Services License: MPL-2.0 Group: System/Libraries @@ -49,7 +49,33 @@ Patch5: malloc.patch Patch6: bmo-1400603.patch Patch7: nss-sqlitename.patch +Patch8: ppc-old-abi-v3.patch +Patch11: nss-fips-use-getrandom.patch +Patch13: nss-fips-dsa-kat.patch +Patch15: nss-fips-pairwise-consistency-check.patch +Patch16: nss-fips-rsa-keygen-strictness.patch +Patch19: nss-fips-cavs-keywrap.patch +Patch20: nss-fips-cavs-kas-ffc.patch +Patch21: nss-fips-cavs-kas-ecc.patch +Patch22: nss-fips-gcm-ctr.patch +Patch23: nss-fips-constructor-self-tests.patch +Patch24: nss-fips-cavs-general.patch +Patch25: nss-fips-cavs-dsa-fixes.patch +Patch26: nss-fips-cavs-rsa-fixes.patch +Patch27: nss-fips-approved-crypto-non-ec.patch +Patch29: nss-fips-zeroization.patch +Patch30: nss-fips-tls-allow-md5-prf.patch +Patch31: nss-fips-use-strong-random-pool.patch +Patch32: nss-fips-detect-fips-mode-fixes.patch +Patch34: nss-fips-combined-hash-sign-dsa-ecdsa.patch +Patch35: nss-fix-dh-pkcs-derive-inverted-logic.patch +Patch36: nss-fips-aes-keywrap-post.patch +%if 0%{?sle_version} >= 120000 && 0%{?sle_version} < 150000 +# aarch64 + gcc4.8 fails to build on SLE-12 due to undefined references +BuildRequires: gcc9-c++ +%else BuildRequires: gcc-c++ +%endif BuildRequires: pkgconfig BuildRequires: pkgconfig(nspr) >= %{NSPR_min_version} BuildRequires: pkgconfig(sqlite3) @@ -179,6 +205,30 @@ %endif %patch6 -p1 %patch7 -p1 +%patch8 -p1 + +# FIPS patches +%patch11 -p1 +%patch13 -p1 +%patch15 -p1 +%patch16 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 + # additional CA certificates #cd security/nss/lib/ckfw/builtins #cat %{SOURCE2} >> certdata.txt @@ -191,6 +241,12 @@ %else %global _lto_cflags %{_lto_cflags} -ffat-lto-objects %endif +%if 0%{?sle_version} >= 120000 && 0%{?sle_version} < 150000 +export CC=gcc-9 +# Yes, they use both... +export CXX=g++-9 +export CCC=g++-9 +%endif cd nss modified="$(sed -n '/^----/n;s/ - .*$//;p;q' "%{SOURCE99}")" DATE="\"$(date -d "${modified}" "+%%b %%e %%Y")\"" @@ -211,7 +267,7 @@ export NSS_USE_SYSTEM_SQLITE=1 #export SQLITE_LIB_NAME=nsssqlite3 MAKE_FLAGS="BUILD_OPT=1" -make --jobs=1 nss_build_all $MAKE_FLAGS +make %{?_smp_mflags} nss_build_all $MAKE_FLAGS # run testsuite %if 0%{?run_testsuite} export BUILD_OPT=1 ++++++ nss-3.52.1.tar.gz -> nss-3.53.1.tar.gz ++++++ /work/SRC/openSUSE:Factory/mozilla-nss/nss-3.52.1.tar.gz /work/SRC/openSUSE:Factory/.mozilla-nss.new.3060/nss-3.53.1.tar.gz differ: char 5, line 1 ++++++ nss-fips-aes-keywrap-post.patch ++++++ # HG changeset patch # User M. Sirringhaus <[email protected]> # Date 1589854460 -7200 # Tue May 19 04:14:20 2020 +0200 # Node ID ce99bba6375432c55a73c1367f619dfef7c7e9fc # Parent 2b4f407fb1f8824fed4df9c4c3f15a2493e71677 commit e78f5a6a2124ce88002796d6aaefc6232f132526 Author: Hans Petter Jansson <[email protected]> AES Keywrap POST. diff --git a/lib/freebl/fipsfreebl.c b/lib/freebl/fipsfreebl.c --- a/lib/freebl/fipsfreebl.c +++ b/lib/freebl/fipsfreebl.c @@ -110,6 +110,9 @@ #define FIPS_AES_192_KEY_SIZE 24 /* 192-bits */ #define FIPS_AES_256_KEY_SIZE 32 /* 256-bits */ +/* FIPS preprocessor directives for AES Keywrap */ +#define FIPS_AES_KEYWRAP_KNOWN_CIPHERTEXT_SIZE 24 /* 192-bits */ + /* FIPS preprocessor directives for message digests */ #define FIPS_KNOWN_HASH_MESSAGE_LENGTH 64 /* 512-bits */ @@ -299,6 +302,9 @@ static const PRUint8 aes_gcm_known_aad[] = { "MozillaallizoM" }; + /* AES Keywrap Known Initialization Vector (64 bits) */ + static const PRUint8 aes_key_wrap_iv[] = { "WrapparW" }; + /* AES Known Ciphertext (128-bit key). */ static const PRUint8 aes_ecb128_known_ciphertext[] = { 0x3c, 0xa5, 0x96, 0xf3, 0x34, 0x6a, 0x96, 0xc1, @@ -353,6 +359,25 @@ 0xf4, 0xb0, 0xc1, 0x8c, 0x86, 0x51, 0xf5, 0xa1 }; + /* AES Keywrap Known Ciphertexts. */ + static const PRUint8 aes_kw128_known_ciphertext[] = { + 0xd7, 0xec, 0x33, 0x3a, 0x35, 0x50, 0x91, 0x4d, + 0x04, 0x69, 0x1f, 0xbc, 0x9b, 0x3a, 0x51, 0x9d, + 0xf3, 0x45, 0x01, 0xec, 0xaa, 0x43, 0x33, 0x42 + }; + + static const PRUint8 aes_kw192_known_ciphertext[] = { + 0x18, 0x44, 0xab, 0x72, 0xbd, 0x35, 0x6c, 0x8f, + 0x34, 0x34, 0x2e, 0x0b, 0xb0, 0x19, 0xd3, 0x46, + 0x3e, 0x53, 0x4f, 0x2f, 0x43, 0xcc, 0xf5, 0x8c + }; + + static const PRUint8 aes_kw256_known_ciphertext[] = { + 0x3e, 0xaf, 0xf3, 0x36, 0xaf, 0xc3, 0x68, 0xab, + 0x5a, 0x07, 0xed, 0x64, 0x5b, 0xf8, 0x81, 0x0d, + 0x9e, 0x67, 0x75, 0xbd, 0x66, 0xe1, 0x52, 0xdc + }; + const PRUint8 *aes_ecb_known_ciphertext = (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_ecb128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_ecb192_known_ciphertext : aes_ecb256_known_ciphertext; @@ -362,10 +387,14 @@ const PRUint8 *aes_gcm_known_ciphertext = (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_gcm128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_gcm192_known_ciphertext : aes_gcm256_known_ciphertext; + const PRUint8 *aes_keywrap_known_ciphertext = + (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_kw128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_kw192_known_ciphertext : aes_kw256_known_ciphertext; + /* AES variables. */ PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2]; PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2]; AESContext *aes_context; + AESKeyWrapContext *aes_keywrap_context; unsigned int aes_bytes_encrypted; unsigned int aes_bytes_decrypted; CK_NSS_GCM_PARAMS gcmParams; @@ -554,6 +583,52 @@ return (SECFailure); } + /********************************/ + /* AES Keywrap En/Decrypt Test. */ + /********************************/ + + /* Create encryption context */ + aes_keywrap_context = AESKeyWrap_CreateContext(aes_known_key, aes_key_wrap_iv, PR_TRUE, + aes_key_size); + if (aes_keywrap_context == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return (SECFailure); + } + + aes_status = AESKeyWrap_Encrypt(aes_keywrap_context, + aes_computed_ciphertext, &aes_bytes_encrypted, + FIPS_AES_ENCRYPT_LENGTH * 2, + aes_known_plaintext, FIPS_AES_ENCRYPT_LENGTH); + + AESKeyWrap_DestroyContext(aes_keywrap_context, PR_TRUE); + + if ((aes_status != SECSuccess) || + (aes_bytes_encrypted != FIPS_AES_KEYWRAP_KNOWN_CIPHERTEXT_SIZE) || + (PORT_Memcmp (aes_computed_ciphertext, aes_keywrap_known_ciphertext, + FIPS_AES_KEYWRAP_KNOWN_CIPHERTEXT_SIZE) != 0)) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return (SECFailure); + } + + /* Create decryption context */ + aes_keywrap_context = AESKeyWrap_CreateContext(aes_known_key, aes_key_wrap_iv, PR_FALSE, + aes_key_size); + + aes_status = AESKeyWrap_Decrypt(aes_keywrap_context, + aes_computed_plaintext, &aes_bytes_decrypted, + FIPS_AES_ENCRYPT_LENGTH, + aes_computed_ciphertext, aes_bytes_encrypted); + + AESKeyWrap_DestroyContext(aes_keywrap_context, PR_TRUE); + + if ((aes_status != SECSuccess) || + (aes_bytes_decrypted != FIPS_AES_ENCRYPT_LENGTH) || + (PORT_Memcmp (aes_computed_plaintext, aes_known_plaintext, + FIPS_AES_ENCRYPT_LENGTH) != 0)) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return (SECFailure); + } + return (SECSuccess); } ++++++ nss-fips-approved-crypto-non-ec.patch ++++++ # HG changeset patch # User M. Sirringhaus <[email protected]> # Date 1590413430 -7200 # Mon May 25 15:30:30 2020 +0200 # Node ID 2d4483f4a1259f965f32ff4c65436e92aef83be7 # Parent 3f4d682c9a1e8b3d939c744ee249e23179db5191 imported patch nss-fips-approved-crypto-non-ec.patch diff --git a/lib/freebl/alg2268.c b/lib/freebl/alg2268.c --- a/lib/freebl/alg2268.c +++ b/lib/freebl/alg2268.c @@ -16,6 +16,8 @@ #include <stddef.h> /* for ptrdiff_t */ #endif +#include "fips.h" + /* ** RC2 symmetric block cypher */ @@ -119,6 +121,7 @@ RC2Context * RC2_AllocateContext(void) { + IN_FIPS_RETURN(NULL); return PORT_ZNew(RC2Context); } SECStatus @@ -133,6 +136,8 @@ #endif PRUint8 tmpB; + IN_FIPS_RETURN(SECFailure); + if (!key || !cx || !len || len > (sizeof cx->B) || efLen8 > (sizeof cx->B)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -204,7 +209,11 @@ RC2_CreateContext(const unsigned char *key, unsigned int len, const unsigned char *iv, int mode, unsigned efLen8) { - RC2Context *cx = PORT_ZNew(RC2Context); + RC2Context *cx; + + IN_FIPS_RETURN(NULL); + + cx = PORT_ZNew(RC2Context); if (cx) { SECStatus rv = RC2_InitContext(cx, key, len, iv, mode, efLen8, 0); if (rv != SECSuccess) { @@ -456,7 +465,11 @@ unsigned int *outputLen, unsigned int maxOutputLen, const unsigned char *input, unsigned int inputLen) { - SECStatus rv = SECSuccess; + SECStatus rv; + + IN_FIPS_RETURN(SECFailure); + + rv = SECSuccess; if (inputLen) { if (inputLen % RC2_BLOCK_SIZE) { PORT_SetError(SEC_ERROR_INPUT_LEN); @@ -490,7 +503,11 @@ unsigned int *outputLen, unsigned int maxOutputLen, const unsigned char *input, unsigned int inputLen) { - SECStatus rv = SECSuccess; + SECStatus rv; + + IN_FIPS_RETURN(SECFailure); + + rv = SECSuccess; if (inputLen) { if (inputLen % RC2_BLOCK_SIZE) { PORT_SetError(SEC_ERROR_INPUT_LEN); diff --git a/lib/freebl/arcfour.c b/lib/freebl/arcfour.c --- a/lib/freebl/arcfour.c +++ b/lib/freebl/arcfour.c @@ -13,6 +13,7 @@ #include "prtypes.h" #include "blapi.h" +#include "fips.h" /* Architecture-dependent defines */ @@ -108,6 +109,7 @@ RC4Context * RC4_AllocateContext(void) { + IN_FIPS_RETURN(NULL); return PORT_ZNew(RC4Context); } @@ -121,6 +123,8 @@ PRUint8 K[256]; PRUint8 *L; + IN_FIPS_RETURN(SECFailure); + /* verify the key length. */ PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE); if (len == 0 || len >= ARCFOUR_STATE_SIZE) { @@ -162,7 +166,11 @@ RC4Context * RC4_CreateContext(const unsigned char *key, int len) { - RC4Context *cx = RC4_AllocateContext(); + RC4Context *cx; + + IN_FIPS_RETURN(NULL); + + cx = RC4_AllocateContext(); if (cx) { SECStatus rv = RC4_InitContext(cx, key, len, NULL, 0, 0, 0); if (rv != SECSuccess) { @@ -176,6 +184,7 @@ void RC4_DestroyContext(RC4Context *cx, PRBool freeit) { + IN_FIPS_RETURN(); if (freeit) PORT_ZFree(cx, sizeof(*cx)); } @@ -548,6 +557,8 @@ unsigned int *outputLen, unsigned int maxOutputLen, const unsigned char *input, unsigned int inputLen) { + IN_FIPS_RETURN(SECFailure); + PORT_Assert(maxOutputLen >= inputLen); if (maxOutputLen < inputLen) { PORT_SetError(SEC_ERROR_OUTPUT_LEN); @@ -571,6 +582,8 @@ unsigned int *outputLen, unsigned int maxOutputLen, const unsigned char *input, unsigned int inputLen) { + IN_FIPS_RETURN(SECFailure); + PORT_Assert(maxOutputLen >= inputLen); if (maxOutputLen < inputLen) { PORT_SetError(SEC_ERROR_OUTPUT_LEN); diff --git a/lib/freebl/deprecated/seed.c b/lib/freebl/deprecated/seed.c --- a/lib/freebl/deprecated/seed.c +++ b/lib/freebl/deprecated/seed.c @@ -17,6 +17,8 @@ #include "seed.h" #include "secerr.h" +#include "../fips.h" + static const seed_word SS[4][256] = { { 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124, @@ -301,6 +303,8 @@ seed_word K0, K1, K2, K3; seed_word t0, t1; + IN_FIPS_RETURN(); + char2word(rawkey, K0); char2word(rawkey + 4, K1); char2word(rawkey + 8, K2); @@ -349,6 +353,8 @@ seed_word L0, L1, R0, R1; seed_word t0, t1; + IN_FIPS_RETURN(); + char2word(s, L0); char2word(s + 4, L1); char2word(s + 8, R0); @@ -385,6 +391,8 @@ seed_word L0, L1, R0, R1; seed_word t0, t1; + IN_FIPS_RETURN(); + char2word(s, L0); char2word(s + 4, L1); char2word(s + 8, R0); @@ -419,6 +427,8 @@ size_t inLen, const SEED_KEY_SCHEDULE *ks, int enc) { + IN_FIPS_RETURN(); + if (enc) { while (inLen > 0) { SEED_encrypt(in, out, ks); @@ -445,6 +455,8 @@ unsigned char tmp[SEED_BLOCK_SIZE]; const unsigned char *iv = ivec; + IN_FIPS_RETURN(); + if (enc) { while (len >= SEED_BLOCK_SIZE) { for (n = 0; n < SEED_BLOCK_SIZE; ++n) { @@ -528,6 +540,7 @@ SEEDContext * SEED_AllocateContext(void) { + IN_FIPS_RETURN(NULL); return PORT_ZNew(SEEDContext); } @@ -536,6 +549,8 @@ unsigned int keylen, const unsigned char *iv, int mode, unsigned int encrypt, unsigned int unused) { + IN_FIPS_RETURN(SECFailure); + if (!cx) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; @@ -567,10 +582,14 @@ SEED_CreateContext(const unsigned char *key, const unsigned char *iv, int mode, PRBool encrypt) { - SEEDContext *cx = PORT_ZNew(SEEDContext); - SECStatus rv = SEED_InitContext(cx, key, SEED_KEY_LENGTH, iv, mode, - encrypt, 0); + SEEDContext *cx; + SECStatus rv; + IN_FIPS_RETURN(NULL); + + cx = PORT_ZNew(SEEDContext); + rv = SEED_InitContext(cx, key, SEED_KEY_LENGTH, iv, mode, + encrypt, 0); if (rv != SECSuccess) { PORT_ZFree(cx, sizeof *cx); cx = NULL; @@ -595,6 +614,8 @@ unsigned int maxOutLen, const unsigned char *in, unsigned int inLen) { + IN_FIPS_RETURN(SECFailure); + if (!cx) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; @@ -635,6 +656,8 @@ unsigned int maxOutLen, const unsigned char *in, unsigned int inLen) { + IN_FIPS_RETURN(SECFailure); + if (!cx) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; diff --git a/lib/freebl/fips.h b/lib/freebl/fips.h --- a/lib/freebl/fips.h +++ b/lib/freebl/fips.h @@ -8,8 +8,20 @@ #ifndef FIPS_H #define FIPS_H +#include "hasht.h" +#include "secerr.h" + +#define IN_FIPS_RETURN(rv) \ + do { \ + if (FIPS_mode()) { \ + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); \ + return rv; \ + } \ + } while (0) + int FIPS_mode(void); char* FIPS_rngDev(void); +PRBool FIPS_hashAlgApproved(HASH_HashType hashAlg); #endif diff --git a/lib/freebl/md2.c b/lib/freebl/md2.c --- a/lib/freebl/md2.c +++ b/lib/freebl/md2.c @@ -13,6 +13,8 @@ #include "blapi.h" +#include "fips.h" + #define MD2_DIGEST_LEN 16 #define MD2_BUFSIZE 16 #define MD2_X_SIZE 48 /* The X array, [CV | INPUT | TMP VARS] */ @@ -66,7 +68,11 @@ MD2_Hash(unsigned char *dest, const char *src) { unsigned int len; - MD2Context *cx = MD2_NewContext(); + MD2Context *cx; + + IN_FIPS_RETURN(SECFailure); + + cx = MD2_NewContext(); if (!cx) { PORT_SetError(PR_OUT_OF_MEMORY_ERROR); return SECFailure; @@ -81,7 +87,11 @@ MD2Context * MD2_NewContext(void) { - MD2Context *cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context)); + MD2Context *cx; + + IN_FIPS_RETURN(NULL); + + cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context)); if (cx == NULL) { PORT_SetError(PR_OUT_OF_MEMORY_ERROR); return NULL; @@ -99,6 +109,8 @@ void MD2_Begin(MD2Context *cx) { + IN_FIPS_RETURN(); + memset(cx, 0, sizeof(*cx)); cx->unusedBuffer = MD2_BUFSIZE; } @@ -196,6 +208,8 @@ { PRUint32 bytesToConsume; + IN_FIPS_RETURN(); + /* Fill the remaining input buffer. */ if (cx->unusedBuffer != MD2_BUFSIZE) { bytesToConsume = PR_MIN(inputLen, cx->unusedBuffer); @@ -226,6 +240,9 @@ unsigned int *digestLen, unsigned int maxDigestLen) { PRUint8 padStart; + + IN_FIPS_RETURN(); + if (maxDigestLen < MD2_BUFSIZE) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return; diff --git a/lib/freebl/md5.c b/lib/freebl/md5.c --- a/lib/freebl/md5.c +++ b/lib/freebl/md5.c @@ -15,6 +15,8 @@ #include "blapi.h" #include "blapii.h" +#include "fips.h" + #define MD5_HASH_LEN 16 #define MD5_BUFFER_SIZE 64 #define MD5_END_BUFFER (MD5_BUFFER_SIZE - 8) @@ -195,6 +197,7 @@ SECStatus MD5_Hash(unsigned char *dest, const char *src) { + IN_FIPS_RETURN(SECFailure); return MD5_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src)); } @@ -204,6 +207,8 @@ unsigned int len; MD5Context cx; + IN_FIPS_RETURN(SECFailure); + MD5_Begin(&cx); MD5_Update(&cx, src, src_length); MD5_End(&cx, dest, &len, MD5_HASH_LEN); @@ -215,7 +220,11 @@ MD5_NewContext(void) { /* no need to ZAlloc, MD5_Begin will init the context */ - MD5Context *cx = (MD5Context *)PORT_Alloc(sizeof(MD5Context)); + MD5Context *cx; + + IN_FIPS_RETURN(NULL); + + cx = (MD5Context *)PORT_Alloc(sizeof(MD5Context)); if (cx == NULL) { PORT_SetError(PR_OUT_OF_MEMORY_ERROR); return NULL; @@ -226,7 +235,8 @@ void MD5_DestroyContext(MD5Context *cx, PRBool freeit) { - memset(cx, 0, sizeof *cx); + if (cx) + memset(cx, 0, sizeof *cx); if (freeit) { PORT_Free(cx); } @@ -235,6 +245,8 @@ void MD5_Begin(MD5Context *cx) { + IN_FIPS_RETURN(); + cx->lsbInput = 0; cx->msbInput = 0; /* memset(cx->inBuf, 0, sizeof(cx->inBuf)); */ @@ -425,6 +437,8 @@ PRUint32 inBufIndex = cx->lsbInput & 63; const PRUint32 *wBuf; + IN_FIPS_RETURN(); + /* Add the number of input bytes to the 64-bit input counter. */ addto64(cx->msbInput, cx->lsbInput, inputLen); if (inBufIndex) { @@ -498,6 +512,8 @@ PRUint32 lowInput, highInput; PRUint32 inBufIndex = cx->lsbInput & 63; + IN_FIPS_RETURN(); + if (maxDigestLen < MD5_HASH_LEN) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return; @@ -546,6 +562,8 @@ #endif PRUint32 cv[4]; + IN_FIPS_RETURN(); + if (maxDigestLen < MD5_HASH_LEN) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return; diff --git a/lib/freebl/nsslowhash.c b/lib/freebl/nsslowhash.c --- a/lib/freebl/nsslowhash.c +++ b/lib/freebl/nsslowhash.c @@ -12,6 +12,7 @@ #include "plhash.h" #include "nsslowhash.h" #include "blapii.h" +#include "fips.h" struct NSSLOWInitContextStr { int count; @@ -92,6 +93,12 @@ { NSSLOWHASHContext *context; + /* return with an error if unapproved hash is requested in FIPS mode */ + if (!FIPS_hashAlgApproved(hashType)) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return NULL; + } + if (post_failed) { PORT_SetError(SEC_ERROR_PKCS11_DEVICE_ERROR); return NULL; diff --git a/lib/freebl/rawhash.c b/lib/freebl/rawhash.c --- a/lib/freebl/rawhash.c +++ b/lib/freebl/rawhash.c @@ -10,6 +10,7 @@ #include "hasht.h" #include "blapi.h" /* below the line */ #include "secerr.h" +#include "fips.h" static void * null_hash_new_context(void) @@ -146,7 +147,8 @@ const SECHashObject * HASH_GetRawHashObject(HASH_HashType hashType) { - if (hashType <= HASH_AlgNULL || hashType >= HASH_AlgTOTAL) { + if (hashType <= HASH_AlgNULL || hashType >= HASH_AlgTOTAL + || (!FIPS_hashAlgApproved(hashType))) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c --- a/lib/softoken/pkcs11c.c +++ b/lib/softoken/pkcs11c.c @@ -7282,7 +7282,7 @@ } else { /* now allocate the hash contexts */ md5 = MD5_NewContext(); - if (md5 == NULL) { + if (md5 == NULL && !isTLS) { crv = CKR_HOST_MEMORY; break; } ++++++ nss-fips-cavs-dsa-fixes.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1574237264 -3600 # Wed Nov 20 09:07:44 2019 +0100 # Node ID 0e904e6179d1db21965df2c405c80c3fc0258658 # Parent 969310ea4c573aac64bf08846b8938b8fa783870 [PATCH] 24 >From ef2620b770082c77dbbbccae2e773157897b005d Mon Sep 17 00:00:00 2001 --- nss/cmd/fipstest/fipstest.c | 112 ++++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 11 deletions(-) diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c --- a/cmd/fipstest/fipstest.c +++ b/cmd/fipstest/fipstest.c @@ -5576,7 +5576,7 @@ void dsa_pqggen_test(char *reqfn) { - char buf[800]; /* holds one line from the input REQUEST file + char buf[2048]; /* holds one line from the input REQUEST file * or to the output RESPONSE file. * 800 to hold seed = (384 public key (x2 for HEX) */ @@ -5592,6 +5592,13 @@ PQGVerify *vfy = NULL; unsigned int keySizeIndex = 0; dsa_pqg_type type = FIPS186_1; + SECItem P = { 0, 0, 0 }; + SECItem Q = { 0, 0, 0 }; + SECItem firstseed = { 0, 0, 0 }; + SECItem pseed = { 0, 0, 0 }; + SECItem qseed = { 0, 0, 0 }; + SECItem index = { 0, 0, 0 }; + HASH_HashType hashtype = HASH_AlgNULL; dsareq = fopen(reqfn, "r"); dsaresp = stdout; @@ -5612,8 +5619,8 @@ output_g = 1; exit(1); } else if (strncmp(&buf[1], "A.2.3", 5) == 0) { - fprintf(stderr, "NSS only Generates G with P&Q\n"); - exit(1); + type = A_2_3; + output_g = 1; } else if (strncmp(&buf[1], "A.1.2.1", 7) == 0) { type = A_1_2_1; output_g = 0; @@ -5627,14 +5634,17 @@ /* [Mod = ... ] */ if (buf[0] == '[') { + int hashbits; if (type == FIPS186_1) { N = 160; if (sscanf(buf, "[mod = %d]", &L) != 1) { goto loser; } - } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) { - goto loser; + } else if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d", &L, &N, &hashbits) != 3) { + goto loser; + } else { + hashtype = sha_get_hashType (hashbits); } fputs(buf, dsaresp); @@ -5656,7 +5666,7 @@ continue; } /* N = ... */ - if (buf[0] == 'N') { + if (buf[0] == 'N' && type != A_2_3) { if (strncmp(buf, "Num", 3) == 0) { if (sscanf(buf, "Num = %d", &count) != 1) { goto loser; @@ -5671,7 +5681,10 @@ rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES, &pqg, &vfy); } else { - rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy); + if (firstseed.data) + SECITEM_ZfreeItem(&firstseed, PR_FALSE); + + rv = FREEBL_Test_PQG_ParamGenV2_p(L, N, 0, &pqg, &vfy, &firstseed, hashtype); } if (rv != SECSuccess) { fprintf(dsaresp, @@ -5682,6 +5695,10 @@ fprintf(dsaresp, "P = %s\n", buf); to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len); fprintf(dsaresp, "Q = %s\n", buf); + if (firstseed.data) { + to_hex_str(buf, firstseed.data, firstseed.len); + fprintf(dsaresp, "firstseed = %s\n", buf); + } if (output_g) { to_hex_str(buf, pqg->base.data, pqg->base.len); fprintf(dsaresp, "G = %s\n", buf); @@ -5697,13 +5714,13 @@ } fprintf(dsaresp, "%s\n", buf); } else { - unsigned int seedlen = vfy->seed.len / 2; - unsigned int pgen_counter = vfy->counter >> 16; - unsigned int qgen_counter = vfy->counter & 0xffff; + unsigned int seedlen = (vfy->seed.len - firstseed.len) / 2; + unsigned int pgen_counter = vfy->counter & 0xffff; + unsigned int qgen_counter = vfy->counter >> 16; /*fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]); */ - to_hex_str(buf, vfy->seed.data, seedlen); + to_hex_str(buf, vfy->seed.data + firstseed.len, seedlen); fprintf(dsaresp, "pseed = %s\n", buf); - to_hex_str(buf, vfy->seed.data + seedlen, seedlen); + to_hex_str(buf, vfy->seed.data + firstseed.len + seedlen, seedlen); fprintf(dsaresp, "qseed = %s\n", buf); fprintf(dsaresp, "pgen_counter = %d\n", pgen_counter); fprintf(dsaresp, "qgen_counter = %d\n", qgen_counter); @@ -5723,12 +5740,85 @@ vfy = NULL; } } - + continue; + } + + if (parse_secitem ("P", buf, &P)) { + fputs(buf, dsaresp); + continue; + } + if (parse_secitem ("Q", buf, &Q)) { + fputs(buf, dsaresp); + continue; + } + if (parse_secitem ("firstseed", buf, &firstseed)) { + fputs(buf, dsaresp); + continue; + } + if (parse_secitem ("pseed", buf, &pseed)) { + fputs(buf, dsaresp); + continue; + } + if (parse_secitem ("qseed", buf, &qseed)) { + fputs(buf, dsaresp); + continue; + } + if (parse_secitem ("index", buf, &index) && type == A_2_3) { + SECStatus rv; + PLArenaPool *arena; + + fputs(buf, dsaresp); + + arena = PORT_NewArena (NSS_FREEBL_DEFAULT_CHUNKSIZE); + pqg = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams)); + pqg->arena = arena; + + arena = PORT_NewArena (NSS_FREEBL_DEFAULT_CHUNKSIZE); + vfy = (PQGVerify *)PORT_ArenaZAlloc(arena, sizeof(PQGVerify)); + vfy->arena = arena; + + SECITEM_CopyItem(pqg->arena, &pqg->prime, &P); + SECITEM_CopyItem(pqg->arena, &pqg->subPrime, &Q); + + SECITEM_AllocItem(vfy->arena, &vfy->seed, firstseed.len + pseed.len + qseed.len); + memcpy (vfy->seed.data, firstseed.data, firstseed.len); + memcpy (vfy->seed.data + firstseed.len, pseed.data, pseed.len); + memcpy (vfy->seed.data + firstseed.len + pseed.len, qseed.data, qseed.len); + + SECITEM_AllocItem(vfy->arena, &vfy->h, 1); + vfy->h.data [0] = index.data [0]; + + rv = FREEBL_Test_PQG_ParamGenV2_p(L, N, 0, &pqg, &vfy, &firstseed, hashtype); + if (rv != SECSuccess) { + fprintf(dsaresp, + "ERROR: Unable to verify PQG parameters"); + goto loser; + } + + to_hex_str(buf, pqg->base.data, pqg->base.len); + fprintf(dsaresp, "G = %s\n\n", buf); + + PQG_DestroyParams(pqg); + pqg = NULL; + PQG_DestroyVerify(vfy); + vfy = NULL; continue; } } loser: fclose(dsareq); + if (P.data) + SECITEM_ZfreeItem(&P, PR_FALSE); + if (Q.data) + SECITEM_ZfreeItem(&Q, PR_FALSE); + if (firstseed.data) + SECITEM_ZfreeItem(&firstseed, PR_FALSE); + if (pseed.data) + SECITEM_ZfreeItem(&pseed, PR_FALSE); + if (qseed.data) + SECITEM_ZfreeItem(&qseed, PR_FALSE); + if (index.data) + SECITEM_ZfreeItem(&index, PR_FALSE); if (pqg != NULL) { PQG_DestroyParams(pqg); } ++++++ nss-fips-cavs-general.patch ++++++ # HG changeset patch # User M. Sirringhaus <[email protected]> # Date 1590413427 -7200 # Mon May 25 15:30:27 2020 +0200 # Node ID 969310ea4c573aac64bf08846b8938b8fa783870 # Parent 60c5e5d73ce1177fa66d8fd6cf49d9b371ca9be4 imported patch nss-fips-cavs-general.patch diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c --- a/cmd/fipstest/fipstest.c +++ b/cmd/fipstest/fipstest.c @@ -5,6 +5,7 @@ #include <stdio.h> #include <stdlib.h> #include <ctype.h> +#include <dlfcn.h> #include "secitem.h" #include "blapi.h" @@ -18,6 +19,9 @@ #include "lowkeyi.h" #include "softoken.h" #include "pkcs11t.h" + +#include "../../lib/freebl/fips.h" + #define __PASTE(x, y) x##y #undef CK_PKCS11_FUNCTION_INFO #undef CK_NEED_ARG_LIST @@ -55,6 +59,10 @@ #define RSA_MAX_TEST_EXPONENT_BYTES 8 #define PQG_TEST_SEED_BYTES 20 +SECStatus (*FREEBL_Test_PQG_ParamGenV2_p) (unsigned int L, unsigned int N, unsigned int seedBytes, + PQGParams **pParams, PQGVerify **pVfy, + SECItem *firstseed, HASH_HashType hashtype); + SECStatus hex_to_byteval(const char *c2, unsigned char *byteval) { @@ -168,6 +176,62 @@ return PR_TRUE; } +#if 0 + +static void +dump_secitem (FILE *out, SECItem *secitem) +{ + char buf [4096]; + + to_hex_str(buf, secitem->data, secitem->len); + fputs (buf, out); +} + +static void +dump_labeled_secitem (FILE *out, const char *name, SECItem *secitem) +{ + fprintf (out, "%s = ", name); + dump_secitem (out, secitem); + fputs ("\n", out); +} + +#endif + +static int +parse_secitem (const char *name, const char *buf, SECItem *secitem) +{ + if (!strncmp (buf, name, strlen (name))) { + int i, j, len; + + i = strlen (name); + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + + len = strspn (&buf[i], "0123456789abcdefABCDEF"); + if (!len) + return 0; + + if (secitem->data) { + SECITEM_ZfreeItem(secitem, PR_FALSE); + secitem->data = NULL; + } + + len = (len + 1) / 2; + SECITEM_AllocItem(NULL, secitem, len); + secitem->len = len; + + memset(secitem->data, 0, secitem->len); + for (j = 0; j < secitem->len; i += 2, j++) { + hex_to_byteval(&buf[i], &secitem->data[j]); + } + + return 1; + } + + return 0; +} + SECStatus tdea_encrypt_buf( int mode, @@ -8930,41 +8994,6 @@ } } -static int -parse_secitem (const char *name, const char *buf, SECItem *secitem) -{ - if (!strncmp (buf, name, strlen (name))) { - int i, j, len; - - i = strlen (name); - while (isspace(buf[i]) || buf[i] == '=') { - i++; - } - - len = strspn (&buf[i], "0123456789abcdefABCDEF"); - if (!len) - return 0; - - if (secitem->data) { - SECITEM_ZfreeItem(secitem, PR_FALSE); - secitem->data = NULL; - } - - len = (len + 1) / 2; - SECITEM_AllocItem(NULL, secitem, len); - secitem->len = len; - - memset(secitem->data, 0, secitem->len); - for (j = 0; j < secitem->len; i += 2, j++) { - hex_to_byteval(&buf[i], &secitem->data[j]); - } - - return 1; - } - - return 0; -} - void kas_ffc_test(char *reqfn, int do_validity) { @@ -9387,12 +9416,34 @@ free_param_specs (pspecs); } +static void +init_functions (void) +{ + void *freebl_so; + + freebl_so = dlopen ("libfreeblpriv3.so", RTLD_LAZY); + if (freebl_so == NULL) + { + fprintf (stderr, "Failed to load libfreeblpriv3.so."); + exit (1); + } + + FREEBL_Test_PQG_ParamGenV2_p = dlsym (freebl_so, "FREEBL_Test_PQG_ParamGenV2"); + + if (FREEBL_Test_PQG_ParamGenV2_p == NULL) + { + fprintf (stderr, "Failed to bind FREEBL_TEST_PQG_ParamGenV2."); + exit (1); + } +} + int main(int argc, char **argv) { if (argc < 2) exit(-1); + init_functions(); RNG_RNGInit(); SECOID_Init(); diff --git a/lib/freebl/freebl.def b/lib/freebl/freebl.def --- a/lib/freebl/freebl.def +++ b/lib/freebl/freebl.def @@ -21,6 +21,7 @@ LIBRARY freebl3 ;- EXPORTS ;- FREEBL_GetVector; +FREEBL_Test_PQG_ParamGenV2; ;+ local: ;+ *; ;+}; diff --git a/lib/freebl/freebl_hash.def b/lib/freebl/freebl_hash.def --- a/lib/freebl/freebl_hash.def +++ b/lib/freebl/freebl_hash.def @@ -21,6 +21,7 @@ LIBRARY freebl3 ;- EXPORTS ;- FREEBL_GetVector; +FREEBL_Test_PQG_ParamGenV2; ;+ local: ;+ *; ;+}; diff --git a/lib/freebl/freebl_hash_vector.def b/lib/freebl/freebl_hash_vector.def --- a/lib/freebl/freebl_hash_vector.def +++ b/lib/freebl/freebl_hash_vector.def @@ -21,6 +21,7 @@ LIBRARY freebl3 ;- EXPORTS ;- FREEBL_GetVector; +FREEBL_Test_PQG_ParamGenV2; ;+ local: ;+ *; ;+}; diff --git a/lib/freebl/pqg.c b/lib/freebl/pqg.c --- a/lib/freebl/pqg.c +++ b/lib/freebl/pqg.c @@ -1231,7 +1231,8 @@ **/ static SECStatus pqg_ParamGen(unsigned int L, unsigned int N, pqgGenType type, - unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy) + unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy, + SECItem *firstseed_out, HASH_HashType hashtype) { unsigned int n; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */ unsigned int seedlen; /* Per FIPS 186-3 app A.1.1.2 (was 'g' 186-1)*/ @@ -1239,7 +1240,6 @@ unsigned int offset; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */ unsigned int outlen; /* Per FIPS 186-3, appendix A.1.1.2. */ unsigned int maxCount; - HASH_HashType hashtype = HASH_AlgNULL; SECItem *seed; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */ PLArenaPool *arena = NULL; PQGParams *params = NULL; @@ -1290,7 +1290,8 @@ /* fill in P Q, */ SECITEM_TO_MPINT((*pParams)->prime, &P); SECITEM_TO_MPINT((*pParams)->subPrime, &Q); - hashtype = getFirstHash(L, N); + if (hashtype == HASH_AlgNULL) + hashtype = getFirstHash(L, N); CHECK_SEC_OK(makeGfromIndex(hashtype, &P, &Q, &(*pVfy)->seed, (*pVfy)->h.data[0], &G)); MPINT_TO_SECITEM(&G, &(*pParams)->base, (*pParams)->arena); @@ -1330,7 +1331,8 @@ /* Select Hash and Compute lengths. */ /* getFirstHash gives us the smallest acceptable hash for this key * strength */ - hashtype = getFirstHash(L, N); + if (hashtype == HASH_AlgNULL) + hashtype = getFirstHash(L, N); outlen = HASH_ResultLen(hashtype) * PR_BITS_PER_BYTE; /* Step 3: n = Ceil(L/outlen)-1; (same as n = Floor((L-1)/outlen)) */ @@ -1532,6 +1534,10 @@ verify->counter = counter; *pParams = params; *pVfy = verify; + + if (firstseed_out) + SECITEM_CopyItem (NULL, firstseed_out, &firstseed); + cleanup: if (pseed.data) { PORT_Free(pseed.data); @@ -1576,7 +1582,7 @@ L = 512 + (j * 64); /* bits in P */ seedBytes = L / 8; return pqg_ParamGen(L, DSA1_Q_BITS, FIPS186_1_TYPE, seedBytes, - pParams, pVfy); + pParams, pVfy, NULL, HASH_AlgNULL); } SECStatus @@ -1591,7 +1597,7 @@ } L = 512 + (j * 64); /* bits in P */ return pqg_ParamGen(L, DSA1_Q_BITS, FIPS186_1_TYPE, seedBytes, - pParams, pVfy); + pParams, pVfy, NULL, HASH_AlgNULL); } SECStatus @@ -1609,7 +1615,26 @@ /* error code already set */ return SECFailure; } - return pqg_ParamGen(L, N, FIPS186_3_ST_TYPE, seedBytes, pParams, pVfy); + return pqg_ParamGen(L, N, FIPS186_3_ST_TYPE, seedBytes, pParams, pVfy, NULL, HASH_AlgNULL); +} + +SECStatus +FREEBL_Test_PQG_ParamGenV2 (unsigned int L, unsigned int N, unsigned int seedBytes, + PQGParams **pParams, PQGVerify **pVfy, SECItem *firstseed_out, + HASH_HashType hashtype) +{ + if (N == 0) { + N = pqg_get_default_N(L); + } + if (seedBytes == 0) { + /* seedBytes == L/8 for probable primes, N/8 for Shawe-Taylor Primes */ + seedBytes = N / 8; + } + if (pqg_validate_dsa2(L, N) != SECSuccess) { + /* error code already set */ + return SECFailure; + } + return pqg_ParamGen(L, N, FIPS186_3_ST_TYPE, seedBytes, pParams, pVfy, firstseed_out, hashtype); } /* ++++++ nss-fips-cavs-kas-ecc.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1574234615 -3600 # Wed Nov 20 08:23:35 2019 +0100 # Node ID f5cf5d16deb68e65b5dd4e799d9e8e3098400d62 # Parent af7d3ee4e96cf685be0b95dff7aa5a1d3ab64a89 [PATCH] 21 >From 4c27df62aa425745620f45710465b0264acacbb0 Mon Sep 17 00:00:00 2001 --- nss/cmd/fipstest/fipstest.c | 304 ++++++++++++++++++++++++++++++++++++ nss/cmd/fipstest/kas.sh | 22 +++ 2 files changed, 326 insertions(+) diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c --- a/cmd/fipstest/fipstest.c +++ b/cmd/fipstest/fipstest.c @@ -9092,6 +9092,301 @@ } } +typedef struct +{ + char param_name [2]; + ECParams *ecparams; + int hash_len; + HASH_HashType hash_type; +} +ParamSpec; + +#define PARAM_SPECS_MAX 12 + +static int +find_free_param_spec (const ParamSpec *pspecs) +{ + int i; + + for (i = 0; i < PARAM_SPECS_MAX; i++) + { + if (pspecs [i].param_name [0] == 0 + && pspecs [i].param_name [1] == 0) + return i; + } + + return 0; +} + +static int +find_param_spec (const ParamSpec *pspecs, char *name) +{ + int i; + + for (i = 0; i < PARAM_SPECS_MAX; i++) + { + if (pspecs [i].param_name [0] == name [0] + && pspecs [i].param_name [1] == name [1]) + return i; + } + + return 0; +} + +static void +free_param_specs (ParamSpec *pspecs) +{ + int i; + + for (i = 0; i < PARAM_SPECS_MAX; i++) + { + if (pspecs [i].ecparams) + PORT_FreeArena(pspecs [i].ecparams->arena, PR_FALSE); + } +} + +#define CURVE_NAME_MAX 64 + +static ECParams * +get_and_decode_nistp_params (int n) +{ + char curve_name [CURVE_NAME_MAX]; + SECItem *encodedparams; + ECParams *ecparams = NULL; + + snprintf (curve_name, CURVE_NAME_MAX, "nistp%d", n); + + encodedparams = getECParams (curve_name); + if (!encodedparams) + return NULL; + + EC_DecodeParams (encodedparams, &ecparams); + SECITEM_FreeItem(encodedparams, PR_TRUE); + return ecparams; +} + +void +kas_ecc_test(char *reqfn, int do_validity) +{ + char buf[2048]; + FILE *req; /* input stream from the REQUEST file */ + FILE *resp; /* output stream to the RESPONSE file */ + ParamSpec pspecs [PARAM_SPECS_MAX]; + SECItem x_ephem_cavs; + SECItem y_ephem_cavs; + SECItem x_ephem_iut; + SECItem y_ephem_iut; + SECItem d_ephem_iut; + SECItem cavs_hash_zz; + SECItem publicValue; + int current_pspec_def = -1; + + req = fopen(reqfn, "r"); + resp = stdout; + memset(&pspecs, 0, sizeof (pspecs)); + memset(&x_ephem_cavs, 0, sizeof(x_ephem_cavs)); + memset(&y_ephem_cavs, 0, sizeof(y_ephem_cavs)); + memset(&x_ephem_iut, 0, sizeof(x_ephem_iut)); + memset(&y_ephem_iut, 0, sizeof(y_ephem_iut)); + memset(&d_ephem_iut, 0, sizeof(d_ephem_iut)); + memset(&cavs_hash_zz, 0, sizeof(cavs_hash_zz)); + memset(&publicValue, 0, sizeof(publicValue)); + + while (fgets(buf, sizeof buf, req) != NULL) { + /* [xx] or + * [xx - SHAxxx] or + * [SHA(s) supported (Used for hashing Z): SHAxxx] */ + if (buf[0] == '[') { + char tbuf [2]; + int num; + + if (strlen (buf) >= 4 && buf [3] == ']' + && sscanf(buf, "[%c%c]", &tbuf [0], &tbuf [1]) == 2) { + int i = current_pspec_def = find_free_param_spec (pspecs); + if (i < 0) + goto out; + + pspecs [i].param_name [0] = tbuf [0]; + pspecs [i].param_name [1] = tbuf [1]; + + fputs(buf, resp); + continue; + } + + if (strlen (buf) >= 6 && buf [3] == ' ' && buf [4] == '-' + && sscanf(buf, "[%c%c - ", &tbuf [0], &tbuf [1]) == 2) { + current_pspec_def = find_param_spec (pspecs, tbuf); + if (current_pspec_def < 0) + goto out; + + fputs(buf, resp); + continue; + } + + if (!strncmp(buf, "[Curve selected:", strlen ("[Curve selected:"))) { + char *p = buf + strlen ("[Curve selected:"); + p += strcspn (p, "0123456789"); + if (!*p) + goto out; + if (sscanf(p, "%d", &num) != 1) + goto out; + + if (current_pspec_def < 0) + goto out; + + pspecs [current_pspec_def].ecparams = get_and_decode_nistp_params (num); + if (!pspecs [current_pspec_def].ecparams) + goto out; + + fputs(buf, resp); + continue; + } + + if (sscanf(buf, "[SHA(s) supported (Used for hashing Z): SHA%d", &num) == 1) { + if (current_pspec_def < 0) + goto out; + + pspecs [current_pspec_def].hash_len = num; + pspecs [current_pspec_def].hash_type = sha_get_hashType(num); + fputs(buf, resp); + continue; + } + + fputs(buf, resp); + continue; + } else if (parse_secitem ("QeCAVSx", buf, &x_ephem_cavs)) { + fputs(buf, resp); + continue; + } else if (parse_secitem ("QeCAVSy", buf, &y_ephem_cavs)) { + fputs(buf, resp); + + if (!do_validity) { + SECItem ZZ; + unsigned char ZZ_hash_buf [1024]; + int field_len; + int len; + ECPrivateKey *privKey; + + field_len = (pspecs [current_pspec_def].ecparams->fieldID.size + 7) >> 3; + + if (EC_NewKey(pspecs [current_pspec_def].ecparams, &privKey) != SECSuccess) + goto out; + + len = privKey->publicValue.len; + if (len % 2 == 0) { + goto out; + } + len = (len - 1) / 2; + if (privKey->publicValue.data[0] != + EC_POINT_FORM_UNCOMPRESSED) { + goto out; + } + + to_hex_str(buf, &privKey->publicValue.data[1], len); + fprintf (resp, "QeIUTx = %s\n", buf); + to_hex_str(buf, &privKey->publicValue.data[1 + len], len); + fprintf (resp, "QeIUTy = %s\n", buf); + + SECITEM_AllocItem(NULL, &publicValue, 1 + 2 * field_len); + publicValue.len = 1 + 2 * field_len; + publicValue.data [0] = EC_POINT_FORM_UNCOMPRESSED; + memcpy (&publicValue.data [1], x_ephem_cavs.data + x_ephem_cavs.len - field_len, field_len); + memcpy (&publicValue.data [1 + field_len], y_ephem_cavs.data + y_ephem_cavs.len - field_len, field_len); + + if (ECDH_Derive (&publicValue, pspecs [current_pspec_def].ecparams, &privKey->privateValue, PR_TRUE, &ZZ) != SECSuccess) { + goto out; + } + + SECITEM_ZfreeItem(&publicValue, PR_FALSE); + publicValue.data = NULL; + + fips_hashBuf_zeropad(pspecs [current_pspec_def].hash_type, ZZ_hash_buf, ZZ.data, ZZ.len, len); + + to_hex_str(buf, ZZ_hash_buf, pspecs [current_pspec_def].hash_len / 8); + fprintf (resp, "HashZZ = %s\n", buf); + + PORT_FreeArena(privKey->ecParams.arena, PR_TRUE); + } + + continue; + } else if (parse_secitem ("deIUT", buf, &d_ephem_iut)) { + fputs(buf, resp); + continue; + } else if (parse_secitem ("QeIUTx", buf, &x_ephem_iut)) { + fputs(buf, resp); + continue; + } else if (parse_secitem ("QeIUTy", buf, &y_ephem_iut)) { + fputs(buf, resp); + continue; + } else if (parse_secitem ("CAVSHashZZ", buf, &cavs_hash_zz)) { + if (do_validity) { + SECItem ZZ; + unsigned char ZZ_hash_buf [1024]; + char Z_buf [1024]; + int field_len; + + field_len = (pspecs [current_pspec_def].ecparams->fieldID.size + 7) >> 3; + + SECITEM_AllocItem(NULL, &publicValue, 1 + 2 * field_len); + publicValue.len = 1 + 2 * field_len; + publicValue.data [0] = EC_POINT_FORM_UNCOMPRESSED; + memcpy (&publicValue.data [1], x_ephem_cavs.data + x_ephem_cavs.len - field_len, field_len); + memcpy (&publicValue.data [1 + field_len], y_ephem_cavs.data + y_ephem_cavs.len - field_len, field_len); + + if (ECDH_Derive (&publicValue, pspecs [current_pspec_def].ecparams, &d_ephem_iut, PR_TRUE, &ZZ) != SECSuccess) { + goto out; + } + + SECITEM_ZfreeItem(&publicValue, PR_FALSE); + publicValue.data = NULL; + + fputs(buf, resp); + + fips_hashBuf_zeropad(pspecs [current_pspec_def].hash_type, ZZ_hash_buf, ZZ.data, ZZ.len, field_len); + to_hex_str(Z_buf, ZZ_hash_buf, pspecs [current_pspec_def].hash_len / 8); + fprintf(resp, "IUTHashZZ = %s\n", Z_buf); + + fprintf(resp, "Result = %s\n", + (cavs_hash_zz.len == pspecs [current_pspec_def].hash_len / 8 + && memcmp (cavs_hash_zz.data, ZZ_hash_buf, pspecs [current_pspec_def].hash_len / 8) == 0) ? "P" : "F"); + } else { + fputs(buf, resp); + } + continue; + } else { + /* Comments, blank lines, ... */ + fputs(buf, resp); + } + } + +out: + fclose(req); + + if (d_ephem_iut.data) { + SECITEM_ZfreeItem(&d_ephem_iut, PR_FALSE); + } + if (x_ephem_iut.data) { + SECITEM_ZfreeItem(&x_ephem_iut, PR_FALSE); + } + if (y_ephem_iut.data) { + SECITEM_ZfreeItem(&y_ephem_iut, PR_FALSE); + } + if (x_ephem_cavs.data) { + SECITEM_ZfreeItem(&x_ephem_cavs, PR_FALSE); + } + if (y_ephem_cavs.data) { + SECITEM_ZfreeItem(&y_ephem_cavs, PR_FALSE); + } + if (cavs_hash_zz.data) { + SECITEM_ZfreeItem(&cavs_hash_zz, PR_FALSE); + } + if (publicValue.data) { + SECITEM_ZfreeItem(&publicValue, PR_FALSE); + } + + free_param_specs (pspecs); +} + int main(int argc, char **argv) { @@ -9287,6 +9582,15 @@ } else { kas_ffc_test(argv[3], PR_FALSE); } + } else if (strcmp(argv[1], "kasecc") == 0) { + /***************/ + /* KAS ECC */ + /***************/ + if (strcmp(argv[2], "validity") == 0) { + kas_ecc_test(argv[3], PR_TRUE); + } else { + kas_ecc_test(argv[3], PR_FALSE); + } } return 0; } diff --git a/cmd/fipstest/kas.sh b/cmd/fipstest/kas.sh --- a/cmd/fipstest/kas.sh +++ b/cmd/fipstest/kas.sh @@ -27,6 +27,16 @@ KASValidityTest_FFCEphem_NOKC_ZZOnly_resp.req " +kas_requests_ecc_function=" +KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req +KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req +" + +kas_requests_ecc_validity=" +KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req +KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req +" + if [ ${COMMAND} = "verify" ]; then for request in $kas_requests; do sh ./validate1.sh ${TESTDIR} $request @@ -45,3 +55,15 @@ echo $request $response fipstest kasffc validity ${REQDIR}/$request > ${RSPDIR}/$response done + +for request in $kas_requests_ecc_function; do + response=`echo $request | sed -e "s/req/rsp/"` + echo $request $response + fipstest kasecc function ${REQDIR}/$request > ${RSPDIR}/$response +done + +for request in $kas_requests_ecc_validity; do + response=`echo $request | sed -e "s/req/rsp/"` + echo $request $response + fipstest kasecc validity ${REQDIR}/$request > ${RSPDIR}/$response +done ++++++ nss-fips-cavs-kas-ffc.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1574234297 -3600 # Wed Nov 20 08:18:17 2019 +0100 # Node ID af7d3ee4e96cf685be0b95dff7aa5a1d3ab64a89 # Parent 5d6e015d1af40b5f5b990d0cf4d97932774c2a61 [PATCH] 20 >From ac98082c3bc0c9f85213078b730980483062f25c Mon Sep 17 00:00:00 2001 --- nss/cmd/fipstest/fipstest.c | 194 ++++++++++++++++++++++++++++++++++++ nss/cmd/fipstest/kas.sh | 47 +++++++++ 2 files changed, 241 insertions(+) create mode 100644 nss/cmd/fipstest/kas.sh diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c --- a/cmd/fipstest/fipstest.c +++ b/cmd/fipstest/fipstest.c @@ -2258,6 +2258,29 @@ return rv; } +SECStatus +fips_hashBuf_zeropad(HASH_HashType type, unsigned char *hashBuf, + unsigned char *msg, int len, int pad_to_len) +{ + unsigned char buf [8192]; + + if (pad_to_len > 8192) + { + fprintf (stderr, "Internal buffer too small.\n"); + exit (1); + } + + if (len > pad_to_len) + { + fprintf (stderr, "Value to hash exceeds maximum length.\n"); + exit (1); + } + + memset (buf, 0, pad_to_len - len); + memcpy (buf + (pad_to_len - len), msg, len); + return fips_hashBuf (type, hashBuf, buf, pad_to_len); +} + int fips_hashLen(HASH_HashType type) { @@ -8907,6 +8930,168 @@ } } +static int +parse_secitem (const char *name, const char *buf, SECItem *secitem) +{ + if (!strncmp (buf, name, strlen (name))) { + int i, j, len; + + i = strlen (name); + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + + len = strspn (&buf[i], "0123456789abcdefABCDEF"); + if (!len) + return 0; + + if (secitem->data) { + SECITEM_ZfreeItem(secitem, PR_FALSE); + secitem->data = NULL; + } + + len = (len + 1) / 2; + SECITEM_AllocItem(NULL, secitem, len); + secitem->len = len; + + memset(secitem->data, 0, secitem->len); + for (j = 0; j < secitem->len; i += 2, j++) { + hex_to_byteval(&buf[i], &secitem->data[j]); + } + + return 1; + } + + return 0; +} + +void +kas_ffc_test(char *reqfn, int do_validity) +{ + char buf[1024]; + FILE *req; /* input stream from the REQUEST file */ + FILE *resp; /* output stream to the RESPONSE file */ + PQGParams keyParams; + HASH_HashType hashType = HASH_AlgNULL; + int hashNum = 0; + SECItem y_ephem_cavs; + SECItem x_ephem_iut; + SECItem y_ephem_iut; + SECItem cavs_hash_zz; + + req = fopen(reqfn, "r"); + resp = stdout; + memset(&keyParams, 0, sizeof(keyParams)); + memset(&y_ephem_cavs, 0, sizeof(y_ephem_cavs)); + memset(&x_ephem_iut, 0, sizeof(x_ephem_iut)); + memset(&y_ephem_iut, 0, sizeof(y_ephem_iut)); + memset(&cavs_hash_zz, 0, sizeof(cavs_hash_zz)); + + while (fgets(buf, sizeof buf, req) != NULL) { + /* [xx] or + * [xx - SHAxxx] or + * [SHA(s) supported (Used for hashing Z): SHAxxx] */ + if (buf[0] == '[') { + unsigned char tbuf [2]; + + if (sscanf(buf, "[%c%c - SHA%d]", &tbuf [0], &tbuf [1], + &hashNum) != 3) { + fputs(buf, resp); + continue; + } + + fputs(buf, resp); + + hashType = sha_get_hashType(hashNum); + if (hashType == HASH_AlgNULL) { + fprintf(resp, "ERROR: invalid hash (SHA-%d)", hashNum); + goto out; + } + + continue; + } else if (parse_secitem ("YephemCAVS", buf, &y_ephem_cavs)) { + fputs(buf, resp); + + if (!do_validity) { + SECItem ZZ; + unsigned char ZZ_hash_buf [1024]; + DHParams dh_params; + DHPrivateKey *dh_privKey; + + dh_params.prime = keyParams.prime; + dh_params.base = keyParams.base; + + DH_NewKey (&dh_params, &dh_privKey); + DH_Derive(&y_ephem_cavs, &keyParams.prime, &dh_privKey->privateValue, &ZZ, 0); + + fips_hashBuf_zeropad(hashType, ZZ_hash_buf, ZZ.data, ZZ.len, keyParams.prime.len); + + to_hex_str(buf, dh_privKey->publicValue.data, dh_privKey->publicValue.len); + fprintf(resp, "YephemIUT = %s\n", buf); + + to_hex_str(buf, ZZ_hash_buf, hashNum / 8); + fprintf(resp, "HashZZ = %s\n", buf); + + PORT_FreeArena(dh_privKey->arena, PR_TRUE); + } + + continue; + } else if (parse_secitem ("XephemIUT", buf, &x_ephem_iut)) { + fputs(buf, resp); + continue; + } else if (parse_secitem ("YephemIUT", buf, &y_ephem_iut)) { + fputs(buf, resp); + continue; + } else if (parse_secitem ("CAVSHashZZ", buf, &cavs_hash_zz)) { + if (do_validity) { + SECItem ZZ; + unsigned char ZZ_hash_buf [1024]; + char Z_buf [1024]; + + DH_Derive(&y_ephem_cavs, &keyParams.prime, &x_ephem_iut, &ZZ, 0); + + fputs(buf, resp); + + to_hex_str(Z_buf, ZZ.data, ZZ.len); + + fips_hashBuf_zeropad(hashType, ZZ_hash_buf, ZZ.data, ZZ.len, keyParams.prime.len); + to_hex_str(Z_buf, ZZ_hash_buf, hashNum / 8); + fprintf(resp, "IUTHashZZ = %s\n", Z_buf); + + fprintf(resp, "Result = %s\n", + (cavs_hash_zz.len == hashNum / 8 && memcmp (cavs_hash_zz.data, ZZ_hash_buf, hashNum / 8) == 0) ? "P" : "F"); + } else { + fputs(buf, resp); + } + continue; + } else if (parse_secitem ("P", buf, &keyParams.prime)) { + fputs(buf, resp); + continue; + } else if (parse_secitem ("Q", buf, &keyParams.subPrime)) { + fputs(buf, resp); + continue; + } else if (parse_secitem ("G", buf, &keyParams.base)) { + fputs(buf, resp); + continue; + } else { + /* Comments, blank lines, ... */ + fputs(buf, resp); + } + } + +out: + fclose(req); + if (keyParams.prime.data) { /* P */ + SECITEM_ZfreeItem(&keyParams.prime, PR_FALSE); + } + if (keyParams.subPrime.data) { /* Q */ + SECITEM_ZfreeItem(&keyParams.subPrime, PR_FALSE); + } + if (keyParams.base.data) { /* G */ + SECITEM_ZfreeItem(&keyParams.base, PR_FALSE); + } +} + int main(int argc, char **argv) { @@ -9093,6 +9278,15 @@ /* AES Keywrap */ /***************/ keywrap(argv[2]); + } else if (strcmp(argv[1], "kasffc") == 0) { + /***************/ + /* KAS FFC */ + /***************/ + if (strcmp(argv[2], "validity") == 0) { + kas_ffc_test(argv[3], PR_TRUE); + } else { + kas_ffc_test(argv[3], PR_FALSE); + } } return 0; } diff --git a/cmd/fipstest/kas.sh b/cmd/fipstest/kas.sh new file mode 100644 --- /dev/null +++ b/cmd/fipstest/kas.sh @@ -0,0 +1,47 @@ +#!/bin/sh +# +# 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/. +# +# A Bourne shell script for running the NIST RNG Validation Suite +# +# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment +# variables appropriately so that the fipstest command and the NSPR and NSS +# shared libraries/DLLs are on the search path. Then run this script in the +# directory where the REQUEST (.req) files reside. The script generates the +# RESPONSE (.rsp) files in the same directory. +BASEDIR=${1-.} +TESTDIR=${BASEDIR}/KAS +COMMAND=${2-run} +REQDIR=${TESTDIR}/req +RSPDIR=${TESTDIR}/resp + +kas_requests_ffc_function=" +KASFunctionTest_FFCEphem_NOKC_ZZOnly_init.req +KASFunctionTest_FFCEphem_NOKC_ZZOnly_resp.req +" + +kas_requests_ffc_validity=" +KASValidityTest_FFCEphem_NOKC_ZZOnly_init.req +KASValidityTest_FFCEphem_NOKC_ZZOnly_resp.req +" + +if [ ${COMMAND} = "verify" ]; then + for request in $kas_requests; do + sh ./validate1.sh ${TESTDIR} $request + done + exit 0 +fi + +for request in $kas_requests_ffc_function; do + response=`echo $request | sed -e "s/req/rsp/"` + echo $request $response + fipstest kasffc function ${REQDIR}/$request > ${RSPDIR}/$response +done + +for request in $kas_requests_ffc_validity; do + response=`echo $request | sed -e "s/req/rsp/"` + echo $request $response + fipstest kasffc validity ${REQDIR}/$request > ${RSPDIR}/$response +done ++++++ nss-fips-cavs-keywrap.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1574234023 -3600 # Wed Nov 20 08:13:43 2019 +0100 # Node ID 5d6e015d1af40b5f5b990d0cf4d97932774c2a61 # Parent 2f570c6952d8edfc1ad9061cd3830f202eec1960 [PATCH 1/2] 19 >From f4cbaf95fcf2519029bb3c4407b2f15aa27c94c1 Mon Sep 17 00:00:00 2001 --- nss/cmd/fipstest/fipstest.c | 160 ++++++++++++++++++++++++++++++++++++ nss/cmd/fipstest/keywrap.sh | 40 +++++++++ 2 files changed, 200 insertions(+) create mode 100644 nss/cmd/fipstest/keywrap.sh diff -r 2f570c6952d8 -r 5d6e015d1af4 cmd/fipstest/fipstest.c --- a/cmd/fipstest/fipstest.c Sun Mar 15 21:54:30 2020 +0100 +++ b/cmd/fipstest/fipstest.c Wed Nov 20 08:13:43 2019 +0100 @@ -8752,6 +8752,161 @@ return; } +void +keywrap (char *reqfn) +{ + char buf[1024]; + FILE *req; /* input stream from the REQUEST file */ + FILE *resp; /* output stream to the RESPONSE file */ + int i, j; + AESKeyWrapContext *ctx = NULL; + unsigned char key_data [1024]; + int key_data_len = 0; + + req = fopen(reqfn, "r"); + resp = stdout; + + while (fgets(buf, sizeof buf, req) != NULL) { + /* K = ... */ + if (buf[0] == 'K') { + /* Skip to value */ + for (i = 1; isspace(buf[i]) || buf[i] == '='; i++) + ; + + if (i == 1) { + /* Unknown variable starting with 'K' */ + fputs(buf, resp); + continue; + } + + for (j = 0; isxdigit(buf[i]) && j < sizeof key_data; i += 2, j++) { + hex_to_byteval(&buf[i], &key_data[j]); + } + + key_data_len = j; + + fputs(buf, resp); + continue; + } + /* C = ... */ + /* This means we're doing decryption */ + /* Make sure we don't pick up COUNT = ... here */ + else if (buf[0] == 'C' && (isspace (buf[1]) || buf[1] == '=')) { + unsigned char data_in [1024]; + unsigned char data_out [1024]; + unsigned int data_in_len, data_out_len; + + if (key_data_len <= 0) { + fprintf(resp, "ERROR: No key specified\n"); + goto out; + } + + /* Skip to value */ + for (i = 1; isspace(buf[i]) || buf[i] == '='; i++) + ; + + if (i == 1) { + /* Unknown variable starting with 'C' */ + fputs(buf, resp); + continue; + } + + fputs(buf, resp); + + for (j = 0; isxdigit(buf[i]) && j < sizeof data_in; i += 2, j++) { + hex_to_byteval(&buf[i], &data_in[j]); + } + + data_in_len = j; + + if (ctx) { + AESKeyWrap_DestroyContext (ctx, PR_TRUE); + ctx = NULL; + } + + ctx = AESKeyWrap_CreateContext(key_data, NULL, PR_FALSE, key_data_len); + if (!ctx) { + fprintf(resp, "ERROR: Unable to create context\n"); + goto out; + } + + if (AESKeyWrap_Decrypt(ctx, data_out, &data_out_len, 1024, data_in, data_in_len) + != SECSuccess) { + fprintf(resp, "FAIL\n"); + continue; + } + + fputs("P = ", resp); + to_hex_str(buf, data_out, data_out_len); + fputs(buf, resp); + fputc('\n', resp); + } + /* P = ... */ + /* This means we're doing encryption */ + else if (buf[0] == 'P') { + unsigned char data_in [1024]; + unsigned char data_out [1024]; + unsigned int data_in_len, data_out_len; + + if (key_data_len <= 0) { + fprintf(resp, "ERROR: No key specified\n"); + goto out; + } + + /* Skip to value */ + for (i = 1; isspace(buf[i]) || buf[i] == '='; i++) + ; + + if (i == 1) { + /* Unknown variable starting with 'P' */ + fputs(buf, resp); + continue; + } + + fputs(buf, resp); + + for (j = 0; isxdigit(buf[i]) && j < sizeof data_in; i += 2, j++) { + hex_to_byteval(&buf[i], &data_in[j]); + } + + data_in_len = j; + + if (ctx) { + AESKeyWrap_DestroyContext (ctx, PR_TRUE); + ctx = NULL; + } + + ctx = AESKeyWrap_CreateContext(key_data, NULL, PR_TRUE, key_data_len); + if (!ctx) { + fprintf(resp, "ERROR: Unable to create context\n"); + goto out; + } + + if (AESKeyWrap_Encrypt(ctx, data_out, &data_out_len, 1024, data_in, data_in_len) + != SECSuccess) { + fprintf(resp, "FAIL\n"); + continue; + } + + fputs("C = ", resp); + to_hex_str(buf, data_out, data_out_len); + fputs(buf, resp); + fputc('\n', resp); + } + /* Comments, blank lines, ... */ + else { + fputs(buf, resp); + continue; + } + } + +out: + fclose(req); + if (ctx) { + AESKeyWrap_DestroyContext (ctx, PR_TRUE); + } +} + int main(int argc, char **argv) { @@ -8933,6 +9088,11 @@ ikev2(argv[2]); } else if (strcmp(argv[1], "kbkdf") == 0) { kbkdf(argv[2]); + } else if (strcmp(argv[1], "keywrap") == 0) { + /***************/ + /* AES Keywrap */ + /***************/ + keywrap(argv[2]); } return 0; } diff -r 2f570c6952d8 -r 5d6e015d1af4 cmd/fipstest/keywrap.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmd/fipstest/keywrap.sh Wed Nov 20 08:13:43 2019 +0100 @@ -0,0 +1,40 @@ +#!/bin/sh +# +# 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/. +# +# A Bourne shell script for running the NIST AES keywrap Algorithm Validation Suite +# +# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment +# variables appropriately so that the fipstest command and the NSPR and NSS +# shared libraries/DLLs are on the search path. Then run this script in the +# directory where the REQUEST (.req) files reside. The script generates the +# RESPONSE (.rsp) files in the same directory. +BASEDIR=${1-.} +TESTDIR=${BASEDIR}/KeyWrap38F +COMMAND=${2-run} +REQDIR=${TESTDIR}/req +RSPDIR=${TESTDIR}/resp + +keywrap_requests=" +KW_AD_128.req +KW_AD_192.req +KW_AD_256.req +KW_AE_128.req +KW_AE_192.req +KW_AE_256.req +" + +if [ ${COMMAND} = "verify" ]; then + for request in $keywrap_requests; do + sh ./validate1.sh ${TESTDIR} $request + done + exit 0 +fi + +for request in $keywrap_requests; do + response=`echo $request | sed -e "s/req/rsp/"` + echo $request $response + fipstest keywrap ${REQDIR}/$request > ${RSPDIR}/$response +done ++++++ nss-fips-cavs-rsa-fixes.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1574237297 -3600 # Wed Nov 20 09:08:17 2019 +0100 # Node ID 3f4d682c9a1e8b3d939c744ee249e23179db5191 # Parent 0e904e6179d1db21965df2c405c80c3fc0258658 [PATCH] 25 >From 9b4636ad75add2ac09ce1844b3071785d563c275 Mon Sep 17 00:00:00 2001 --- nss/cmd/fipstest/fipstest.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c --- a/cmd/fipstest/fipstest.c +++ b/cmd/fipstest/fipstest.c @@ -6536,7 +6536,7 @@ /* Output the signature */ fputs(buf, rsaresp); to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed); - fprintf(rsaresp, "S = %s\n", buf); + fprintf(rsaresp, "S = %s\n\n", buf); /* Perform RSA verification with the RSA public key. */ rv = RSA_HashCheckSign(shaOid, @@ -9536,6 +9536,7 @@ init_functions(); RNG_RNGInit(); SECOID_Init(); + BL_Init(); /*************/ /* TDEA */ ++++++ nss-fips-combined-hash-sign-dsa-ecdsa.patch ++++++ >From 7f3606a84f6c62b002246ee73121279e59f83437 Mon Sep 17 00:00:00 2001 From: Hans Petter Jansson <[email protected]> Date: Thu, 28 May 2020 22:44:22 +0200 Subject: [PATCH] CKM_(EC)DSA_SHAxxx mechs: Add some missing pieces. This includes pairwise consistency checks and entry points for power-on self tests. --- cmd/lib/pk11table.c | 8 ++ lib/pk11wrap/pk11mech.c | 8 ++ lib/softoken/pkcs11c.c | 213 +++++++++++++++++++++++++++------------- lib/softoken/softoken.h | 10 ++ 4 files changed, 169 insertions(+), 70 deletions(-) diff --git a/cmd/lib/pk11table.c b/cmd/lib/pk11table.c index f7a45fa..d302436 100644 --- a/cmd/lib/pk11table.c +++ b/cmd/lib/pk11table.c @@ -273,6 +273,10 @@ const Constant _consts[] = { mkEntry(CKM_DSA_KEY_PAIR_GEN, Mechanism), mkEntry(CKM_DSA, Mechanism), mkEntry(CKM_DSA_SHA1, Mechanism), + mkEntry(CKM_DSA_SHA224, Mechanism), + mkEntry(CKM_DSA_SHA256, Mechanism), + mkEntry(CKM_DSA_SHA384, Mechanism), + mkEntry(CKM_DSA_SHA512, Mechanism), mkEntry(CKM_DH_PKCS_KEY_PAIR_GEN, Mechanism), mkEntry(CKM_DH_PKCS_DERIVE, Mechanism), mkEntry(CKM_X9_42_DH_DERIVE, Mechanism), @@ -438,6 +442,10 @@ const Constant _consts[] = { mkEntry(CKM_EC_KEY_PAIR_GEN, Mechanism), mkEntry(CKM_ECDSA, Mechanism), mkEntry(CKM_ECDSA_SHA1, Mechanism), + mkEntry(CKM_ECDSA_SHA224, Mechanism), + mkEntry(CKM_ECDSA_SHA256, Mechanism), + mkEntry(CKM_ECDSA_SHA384, Mechanism), + mkEntry(CKM_ECDSA_SHA512, Mechanism), mkEntry(CKM_ECDH1_DERIVE, Mechanism), mkEntry(CKM_ECDH1_COFACTOR_DERIVE, Mechanism), mkEntry(CKM_ECMQV_DERIVE, Mechanism), diff --git a/lib/pk11wrap/pk11mech.c b/lib/pk11wrap/pk11mech.c index d94d59a..ac280f0 100644 --- a/lib/pk11wrap/pk11mech.c +++ b/lib/pk11wrap/pk11mech.c @@ -376,6 +376,10 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type, unsigned long len) return CKK_RSA; case CKM_DSA: case CKM_DSA_SHA1: + case CKM_DSA_SHA224: + case CKM_DSA_SHA256: + case CKM_DSA_SHA384: + case CKM_DSA_SHA512: case CKM_DSA_KEY_PAIR_GEN: return CKK_DSA; case CKM_DH_PKCS_DERIVE: @@ -386,6 +390,10 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type, unsigned long len) return CKK_KEA; case CKM_ECDSA: case CKM_ECDSA_SHA1: + case CKM_ECDSA_SHA224: + case CKM_ECDSA_SHA256: + case CKM_ECDSA_SHA384: + case CKM_ECDSA_SHA512: case CKM_EC_KEY_PAIR_GEN: /* aka CKM_ECDSA_KEY_PAIR_GEN */ case CKM_ECDH1_DERIVE: return CKK_EC; /* CKK_ECDSA is deprecated */ diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c index 08f94bc..ec6b205 100644 --- a/lib/softoken/pkcs11c.c +++ b/lib/softoken/pkcs11c.c @@ -2606,7 +2606,7 @@ nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen, static SECStatus nsc_DSA_Sign_Stub(void *ctx, void *sigBuf, unsigned int *sigLen, unsigned int maxSigLen, - void *dataBuf, unsigned int dataLen) + const void *dataBuf, unsigned int dataLen) { SECItem signature, digest; SECStatus rv; @@ -2624,6 +2624,22 @@ nsc_DSA_Sign_Stub(void *ctx, void *sigBuf, return rv; } +SECStatus +DSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, + unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, + const unsigned char *hash, unsigned int hashLen) +{ + SECStatus rv; + + rv = nsc_DSA_Sign_Stub(key, sig, sigLen, maxLen, hash, hashLen); + + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } + + return rv; +} + static SECStatus nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen, void *dataBuf, unsigned int dataLen) @@ -2641,7 +2657,7 @@ nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen, static SECStatus nsc_ECDSASignStub(void *ctx, void *sigBuf, unsigned int *sigLen, unsigned int maxSigLen, - void *dataBuf, unsigned int dataLen) + const void *dataBuf, unsigned int dataLen) { SECItem signature, digest; SECStatus rv; @@ -2659,6 +2675,22 @@ nsc_ECDSASignStub(void *ctx, void *sigBuf, return rv; } +SECStatus +ECDSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, + unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, + const unsigned char *hash, unsigned int hashLen) +{ + SECStatus rv; + + rv = nsc_ECDSASignStub(key, sig, sigLen, maxLen, hash, hashLen); + + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } + + return rv; +} + /* NSC_SignInit setups up the signing operations. There are three basic * types of signing: * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied @@ -3511,6 +3543,22 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSession, info->hashOid = SEC_OID_##mmm; \ goto finish_rsa; +#define INIT_DSA_VFY_MECH(mmm) \ + case CKM_DSA_##mmm: \ + context->multi = PR_TRUE; \ + crv = sftk_doSub##mmm(context); \ + if (crv != CKR_OK) \ + break; \ + goto finish_dsa; + +#define INIT_ECDSA_VFY_MECH(mmm) \ + case CKM_ECDSA_##mmm: \ + context->multi = PR_TRUE; \ + crv = sftk_doSub##mmm(context); \ + if (crv != CKR_OK) \ + break; \ + goto finish_ecdsa; + switch (pMechanism->mechanism) { INIT_RSA_VFY_MECH(MD5) INIT_RSA_VFY_MECH(MD2) @@ -3575,13 +3623,15 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSession, context->destroy = (SFTKDestroy)sftk_Space; context->verify = (SFTKVerify)sftk_RSACheckSignPSS; break; - case CKM_DSA_SHA1: - context->multi = PR_TRUE; - crv = sftk_doSubSHA1(context); - if (crv != CKR_OK) - break; - /* fall through */ + + INIT_DSA_VFY_MECH(SHA1) + INIT_DSA_VFY_MECH(SHA224) + INIT_DSA_VFY_MECH(SHA256) + INIT_DSA_VFY_MECH(SHA384) + INIT_DSA_VFY_MECH(SHA512) + case CKM_DSA: + finish_dsa: if (key_type != CKK_DSA) { crv = CKR_KEY_TYPE_INCONSISTENT; break; @@ -3594,13 +3644,15 @@ NSC_VerifyInit(CK_SESSION_HANDLE hSession, context->verify = (SFTKVerify)nsc_DSA_Verify_Stub; context->destroy = sftk_Null; break; - case CKM_ECDSA_SHA1: - context->multi = PR_TRUE; - crv = sftk_doSubSHA1(context); - if (crv != CKR_OK) - break; - /* fall through */ + + INIT_ECDSA_VFY_MECH(SHA1) + INIT_ECDSA_VFY_MECH(SHA224) + INIT_ECDSA_VFY_MECH(SHA256) + INIT_ECDSA_VFY_MECH(SHA384) + INIT_ECDSA_VFY_MECH(SHA512) + case CKM_ECDSA: + finish_ecdsa: if (key_type != CKK_EC) { crv = CKR_KEY_TYPE_INCONSISTENT; break; @@ -4733,6 +4785,73 @@ loser: #define PAIRWISE_DIGEST_LENGTH SHA224_LENGTH /* 224-bits */ #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ +static CK_RV +pairwise_signverify_mech (CK_SESSION_HANDLE hSession, + SFTKObject *publicKey, SFTKObject *privateKey, + CK_MECHANISM mech, + CK_ULONG signature_length, + CK_ULONG pairwise_digest_length) +{ + /* Variables used for Signature/Verification functions. */ + /* Must be at least 256 bits for DSA2 digest */ + unsigned char *known_digest = (unsigned char *)"Mozilla Rules the World through NSS!"; + unsigned char *signature; + CK_RV crv; + + /* Allocate space for signature data. */ + signature = (unsigned char *)PORT_ZAlloc(signature_length); + if (signature == NULL) { + return CKR_HOST_MEMORY; + } + + /* Sign the known hash using the private key. */ + crv = NSC_SignInit(hSession, &mech, privateKey->handle); + if (crv != CKR_OK) { + PORT_Free(signature); + return crv; + } + + crv = NSC_Sign(hSession, + known_digest, + pairwise_digest_length, + signature, + &signature_length); + if (crv != CKR_OK) { + PORT_Free(signature); + return crv; + } + + /* detect trivial signing transforms */ + 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; + } + + /* Verify the known hash using the public key. */ + crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); + if (crv != CKR_OK) { + PORT_Free(signature); + return crv; + } + + crv = NSC_Verify(hSession, + known_digest, + pairwise_digest_length, + signature, + signature_length); + + /* Free signature data. */ + PORT_Free(signature); + + if ((crv == CKR_SIGNATURE_LEN_RANGE) || + (crv == CKR_SIGNATURE_INVALID)) { + return CKR_GENERAL_ERROR; + } + + return crv; +} + /* * FIPS 140-2 pairwise consistency check utilized to validate key pair. * @@ -4780,8 +4899,6 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, /* Variables used for Signature/Verification functions. */ /* Must be at least 256 bits for DSA2 digest */ - unsigned char *known_digest = (unsigned char *)"Mozilla Rules the World through NSS!"; - unsigned char *signature; CK_ULONG signature_length; if (keyType == CKK_RSA) { @@ -4935,76 +5052,32 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, } } +#define SIGNVERIFY_CHECK_MECH(vfymech) \ + mech.mechanism = vfymech; \ + crv = pairwise_signverify_mech (hSession, publicKey, privateKey, \ + mech, signature_length, pairwise_digest_length); \ + if (crv != CKR_OK) \ + return crv; + if (canSignVerify) { - /* Determine length of signature. */ switch (keyType) { case CKK_RSA: signature_length = modulusLen; - mech.mechanism = CKM_RSA_PKCS; + SIGNVERIFY_CHECK_MECH(CKM_SHA224_RSA_PKCS) break; case CKK_DSA: signature_length = DSA_MAX_SIGNATURE_LEN; pairwise_digest_length = subPrimeLen; - mech.mechanism = CKM_DSA; + SIGNVERIFY_CHECK_MECH(CKM_DSA_SHA224) break; case CKK_EC: signature_length = MAX_ECKEY_LEN * 2; - mech.mechanism = CKM_ECDSA; + SIGNVERIFY_CHECK_MECH(CKM_ECDSA_SHA224) break; default: return CKR_DEVICE_ERROR; } - /* Allocate space for signature data. */ - signature = (unsigned char *)PORT_ZAlloc(signature_length); - if (signature == NULL) { - return CKR_HOST_MEMORY; - } - - /* Sign the known hash using the private key. */ - crv = NSC_SignInit(hSession, &mech, privateKey->handle); - if (crv != CKR_OK) { - PORT_Free(signature); - return crv; - } - - crv = NSC_Sign(hSession, - known_digest, - pairwise_digest_length, - signature, - &signature_length); - if (crv != CKR_OK) { - PORT_Free(signature); - return crv; - } - - /* detect trivial signing transforms */ - 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; - } - - /* Verify the known hash using the public key. */ - crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); - if (crv != CKR_OK) { - PORT_Free(signature); - return crv; - } - - crv = NSC_Verify(hSession, - known_digest, - pairwise_digest_length, - signature, - signature_length); - - /* Free signature data. */ - PORT_Free(signature); - - if ((crv == CKR_SIGNATURE_LEN_RANGE) || - (crv == CKR_SIGNATURE_INVALID)) { - return CKR_GENERAL_ERROR; - } if (crv != CKR_OK) { return crv; } diff --git a/lib/softoken/softoken.h b/lib/softoken/softoken.h index 30586fc..d5aaffa 100644 --- a/lib/softoken/softoken.h +++ b/lib/softoken/softoken.h @@ -35,6 +35,16 @@ RSA_HashCheckSign(SECOidTag hashOid, NSSLOWKEYPublicKey *key, const unsigned char *sig, unsigned int sigLen, const unsigned char *hash, unsigned int hashLen); +extern SECStatus +DSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, + unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, + const unsigned char *hash, unsigned int hashLen); + +extern SECStatus +ECDSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, + unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, + const unsigned char *hash, unsigned int hashLen); + /* ** Prepare a buffer for padded CBC encryption, growing to the appropriate ** boundary, filling with the appropriate padding. -- 2.26.2 ++++++ nss-fips-constructor-self-tests.patch ++++++ ++++ 1450 lines (skipped) ++++++ nss-fips-detect-fips-mode-fixes.patch ++++++ # HG changeset patch # User M. Sirringhaus <[email protected]> # Date 1584305671 -3600 # Sun Mar 15 21:54:31 2020 +0100 # Node ID 715834d4a258c535f3abbf116d69d5e77392593b # Parent 4ddd7d49eeed4ea32850daf41a472ccb50dee45e commit facacdb9078693d7a4219e84f73ea7b8f977ddc2 Author: Hans Petter Jansson <[email protected]> Patch 32: nss-fips-detect-fips-mode-fixes.patch diff --git a/lib/freebl/nsslowhash.c b/lib/freebl/nsslowhash.c --- a/lib/freebl/nsslowhash.c +++ b/lib/freebl/nsslowhash.c @@ -2,10 +2,15 @@ * 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/. */ +#define _GNU_SOURCE 1 +#include <stdlib.h> + #ifdef FREEBL_NO_DEPEND #include "stubs.h" #endif + #include "prtypes.h" +#include "prenv.h" #include "secerr.h" #include "blapi.h" #include "hasht.h" @@ -24,6 +29,23 @@ }; #ifndef NSS_FIPS_DISABLED + +static PRBool +getFIPSEnv(void) +{ + char *fipsEnv = secure_getenv("NSS_FIPS"); + if (!fipsEnv) { + return PR_FALSE; + } + if ((strcasecmp(fipsEnv, "fips") == 0) || + (strcasecmp(fipsEnv, "true") == 0) || + (strcasecmp(fipsEnv, "on") == 0) || + (strcasecmp(fipsEnv, "1") == 0)) { + return PR_TRUE; + } + return PR_FALSE; +} + static int nsslow_GetFIPSEnabled(void) { @@ -45,6 +67,7 @@ #endif /* LINUX */ return 1; } + #endif /* NSS_FIPS_DISABLED */ static NSSLOWInitContext dummyContext = { 0 }; @@ -60,7 +83,7 @@ #ifndef NSS_FIPS_DISABLED /* make sure the FIPS product is installed if we are trying to * go into FIPS mode */ - if (nsslow_GetFIPSEnabled()) { + if (nsslow_GetFIPSEnabled() || getFIPSEnv()) { if (BL_FIPSEntryOK(PR_TRUE) != SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); post_failed = PR_TRUE; diff --git a/lib/sysinit/nsssysinit.c b/lib/sysinit/nsssysinit.c --- a/lib/sysinit/nsssysinit.c +++ b/lib/sysinit/nsssysinit.c @@ -178,16 +178,16 @@ f = fopen("/proc/sys/crypto/fips_enabled", "r"); if (!f) { /* if we don't have a proc flag, fall back to the - * environment variable */ + * environment variable */ return getFIPSEnv(); } size = fread(&d, 1, 1, f); fclose(f); if (size != 1) - return PR_FALSE; + return getFIPSEnv(); if (d != '1') - return PR_FALSE; + return getFIPSEnv(); return PR_TRUE; #else return PR_FALSE; ++++++ nss-fips-dsa-kat.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1505605677 -7200 # Sun Sep 17 01:47:57 2017 +0200 # Node ID 4ae6bed68a83c01f6d2ce7a37bdb0bdb0556416f # Parent 5e191a391c38967e49a1d005800713ccd1010b09 [PATCH 2/6] Make DSA KAT FIPS compliant (1024 -> 2048 bit key). >From b88701933a284ba8640df66b954c04d36ee592c9 Mon Sep 17 00:00:00 2001 --- nss/lib/freebl/dsa.c | 2 +- nss/lib/freebl/fipsfreebl.c | 143 +++++++++++++++++++++++++++----------------- 2 files changed, 90 insertions(+), 55 deletions(-) diff --git a/lib/freebl/dsa.c b/lib/freebl/dsa.c --- a/lib/freebl/dsa.c +++ b/lib/freebl/dsa.c @@ -533,7 +533,7 @@ return rv; } -/* For FIPS compliance testing. Seed must be exactly 20 bytes. */ +/* For FIPS compliance testing. Seed must be the same size as subprime. */ SECStatus DSA_SignDigestWithSeed(DSAPrivateKey *key, SECItem *signature, diff --git a/lib/freebl/fipsfreebl.c b/lib/freebl/fipsfreebl.c --- a/lib/freebl/fipsfreebl.c +++ b/lib/freebl/fipsfreebl.c @@ -124,11 +124,11 @@ /* FIPS preprocessor directives for DSA. */ #define FIPS_DSA_TYPE siBuffer -#define FIPS_DSA_DIGEST_LENGTH 20 /* 160-bits */ -#define FIPS_DSA_SUBPRIME_LENGTH 20 /* 160-bits */ -#define FIPS_DSA_SIGNATURE_LENGTH 40 /* 320-bits */ -#define FIPS_DSA_PRIME_LENGTH 128 /* 1024-bits */ -#define FIPS_DSA_BASE_LENGTH 128 /* 1024-bits */ +#define FIPS_DSA_DIGEST_LENGTH 28 /* 224-bits */ +#define FIPS_DSA_SUBPRIME_LENGTH 28 /* 224-bits */ +#define FIPS_DSA_SIGNATURE_LENGTH 56 /* 448-bits */ +#define FIPS_DSA_PRIME_LENGTH 256 /* 2048-bits */ +#define FIPS_DSA_BASE_LENGTH 256 /* 2048-bits */ /* FIPS preprocessor directives for RNG. */ #define FIPS_RNG_XKEY_LENGTH 32 /* 256-bits */ @@ -1445,70 +1445,105 @@ static SECStatus freebl_fips_DSA_PowerUpSelfTest(void) { - /* DSA Known P (1024-bits), Q (160-bits), and G (1024-bits) Values. */ + /* DSA Known P (2048-bits), Q (224-bits), and G (2048-bits) Values. */ static const PRUint8 dsa_P[] = { - 0x80, 0xb0, 0xd1, 0x9d, 0x6e, 0xa4, 0xf3, 0x28, - 0x9f, 0x24, 0xa9, 0x8a, 0x49, 0xd0, 0x0c, 0x63, - 0xe8, 0x59, 0x04, 0xf9, 0x89, 0x4a, 0x5e, 0xc0, - 0x6d, 0xd2, 0x67, 0x6b, 0x37, 0x81, 0x83, 0x0c, - 0xfe, 0x3a, 0x8a, 0xfd, 0xa0, 0x3b, 0x08, 0x91, - 0x1c, 0xcb, 0xb5, 0x63, 0xb0, 0x1c, 0x70, 0xd0, - 0xae, 0xe1, 0x60, 0x2e, 0x12, 0xeb, 0x54, 0xc7, - 0xcf, 0xc6, 0xcc, 0xae, 0x97, 0x52, 0x32, 0x63, - 0xd3, 0xeb, 0x55, 0xea, 0x2f, 0x4c, 0xd5, 0xd7, - 0x3f, 0xda, 0xec, 0x49, 0x27, 0x0b, 0x14, 0x56, - 0xc5, 0x09, 0xbe, 0x4d, 0x09, 0x15, 0x75, 0x2b, - 0xa3, 0x42, 0x0d, 0x03, 0x71, 0xdf, 0x0f, 0xf4, - 0x0e, 0xe9, 0x0c, 0x46, 0x93, 0x3d, 0x3f, 0xa6, - 0x6c, 0xdb, 0xca, 0xe5, 0xac, 0x96, 0xc8, 0x64, - 0x5c, 0xec, 0x4b, 0x35, 0x65, 0xfc, 0xfb, 0x5a, - 0x1b, 0x04, 0x1b, 0xa1, 0x0e, 0xfd, 0x88, 0x15 + 0xfe, 0x9f, 0xba, 0xff, 0x39, 0xa6, 0x00, 0x77, + 0x93, 0xfe, 0xa4, 0x58, 0x17, 0xf8, 0x37, 0x54, + 0x76, 0x39, 0x18, 0xcb, 0xbe, 0xca, 0x62, 0x8b, + 0x85, 0xbc, 0x60, 0x23, 0xf4, 0x7a, 0xb5, 0x75, + 0x31, 0xf4, 0x82, 0x83, 0x63, 0xc2, 0xdb, 0x8e, + 0x50, 0x67, 0xd6, 0xd9, 0xae, 0xa0, 0xd6, 0x13, + 0xc2, 0x35, 0x5b, 0x76, 0xf1, 0x00, 0x9c, 0x37, + 0xcb, 0x46, 0x3f, 0x6e, 0xef, 0xca, 0xff, 0xcc, + 0x1e, 0x15, 0xa1, 0x96, 0x70, 0x4c, 0xc9, 0x4d, + 0x7e, 0xde, 0x00, 0x1e, 0x76, 0x68, 0x35, 0x1c, + 0x31, 0x25, 0x37, 0x91, 0x98, 0x64, 0x40, 0x4c, + 0xf1, 0xc3, 0x0e, 0xf7, 0xf3, 0x16, 0x17, 0x79, + 0x7a, 0xa3, 0x11, 0x9a, 0xba, 0x72, 0x67, 0xe9, + 0x70, 0xd0, 0x16, 0x6a, 0x1a, 0x53, 0x4e, 0x1b, + 0xca, 0xb2, 0x79, 0xd8, 0x8c, 0x60, 0x53, 0xdb, + 0x48, 0x1c, 0x00, 0x2e, 0xd3, 0x29, 0x35, 0x14, + 0x6d, 0xd6, 0x23, 0x7c, 0x1c, 0xf3, 0x0d, 0x6a, + 0x7e, 0xb7, 0x09, 0x7d, 0xf2, 0x06, 0x29, 0x1c, + 0x1a, 0xdf, 0xd9, 0xe6, 0xb9, 0x2e, 0xd6, 0xb8, + 0xbf, 0xc5, 0xcd, 0xe7, 0xf4, 0xf9, 0x91, 0x38, + 0x2f, 0x61, 0xf9, 0xfe, 0xce, 0x16, 0x85, 0xc8, + 0xb7, 0xdd, 0x54, 0xe0, 0xa1, 0x54, 0x4f, 0xb3, + 0xdb, 0x72, 0xf3, 0xb9, 0xaa, 0xfe, 0x7b, 0xdd, + 0x5e, 0x59, 0x44, 0x6c, 0x4a, 0xfe, 0x67, 0x9b, + 0xcf, 0x78, 0x05, 0xd4, 0xc8, 0x98, 0xb3, 0x60, + 0x46, 0x44, 0x4e, 0x0b, 0xec, 0x19, 0x6c, 0xda, + 0xd6, 0x40, 0x3c, 0xd9, 0x96, 0xc8, 0x4a, 0x3b, + 0xc9, 0xb5, 0x52, 0x89, 0x2e, 0x68, 0xb9, 0xa0, + 0xd3, 0xbc, 0xa8, 0xd7, 0x6a, 0x7d, 0xe1, 0xf4, + 0x8c, 0x68, 0x3e, 0xc1, 0x5a, 0xac, 0x46, 0x6d, + 0xad, 0xe3, 0x89, 0x7f, 0x92, 0xa6, 0x29, 0xb2, + 0xc3, 0x3b, 0x20, 0x5f, 0x71, 0x00, 0x27, 0x87 }; static const PRUint8 dsa_Q[] = { - 0xad, 0x22, 0x59, 0xdf, 0xe5, 0xec, 0x4c, 0x6e, - 0xf9, 0x43, 0xf0, 0x4b, 0x2d, 0x50, 0x51, 0xc6, - 0x91, 0x99, 0x8b, 0xcf + 0xbc, 0xc9, 0xda, 0xca, 0xf9, 0x6b, 0xfa, 0x7e, + 0xbd, 0x9b, 0xfb, 0x48, 0x35, 0x1e, 0xe5, 0x8c, + 0x64, 0x46, 0xc7, 0x04, 0xb2, 0x44, 0x70, 0x9b, + 0x0a, 0x3f, 0x03, 0x01 }; static const PRUint8 dsa_G[] = { - 0x78, 0x6e, 0xa9, 0xd8, 0xcd, 0x4a, 0x85, 0xa4, - 0x45, 0xb6, 0x6e, 0x5d, 0x21, 0x50, 0x61, 0xf6, - 0x5f, 0xdf, 0x5c, 0x7a, 0xde, 0x0d, 0x19, 0xd3, - 0xc1, 0x3b, 0x14, 0xcc, 0x8e, 0xed, 0xdb, 0x17, - 0xb6, 0xca, 0xba, 0x86, 0xa9, 0xea, 0x51, 0x2d, - 0xc1, 0xa9, 0x16, 0xda, 0xf8, 0x7b, 0x59, 0x8a, - 0xdf, 0xcb, 0xa4, 0x67, 0x00, 0x44, 0xea, 0x24, - 0x73, 0xe5, 0xcb, 0x4b, 0xaf, 0x2a, 0x31, 0x25, - 0x22, 0x28, 0x3f, 0x16, 0x10, 0x82, 0xf7, 0xeb, - 0x94, 0x0d, 0xdd, 0x09, 0x22, 0x14, 0x08, 0x79, - 0xba, 0x11, 0x0b, 0xf1, 0xff, 0x2d, 0x67, 0xac, - 0xeb, 0xb6, 0x55, 0x51, 0x69, 0x97, 0xa7, 0x25, - 0x6b, 0x9c, 0xa0, 0x9b, 0xd5, 0x08, 0x9b, 0x27, - 0x42, 0x1c, 0x7a, 0x69, 0x57, 0xe6, 0x2e, 0xed, - 0xa9, 0x5b, 0x25, 0xe8, 0x1f, 0xd2, 0xed, 0x1f, - 0xdf, 0xe7, 0x80, 0x17, 0xba, 0x0d, 0x4d, 0x38 + 0x5d, 0x23, 0xd1, 0xc5, 0x2e, 0x7e, 0x22, 0x3b, + 0x98, 0x03, 0xc3, 0xc0, 0x9d, 0xbe, 0x8f, 0x68, + 0x6b, 0xd0, 0xbf, 0x72, 0x20, 0x89, 0x5c, 0x8f, + 0x4c, 0x8e, 0x66, 0xfe, 0x8e, 0xfc, 0x02, 0x21, + 0xf3, 0xea, 0xc5, 0x23, 0x96, 0x9b, 0xa4, 0x2e, + 0xac, 0x35, 0x9f, 0x70, 0x90, 0x79, 0xd9, 0x42, + 0xfa, 0x0e, 0x4c, 0x1f, 0x55, 0xcf, 0x8b, 0xb5, + 0x98, 0x71, 0xfa, 0xf1, 0xbc, 0xfd, 0xc7, 0x2b, + 0x5a, 0xa6, 0x53, 0x86, 0xf1, 0xa3, 0xd5, 0xbc, + 0xad, 0x08, 0x80, 0x23, 0x40, 0xea, 0xc9, 0x2f, + 0x58, 0xfb, 0xa9, 0xda, 0x8d, 0xc5, 0xfa, 0x46, + 0x0a, 0x0a, 0xe8, 0x03, 0xef, 0x04, 0x53, 0x09, + 0xc4, 0x7f, 0x69, 0x59, 0x68, 0xb5, 0x52, 0x91, + 0x3d, 0xe1, 0xbc, 0xa0, 0x6b, 0x41, 0xec, 0x07, + 0x0b, 0xf5, 0xf5, 0x62, 0xf5, 0xeb, 0xb7, 0x7e, + 0xc5, 0x32, 0x3d, 0x1e, 0x03, 0xda, 0x75, 0x24, + 0xb6, 0xe5, 0xb9, 0xfd, 0x36, 0x3d, 0xa4, 0xbf, + 0xc4, 0xee, 0x3b, 0xb5, 0x14, 0x85, 0x5c, 0x2d, + 0x80, 0xb2, 0x55, 0xb6, 0x70, 0x21, 0xf2, 0x94, + 0x63, 0xa5, 0xc2, 0x6f, 0xee, 0x34, 0x81, 0xae, + 0xc6, 0x0f, 0xf3, 0xef, 0xb4, 0xde, 0xa5, 0x58, + 0x6f, 0x57, 0xc1, 0x51, 0x0a, 0xe4, 0x4e, 0xf0, + 0xed, 0xee, 0x42, 0xdc, 0xff, 0x4b, 0x14, 0xa3, + 0xcc, 0x6e, 0xa8, 0x0c, 0x29, 0x81, 0xdb, 0xce, + 0x78, 0x4d, 0x43, 0xe0, 0xe1, 0x60, 0xc8, 0x3e, + 0x54, 0x00, 0x29, 0x20, 0x25, 0x40, 0x22, 0xac, + 0xfa, 0x75, 0xb1, 0x4e, 0xcc, 0x61, 0x54, 0x27, + 0x2c, 0x95, 0xaf, 0x4c, 0x02, 0xa7, 0x55, 0xbd, + 0xed, 0xe2, 0x25, 0xfc, 0xba, 0xd2, 0x5b, 0xd7, + 0x33, 0xa1, 0xe9, 0xb4, 0x7f, 0x7e, 0xfe, 0xbb, + 0xfa, 0x54, 0xce, 0x3c, 0xbc, 0xd1, 0x03, 0x50, + 0x9d, 0xa9, 0x38, 0x9a, 0xf8, 0x67, 0xb1, 0xa3 }; - /* DSA Known Random Values (known random key block is 160-bits) */ - /* and (known random signature block is 160-bits). */ + /* DSA Known Random Values (known random key block is 224-bits) */ + /* and (known random signature block is 224-bits). */ static const PRUint8 dsa_known_random_key_block[] = { - "Mozilla Rules World!" + "Mozilla Rules World! Always." }; static const PRUint8 dsa_known_random_signature_block[] = { - "Random DSA Signature" + "Random DSA Signature, Longer" }; - /* DSA Known Digest (160-bits) */ - static const PRUint8 dsa_known_digest[] = { "DSA Signature Digest" }; + /* DSA Known Digest (224-bits) */ + static const PRUint8 dsa_known_digest[] = { "DSA Signature Digest, Longer" }; - /* DSA Known Signature (320-bits). */ + /* DSA Known Signature (448-bits). */ static const PRUint8 dsa_known_signature[] = { - 0x25, 0x7c, 0x3a, 0x79, 0x32, 0x45, 0xb7, 0x32, - 0x70, 0xca, 0x62, 0x63, 0x2b, 0xf6, 0x29, 0x2c, - 0x22, 0x2a, 0x03, 0xce, 0x48, 0x15, 0x11, 0x72, - 0x7b, 0x7e, 0xf5, 0x7a, 0xf3, 0x10, 0x3b, 0xde, - 0x34, 0xc1, 0x9e, 0xd7, 0x27, 0x9e, 0x77, 0x38 + 0x27, 0x04, 0xff, 0xd5, 0x2d, 0x80, 0x32, 0xea, + 0xac, 0xb5, 0x8b, 0x47, 0x17, 0xb1, 0x80, 0xed, + 0xd6, 0x0f, 0x72, 0x75, 0xe5, 0xba, 0x08, 0xc9, + 0x29, 0xc8, 0xc7, 0x75, 0x84, 0x60, 0x5a, 0xe9, + 0x55, 0xa4, 0x1c, 0xf0, 0xe3, 0xce, 0x4c, 0x8e, + 0x83, 0x3e, 0x7a, 0x77, 0x56, 0x7f, 0x83, 0xad, + 0x68, 0x36, 0x13, 0xa9, 0xd6, 0x08, 0x1f, 0x19 }; /* DSA variables. */ @@ -1550,7 +1585,7 @@ dsa_signature_item.len = sizeof dsa_computed_signature; dsa_digest_item.data = (unsigned char *)dsa_known_digest; - dsa_digest_item.len = SHA1_LENGTH; + dsa_digest_item.len = SHA224_LENGTH; /* Perform DSA signature process. */ dsa_status = DSA_SignDigestWithSeed(dsa_private_key, ++++++ nss-fips-gcm-ctr.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1574234739 -3600 # Wed Nov 20 08:25:39 2019 +0100 # Node ID 5396ffb26887cc0cd42b9f12cc6c8e3dfdaf194b # Parent f5cf5d16deb68e65b5dd4e799d9e8e3098400d62 [PATCH] 22 >From 41dd171b242b0cb550d12760da110db7e2c21daf Mon Sep 17 00:00:00 2001 --- nss/lib/freebl/gcm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff -r f5cf5d16deb6 -r 5396ffb26887 lib/freebl/gcm.c --- a/lib/freebl/gcm.c Wed Nov 20 08:23:35 2019 +0100 +++ b/lib/freebl/gcm.c Wed Nov 20 08:25:39 2019 +0100 @@ -532,8 +532,14 @@ unsigned char tagKey[MAX_BLOCK_SIZE]; PRBool ctr_context_init; gcmIVContext gcm_iv; + unsigned long long gcm_iv_bytes; }; +/* NIST SP-800-38D limits the use of GCM with a single IV to 2^39 - 256 + * bits which translates to 2^32 - 2 128bit blocks or 2^36 - 32 bytes + */ +#define MAX_GCM_BYTES_PER_IV ((1ULL << 36) - 32) + SECStatus gcm_InitCounter(GCMContext *gcm, const unsigned char *iv, unsigned int ivLen, unsigned int tagBits, const unsigned char *aad, unsigned int aadLen); @@ -669,6 +675,8 @@ goto loser; } + gcm->gcm_iv_bytes = MAX_GCM_BYTES_PER_IV; + /* finally mix in the AAD data */ rv = gcmHash_Reset(ghash, aad, aadLen); if (rv != SECSuccess) { @@ -766,6 +774,13 @@ return SECFailure; } + /* bail out if this invocation requests processing more than what is + * considered to be a safe limit */ + if (gcm->gcm_iv_bytes < (unsigned long long)inlen) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + return SECFailure; + } + tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE; if (UINT_MAX - inlen < tagBytes) { PORT_SetError(SEC_ERROR_INPUT_LEN); @@ -794,6 +809,7 @@ *outlen = 0; return SECFailure; }; + gcm->gcm_iv_bytes -= inlen; *outlen += len; return SECSuccess; } ++++++ nss-fips-pairwise-consistency-check.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1574138371 -3600 # Tue Nov 19 05:39:31 2019 +0100 # Node ID 557f9009507c9e70941dbe39965028049e1ef5a2 # Parent 4ae6bed68a83c01f6d2ce7a37bdb0bdb0556416f [PATCH 07/22] 15 >From 2a162c34b7aad7399f33069cd9930fd92714861c Mon Sep 17 00:00:00 2001 --- nss/lib/softoken/pkcs11c.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c --- a/lib/softoken/pkcs11c.c +++ b/lib/softoken/pkcs11c.c @@ -4730,8 +4730,8 @@ return crv; } -#define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */ -#define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ +#define PAIRWISE_DIGEST_LENGTH SHA224_LENGTH /* 224-bits */ +#define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ /* * FIPS 140-2 pairwise consistency check utilized to validate key pair. @@ -5591,6 +5591,7 @@ (PRUint32)crv); sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg); } + sftk_fatalError = PR_TRUE; } } ++++++ nss-fips-rsa-keygen-strictness.patch ++++++ # HG changeset patch # User M. Sirringhaus <[email protected]> # Date 1584305670 -3600 # Sun Mar 15 21:54:30 2020 +0100 # Node ID 2f570c6952d8edfc1ad9061cd3830f202eec1960 # Parent 557f9009507c9e70941dbe39965028049e1ef5a2 commit 4b8c0eac6b092717157b4141c82b4d76ccdc91b3 Author: Hans Petter Jansson <[email protected]> Patch 16: nss-fips-rsa-keygen-strictness.patch diff --git a/lib/freebl/mpi/mpprime.c b/lib/freebl/mpi/mpprime.c --- a/lib/freebl/mpi/mpprime.c +++ b/lib/freebl/mpi/mpprime.c @@ -14,6 +14,8 @@ #include <stdlib.h> #include <string.h> +#include "../fips.h" + #define SMALL_TABLE 0 /* determines size of hard-wired prime table */ #define RANDOM() rand() @@ -451,6 +453,25 @@ } else num_tests = 50; + /* FIPS 186-4 mandates more M-R tests for probable primes generation - make + * sure the minimums are observed (see Appendix C, tables C.1 and C.2). + * For DSA this is handled in pqg_ParamGen() through the use of + * prime_testcount_p() and prime_testcount_q() respectively. + * For RSA this unfortunately seems to be the right place to prevent larger + * code changes. On the other hand, it seems to generally speed things up, + * since there are measurably less errors while calculating inverse modulo in + * rsa_build_from_primes(). + */ + if (FIPS_mode()) { + if (nBits >= 1536) + i = 4; + else + i = 5; + if (i > num_tests) + num_tests = i; + i = 0; + } + if (strong) --nBits; MP_CHECKOK(mpl_set_bit(start, nBits - 1, 1)); diff --git a/lib/freebl/rsa.c b/lib/freebl/rsa.c --- a/lib/freebl/rsa.c +++ b/lib/freebl/rsa.c @@ -16,11 +16,13 @@ #include "prinit.h" #include "blapi.h" #include "mpi.h" +#include "mpi-priv.h" #include "mpprime.h" #include "mplogic.h" #include "secmpi.h" #include "secitem.h" #include "blapii.h" +#include "fips.h" /* ** Number of times to attempt to generate a prime (p or q) from a random @@ -143,11 +145,24 @@ err = mp_invmod(d, &phi, e); } else { err = mp_invmod(e, &phi, d); - } + /* FIPS 186-4 (B.3.1.3.a) places additional requirements on the + * private exponent d: + * 2^(n/2) < d < lcm(p-1, q-1) = phi + */ + if (FIPS_mode() && (MP_OKAY == err)) { + CHECK_MPI_OK( mp_2expt(&tmp, keySizeInBits / 2) ); + if ((mp_cmp(d, &tmp) <= 0) || (mp_cmp(d, &phi) >= 0)) { + /* new set of p, q is needed for another calculation of d */ + err = MP_UNDEF; + } + } + } } else { err = MP_OKAY; } - /* Verify that phi(n) and e have no common divisors */ + /* Verify that phi(n) and e have no common divisors + * This is also the coprimality constraint from FIPS 186-4 (B.3.1.2.a) + */ if (err != MP_OKAY) { if (err == MP_UNDEF) { PORT_SetError(SEC_ERROR_NEED_RANDOM); @@ -280,10 +295,12 @@ mp_int q = { 0, 0, 0, NULL }; mp_int e = { 0, 0, 0, NULL }; mp_int d = { 0, 0, 0, NULL }; + mp_int u = { 0, 0, 0, NULL }; + mp_int v = { 0, 0, 0, NULL }; int kiter; int max_attempts; mp_err err = MP_OKAY; - SECStatus rv = SECSuccess; + SECStatus rv = SECFailure; int prerr = 0; RSAPrivateKey *key = NULL; PLArenaPool *arena = NULL; @@ -301,11 +318,40 @@ PORT_SetError(SEC_ERROR_INVALID_ARGS); goto cleanup; } + + MP_DIGITS(&p) = 0; + MP_DIGITS(&q) = 0; + MP_DIGITS(&d) = 0; + MP_DIGITS(&u) = 0; + MP_DIGITS(&v) = 0; + CHECK_MPI_OK(mp_init(&p)); + CHECK_MPI_OK(mp_init(&q)); + CHECK_MPI_OK(mp_init(&d)); + CHECK_MPI_OK(mp_init(&u)); + CHECK_MPI_OK(mp_init(&v)); + #ifndef NSS_FIPS_DISABLED - /* Check that the exponent is not smaller than 65537 */ - if (mp_cmp_d(&e, 0x10001) < 0) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - goto cleanup; + if (FIPS_mode()) { + /* Check that the exponent is not smaller than 65537 */ + if (mp_cmp_d(&e, 0x10001) < 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto cleanup; + } + + /* FIPS 186-4 requires 2^16 < e < 2^256 (B.3.1.1.b) */ + CHECK_MPI_OK( mp_2expt(&v, 256) ); + if (!(mp_cmp(&e, &v) < 0 )) { + err = MP_BADARG; + goto cleanup; + } + + /* FIPS 186-4 mandates keys to be either 2048, 3072 or 4096 bits long. + * We also allow a key length of 4096, since this is needed in order to + * pass the CAVS RSA SigGen test. */ + if (keySizeInBits < 2048) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto cleanup; + } } #endif @@ -323,12 +369,7 @@ key->arena = arena; /* length of primes p and q (in bytes) */ primeLen = keySizeInBits / (2 * PR_BITS_PER_BYTE); - MP_DIGITS(&p) = 0; - MP_DIGITS(&q) = 0; - MP_DIGITS(&d) = 0; - CHECK_MPI_OK(mp_init(&p)); - CHECK_MPI_OK(mp_init(&q)); - CHECK_MPI_OK(mp_init(&d)); + /* 3. Set the version number (PKCS1 v1.5 says it should be zero) */ SECITEM_AllocItem(arena, &key->version, 1); key->version.data[0] = 0; @@ -339,13 +380,64 @@ PORT_SetError(0); CHECK_SEC_OK(generate_prime(&p, primeLen)); CHECK_SEC_OK(generate_prime(&q, primeLen)); - /* Assure p > q */ + /* Assure p >= q */ /* NOTE: PKCS #1 does not require p > q, and NSS doesn't use any * implementation optimization that requires p > q. We can remove * this code in the future. */ if (mp_cmp(&p, &q) < 0) mp_exch(&p, &q); + + /* FIPS 186-4 puts additional requirements on the primes (B.3.1.2.a-d) + * (n = key bit length): + * 1) both (p-1) and (q-1) are coprime to e (B.3.1.2.a), i.e.: + * gcd(p-1,e) = 1, gcd(q-1,e) = 1 + * this is ensured in rsa_build_from_primes(), where + * phi = lcm(p-1)(q-1) is tested for coprimality to e + * 2) magnitude constraint (B.3.1.2.b and B.3.1.2.c): + * both p and q are from open the interval + * I = ( sqrt(2) * 2^(n/2 - 1) , 2^(n/2 - 1) ) + * 3) minimum distance (B.3.1.2.d): abs(p-q) > 2 ^ (n/2 - 100) + */ + if (FIPS_mode()) { + /* 2 */ + /* in order not to constrain the selection too much, + * expand the inequality: + * x > 2^(1/2) * 2^(n/2 - 1) + * = 2^(1/2 + k) * 2^(n/2 - k - 1) + * = y(k) * r(k) + * for z(k) >= y(k) it clearly holds: + * x > z(k) * r(k) + * one suitable z(k) such that z(k)/y(k) - 1 = o(1) is + * ceil(y(k)) for big-enough k + * ceil(y(30))/y(30) - 1 < 10^-10, so lets use that + * 2^30.5 = 1518500249.98802484622388101120... + * the magic constant is thus z(30) = 1518500250 < 2^31 + * + * Additionally, since p >= q is required above, the + * condtitions can be shortened to: + * 1518500250 * 2^(n/2 - 31) = v < q + * p < u = 2^(n/2 - 1) + */ + CHECK_MPI_OK( mp_2expt(&u, keySizeInBits / 2 - 31) ); + CHECK_MPI_OK( mp_mul_d(&u, 1518500250, &v) ); + CHECK_MPI_OK( mp_2expt(&u, keySizeInBits / 2) ); + if ((mp_cmp(&q, &v) <= 0) || (mp_cmp(&p, &u) >= 0)) { + prerr = SEC_ERROR_NEED_RANDOM; /* retry with different values */ + kiter++; + continue; + } + /* 3 */ + CHECK_MPI_OK( mp_sub(&p, &q, &u) ); + CHECK_MPI_OK( mp_abs(&u, &u) ); + CHECK_MPI_OK( mp_2expt(&v, keySizeInBits / 2 - 100) ); + if (mp_cmp(&u, &v) < 0) { + prerr = SEC_ERROR_NEED_RANDOM; /* retry with different values */ + kiter++; + continue; + } + } + /* Attempt to use these primes to generate a key */ rv = rsa_build_from_primes(&p, &q, &e, PR_FALSE, /* needPublicExponent=false */ @@ -368,7 +460,9 @@ mp_clear(&q); mp_clear(&e); mp_clear(&d); - if (err) { + mp_clear(&u); + mp_clear(&v); + if (err != MP_OKAY) { MP_TO_SEC_ERROR(err); rv = SECFailure; } ++++++ nss-fips-tls-allow-md5-prf.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1574240734 -3600 # Wed Nov 20 10:05:34 2019 +0100 # Node ID 0efca22bbafd7575b20461f255c46157c9321822 # Parent 3a2cb65dc157344cdad19e8e16e9c33e36f82d96 [PATCH] 30 >From ca3b695ac461eccf4ed97e1b3fe0a311c80a792f Mon Sep 17 00:00:00 2001 --- nss/lib/freebl/md5.c | 67 ++++++++++++++++++++++++++------------ nss/lib/freebl/rawhash.c | 37 +++++++++++++++++++++ nss/lib/freebl/tlsprfalg.c | 5 ++- nss/lib/softoken/pkcs11c.c | 4 +-- 4 files changed, 90 insertions(+), 23 deletions(-) diff --git a/lib/freebl/md5.c b/lib/freebl/md5.c --- a/lib/freebl/md5.c +++ b/lib/freebl/md5.c @@ -217,13 +217,11 @@ } MD5Context * -MD5_NewContext(void) +MD5_NewContext_NonFIPS(void) { /* no need to ZAlloc, MD5_Begin will init the context */ MD5Context *cx; - IN_FIPS_RETURN(NULL); - cx = (MD5Context *)PORT_Alloc(sizeof(MD5Context)); if (cx == NULL) { PORT_SetError(PR_OUT_OF_MEMORY_ERROR); @@ -232,6 +230,13 @@ return cx; } +MD5Context * +MD5_NewContext(void) +{ + IN_FIPS_RETURN(NULL); + return MD5_NewContext_NonFIPS(); +} + void MD5_DestroyContext(MD5Context *cx, PRBool freeit) { @@ -243,10 +248,8 @@ } void -MD5_Begin(MD5Context *cx) +MD5_Begin_NonFIPS(MD5Context *cx) { - IN_FIPS_RETURN(); - cx->lsbInput = 0; cx->msbInput = 0; /* memset(cx->inBuf, 0, sizeof(cx->inBuf)); */ @@ -256,6 +259,13 @@ cx->cv[3] = CV0_4; } +void +MD5_Begin(MD5Context *cx) +{ + IN_FIPS_RETURN(); + MD5_Begin_NonFIPS(cx); +} + #define cls(i32, s) (tmp = i32, tmp << s | tmp >> (32 - s)) #if defined(SOLARIS) || defined(HPUX) @@ -431,14 +441,12 @@ } void -MD5_Update(MD5Context *cx, const unsigned char *input, unsigned int inputLen) +MD5_Update_NonFIPS(MD5Context *cx, const unsigned char *input, unsigned int inputLen) { PRUint32 bytesToConsume; PRUint32 inBufIndex = cx->lsbInput & 63; const PRUint32 *wBuf; - IN_FIPS_RETURN(); - /* Add the number of input bytes to the 64-bit input counter. */ addto64(cx->msbInput, cx->lsbInput, inputLen); if (inBufIndex) { @@ -487,6 +495,13 @@ memcpy(cx->inBuf, input, inputLen); } +void +MD5_Update(MD5Context *cx, const unsigned char *input, unsigned int inputLen) +{ + IN_FIPS_RETURN(); + MD5_Update_NonFIPS(cx, input, inputLen); +} + static const unsigned char padbytes[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -503,8 +518,8 @@ }; void -MD5_End(MD5Context *cx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen) +MD5_End_NonFIPS(MD5Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) { #ifndef IS_LITTLE_ENDIAN PRUint32 tmp; @@ -512,8 +527,6 @@ PRUint32 lowInput, highInput; PRUint32 inBufIndex = cx->lsbInput & 63; - IN_FIPS_RETURN(); - if (maxDigestLen < MD5_HASH_LEN) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return; @@ -525,10 +538,10 @@ lowInput <<= 3; if (inBufIndex < MD5_END_BUFFER) { - MD5_Update(cx, padbytes, MD5_END_BUFFER - inBufIndex); + MD5_Update_NonFIPS(cx, padbytes, MD5_END_BUFFER - inBufIndex); } else { - MD5_Update(cx, padbytes, - MD5_END_BUFFER + MD5_BUFFER_SIZE - inBufIndex); + MD5_Update_NonFIPS(cx, padbytes, + MD5_END_BUFFER + MD5_BUFFER_SIZE - inBufIndex); } /* Store the number of bytes input (before padding) in final 64 bits. */ @@ -554,16 +567,22 @@ } void -MD5_EndRaw(MD5Context *cx, unsigned char *digest, - unsigned int *digestLen, unsigned int maxDigestLen) +MD5_End(MD5Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) +{ + IN_FIPS_RETURN(); + MD5_End_NonFIPS(cx, digest, digestLen, maxDigestLen); +} + +void +MD5_EndRaw_NonFIPS(MD5Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) { #ifndef IS_LITTLE_ENDIAN PRUint32 tmp; #endif PRUint32 cv[4]; - IN_FIPS_RETURN(); - if (maxDigestLen < MD5_HASH_LEN) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return; @@ -581,6 +600,14 @@ *digestLen = MD5_HASH_LEN; } +void +MD5_EndRaw(MD5Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) +{ + IN_FIPS_RETURN(); + MD5_EndRaw_NonFIPS(cx, digest, digestLen, maxDigestLen); +} + unsigned int MD5_FlattenSize(MD5Context *cx) { diff --git a/lib/freebl/rawhash.c b/lib/freebl/rawhash.c --- a/lib/freebl/rawhash.c +++ b/lib/freebl/rawhash.c @@ -154,3 +154,40 @@ } return &SECRawHashObjects[hashType]; } + +/* Defined in md5.c */ + +MD5Context *MD5_NewContext_NonFIPS(void); +void MD5_Begin_NonFIPS(MD5Context *cx); +void MD5_Update_NonFIPS(MD5Context *cx, const unsigned char *input, unsigned int inputLen); +void MD5_End_NonFIPS(MD5Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); +void MD5_EndRaw_NonFIPS(MD5Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); + +static const SECHashObject SECRawHashObjectMD5NonFIPS = { + MD5_LENGTH, + (void *(*)(void))MD5_NewContext_NonFIPS, + (void *(*)(void *))null_hash_clone_context, + (void (*)(void *, PRBool))MD5_DestroyContext, + (void (*)(void *))MD5_Begin_NonFIPS, + (void (*)(void *, const unsigned char *, unsigned int))MD5_Update_NonFIPS, + (void (*)(void *, unsigned char *, unsigned int *, unsigned int))MD5_End_NonFIPS, + MD5_BLOCK_LENGTH, + HASH_AlgMD5, + (void (*)(void *, unsigned char *, unsigned int *, unsigned int))MD5_EndRaw_NonFIPS +}; + +const SECHashObject * +HASH_GetRawHashObjectNonFIPS(HASH_HashType hashType) +{ + if (hashType <= HASH_AlgNULL || hashType >= HASH_AlgTOTAL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } + + if (hashType == HASH_AlgMD5) + return &SECRawHashObjectMD5NonFIPS; + + return &SECRawHashObjects[hashType]; +} diff --git a/lib/freebl/tlsprfalg.c b/lib/freebl/tlsprfalg.c --- a/lib/freebl/tlsprfalg.c +++ b/lib/freebl/tlsprfalg.c @@ -12,6 +12,9 @@ #include "hasht.h" #include "alghmac.h" +/* To get valid MD5 object in FIPS mode */ +const SECHashObject *HASH_GetRawHashObjectNonFIPS(HASH_HashType hashType); + #define PHASH_STATE_MAX_LEN HASH_LENGTH_MAX /* TLS P_hash function */ @@ -27,7 +30,7 @@ SECStatus status; HMACContext *cx; SECStatus rv = SECFailure; - const SECHashObject *hashObj = HASH_GetRawHashObject(hashType); + const SECHashObject *hashObj = HASH_GetRawHashObjectNonFIPS(hashType); PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len)); PORT_Assert((seed != NULL) && (seed->data != NULL)); diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c --- a/lib/softoken/pkcs11c.c +++ b/lib/softoken/pkcs11c.c @@ -6953,7 +6953,7 @@ SFTKAttribute *att2 = NULL; unsigned char *buf; SHA1Context *sha; - MD5Context *md5; + MD5Context *md5 = NULL; MD2Context *md2; CK_ULONG macSize; CK_ULONG tmpKeySize; @@ -7484,7 +7484,7 @@ } sftk_FreeAttribute(att2); md5 = MD5_NewContext(); - if (md5 == NULL) { + if (md5 == NULL && !isTLS) { crv = CKR_HOST_MEMORY; break; } ++++++ nss-fips-use-getrandom.patch ++++++ # HG changeset patch # User M. Sirringhaus <[email protected]> # Date 1574137588 -3600 # Tue Nov 19 05:26:28 2019 +0100 # Node ID 5e191a391c38967e49a1d005800713ccd1010b09 # Parent 92da25f8ea7d41e938858872e2b6a2fb1aa53bb2 commit c2a88344b616c75b1873fb163491d7362a4c3e5b Author: Hans Petter Jansson <[email protected]> 11 diff --git a/coreconf/Linux.mk b/coreconf/Linux.mk --- a/coreconf/Linux.mk +++ b/coreconf/Linux.mk @@ -184,6 +184,18 @@ LDFLAGS += -Wl,-z,relro endif +# +# On Linux 3.17 or later, use getrandom() to obtain entropy where possible. +# Set NSS_USE_GETRANDOM to 0 in the environment to override this. +# +ifneq ($(OS_TARGET),Android) +ifeq (3.17,$(firstword $(sort 3.17 $(OS_RELEASE)))) +ifneq ($(NSS_USE_GETRANDOM),0) + DEFINES += -DNSS_USE_GETRANDOM +endif +endif +endif + USE_SYSTEM_ZLIB = 1 ZLIB_LIBS = -lz diff --git a/lib/freebl/unix_rand.c b/lib/freebl/unix_rand.c --- a/lib/freebl/unix_rand.c +++ b/lib/freebl/unix_rand.c @@ -13,6 +13,10 @@ #include <sys/wait.h> #include <sys/stat.h> #include <sys/types.h> +#ifdef NSS_USE_GETRANDOM +# include <sys/syscall.h> +# include <linux/random.h> +#endif #include <dirent.h> #include "secrng.h" #include "secerr.h" @@ -21,6 +25,43 @@ #include "prprf.h" #include "prenv.h" +#ifdef NSS_USE_GETRANDOM +# ifndef __NR_getrandom +# if defined __x86_64__ +# define __NR_getrandom 318 +# elif defined(__i386__) +# define __NR_getrandom 355 +# elif defined(__arm__) +# define __NR_getrandom 384 +# elif defined(__aarch64__) +# define __NR_getrandom 278 +# elif defined(__ia64__) +# define __NR_getrandom 1339 +# elif defined(__m68k__) +# define __NR_getrandom 352 +# elif defined(__s390x__) +# define __NR_getrandom 349 +# elif defined(__powerpc__) +# define __NR_getrandom 359 +# elif defined _MIPS_SIM +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define __NR_getrandom 4353 +# endif +# if _MIPS_SIM == _MIPS_SIM_NABI32 +# define __NR_getrandom 6317 +# endif +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define __NR_getrandom 5313 +# endif +# else +# warning "__NR_getrandom unknown for your architecture" +# endif +# endif +# ifndef GRND_RANDOM +# define GRND_RANDOM 0x02 +# endif +#endif + size_t RNG_FileUpdate(const char *fileName, size_t limit); /* @@ -862,6 +903,26 @@ size_t RNG_SystemRNG(void *dest, size_t maxLen) { +#ifdef NSS_USE_GETRANDOM + unsigned char *buf = dest; + size_t inBytes = 0; + int ret; + + do { + ret = syscall(__NR_getrandom, buf + inBytes, maxLen - inBytes, 0); + + if (0 < ret) + inBytes += ret; + } while ((0 < ret || EINTR == errno || ERESTART == errno) + && inBytes < maxLen); + + if (inBytes != maxLen) { + PORT_SetError(SEC_ERROR_NEED_RANDOM); /* system RNG failed */ + inBytes = 0; + } + + return inBytes; +#else FILE *file; int fd; int bytes; @@ -895,4 +956,5 @@ fileBytes = 0; } return fileBytes; +#endif } ++++++ nss-fips-use-strong-random-pool.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1574240799 -3600 # Wed Nov 20 10:06:39 2019 +0100 # Node ID 4ddd7d49eeed4ea32850daf41a472ccb50dee45e # Parent 0efca22bbafd7575b20461f255c46157c9321822 [PATCH] 31 >From a7cbf64ba8ac07a4a1fdea91f39da56d86af03bf Mon Sep 17 00:00:00 2001 --- nss/lib/freebl/unix_rand.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/freebl/unix_rand.c b/lib/freebl/unix_rand.c --- a/lib/freebl/unix_rand.c +++ b/lib/freebl/unix_rand.c @@ -24,6 +24,7 @@ #include "prthread.h" #include "prprf.h" #include "prenv.h" +#include "fips.h" #ifdef NSS_USE_GETRANDOM # ifndef __NR_getrandom @@ -779,7 +780,7 @@ } /* grab some data from system's PRNG before any other files. */ - bytes = RNG_FileUpdate("/dev/urandom", SYSTEM_RNG_SEED_COUNT); + bytes = RNG_FileUpdate(FIPS_mode() ? "/dev/random" : "/dev/urandom", SYSTEM_RNG_SEED_COUNT); if (!bytes) { PORT_SetError(SEC_ERROR_NEED_RANDOM); } @@ -909,7 +910,8 @@ int ret; do { - ret = syscall(__NR_getrandom, buf + inBytes, maxLen - inBytes, 0); + ret = syscall(__NR_getrandom, buf + inBytes, maxLen - inBytes, + FIPS_mode () ? GRND_RANDOM : 0); if (0 < ret) inBytes += ret; @@ -929,7 +931,7 @@ size_t fileBytes = 0; unsigned char *buffer = dest; - file = fopen("/dev/urandom", "r"); + file = fopen(FIPS_mode() ? "/dev/random" : "/dev/urandom", "r"); if (file == NULL) { PORT_SetError(SEC_ERROR_NEED_RANDOM); return 0; ++++++ nss-fips-zeroization.patch ++++++ # HG changeset patch # User Hans Petter Jansson <[email protected]> # Date 1574240665 -3600 # Wed Nov 20 10:04:25 2019 +0100 # Node ID 3a2cb65dc157344cdad19e8e16e9c33e36f82d96 # Parent 2d4483f4a1259f965f32ff4c65436e92aef83be7 [PATCH 07/10] 29 >From 76da775313bd40a1353a9d2f6cc43ebe1a287574 Mon Sep 17 00:00:00 2001 --- nss/lib/freebl/aeskeywrap.c | 1 + nss/lib/freebl/cts.c | 18 +++++++++------ nss/lib/freebl/dh.c | 4 ++++ nss/lib/freebl/ec.c | 2 +- nss/lib/freebl/gcm.c | 45 +++++++++++++++++++++++++++++++++---- 5 files changed, 58 insertions(+), 12 deletions(-) diff --git a/lib/freebl/aeskeywrap.c b/lib/freebl/aeskeywrap.c --- a/lib/freebl/aeskeywrap.c +++ b/lib/freebl/aeskeywrap.c @@ -102,6 +102,7 @@ { if (cx) { AES_DestroyContext(&cx->aescx, PR_FALSE); + memset(cx->iv, 0, sizeof (cx->iv)); /* memset(cx, 0, sizeof *cx); */ if (freeit) { PORT_Free(cx->mem); diff --git a/lib/freebl/cts.c b/lib/freebl/cts.c --- a/lib/freebl/cts.c +++ b/lib/freebl/cts.c @@ -37,6 +37,7 @@ void CTS_DestroyContext(CTSContext *cts, PRBool freeit) { + PORT_Memset(cts, 0, sizeof(CTSContext)); if (freeit) { PORT_Free(cts); } @@ -135,7 +136,7 @@ PORT_Memset(lastBlock + inlen, 0, blocksize - inlen); rv = (*cts->cipher)(cts->context, outbuf, &tmp, maxout, lastBlock, blocksize, blocksize); - PORT_Memset(lastBlock, 0, blocksize); + PORT_Memset(lastBlock, 0, MAX_BLOCK_SIZE); if (rv == SECSuccess) { *outlen = written + blocksize; } else { @@ -230,13 +231,15 @@ rv = (*cts->cipher)(cts->context, outbuf, outlen, maxout, inbuf, fullblocks, blocksize); if (rv != SECSuccess) { - return SECFailure; + rv = SECFailure; + goto cleanup; } *outlen = fullblocks; /* AES low level doesn't set outlen */ inbuf += fullblocks; inlen -= fullblocks; if (inlen == 0) { - return SECSuccess; + rv = SECSuccess; + goto cleanup; } outbuf += fullblocks; @@ -280,9 +283,9 @@ rv = (*cts->cipher)(cts->context, Pn, &tmpLen, blocksize, lastBlock, blocksize, blocksize); if (rv != SECSuccess) { - PORT_Memset(lastBlock, 0, blocksize); PORT_Memset(saveout, 0, *outlen); - return SECFailure; + rv = SECFailure; + goto cleanup; } /* make up for the out of order CBC decryption */ XOR_BLOCK(Pn, Cn_2, blocksize); @@ -297,7 +300,8 @@ /* clear last block. At this point last block contains Pn xor Cn_1 xor * Cn_2, both of with an attacker would know, so we need to clear this * buffer out */ - PORT_Memset(lastBlock, 0, blocksize); +cleanup: + PORT_Memset(lastBlock, 0, MAX_BLOCK_SIZE); /* Cn, Cn_1, and Cn_2 have encrypted data, so no need to clear them */ - return SECSuccess; + return rv; } diff --git a/lib/freebl/dh.c b/lib/freebl/dh.c --- a/lib/freebl/dh.c +++ b/lib/freebl/dh.c @@ -192,6 +192,10 @@ rv = SECFailure; } if (rv) { + SECITEM_ZfreeItem(&key->prime, PR_FALSE); + SECITEM_ZfreeItem(&key->base, PR_FALSE); + SECITEM_ZfreeItem(&key->publicValue, PR_FALSE); + SECITEM_ZfreeItem(&key->privateValue, PR_FALSE); *privKey = NULL; PORT_FreeArena(arena, PR_TRUE); } diff --git a/lib/freebl/ec.c b/lib/freebl/ec.c --- a/lib/freebl/ec.c +++ b/lib/freebl/ec.c @@ -958,7 +958,7 @@ ECParams *ecParams = NULL; SECItem pointC = { siBuffer, NULL, 0 }; int slen; /* length in bytes of a half signature (r or s) */ - int flen; /* length in bytes of the field size */ + int flen = 0; /* length in bytes of the field size */ unsigned olen; /* length in bytes of the base point order */ unsigned obits; /* length in bits of the base point order */ diff --git a/lib/freebl/gcm.c b/lib/freebl/gcm.c --- a/lib/freebl/gcm.c +++ b/lib/freebl/gcm.c @@ -162,6 +162,9 @@ *r_high = (uint64_t)(r >> 64); *r_low = (uint64_t)r; + + /* Zeroization */ + x1 = x2 = x3 = x4 = x5 = y1 = y2 = y3 = y4 = y5 = r = z = 0; } SECStatus @@ -200,6 +203,12 @@ } ghash->x_low = ci_low; ghash->x_high = ci_high; + + /* Zeroization */ + ci_low = ci_high = z2_low = z2_high = z0_low = z0_high = z1a_low = z1a_high = 0; + z_low = z_high = 0; + i = 0; + return SECSuccess; } #else @@ -239,6 +248,10 @@ z = z0 | z1 | z2 | z3; *r_high = (uint32_t)(z >> 32); *r_low = (uint32_t)z; + + /* Zeroization */ + x0 = x1 = x2 = x3 = y0 = y1 = y2 = y3 = 0; + z0 = z1 = z2 = z3 = z = 0; } SECStatus @@ -324,6 +337,20 @@ ghash->x_high = z_high_h; ghash->x_low = z_high_l; } + + /* Zeroization */ + ci_low = ci_high = z_high_h = z_high_l = z_low_h = z_low_l = 0; + + ci_high_h = ci_high_l = ci_low_h = ci_low_l + = b_a_h = b_a_l = a_a_h = a_a_l = b_b_h = b_b_l + = a_b_h = a_b_l = b_c_h = b_c_l = a_c_h = a_c_l = c_c_h = c_c_l + = ci_highXlow_h = ci_highXlow_l = c_a_h = c_a_l = c_b_h = c_b_l + = h_high_h = h_high_l = h_low_h = h_low_l = h_highXlow_h = h_highXlow_l + = h_highX_xored + = 0; + + i = 0; + return SECSuccess; } #endif /* HAVE_INT128_SUPPORT */ @@ -859,11 +886,13 @@ /* verify the block */ rv = gcmHash_Update(gcm->ghash_context, inbuf, inlen); if (rv != SECSuccess) { - return SECFailure; + rv = SECFailure; + goto cleanup; } rv = gcm_GetTag(gcm, tag, &len, AES_BLOCK_SIZE); if (rv != SECSuccess) { - return SECFailure; + rv = SECFailure; + goto cleanup; } /* Don't decrypt if we can't authenticate the encrypted data! * This assumes that if tagBits is not a multiple of 8, intag will @@ -871,10 +900,18 @@ 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)); - return SECFailure; + rv = SECFailure; + goto cleanup; } +cleanup: + tagBytes = 0; PORT_Memset(tag, 0, sizeof(tag)); + intag = NULL; + len = 0; + if (rv != SECSuccess) { + return rv; + } + /* finish the decryption */ return CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout, inbuf, inlen, AES_BLOCK_SIZE); ++++++ nss-fix-dh-pkcs-derive-inverted-logic.patch ++++++ # HG changeset patch # User M. Sirringhaus <[email protected]> # Date 1590586654 -7200 # Wed May 27 15:37:34 2020 +0200 # Node ID 582ed54a5cda147cd5996603d6066817edb687fa # Parent ce99bba6375432c55a73c1367f619dfef7c7e9fc imported patch nss-fix-dh-pkcs-derive-inverted-logic.patch diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c --- a/lib/softoken/pkcs11c.c +++ b/lib/softoken/pkcs11c.c @@ -8316,7 +8316,7 @@ if (crv == CKR_OK) { rv = KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime); PORT_Free(dhSubPrime.data); - if (rv != SECSuccess) { + if (rv == PR_FALSE) { crv = CKR_ARGUMENTS_BAD; PORT_Free(dhPrime.data); PORT_Free(dhValue.data); ++++++ nss-sqlitename.patch ++++++ --- /var/tmp/diff_new_pack.toDILa/_old 2020-06-30 21:53:08.054140428 +0200 +++ /var/tmp/diff_new_pack.toDILa/_new 2020-06-30 21:53:08.054140428 +0200 @@ -1,32 +1,29 @@ # HG changeset patch -# Parent b96f2a8d5f606fd982a8fe3655c4b71e282c3976 +# User M. Sirringhaus <[email protected]> +# Date 1590407652 -7200 +# Mon May 25 13:54:12 2020 +0200 +# Node ID b1d7045b31cf4090c0b78003c77a2eb6c8c57436 +# Parent e3d3ed5e142b172289d9d4a1c7fc63dfd4359410 Index: security/nss/lib/sqlite/manifest.mn =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/sqlite/manifest.mn,v retrieving revision 1.5 -diff --git a/lib/sqlite/manifest.mn b/lib/sqlite/manifest.mn ---- a/lib/sqlite/manifest.mn -+++ b/lib/sqlite/manifest.mn -@@ -1,19 +1,20 @@ - # - # 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 = ../.. +diff -r e3d3ed5e142b -r b1d7045b31cf lib/sqlite/manifest.mn +--- a/lib/sqlite/manifest.mn Mon Sep 18 11:24:00 2017 +0200 ++++ b/lib/sqlite/manifest.mn Mon May 25 13:54:12 2020 +0200 +@@ -6,11 +6,11 @@ MODULE = nss -LIBRARY_NAME = sqlite +LIBRARY_NAME = nsssqlite LIBRARY_VERSION = 3 - MAPFILE = $(OBJDIR)/sqlite.def +-MAPFILE = $(OBJDIR)/$(LIBRARY_NAME).def ++MAPFILE = $(OBJDIR)/sqlite.def + RES = $(NULL) +- +MAPFILE_SOURCE = sqlite.def DEFINES += -DSQLITE_THREADSAFE=1 - EXPORTS = \ - $(NULL) - PRIVATE_EXPORTS = \ - sqlite3.h \ - $(NULL) ++++++ ppc-old-abi-v3.patch ++++++ >From a7a862bab5e4aae4615ddae3cbe230345f92ed0d Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <[email protected]> Date: Mon, 1 Jun 2020 12:11:45 +0300 Subject: [PATCH v3] Bug 1642174 /usr/bin/ld: OBJS/Linux_SINGLE_SHLIB/sha512-p8.o: ABI version 2 is not compatible with ABI version 1 output Don't try to build the SHA-2 accelerated asm on old-ABI ppc. Currently make only, I don't have enough gyp-fu to do that side. However, the reporters of 1642174 and 1635625 both used make, not gyp. Signed-off-by: Lauri Kasanen <[email protected]> --- lib/freebl/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/freebl/Makefile b/lib/freebl/Makefile index 5f7384429..e0461c7d3 100644 --- a/lib/freebl/Makefile +++ b/lib/freebl/Makefile @@ -267,9 +267,12 @@ ifeq ($(CPU_ARCH),arm) endif ifeq ($(CPU_ARCH),ppc) EXTRA_SRCS += gcm-ppc.c - ASFILES += sha512-p8.s ifdef USE_64 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 + endif endif # USE_64 endif # ppc endif # Linux -- 2.19.1 ++++++ system-nspr.patch ++++++ --- /var/tmp/diff_new_pack.toDILa/_old 2020-06-30 21:53:08.094140552 +0200 +++ /var/tmp/diff_new_pack.toDILa/_new 2020-06-30 21:53:08.094140552 +0200 @@ -1,25 +1,17 @@ -# HG changeset patch -# Parent bbf8e741ac966df6cf513ea042d1351eb279c122 - diff --git a/Makefile b/Makefile +index eb4ed1a..de9c13d 100644 --- a/Makefile +++ b/Makefile -@@ -42,17 +42,17 @@ include $(CORE_DEPTH)/coreconf/rules.mk +@@ -48,12 +48,10 @@ include $(CORE_DEPTH)/coreconf/rules.mk ####################################################################### - - - ####################################################################### - # (7) Execute "local" rules. (OPTIONAL). # - ####################################################################### - --nss_build_all: build_nspr all latest -+nss_build_all: all latest - - nss_clean_all: clobber_nspr clobber + nss_build_all: +- $(MAKE) build_nspr + $(MAKE) all + $(MAKE) latest + + nss_clean_all: +- $(MAKE) clobber_nspr + $(MAKE) clobber NSPR_CONFIG_STATUS = $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)/config.status - NSPR_CONFIGURE = $(CORE_DEPTH)/../nspr/configure - - # - # Translate coreconf build options to NSPR configure options.
