From 35803579ef863e4b28bbe6a5948aca0f2fbc2185 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: May 14 2018 13:02:13 +0000 Subject: import nss-softokn-3.36.0-5.el7_5 --- diff --git a/.gitignore b/.gitignore index 1760934..afa7d16 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/nss-softokn-3.34.0.tar.gz +SOURCES/nss-softokn-3.36.0.tar.gz diff --git a/.nss-softokn.metadata b/.nss-softokn.metadata index 5f27f1b..6b16009 100644 --- a/.nss-softokn.metadata +++ b/.nss-softokn.metadata @@ -1 +1 @@ -185931ac63238c24c36369863495110450f2ee0e SOURCES/nss-softokn-3.34.0.tar.gz +96e5512e1f34b79f65989abb10d45afc0f249f7e SOURCES/nss-softokn-3.36.0.tar.gz diff --git a/SOURCES/nss-softokn-3.16-add_encrypt_derive.patch b/SOURCES/nss-softokn-3.16-add_encrypt_derive.patch index be37be3..b6ba1d7 100644 --- a/SOURCES/nss-softokn-3.16-add_encrypt_derive.patch +++ b/SOURCES/nss-softokn-3.16-add_encrypt_derive.patch @@ -1,265 +1,59 @@ diff -up nss/lib/softoken/pkcs11.c.add_encrypt_derive nss/lib/softoken/pkcs11.c ---- nss/lib/softoken/pkcs11.c.add_encrypt_derive 2017-10-30 10:38:09.000000000 +0100 -+++ nss/lib/softoken/pkcs11.c 2017-11-03 14:15:03.648179954 +0100 -@@ -421,11 +421,22 @@ static const struct mechanismList mechan - #endif - /* --------------------- Secret Key Operations ------------------------ */ - { CKM_GENERIC_SECRET_KEY_GEN, { 1, 32, CKF_GENERATE }, PR_TRUE }, -- { CKM_CONCATENATE_BASE_AND_KEY, { 1, 32, CKF_GENERATE }, PR_FALSE }, -- { CKM_CONCATENATE_BASE_AND_DATA, { 1, 32, CKF_GENERATE }, PR_FALSE }, -- { CKM_CONCATENATE_DATA_AND_BASE, { 1, 32, CKF_GENERATE }, PR_FALSE }, -- { CKM_XOR_BASE_AND_DATA, { 1, 32, CKF_GENERATE }, PR_FALSE }, -+ { CKM_CONCATENATE_BASE_AND_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_CONCATENATE_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_CONCATENATE_DATA_AND_BASE, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_XOR_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, +--- nss/lib/softoken/pkcs11.c.add_encrypt_derive 2018-02-27 15:47:47.000000000 +0100 ++++ nss/lib/softoken/pkcs11.c 2018-03-01 16:01:05.853165433 +0100 +@@ -426,6 +426,8 @@ static const struct mechanismList mechan + { CKM_CONCATENATE_DATA_AND_BASE, { 1, 32, CKF_DERIVE }, PR_FALSE }, + { CKM_XOR_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, { CKM_EXTRACT_KEY_FROM_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_EXTRACT_KEY_FROM_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE }, + { CKM_DES_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, + { CKM_DES_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_DES3_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_DES3_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_AES_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_AES_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_CAMELLIA_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_CAMELLIA_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_SEED_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, -+ { CKM_SEED_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, - /* ---------------------- SSL Key Derivations ------------------------- */ - { CKM_SSL3_PRE_MASTER_KEY_GEN, { 48, 48, CKF_GENERATE }, PR_FALSE }, - { CKM_SSL3_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE }, + { CKM_DES3_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, + { CKM_DES3_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, + { CKM_AES_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE }, diff -up nss/lib/softoken/pkcs11c.c.add_encrypt_derive nss/lib/softoken/pkcs11c.c ---- nss/lib/softoken/pkcs11c.c.add_encrypt_derive 2017-10-30 10:38:09.000000000 +0100 -+++ nss/lib/softoken/pkcs11c.c 2017-11-03 14:19:35.665109757 +0100 -@@ -6242,6 +6242,44 @@ sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_UL - } - - /* -+ * Handle The derive from a block encryption cipher -+ */ -+CK_RV -+sftk_DeriveEncrypt(SFTKObject *key, CK_ULONG keySize, void *cipherInfo, -+ int blockSize, unsigned char *data, CK_ULONG len, SFTKCipher encrypt) -+{ -+ unsigned char *tmpdata = NULL; -+ SECStatus rv; -+ unsigned int outLen; -+ CK_RV crv; -+ -+ if ((len % blockSize) != 0) { -+ return CKR_MECHANISM_PARAM_INVALID; -+ } -+ if (keySize && (len < keySize)) { -+ return CKR_MECHANISM_PARAM_INVALID; -+ } -+ if (keySize == 0) { -+ keySize = len; -+ } -+ -+ tmpdata = PORT_Alloc(len); -+ if (tmpdata == NULL) { -+ return CKR_HOST_MEMORY; -+ } -+ rv = (*encrypt)(cipherInfo, tmpdata, &outLen, len, data, len); -+ if (rv != SECSuccess) { -+ crv = sftk_MapCryptError(PORT_GetError()); -+ PORT_ZFree(tmpdata, len); -+ return crv; -+ } -+ -+ crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize); -+ PORT_ZFree(tmpdata, len); -+ return crv; -+} -+ -+/* - * SSL Key generation given pre master secret - */ - #define NUM_MIXERS 9 -@@ -6286,6 +6324,9 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession - CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; - CK_OBJECT_CLASS classType = CKO_SECRET_KEY; - CK_KEY_DERIVATION_STRING_DATA *stringPtr; -+ CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; -+ CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr; -+ void *cipherInfo; - CK_MECHANISM_TYPE mechanism = pMechanism->mechanism; - PRBool isTLS = PR_FALSE; - PRBool isDH = PR_FALSE; -@@ -6295,6 +6336,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession - unsigned int outLen; - unsigned char sha_out[SHA1_LENGTH]; - unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH]; -+ unsigned char des3key[24]; - PRBool isFIPS; - HASH_HashType hashType; - PRBool extractValue = PR_TRUE; -@@ -6899,6 +6941,168 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession +--- nss/lib/softoken/pkcs11c.c.add_encrypt_derive 2018-02-27 15:47:47.000000000 +0100 ++++ nss/lib/softoken/pkcs11c.c 2018-03-01 16:01:18.468880916 +0100 +@@ -6935,6 +6935,43 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession break; } + case CKM_DES_ECB_ENCRYPT_DATA: -+ stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; -+ cipherInfo = DES_CreateContext((unsigned char *)att->attrib.pValue, -+ NULL, NSS_DES, PR_TRUE); -+ if (cipherInfo == NULL) { -+ crv = CKR_HOST_MEMORY; -+ break; -+ } -+ crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 8, -+ stringPtr->pData, stringPtr->ulLen, (SFTKCipher)DES_Encrypt); -+ DES_DestroyContext(cipherInfo, PR_TRUE); -+ break; -+ -+ case CKM_DES_CBC_ENCRYPT_DATA: -+ desEncryptPtr = (CK_DES_CBC_ENCRYPT_DATA_PARAMS *) -+ pMechanism->pParameter; -+ cipherInfo = DES_CreateContext((unsigned char *)att->attrib.pValue, -+ desEncryptPtr->iv, NSS_DES_CBC, PR_TRUE); -+ if (cipherInfo == NULL) { -+ crv = CKR_HOST_MEMORY; -+ break; -+ } -+ crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 8, -+ desEncryptPtr->pData, desEncryptPtr->length, -+ (SFTKCipher)DES_Encrypt); -+ DES_DestroyContext(cipherInfo, PR_TRUE); -+ break; -+ -+ case CKM_DES3_ECB_ENCRYPT_DATA: -+ stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; -+ if (att->attrib.ulValueLen == 16) { -+ PORT_Memcpy(des3key, att->attrib.pValue, 16); -+ PORT_Memcpy(des3key + 16, des3key, 8); -+ } else if (att->attrib.ulValueLen == 24) { -+ PORT_Memcpy(des3key, att->attrib.pValue, 24); -+ } else { -+ crv = CKR_KEY_SIZE_RANGE; -+ break; -+ } -+ cipherInfo = DES_CreateContext(des3key, NULL, NSS_DES_EDE3, PR_TRUE); -+ PORT_Memset(des3key, 0, 24); -+ if (cipherInfo == NULL) { -+ crv = CKR_HOST_MEMORY; -+ break; -+ } -+ crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 8, -+ stringPtr->pData, stringPtr->ulLen, (SFTKCipher)DES_Encrypt); -+ DES_DestroyContext(cipherInfo, PR_TRUE); -+ break; -+ -+ case CKM_DES3_CBC_ENCRYPT_DATA: -+ desEncryptPtr = (CK_DES_CBC_ENCRYPT_DATA_PARAMS *) ++ case CKM_DES_CBC_ENCRYPT_DATA: { ++ void *cipherInfo; ++ CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr; ++ int mode; ++ unsigned char *iv; ++ unsigned char *data; ++ CK_ULONG len; ++ ++ if (mechanism == CKM_DES_ECB_ENCRYPT_DATA) { ++ stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) + pMechanism->pParameter; -+ if (att->attrib.ulValueLen == 16) { -+ PORT_Memcpy(des3key, att->attrib.pValue, 16); -+ PORT_Memcpy(des3key + 16, des3key, 8); -+ } else if (att->attrib.ulValueLen == 24) { -+ PORT_Memcpy(des3key, att->attrib.pValue, 24); ++ mode = NSS_DES; ++ iv = NULL; ++ data = stringPtr->pData; ++ len = stringPtr->ulLen; + } else { -+ crv = CKR_KEY_SIZE_RANGE; -+ break; ++ mode = NSS_DES_CBC; ++ desEncryptPtr = ++ (CK_DES_CBC_ENCRYPT_DATA_PARAMS *) ++ pMechanism->pParameter; ++ iv = desEncryptPtr->iv; ++ data = desEncryptPtr->pData; ++ len = desEncryptPtr->length; + } -+ cipherInfo = DES_CreateContext(des3key, desEncryptPtr->iv, -+ NSS_DES_EDE3_CBC, PR_TRUE); -+ PORT_Memset(des3key, 0, 24); ++ cipherInfo = DES_CreateContext((unsigned char *)att->attrib.pValue, iv, mode, PR_TRUE); + if (cipherInfo == NULL) { + crv = CKR_HOST_MEMORY; + break; + } -+ crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 8, -+ desEncryptPtr->pData, desEncryptPtr->length, -+ (SFTKCipher)DES_Encrypt); ++ crv = sftk_DeriveEncrypt((SFTKCipher)DES_Encrypt, ++ cipherInfo, 8, key, keySize, ++ data, len); + DES_DestroyContext(cipherInfo, PR_TRUE); + break; ++ } + -+ case CKM_AES_ECB_ENCRYPT_DATA: -+ stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; -+ cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue, -+ NULL, NSS_AES, PR_TRUE, att->attrib.ulValueLen, 16); -+ if (cipherInfo == NULL) { -+ crv = CKR_HOST_MEMORY; -+ break; -+ } -+ crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16, -+ stringPtr->pData, stringPtr->ulLen, (SFTKCipher)AES_Encrypt); -+ AES_DestroyContext(cipherInfo, PR_TRUE); -+ break; -+ -+ case CKM_AES_CBC_ENCRYPT_DATA: -+ aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) -+ pMechanism->pParameter; -+ cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue, -+ aesEncryptPtr->iv, NSS_AES_CBC, -+ PR_TRUE, att->attrib.ulValueLen, 16); -+ if (cipherInfo == NULL) { -+ crv = CKR_HOST_MEMORY; -+ break; -+ } -+ crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16, -+ aesEncryptPtr->pData, aesEncryptPtr->length, -+ (SFTKCipher)AES_Encrypt); -+ AES_DestroyContext(cipherInfo, PR_TRUE); -+ break; -+ -+ case CKM_CAMELLIA_ECB_ENCRYPT_DATA: -+ stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; -+ cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue, -+ NULL, NSS_CAMELLIA, PR_TRUE, att->attrib.ulValueLen); -+ if (cipherInfo == NULL) { -+ crv = CKR_HOST_MEMORY; -+ break; -+ } -+ crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16, -+ stringPtr->pData, stringPtr->ulLen, -+ (SFTKCipher)Camellia_Encrypt); -+ Camellia_DestroyContext(cipherInfo, PR_TRUE); -+ break; -+ -+ case CKM_CAMELLIA_CBC_ENCRYPT_DATA: -+ aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) -+ pMechanism->pParameter; -+ cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue, -+ aesEncryptPtr->iv, NSS_CAMELLIA_CBC, -+ PR_TRUE, att->attrib.ulValueLen); -+ if (cipherInfo == NULL) { -+ crv = CKR_HOST_MEMORY; -+ break; -+ } -+ crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16, -+ aesEncryptPtr->pData, aesEncryptPtr->length, -+ (SFTKCipher)Camellia_Encrypt); -+ Camellia_DestroyContext(cipherInfo, PR_TRUE); -+ break; -+ -+ case CKM_SEED_ECB_ENCRYPT_DATA: -+ stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; -+ cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue, -+ NULL, NSS_SEED, PR_TRUE); -+ if (cipherInfo == NULL) { -+ crv = CKR_HOST_MEMORY; -+ break; -+ } -+ crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16, -+ stringPtr->pData, stringPtr->ulLen, (SFTKCipher)SEED_Encrypt); -+ SEED_DestroyContext(cipherInfo, PR_TRUE); -+ break; -+ -+ case CKM_SEED_CBC_ENCRYPT_DATA: -+ aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) -+ pMechanism->pParameter; -+ cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue, -+ aesEncryptPtr->iv, NSS_SEED_CBC, PR_TRUE); -+ if (cipherInfo == NULL) { -+ crv = CKR_HOST_MEMORY; -+ break; -+ } -+ crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16, -+ aesEncryptPtr->pData, aesEncryptPtr->length, -+ (SFTKCipher)SEED_Encrypt); -+ SEED_DestroyContext(cipherInfo, PR_TRUE); -+ break; -+ - case CKM_CONCATENATE_BASE_AND_KEY: { - SFTKObject *newKey; - + case CKM_DES3_ECB_ENCRYPT_DATA: + case CKM_DES3_CBC_ENCRYPT_DATA: { + void *cipherInfo; diff --git a/SOURCES/nss-softokn-3.28-fix-fips-login.patch b/SOURCES/nss-softokn-3.28-fix-fips-login.patch deleted file mode 100644 index d8464e9..0000000 --- a/SOURCES/nss-softokn-3.28-fix-fips-login.patch +++ /dev/null @@ -1,107 +0,0 @@ -diff -up ./nss/lib/softoken/fipstokn.c.fix-fips-login ./nss/lib/softoken/fipstokn.c ---- ./nss/lib/softoken/fipstokn.c.fix-fips-login 2017-02-17 05:20:06.000000000 -0800 -+++ ./nss/lib/softoken/fipstokn.c 2017-05-05 15:29:23.934308889 -0700 -@@ -540,7 +540,10 @@ FC_GetTokenInfo(CK_SLOT_ID slotID, CK_TO - - crv = NSC_GetTokenInfo(slotID, pInfo); - if (crv == CKR_OK) { -- if ((pInfo->flags & CKF_LOGIN_REQUIRED) == 0) { -+ /* use the global database to figure out if we are running in -+ * FIPS 140 Level 1 or Level 2 */ -+ if (slotID == FIPS_SLOT_ID && -+ (pInfo->flags & CKF_LOGIN_REQUIRED) == 0) { - isLevel2 = PR_FALSE; - } - } -@@ -616,7 +619,8 @@ FC_InitPIN(CK_SESSION_HANDLE hSession, - * we need to make sure the pin meets FIPS requirements */ - if ((ulPinLen == 0) || ((rv = sftk_newPinCheck(pPin, ulPinLen)) == CKR_OK)) { - rv = NSC_InitPIN(hSession, pPin, ulPinLen); -- if (rv == CKR_OK) { -+ if ((rv == CKR_OK) && -+ (sftk_SlotIDFromSessionHandle(hSession) == FIPS_SLOT_ID)) { - isLevel2 = (ulPinLen > 0) ? PR_TRUE : PR_FALSE; - } - } -@@ -644,7 +648,8 @@ FC_SetPIN(CK_SESSION_HANDLE hSession, CK - if ((rv = sftk_fipsCheck()) == CKR_OK && - (rv = sftk_newPinCheck(pNewPin, usNewLen)) == CKR_OK) { - rv = NSC_SetPIN(hSession, pOldPin, usOldLen, pNewPin, usNewLen); -- if (rv == CKR_OK) { -+ if ((rv == CKR_OK) && -+ (sftk_SlotIDFromSessionHandle(hSession) == FIPS_SLOT_ID)) { - /* if we set the password in level1 we now go - * to level2. NOTE: we don't allow the user to - * go from level2 to level1 */ -@@ -705,12 +710,24 @@ FC_GetSessionInfo(CK_SESSION_HANDLE hSes - - rv = NSC_GetSessionInfo(hSession, pInfo); - if (rv == CKR_OK) { -- if ((isLoggedIn) && (pInfo->state == CKS_RO_PUBLIC_SESSION)) { -- pInfo->state = CKS_RO_USER_FUNCTIONS; -- } -- if ((isLoggedIn) && (pInfo->state == CKS_RW_PUBLIC_SESSION)) { -- pInfo->state = CKS_RW_USER_FUNCTIONS; -- } -+ /* handle the case where the auxilary slot doesn't require login. -+ * piggy back on the main token's login state */ -+ if (isLoggedIn && -+ ((pInfo->state == CKS_RO_PUBLIC_SESSION) || -+ (pInfo->state == CKS_RW_PUBLIC_SESSION))) { -+ CK_RV crv; -+ CK_TOKEN_INFO tInfo; -+ crv = NSC_GetTokenInfo(sftk_SlotIDFromSessionHandle(hSession), -+ &tInfo); -+ /* if the token doesn't login, use our global login state */ -+ if ((crv == CKR_OK) && ((tInfo.flags & CKF_LOGIN_REQUIRED) == 0)) { -+ if (pInfo->state == CKS_RO_PUBLIC_SESSION) { -+ pInfo->state = CKS_RO_USER_FUNCTIONS; -+ } else { -+ pInfo->state = CKS_RW_USER_FUNCTIONS; -+ } -+ } -+ } - } - return rv; - } -diff -up ./nss/lib/softoken/pkcs11.c.fix-fips-login ./nss/lib/softoken/pkcs11.c ---- ./nss/lib/softoken/pkcs11.c.fix-fips-login 2017-05-05 15:33:02.247012129 -0700 -+++ ./nss/lib/softoken/pkcs11.c 2017-05-05 15:34:43.399727983 -0700 -@@ -2370,17 +2370,22 @@ sftk_SlotFromID(CK_SLOT_ID slotID, PRBoo - return slot; - } - --SFTKSlot * --sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle) -+CK_SLOT_ID -+sftk_SlotIDFromSessionHandle(CK_SESSION_HANDLE handle) - { - CK_ULONG slotIDIndex = (handle >> 24) & 0x7f; - CK_ULONG moduleIndex = (handle >> 31) & 1; - - if (slotIDIndex >= nscSlotCount[moduleIndex]) { -- return NULL; -+ return (CK_SLOT_ID)-1; - } -+ return nscSlotList[moduleIndex][slotIDIndex]; -+} - -- return sftk_SlotFromID(nscSlotList[moduleIndex][slotIDIndex], PR_FALSE); -+SFTKSlot * -+sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle) -+{ -+ return sftk_SlotFromID(sftk_SlotIDFromSessionHandle(handle), PR_FALSE); - } - - static CK_RV -diff -up ./nss/lib/softoken/pkcs11i.h.fix-fips-login ./nss/lib/softoken/pkcs11i.h ---- ./nss/lib/softoken/pkcs11i.h.fix-fips-login 2017-02-17 05:20:06.000000000 -0800 -+++ ./nss/lib/softoken/pkcs11i.h 2017-05-05 15:29:23.934308889 -0700 -@@ -667,6 +667,7 @@ extern CK_RV sftk_handleObject(SFTKObjec - - extern SFTKSlot *sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all); - extern SFTKSlot *sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle); -+extern CK_SLOT_ID sftk_SlotIDFromSessionHandle(CK_SESSION_HANDLE handle); - extern SFTKSession *sftk_SessionFromHandle(CK_SESSION_HANDLE handle); - extern void sftk_FreeSession(SFTKSession *session); - extern SFTKSession *sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, diff --git a/SOURCES/nss-softokn-add-kas-tests.patch b/SOURCES/nss-softokn-add-kas-tests.patch new file mode 100644 index 0000000..dc6efff --- /dev/null +++ b/SOURCES/nss-softokn-add-kas-tests.patch @@ -0,0 +1,1254 @@ +diff --git a/cmd/fipstest/fipstest.c b/cmd/fipstest/fipstest.c +--- a/cmd/fipstest/fipstest.c ++++ b/cmd/fipstest/fipstest.c +@@ -2330,16 +2330,44 @@ sha_get_hashType(int hashbits) + hashType = HASH_AlgSHA512; + break; + default: + break; + } + return hashType; + } + ++HASH_HashType ++hash_string_to_hashType(const char * src) ++{ ++ HASH_HashType shaAlg = HASH_AlgNULL; ++ if (strncmp(src, "SHA-1", 5) == 0) { ++ shaAlg = HASH_AlgSHA1; ++ } else if (strncmp(src, "SHA-224", 7) == 0) { ++ shaAlg = HASH_AlgSHA224; ++ } else if (strncmp(src, "SHA-256", 7) == 0) { ++ shaAlg = HASH_AlgSHA256; ++ } else if (strncmp(src, "SHA-384", 7) == 0) { ++ shaAlg = HASH_AlgSHA384; ++ } else if (strncmp(src, "SHA-512", 7) == 0) { ++ shaAlg = HASH_AlgSHA512; ++ } else if (strncmp(src, "SHA1", 4) == 0) { ++ shaAlg = HASH_AlgSHA1; ++ } else if (strncmp(src, "SHA224", 6) == 0) { ++ shaAlg = HASH_AlgSHA224; ++ } else if (strncmp(src, "SHA256", 6) == 0) { ++ shaAlg = HASH_AlgSHA256; ++ } else if (strncmp(src, "SHA384", 6) == 0) { ++ shaAlg = HASH_AlgSHA384; ++ } else if (strncmp(src, "SHA512", 6) == 0) { ++ shaAlg = HASH_AlgSHA512; ++ } ++ return shaAlg; ++} ++ + /* + * Perform the ECDSA Key Pair Generation Test. + * + * reqfn is the pathname of the REQUEST file. + * + * The output RESPONSE file is written to stdout. + */ + void +@@ -2623,27 +2651,18 @@ ecdsa_siggen_test(char *reqfn) + *dst++ = tolower(*src); + src += 2; /* skip the hyphen */ + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst = '\0'; + src++; /* skip the comma */ + /* set the SHA Algorithm */ +- if (strncmp(src, "SHA-1", 5) == 0) { +- shaAlg = HASH_AlgSHA1; +- } else if (strncmp(src, "SHA-224", 7) == 0) { +- shaAlg = HASH_AlgSHA224; +- } else if (strncmp(src, "SHA-256", 7) == 0) { +- shaAlg = HASH_AlgSHA256; +- } else if (strncmp(src, "SHA-384", 7) == 0) { +- shaAlg = HASH_AlgSHA384; +- } else if (strncmp(src, "SHA-512", 7) == 0) { +- shaAlg = HASH_AlgSHA512; +- } else { ++ shaAlg = hash_string_to_hashType(src); ++ if (shaAlg == HASH_AlgNULL){ + fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type"); + goto loser; + } + if (ecparams != NULL) { + PORT_FreeArena(ecparams->arena, PR_FALSE); + ecparams = NULL; + } + encodedparams = getECParams(curve); +@@ -2793,27 +2812,18 @@ ecdsa_sigver_test(char *reqfn) + *dst++ = tolower(*src); + src += 2; /* skip the hyphen */ + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst = '\0'; + src++; /* skip the comma */ + /* set the SHA Algorithm */ +- if (strncmp(src, "SHA-1", 5) == 0) { +- shaAlg = HASH_AlgSHA1; +- } else if (strncmp(src, "SHA-224", 7) == 0) { +- shaAlg = HASH_AlgSHA224; +- } else if (strncmp(src, "SHA-256", 7) == 0) { +- shaAlg = HASH_AlgSHA256; +- } else if (strncmp(src, "SHA-384", 7) == 0) { +- shaAlg = HASH_AlgSHA384; +- } else if (strncmp(src, "SHA-512", 7) == 0) { +- shaAlg = HASH_AlgSHA512; +- } else { ++ shaAlg = hash_string_to_hashType(src); ++ if (shaAlg == HASH_AlgNULL) { + fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type"); + goto loser; + } + encodedparams = getECParams(curve); + if (encodedparams == NULL) { + fprintf(stderr, "Unknown curve %s.", curve); + goto loser; + } +@@ -2951,16 +2961,932 @@ ecdsa_sigver_test(char *reqfn) + } + loser: + if (ecpub.ecParams.arena != NULL) { + PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE); + } + fclose(ecdsareq); + } + ++/* ++ * Perform the ECDH Functional Test. ++ * ++ * reqfn is the pathname of the REQUEST file. ++ * ++ * The output RESPONSE file is written to stdout. ++ */ ++#define MAX_ECC_PARAMS 256 ++void ++ecdh_functional(char *reqfn, PRBool response) ++{ ++ char buf[256]; /* holds one line from the input REQUEST file. ++ * needs to be large enough to hold the longest ++ * line "Qx = <144 hex digits>\n". ++ */ ++ FILE *ecdhreq; /* input stream from the REQUEST file */ ++ FILE *ecdhresp; /* output stream to the RESPONSE file */ ++ char curve[16]; /* "nistxddd" */ ++ unsigned char hashBuf[HASH_LENGTH_MAX]; ++ ECParams *ecparams[MAX_ECC_PARAMS] = {NULL}; ++ ECPrivateKey *ecpriv = NULL; ++ ECParams *current_ecparams = NULL; ++ SECItem pubkey; ++ SECItem ZZ; ++ unsigned int i; ++ unsigned int len = 0; ++ unsigned int uit_len = 0; ++ int current_curve = -1; ++ HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ ++ ++ ecdhreq = fopen(reqfn, "r"); ++ ecdhresp = stdout; ++ strcpy(curve, "nist"); ++ pubkey.data = NULL; ++ while (fgets(buf, sizeof buf, ecdhreq) != NULL) { ++ /* a comment or blank line */ ++ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ if (buf[0] == '[') { ++ /* [Ex] */ ++ if (buf[1] == 'E' && buf[3] == ']') { ++ current_curve = buf[2] - 'A'; ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ /* [Curve selected: x-nnn */ ++ if (strncmp(buf, "[Curve ", 7) == 0) { ++ const char *src; ++ char *dst; ++ SECItem *encodedparams; ++ ++ if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) { ++ fprintf(stderr, "No curve type defined\n"); ++ goto loser; ++ } ++ ++ src = &buf[1]; ++ /* skip passed the colon */ ++ while (*src && *src != ':') src++; ++ if (*src != ':') { ++ fprintf(stderr, ++ "No colon in curve selected statement\n%s", buf); ++ goto loser; ++ } ++ src++; ++ /* skip to the first non-space */ ++ while (*src && *src == ' ') src++; ++ dst = &curve[4]; ++ *dst++ = tolower(*src); ++ src += 2; /* skip the hyphen */ ++ *dst++ = *src++; ++ *dst++ = *src++; ++ *dst++ = *src++; ++ *dst = '\0'; ++ if (ecparams[current_curve] != NULL) { ++ PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE); ++ ecparams[current_curve] = NULL; ++ } ++ encodedparams = getECParams(curve); ++ if (encodedparams == NULL) { ++ fprintf(stderr, "Unknown curve %s.", curve); ++ goto loser; ++ } ++ if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) ++ != SECSuccess) { ++ fprintf(stderr, "Curve %s not supported.\n", curve); ++ goto loser; ++ } ++ SECITEM_FreeItem(encodedparams, PR_TRUE); ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ /* [Ex - SHAxxx] */ ++ if (buf[1] == 'E' && buf[3] == ' ') { ++ const char *src; ++ current_curve = buf[2] - 'A'; ++ if ((current_curve < 0) || (current_curve > 256)) { ++ fprintf(stderr, "bad curve type defined (%c)\n", buf[2]); ++ goto loser; ++ } ++ current_ecparams = ecparams[current_curve]; ++ if (current_ecparams == NULL) { ++ fprintf(stderr, "no curve defined for type %c defined\n", ++ buf[2]); ++ goto loser; ++ } ++ /* skip passed the colon */ ++ src = &buf[1]; ++ while (*src && *src != '-') src++; ++ if (*src != '-') { ++ fprintf(stderr, ++ "No data in curve selected statement\n%s",buf); ++ goto loser; ++ } ++ src++; ++ /* skip to the first non-space */ ++ while (*src && *src == ' ') src++; ++ hash = hash_string_to_hashType(src); ++ if (hash == HASH_AlgNULL){ ++ fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type"); ++ goto loser; ++ } ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ /* COUNT = ... */ ++ if (strncmp(buf, "COUNT", 5) == 0) { ++ fputs(buf, ecdhresp); ++ if (current_ecparams == NULL) { ++ fprintf(stderr, "no curve defined for type %c defined\n", ++ buf[2]); ++ goto loser; ++ } ++ len = (current_ecparams->fieldID.size + 7) >> 3; ++ if (pubkey.data != NULL) { ++ PORT_Free(pubkey.data); ++ pubkey.data = NULL; ++ } ++ SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams)); ++ if (pubkey.data == NULL) { ++ goto loser; ++ } ++ pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED; ++ continue; ++ } ++ /* QeCAVSx = ... */ ++ if (strncmp(buf, "QeCAVSx", 7) == 0) { ++ fputs(buf, ecdhresp); ++ i = 7; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ from_hex_str(&pubkey.data[1], len, &buf[i]); ++ continue; ++ } ++ /* QeCAVSy = ... */ ++ if (strncmp(buf, "QeCAVSy", 7) == 0) { ++ fputs(buf, ecdhresp); ++ i = 7; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ from_hex_str(&pubkey.data[1 + len], len, &buf[i]); ++ if (current_ecparams == NULL) { ++ fprintf(stderr, "no curve defined\n"); ++ goto loser; ++ } ++ /* validate CAVS public key */ ++ if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) { ++ fprintf(stderr,"BAD key detected\n"); ++ goto loser; ++ } ++ ++ /* generate ECC key pair */ ++ if (EC_NewKey(current_ecparams, &ecpriv) != SECSuccess) { ++ fprintf(stderr,"Failed to generate new key\n"); ++ goto loser; ++ } ++ /* validate UIT generated public key */ ++ if (EC_ValidatePublicKey(current_ecparams, &ecpriv->publicValue) != ++ SECSuccess) { ++ fprintf(stderr,"generate key did not validate\n"); ++ goto loser; ++ } ++ /* output UIT public key */ ++ uit_len = ecpriv->publicValue.len; ++ if (uit_len % 2 == 0) { ++ fprintf(stderr,"generate key had invalid public value len\n"); ++ goto loser; ++ } ++ uit_len = (uit_len - 1) / 2; ++ if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) { ++ fprintf(stderr,"generate key was compressed\n"); ++ goto loser; ++ } ++ fputs("QeIUTx = ", ecdhresp); ++ to_hex_str(buf, &ecpriv->publicValue.data[1], uit_len); ++ fputs(buf, ecdhresp); ++ fputc('\n', ecdhresp); ++ fputs("QeIUTy = ", ecdhresp); ++ to_hex_str(buf, &ecpriv->publicValue.data[1 + uit_len], uit_len); ++ fputs(buf, ecdhresp); ++ fputc('\n', ecdhresp); ++ /* ECDH */ ++ if (ECDH_Derive(&pubkey,current_ecparams, &ecpriv->privateValue, ++ PR_FALSE, &ZZ) != SECSuccess) { ++ fprintf(stderr,"Derive failed\n"); ++ goto loser; ++ } ++ /* output hash of ZZ */ ++ if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess ) { ++ fprintf(stderr,"hash of derived key failed\n"); ++ goto loser; ++ } ++ SECITEM_FreeItem(&ZZ, PR_FALSE); ++ fputs("HashZZ = ", ecdhresp); ++ to_hex_str(buf, hashBuf, fips_hashLen(hash)); ++ fputs(buf, ecdhresp); ++ fputc('\n', ecdhresp); ++ fputc('\n', ecdhresp); ++ PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); ++ ecpriv = NULL; ++ continue; ++ } ++ } ++loser: ++ if (ecpriv != NULL) { ++ PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); ++ } ++ for (i=0; i < MAX_ECC_PARAMS; i++) { ++ if (ecparams[i] != NULL) { ++ PORT_FreeArena(ecparams[i]->arena, PR_FALSE); ++ ecparams[i] = NULL; ++ } ++ } ++ if (pubkey.data != NULL) { ++ PORT_Free(pubkey.data); ++ } ++ fclose(ecdhreq); ++} ++ ++#define MATCH_OPENSSL 1 ++/* ++ * Perform the ECDH Validity Test. ++ * ++ * reqfn is the pathname of the REQUEST file. ++ * ++ * The output RESPONSE file is written to stdout. ++ */ ++void ++ecdh_verify(char *reqfn, PRBool response) ++{ ++ char buf[256]; /* holds one line from the input REQUEST file. ++ * needs to be large enough to hold the longest ++ * line "Qx = <144 hex digits>\n". ++ */ ++ FILE *ecdhreq; /* input stream from the REQUEST file */ ++ FILE *ecdhresp; /* output stream to the RESPONSE file */ ++ char curve[16]; /* "nistxddd" */ ++ unsigned char hashBuf[HASH_LENGTH_MAX]; ++ unsigned char cavsHashBuf[HASH_LENGTH_MAX]; ++ unsigned char private_data[MAX_ECKEY_LEN]; ++ ECParams *ecparams[MAX_ECC_PARAMS] = {NULL}; ++ ECParams *current_ecparams = NULL; ++ SECItem pubkey; ++ SECItem ZZ; ++ SECItem private_value; ++ unsigned int i; ++ unsigned int len = 0; ++ int current_curve = -1; ++ HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ ++ ++ ecdhreq = fopen(reqfn, "r"); ++ ecdhresp = stdout; ++ strcpy(curve, "nist"); ++ pubkey.data = NULL; ++ while (fgets(buf, sizeof buf, ecdhreq) != NULL) { ++ /* a comment or blank line */ ++ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ if (buf[0] == '[') { ++ /* [Ex] */ ++ if (buf[1] == 'E' && buf[3] == ']') { ++ current_curve = buf[2] - 'A'; ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ /* [Curve selected: x-nnn */ ++ if (strncmp(buf, "[Curve ", 7) == 0) { ++ const char *src; ++ char *dst; ++ SECItem *encodedparams; ++ ++ if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) { ++ fprintf(stderr, "No curve type defined\n"); ++ goto loser; ++ } ++ ++ src = &buf[1]; ++ /* skip passed the colon */ ++ while (*src && *src != ':') src++; ++ if (*src != ':') { ++ fprintf(stderr, ++ "No colon in curve selected statement\n%s", buf); ++ goto loser; ++ } ++ src++; ++ /* skip to the first non-space */ ++ while (*src && *src == ' ') src++; ++ dst = &curve[4]; ++ *dst++ = tolower(*src); ++ src += 2; /* skip the hyphen */ ++ *dst++ = *src++; ++ *dst++ = *src++; ++ *dst++ = *src++; ++ *dst = '\0'; ++ if (ecparams[current_curve] != NULL) { ++ PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE); ++ ecparams[current_curve] = NULL; ++ } ++ encodedparams = getECParams(curve); ++ if (encodedparams == NULL) { ++ fprintf(stderr, "Unknown curve %s.\n", curve); ++ goto loser; ++ } ++ if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) ++ != SECSuccess) { ++ fprintf(stderr, "Curve %s not supported.\n", curve); ++ goto loser; ++ } ++ SECITEM_FreeItem(encodedparams, PR_TRUE); ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ /* [Ex - SHAxxx] */ ++ if (buf[1] == 'E' && buf[3] == ' ') { ++ const char *src; ++ current_curve = buf[2] - 'A'; ++ if ((current_curve < 0) || (current_curve > 256)) { ++ fprintf(stderr, "bad curve type defined (%c)\n", buf[2]); ++ goto loser; ++ } ++ current_ecparams = ecparams[current_curve]; ++ if (current_ecparams == NULL) { ++ fprintf(stderr, "no curve defined for type %c defined\n", ++ buf[2]); ++ goto loser; ++ } ++ /* skip passed the colon */ ++ src = &buf[1]; ++ while (*src && *src != '-') src++; ++ if (*src != '-') { ++ fprintf(stderr, ++ "No data in curve selected statement\n%s",buf); ++ goto loser; ++ } ++ src++; ++ /* skip to the first non-space */ ++ while (*src && *src == ' ') src++; ++ hash = hash_string_to_hashType(src); ++ if (hash == HASH_AlgNULL){ ++ fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type"); ++ goto loser; ++ } ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ /* COUNT = ... */ ++ if (strncmp(buf, "COUNT", 5) == 0) { ++ fputs(buf, ecdhresp); ++ if (current_ecparams == NULL) { ++ fprintf(stderr, "no curve defined for type %c defined\n", ++ buf[2]); ++ goto loser; ++ } ++ len = (current_ecparams->fieldID.size + 7) >> 3; ++ if (pubkey.data != NULL) { ++ PORT_Free(pubkey.data); ++ pubkey.data = NULL; ++ } ++ SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams)); ++ if (pubkey.data == NULL) { ++ goto loser; ++ } ++ pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED; ++ continue; ++ } ++ /* QeCAVSx = ... */ ++ if (strncmp(buf, "QeCAVSx", 7) == 0) { ++ fputs(buf, ecdhresp); ++ i = 7; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ from_hex_str(&pubkey.data[1], len, &buf[i]); ++ continue; ++ } ++ /* QeCAVSy = ... */ ++ if (strncmp(buf, "QeCAVSy", 7) == 0) { ++ fputs(buf, ecdhresp); ++ i = 7; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ from_hex_str(&pubkey.data[1 + len], len, &buf[i]); ++ continue; ++ } ++ if (strncmp(buf, "deIUT", 5) == 0) { ++ fputs(buf, ecdhresp); ++ i = 5; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ from_hex_str(private_data, len, &buf[i]); ++ private_value.data = private_data; ++ private_value.len = len; ++ continue; ++ } ++ if (strncmp(buf, "QeIUTx", 6) == 0) { ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ if (strncmp(buf, "QeIUTy", 6) == 0) { ++ fputs(buf, ecdhresp); ++ continue; ++ } ++ if (strncmp(buf, "CAVSHashZZ", 10) == 0) { ++ fputs(buf, ecdhresp); ++ i = 10; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]); ++ if (current_ecparams == NULL) { ++ fprintf(stderr, "no curve defined for type defined\n"); ++ goto loser; ++ } ++ /* validate CAVS public key */ ++ if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) { ++#ifdef MATCH_OPENSSL ++ fprintf(ecdhresp, "Result = F\n"); ++#else ++ fprintf(ecdhresp, "Result = F # key didn't validate\n"); ++#endif ++ continue; ++ } ++ ++ /* ECDH */ ++ if (ECDH_Derive(&pubkey, current_ecparams, &private_value, ++ PR_FALSE, &ZZ) != SECSuccess) { ++ fprintf(stderr,"Derive failed\n"); ++ goto loser; ++ } ++ /* output ZZ */ ++#ifndef MATCH_OPENSSL ++ fputs("Z = ", ecdhresp); ++ to_hex_str(buf, ZZ.data, ZZ.len); ++ fputs(buf, ecdhresp); ++ fputc('\n', ecdhresp); ++#endif ++ ++ if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess ) { ++ fprintf(stderr,"hash of derived key failed\n"); ++ goto loser; ++ } ++ SECITEM_FreeItem(&ZZ, PR_FALSE); ++#ifndef MATCH_NIST ++ fputs("IUTHashZZ = ", ecdhresp); ++ to_hex_str(buf, hashBuf, fips_hashLen(hash)); ++ fputs(buf, ecdhresp); ++ fputc('\n', ecdhresp); ++#endif ++ if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) { ++#ifdef MATCH_OPENSSL ++ fprintf(ecdhresp, "Result = F\n"); ++#else ++ fprintf(ecdhresp, "Result = F # hash doesn't match\n"); ++#endif ++ } else { ++ fprintf(ecdhresp, "Result = P\n"); ++ } ++#ifndef MATCH_OPENSSL ++ fputc('\n', ecdhresp); ++#endif ++ continue; ++ } ++ } ++loser: ++ for (i=0; i < MAX_ECC_PARAMS; i++) { ++ if (ecparams[i] != NULL) { ++ PORT_FreeArena(ecparams[i]->arena, PR_FALSE); ++ ecparams[i] = NULL; ++ } ++ } ++ if (pubkey.data != NULL) { ++ PORT_Free(pubkey.data); ++ } ++ fclose(ecdhreq); ++} ++ ++/* ++ * Perform the DH Functional Test. ++ * ++ * reqfn is the pathname of the REQUEST file. ++ * ++ * The output RESPONSE file is written to stdout. ++ */ ++#define MAX_ECC_PARAMS 256 ++void ++dh_functional(char *reqfn, PRBool response) ++{ ++ char buf[1024]; /* holds one line from the input REQUEST file. ++ * needs to be large enough to hold the longest ++ * line "YephCAVS = <512 hex digits>\n". ++ */ ++ FILE *dhreq; /* input stream from the REQUEST file */ ++ FILE *dhresp; /* output stream to the RESPONSE file */ ++ unsigned char hashBuf[HASH_LENGTH_MAX]; ++ DSAPrivateKey *dsapriv = NULL; ++ PQGParams pqg = { 0 }; ++ unsigned char pubkeydata[DSA_MAX_P_BITS/8]; ++ SECItem pubkey; ++ SECItem ZZ; ++ unsigned int i,j; ++ unsigned int pgySize; ++ HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ ++ ++ dhreq = fopen(reqfn, "r"); ++ dhresp = stdout; ++ while (fgets(buf, sizeof buf, dhreq) != NULL) { ++ /* a comment or blank line */ ++ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { ++ fputs(buf, dhresp); ++ continue; ++ } ++ if (buf[0] == '[') { ++ /* [Fx - SHAxxx] */ ++ if (buf[1] == 'F' && buf[3] == ' ') { ++ const char *src; ++ /* skip passed the colon */ ++ src = &buf[1]; ++ while (*src && *src != '-') src++; ++ if (*src != '-') { ++ fprintf(stderr, "No hash specified\n%s",buf); ++ goto loser; ++ } ++ src++; ++ /* skip to the first non-space */ ++ while (*src && *src == ' ') src++; ++ hash = hash_string_to_hashType(src); ++ if (hash == HASH_AlgNULL){ ++ fprintf(dhresp, "ERROR: Unable to find SHAAlg type"); ++ goto loser; ++ } ++ /* clear the PQG parameters */ ++ if (pqg.prime.data) { /* P */ ++ SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); ++ } ++ if (pqg.subPrime.data) { /* Q */ ++ SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); ++ } ++ if (pqg.base.data) { /* G */ ++ SECITEM_ZfreeItem(&pqg.base, PR_FALSE); ++ } ++ pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */ ++ SECITEM_AllocItem(NULL, &pqg.prime, pgySize); ++ SECITEM_AllocItem(NULL, &pqg.base, pgySize); ++ pqg.prime.len = pqg.base.len = pgySize; ++ ++ /* set q to the max allows */ ++ SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS/ 8); ++ pqg.subPrime.len = DSA_MAX_Q_BITS / 8; ++ fputs(buf, dhresp); ++ continue; ++ } ++ fputs(buf, dhresp); ++ continue; ++ } ++ if (buf[0] == 'P') { ++ i = 1; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ for (j = 0; j < pqg.prime.len; i += 2, j++) { ++ if (!isxdigit(buf[i])) { ++ pqg.prime.len = j; ++ break; ++ } ++ hex_to_byteval(&buf[i], &pqg.prime.data[j]); ++ } ++ ++ fputs(buf, dhresp); ++ continue; ++ } ++ ++ /* Q = ... */ ++ if (buf[0] == 'Q') { ++ i = 1; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ for (j = 0; j < pqg.subPrime.len; i += 2, j++) { ++ if (!isxdigit(buf[i])) { ++ pqg.subPrime.len = j; ++ break; ++ } ++ hex_to_byteval(&buf[i], &pqg.subPrime.data[j]); ++ } ++ ++ fputs(buf, dhresp); ++ continue; ++ } ++ ++ /* G = ... */ ++ if (buf[0] == 'G') { ++ i = 1; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ for (j = 0; j < pqg.base.len; i += 2, j++) { ++ if (!isxdigit(buf[i])) { ++ pqg.base.len = j; ++ break; ++ } ++ hex_to_byteval(&buf[i], &pqg.base.data[j]); ++ } ++ ++ fputs(buf, dhresp); ++ continue; ++ } ++ ++ /* COUNT = ... */ ++ if (strncmp(buf, "COUNT", 5) == 0) { ++ fputs(buf, dhresp); ++ continue; ++ } ++ ++ /* YephemCAVS = ... */ ++ if (strncmp(buf, "YephemCAVS", 10) == 0) { ++ fputs(buf, dhresp); ++ i = 10; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ from_hex_str(pubkeydata, pqg.prime.len, &buf[i]); ++ pubkey.data = pubkeydata; ++ pubkey.len = pqg.prime.len; ++ ++ /* generate FCC key pair, nist uses pqg rather then pg, ++ * so use DSA to generate the key */ ++ if (DSA_NewKey(&pqg, &dsapriv) != SECSuccess) { ++ fprintf(stderr,"Failed to generate new key\n"); ++ goto loser; ++ } ++ fputs("XephemIUT = ", dhresp); ++ to_hex_str(buf, dsapriv->privateValue.data, dsapriv->privateValue.len); ++ fputs(buf, dhresp); ++ fputc('\n', dhresp); ++ fputs("YephemIUT = ", dhresp); ++ to_hex_str(buf, dsapriv->publicValue.data, dsapriv->publicValue.len); ++ fputs(buf, dhresp); ++ fputc('\n', dhresp); ++ /* DH */ ++ if (DH_Derive(&pubkey,&pqg.prime, &dsapriv->privateValue, ++ &ZZ, pqg.prime.len) != SECSuccess) { ++ fprintf(stderr,"Derive failed\n"); ++ goto loser; ++ } ++ /* output hash of ZZ */ ++ if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess ) { ++ fprintf(stderr,"hash of derived key failed\n"); ++ goto loser; ++ } ++ SECITEM_FreeItem(&ZZ, PR_FALSE); ++ fputs("HashZZ = ", dhresp); ++ to_hex_str(buf, hashBuf, fips_hashLen(hash)); ++ fputs(buf, dhresp); ++ fputc('\n', dhresp); ++ fputc('\n', dhresp); ++ PORT_FreeArena(dsapriv->params.arena, PR_TRUE); ++ dsapriv = NULL; ++ continue; ++ } ++ } ++loser: ++ if (dsapriv != NULL) { ++ PORT_FreeArena(dsapriv->params.arena, PR_TRUE); ++ } ++ fclose(dhreq); ++} ++ ++#define MATCH_OPENSSL 1 ++/* ++ * Perform the DH Validity Test. ++ * ++ * reqfn is the pathname of the REQUEST file. ++ * ++ * The output RESPONSE file is written to stdout. ++ */ ++void ++dh_verify(char *reqfn, PRBool response) ++{ ++ char buf[1024]; /* holds one line from the input REQUEST file. ++ * needs to be large enough to hold the longest ++ * line "YephCAVS = <512 hex digits>\n". ++ */ ++ FILE *dhreq; /* input stream from the REQUEST file */ ++ FILE *dhresp; /* output stream to the RESPONSE file */ ++ unsigned char hashBuf[HASH_LENGTH_MAX]; ++ unsigned char cavsHashBuf[HASH_LENGTH_MAX]; ++ PQGParams pqg = { 0 }; ++ unsigned char pubkeydata[DSA_MAX_P_BITS/8]; ++ unsigned char privkeydata[DSA_MAX_P_BITS/8]; ++ SECItem pubkey; ++ SECItem privkey; ++ SECItem ZZ; ++ unsigned int i,j; ++ unsigned int pgySize; ++ HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ ++ ++ dhreq = fopen(reqfn, "r"); ++ dhresp = stdout; ++ while (fgets(buf, sizeof buf, dhreq) != NULL) { ++ /* a comment or blank line */ ++ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { ++ fputs(buf, dhresp); ++ continue; ++ } ++ if (buf[0] == '[') { ++ /* [Fx - SHAxxx] */ ++ if (buf[1] == 'F' && buf[3] == ' ') { ++ const char *src; ++ /* skip passed the colon */ ++ src = &buf[1]; ++ while (*src && *src != '-') src++; ++ if (*src != '-') { ++ fprintf(stderr, "No hash specified\n%s",buf); ++ goto loser; ++ } ++ src++; ++ /* skip to the first non-space */ ++ while (*src && *src == ' ') src++; ++ hash = hash_string_to_hashType(src); ++ if (hash == HASH_AlgNULL){ ++ fprintf(dhresp, "ERROR: Unable to find SHAAlg type"); ++ goto loser; ++ } ++ /* clear the PQG parameters */ ++ if (pqg.prime.data) { /* P */ ++ SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); ++ } ++ if (pqg.subPrime.data) { /* Q */ ++ SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); ++ } ++ if (pqg.base.data) { /* G */ ++ SECITEM_ZfreeItem(&pqg.base, PR_FALSE); ++ } ++ pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */ ++ SECITEM_AllocItem(NULL, &pqg.prime, pgySize); ++ SECITEM_AllocItem(NULL, &pqg.base, pgySize); ++ pqg.prime.len = pqg.base.len = pgySize; ++ ++ /* set q to the max allows */ ++ SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS/ 8); ++ pqg.subPrime.len = DSA_MAX_Q_BITS / 8; ++ fputs(buf, dhresp); ++ continue; ++ } ++ fputs(buf, dhresp); ++ continue; ++ } ++ if (buf[0] == 'P') { ++ i = 1; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ for (j = 0; j < pqg.prime.len; i += 2, j++) { ++ if (!isxdigit(buf[i])) { ++ pqg.prime.len = j; ++ break; ++ } ++ hex_to_byteval(&buf[i], &pqg.prime.data[j]); ++ } ++ ++ fputs(buf, dhresp); ++ continue; ++ } ++ ++ /* Q = ... */ ++ if (buf[0] == 'Q') { ++ i = 1; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ for (j = 0; j < pqg.subPrime.len; i += 2, j++) { ++ if (!isxdigit(buf[i])) { ++ pqg.subPrime.len = j; ++ break; ++ } ++ hex_to_byteval(&buf[i], &pqg.subPrime.data[j]); ++ } ++ ++ fputs(buf, dhresp); ++ continue; ++ } ++ ++ /* G = ... */ ++ if (buf[0] == 'G') { ++ i = 1; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ for (j = 0; j < pqg.base.len; i += 2, j++) { ++ if (!isxdigit(buf[i])) { ++ pqg.base.len = j; ++ break; ++ } ++ hex_to_byteval(&buf[i], &pqg.base.data[j]); ++ } ++ ++ fputs(buf, dhresp); ++ continue; ++ } ++ ++ /* COUNT = ... */ ++ if (strncmp(buf, "COUNT", 5) == 0) { ++ fputs(buf, dhresp); ++ continue; ++ } ++ ++ /* YephemCAVS = ... */ ++ if (strncmp(buf, "YephemCAVS", 10) == 0) { ++ fputs(buf, dhresp); ++ i = 10; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ from_hex_str(pubkeydata, pqg.prime.len, &buf[i]); ++ pubkey.data = pubkeydata; ++ pubkey.len = pqg.prime.len; ++ continue; ++ } ++ /* XephemUIT = ... */ ++ if (strncmp(buf, "XephemIUT", 9) == 0) { ++ fputs(buf, dhresp); ++ i = 9; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ from_hex_str(privkeydata, pqg.subPrime.len, &buf[i]); ++ privkey.data = privkeydata; ++ privkey.len = pqg.subPrime.len; ++ continue; ++ } ++ /* YephemUIT = ... */ ++ if (strncmp(buf, "YephemIUT", 9) == 0) { ++ fputs(buf, dhresp); ++ continue; ++ } ++ /* CAVSHashZZ = ... */ ++ if (strncmp(buf, "CAVSHashZZ", 10) == 0) { ++ fputs(buf, dhresp); ++ i = 10; ++ while (isspace(buf[i]) || buf[i] == '=') { ++ i++; ++ } ++ from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]); ++ /* do the DH operation*/ ++ if (DH_Derive(&pubkey,&pqg.prime, &privkey, ++ &ZZ, pqg.prime.len) != SECSuccess) { ++ fprintf(stderr,"Derive failed\n"); ++ goto loser; ++ } ++ /* output ZZ */ ++#ifndef MATCH_OPENSSL ++ fputs("Z = ", dhresp); ++ to_hex_str(buf, ZZ.data, ZZ.len); ++ fputs(buf, dhresp); ++ fputc('\n', dhresp); ++#endif ++ if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess ) { ++ fprintf(stderr,"hash of derived key failed\n"); ++ goto loser; ++ } ++ SECITEM_FreeItem(&ZZ, PR_FALSE); ++#ifndef MATCH_NIST_ ++ fputs("IUTHashZZ = ", dhresp); ++ to_hex_str(buf, hashBuf, fips_hashLen(hash)); ++ fputs(buf, dhresp); ++ fputc('\n', dhresp); ++#endif ++ if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) { ++ fprintf(dhresp, "Result = F\n"); ++ } else { ++ fprintf(dhresp, "Result = P\n"); ++ } ++#ifndef MATCH_OPENSSL ++ fputc('\n', dhresp); ++#endif ++ continue; ++ } ++ } ++loser: ++ fclose(dhreq); ++} ++ + PRBool + isblankline(char *b) + { + while (isspace(*b)) + b++; + if ((*b == '\n') || (*b == 0)) { + return PR_TRUE; + } +@@ -5337,27 +6263,18 @@ rsa_siggen_test(char *reqfn) + + /* SHAAlg = ... */ + if (strncmp(buf, "SHAAlg", 6) == 0) { + i = 6; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + /* set the SHA Algorithm */ +- if (strncmp(&buf[i], "SHA1", 4) == 0) { +- shaAlg = HASH_AlgSHA1; +- } else if (strncmp(&buf[i], "SHA224", 6) == 0) { +- shaAlg = HASH_AlgSHA224; +- } else if (strncmp(&buf[i], "SHA256", 6) == 0) { +- shaAlg = HASH_AlgSHA256; +- } else if (strncmp(&buf[i], "SHA384", 6) == 0) { +- shaAlg = HASH_AlgSHA384; +- } else if (strncmp(&buf[i], "SHA512", 6) == 0) { +- shaAlg = HASH_AlgSHA512; +- } else { ++ shaAlg = hash_string_to_hashType(&buf[i]); ++ if (shaAlg == HASH_AlgNULL) { + fprintf(rsaresp, "ERROR: Unable to find SHAAlg type"); + goto loser; + } + fputs(buf, rsaresp); + continue; + } + /* Msg = ... */ + if (strncmp(buf, "Msg", 3) == 0) { +@@ -5532,27 +6449,18 @@ rsa_sigver_test(char *reqfn) + + /* SHAAlg = ... */ + if (strncmp(buf, "SHAAlg", 6) == 0) { + i = 6; + while (isspace(buf[i]) || buf[i] == '=') { + i++; + } + /* set the SHA Algorithm */ +- if (strncmp(&buf[i], "SHA1", 4) == 0) { +- shaAlg = HASH_AlgSHA1; +- } else if (strncmp(&buf[i], "SHA224", 6) == 0) { +- shaAlg = HASH_AlgSHA224; +- } else if (strncmp(&buf[i], "SHA256", 6) == 0) { +- shaAlg = HASH_AlgSHA256; +- } else if (strncmp(&buf[i], "SHA384", 6) == 0) { +- shaAlg = HASH_AlgSHA384; +- } else if (strncmp(&buf[i], "SHA512", 6) == 0) { +- shaAlg = HASH_AlgSHA512; +- } else { ++ shaAlg = hash_string_to_hashType(&buf[i]); ++ if (shaAlg == HASH_AlgNULL) { + fprintf(rsaresp, "ERROR: Unable to find SHAAlg type"); + goto loser; + } + fputs(buf, rsaresp); + continue; + } + + /* e = ... public Key */ +@@ -6103,16 +7011,44 @@ main(int argc, char **argv) + } else if (strcmp(argv[2], "siggen") == 0) { + /* Signature Generation Test */ + ecdsa_siggen_test(argv[3]); + } else if (strcmp(argv[2], "sigver") == 0) { + /* Signature Verification Test */ + ecdsa_sigver_test(argv[3]); + } + /*************/ ++ /* ECDH */ ++ /*************/ ++ } else if (strcmp(argv[1], "ecdh") == 0) { ++ /* argv[2]={init|resp}-{func|verify} argv[3]=.req */ ++ if (strcmp(argv[2], "init-func") == 0) { ++ ecdh_functional(argv[3], 0); ++ } else if (strcmp(argv[2], "resp-func") == 0) { ++ ecdh_functional(argv[3], 1); ++ } else if (strcmp(argv[2], "init-verify") == 0) { ++ ecdh_verify(argv[3], 0); ++ } else if (strcmp(argv[2], "resp-verify") == 0) { ++ ecdh_verify(argv[3], 1); ++ } ++ /*************/ ++ /* DH */ ++ /*************/ ++ } else if (strcmp(argv[1], "dh") == 0) { ++ /* argv[2]={init|resp}-{func|verify} argv[3]=.req */ ++ if (strcmp(argv[2], "init-func") == 0) { ++ dh_functional(argv[3], 0); ++ } else if (strcmp(argv[2], "resp-func") == 0) { ++ dh_functional(argv[3], 1); ++ } else if (strcmp(argv[2], "init-verify") == 0) { ++ dh_verify(argv[3], 0); ++ } else if (strcmp(argv[2], "resp-verify") == 0) { ++ dh_verify(argv[3], 1); ++ } ++ /*************/ + /* RNG */ + /*************/ + } else if (strcmp(argv[1], "rng") == 0) { + /* argv[2]=vst|mct argv[3]=.req */ + if (strcmp(argv[2], "vst") == 0) { + /* Variable Seed Test */ + rng_vst(argv[3]); + } else if (strcmp(argv[2], "mct") == 0) { +diff --git a/cmd/fipstest/kas.sh b/cmd/fipstest/kas.sh +new file mode 100755 +--- /dev/null ++++ b/cmd/fipstest/kas.sh +@@ -0,0 +1,84 @@ ++#!/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 DSA Validation System ++# ++# 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 ++ ++ ++# ++if [ ${COMMAND} = "verify" ]; then ++# ++# need verify for KAS tests ++ ++# verify generated keys ++# name=KeyPair ++# echo ">>>>> $name" ++# fipstest dsa keyver ${RSPDIR}/$name.rsp | grep ^Result.=.F ++# verify generated pqg values ++# name=PQGGen ++# echo ">>>>> $name" ++# fipstest dsa pqgver ${RSPDIR}/$name.rsp | grep ^Result.=.F ++# verify PQGVer with known answer ++# sh ./validate1.sh ${TESTDIR} PQGVer.req ' ' '-e /^Result.=.F/s;.(.*);; -e /^Result.=.P/s;.(.*);;' ++# verify signatures ++# name=SigGen ++# echo ">>>>> $name" ++# fipstest dsa sigver ${RSPDIR}/$name.rsp | grep ^Result.=.F ++# verify SigVer with known answer ++# sh ./validate1.sh ${TESTDIR} SigVer.req ' ' '-e /^X.=/d -e /^Result.=.F/s;.(.*);;' ++ exit 0 ++fi ++ ++request=KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req ++response=`echo $request | sed -e "s/req/rsp/"` ++echo $request $response ++fipstest ecdh init-func ${REQDIR}/$request > ${RSPDIR}/$response ++ ++request=KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req ++response=`echo $request | sed -e "s/req/rsp/"` ++echo $request $response ++fipstest ecdh resp-func ${REQDIR}/$request > ${RSPDIR}/$response ++ ++request=KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init.req ++response=`echo $request | sed -e "s/req/rsp/"` ++echo $request $response ++fipstest ecdh init-verify ${REQDIR}/$request > ${RSPDIR}/$response ++ ++request=KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_resp.req ++response=`echo $request | sed -e "s/req/rsp/"` ++echo $request $response ++fipstest ecdh resp-verify ${REQDIR}/$request > ${RSPDIR}/$response ++ ++request=KASFunctionTest_FFCEphem_NOKC_ZZOnly_init.req ++response=`echo $request | sed -e "s/req/rsp/"` ++echo $request $response ++fipstest dh init-func ${REQDIR}/$request > ${RSPDIR}/$response ++ ++request=KASFunctionTest_FFCEphem_NOKC_ZZOnly_resp.req ++response=`echo $request | sed -e "s/req/rsp/"` ++echo $request $response ++fipstest dh resp-func ${REQDIR}/$request > ${RSPDIR}/$response ++ ++request=KASValidityTest_FFCEphem_NOKC_ZZOnly_init.req ++response=`echo $request | sed -e "s/req/rsp/"` ++echo $request $response ++fipstest dh init-verify ${REQDIR}/$request > ${RSPDIR}/$response ++ ++request=KASValidityTest_FFCEphem_NOKC_ZZOnly_resp.req ++response=`echo $request | sed -e "s/req/rsp/"` ++echo $request $response ++fipstest dh resp-verify ${REQDIR}/$request > ${RSPDIR}/$response ++ +diff --git a/cmd/fipstest/runtest.sh b/cmd/fipstest/runtest.sh +--- a/cmd/fipstest/runtest.sh ++++ b/cmd/fipstest/runtest.sh +@@ -1,14 +1,14 @@ + #!/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/. + # + TESTDIR=${1-.} + COMMAND=${2-run} +-TESTS="aes aesgcm dsa ecdsa hmac tls rng rsa sha tdea" ++TESTS="aes aesgcm dsa ecdsa hmac kas tls rng rsa sha tdea" + for i in $TESTS + do + echo "********************Running $i tests" + sh ./${i}.sh ${TESTDIR} ${COMMAND} + done diff --git a/SOURCES/nss-softokn-aes-zeroize.patch b/SOURCES/nss-softokn-aes-zeroize.patch new file mode 100644 index 0000000..1605470 --- /dev/null +++ b/SOURCES/nss-softokn-aes-zeroize.patch @@ -0,0 +1,51 @@ +diff --git a/lib/freebl/intel-gcm-wrap.c b/lib/freebl/intel-gcm-wrap.c +--- a/lib/freebl/intel-gcm-wrap.c ++++ b/lib/freebl/intel-gcm-wrap.c +@@ -138,16 +138,17 @@ intel_AES_GCM_CreateContext(void *contex + loser: + PORT_Free(gcm); + return NULL; + } + + void + intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit) + { ++ PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext)); + if (freeit) { + PORT_Free(gcm); + } + } + + SECStatus + intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm, + unsigned char *outbuf, +diff --git a/lib/freebl/rijndael.c b/lib/freebl/rijndael.c +--- a/lib/freebl/rijndael.c ++++ b/lib/freebl/rijndael.c +@@ -1027,23 +1027,25 @@ AES_CreateContext(const unsigned char *k + * AES_DestroyContext + * + * Zero an AES cipher context. If freeit is true, also free the pointer + * to the context. + */ + void + AES_DestroyContext(AESContext *cx, PRBool freeit) + { ++ void *mem = cx->mem; + if (cx->worker_cx && cx->destroy) { + (*cx->destroy)(cx->worker_cx, PR_TRUE); + cx->worker_cx = NULL; + cx->destroy = NULL; + } ++ PORT_Memset(cx, 0, sizeof(AESContext)); + if (freeit) { +- PORT_Free(cx->mem); ++ PORT_Free(mem); + } + } + + /* + * AES_Encrypt + * + * Encrypt an arbitrary-length buffer. The output buffer must already be + * allocated to at least inputLen. diff --git a/SOURCES/nss-softokn-fix-ecc-post.patch b/SOURCES/nss-softokn-fix-ecc-post.patch deleted file mode 100644 index 3fe1836..0000000 --- a/SOURCES/nss-softokn-fix-ecc-post.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff -up ./nss/lib/freebl/fipsfreebl.c.ecc_post ./nss/lib/freebl/fipsfreebl.c ---- ./nss/lib/freebl/fipsfreebl.c.ecc_post 2017-07-21 18:33:27.946809392 -0700 -+++ ./nss/lib/freebl/fipsfreebl.c 2017-07-21 18:34:09.065510689 -0700 -@@ -15,9 +15,7 @@ - #include "secerr.h" - #include "prtypes.h" - --#ifdef NSS_ENABLE_ECC - #include "ec.h" /* Required for ECDSA */ --#endif - - /* - * different platforms have different ways of calling and initial entry point -@@ -1077,7 +1075,6 @@ rsa_loser: - return (SECFailure); - } - --#ifdef NSS_ENABLE_ECC - - static SECStatus - freebl_fips_ECDSA_Test(ECParams *ecparams, -@@ -1275,8 +1272,6 @@ freebl_fips_ECDSA_PowerUpSelfTest() - return (SECSuccess); - } - --#endif /* NSS_ENABLE_ECC */ -- - static SECStatus - freebl_fips_DSA_PowerUpSelfTest(void) - { -@@ -1559,13 +1554,11 @@ freebl_fipsPowerUpSelfTest(unsigned int - if (rv != SECSuccess) - return rv; - --#ifdef NSS_ENABLE_ECC - /* ECDSA Power-Up SelfTest(s). */ - rv = freebl_fips_ECDSA_PowerUpSelfTest(); - - if (rv != SECSuccess) - return rv; --#endif - } - /* Passed Power-Up SelfTest(s). */ - return (SECSuccess); diff --git a/SOURCES/nss-softokn-fs-probe.patch b/SOURCES/nss-softokn-fs-probe.patch new file mode 100644 index 0000000..a070bae --- /dev/null +++ b/SOURCES/nss-softokn-fs-probe.patch @@ -0,0 +1,79 @@ +# HG changeset patch +# User David Keeler +# Date 1500978196 -7200 +# Tue Jul 25 12:23:16 2017 +0200 +# Node ID 9c94423e0669decabbb22b0d52ce31115c750265 +# Parent f212be04f3d0265340bf5ae20ffbbccdda68b0aa +bug 1382736 - Don't perform costly filesystem probes at startup r=ttaubert + +Differential Revision: https://nss-review.dev.mozaws.net/D374 + +diff --git a/lib/softoken/sdb.c b/lib/softoken/sdb.c +--- a/lib/softoken/sdb.c ++++ b/lib/softoken/sdb.c +@@ -1866,30 +1866,29 @@ sdb_init(char *dbname, char *table, sdbD + * so we use it for the cache (see sdb_buildCache for how it's done).*/ + + /* +- * we decide whether or not to use the cache based on the following input. +- * +- * NSS_SDB_USE_CACHE environment variable is non-existant or set to +- * anything other than "no" or "yes" ("auto", for instance). +- * This is the normal case. NSS will measure the performance of access +- * to the temp database versus the access to the users passed in +- * database location. If the temp database location is "significantly" +- * faster we will use the cache. +- * +- * NSS_SDB_USE_CACHE environment variable is set to "no": cache will not +- * be used. +- * +- * NSS_SDB_USE_CACHE environment variable is set to "yes": cache will +- * always be used. +- * +- * It is expected that most applications would use the "auto" selection, +- * the environment variable is primarily to simplify testing, and to +- * correct potential corner cases where */ ++ * we decide whether or not to use the cache based on the following input. ++ * ++ * NSS_SDB_USE_CACHE environment variable is set to anything other than ++ * "yes" or "no" (for instance, "auto"): NSS will measure the performance ++ * of access to the temp database versus the access to the user's ++ * passed-in database location. If the temp database location is ++ * "significantly" faster we will use the cache. ++ * ++ * NSS_SDB_USE_CACHE environment variable is nonexistent or set to "no": ++ * cache will not be used. ++ * ++ * NSS_SDB_USE_CACHE environment variable is set to "yes": cache will ++ * always be used. ++ * ++ * It is expected that most applications will not need this feature, and ++ * thus it is disabled by default. ++ */ + + env = PR_GetEnvSecure("NSS_SDB_USE_CACHE"); + +- if (env && PORT_Strcasecmp(env, "no") == 0) { ++ if (!env || PORT_Strcasecmp(env, "no") == 0) { + enableCache = PR_FALSE; +- } else if (env && PORT_Strcasecmp(env, "yes") == 0) { ++ } else if (PORT_Strcasecmp(env, "yes") == 0) { + enableCache = PR_TRUE; + } else { + char *tempDir = NULL; +@@ -2035,10 +2034,11 @@ s_open(const char *directory, const char + { + char *env; + env = PR_GetEnvSecure("NSS_SDB_USE_CACHE"); +- /* If the environment variable is set to yes or no, sdb_init() will +- * ignore the value of accessOps, and we can skip the measuring.*/ +- if (!env || ((PORT_Strcasecmp(env, "no") != 0) && +- (PORT_Strcasecmp(env, "yes") != 0))) { ++ /* If the environment variable is undefined or set to yes or no, ++ * sdb_init() will ignore the value of accessOps, and we can skip the ++ * measuring.*/ ++ if (env && PORT_Strcasecmp(env, "no") != 0 && ++ PORT_Strcasecmp(env, "yes") != 0) { + accessOps = sdb_measureAccess(directory); + } + } diff --git a/SPECS/nss-softokn.spec b/SPECS/nss-softokn.spec index c6d5557..e598ef8 100644 --- a/SPECS/nss-softokn.spec +++ b/SPECS/nss-softokn.spec @@ -1,7 +1,7 @@ -%global nspr_version 4.17.0 +%global nspr_version 4.19.0 %global nss_name nss -%global nss_util_version 3.34.0 -%global nss_util_build -2 +%global nss_util_version 3.36.0 +%global nss_util_build -1 %global unsupported_tools_directory %{_libdir}/nss/unsupported-tools %global saved_files_dir %{_libdir}/nss/saved %global prelink_conf_dir %{_sysconfdir}/prelink.conf.d/ @@ -31,8 +31,8 @@ Summary: Network Security Services Softoken Module Name: nss-softokn -Version: 3.34.0 -Release: 2%{?dist} +Version: 3.36.0 +Release: 5%{?dist} License: MPLv2.0 URL: http://www.mozilla.org/projects/security/pki/nss/ Group: System Environment/Libraries @@ -77,12 +77,23 @@ Source6: nss-softokn-dracut.conf # Once has been bootstapped the patch may be removed, but it doesn't hurt to keep it. Patch10: iquote.patch +# Upstream: https://bugzilla.mozilla.org/show_bug.cgi?id=1236720 +# Although the greater part of the patch has been upstreamed, we still +# need a downstream patch to keep the single DES mechanisms we had +# provided in a downstream patch for compatibility reasons. Patch97: nss-softokn-3.16-add_encrypt_derive.patch Patch102: nss-softokn-tls-abi-fix.patch -# Not upstreamed: https://bugzilla.redhat.com/show_bug.cgi?id=1390154 -Patch105: nss-softokn-3.28-fix-fips-login.patch -Patch107: nss-softokn-fix-ecc-post.patch + +# Not upstreamed: https://bugzilla.redhat.com/show_bug.cgi?id=1548394 +Patch103: nss-softokn-add-kas-tests.patch + +# To revert the upstream change in the default behavior in: +# https://bugzilla.mozilla.org/show_bug.cgi?id=1382736 +Patch104: nss-softokn-fs-probe.patch + +# Not upstreamed: https://bugzilla.redhat.com/show_bug.cgi?id=1555108 +Patch105: nss-softokn-aes-zeroize.patch %description Network Security Services Softoken Cryptographic Module @@ -139,11 +150,14 @@ Header and library files for doing development with Network Security Services. # activate if needed when doing a major update with new apis #%patch10 -p0 -b .iquote -%patch97 -p0 -b .add_encrypt_derive +pushd nss +%patch97 -p1 -b .add_encrypt_derive +%patch103 -p1 -b .add-kas-tests +%patch104 -p1 -R -b .fs-probe +%patch105 -p1 -b .aes-zeroize +popd %patch102 -p1 -b .tls-abi-fix -%patch105 -p1 -b .fix-fips-login -%patch107 -p1 -b .ecc_post %build @@ -469,6 +483,34 @@ done %{_includedir}/nss3/shsign.h %changelog +* Mon Mar 19 2018 Daiki Ueno - 3.36.0-5 +- Use correct tarball of NSS 3.36.0 release + +* Thu Mar 15 2018 Bob Relyea - 3.36.0-4 +- Clear AES key information after use + +* Wed Mar 7 2018 Daiki Ueno - 3.36.0-3 +- Revert the default behavior change in filesystem probes + +* Wed Mar 7 2018 Bob Relyea - 3.36.0-2 +- Add KAS tests to fipstest + +* Mon Mar 5 2018 Daiki Ueno - 3.36.0-1 +- Update to NSS 3.36.0 + +* Mon Mar 5 2018 Daiki Ueno - 3.36.0-0.3.beta +- Apply upstream patch likely to be part of the official release + +* Thu Mar 1 2018 Daiki Ueno - 3.36.0-0.2.beta +- Restore nss-softokn-3.16-add_encrypt_derive.patch to add back + support for single DES mechanisms + +* Thu Mar 1 2018 Daiki Ueno - 3.36.0-0.1.beta +- Update to NSS 3.36 BETA +- Remove upstreamed nss-softokn-3.16-add_encrypt_derive.patch +- Remove upstreamed nss-softokn-3.28-fix-fips-login.patch +- Remove upstreamed nss-softokn-fix-ecc-post.patch + * Tue Jan 16 2018 Daiki Ueno - 3.34.0-2 - Rebuild to utilize ECC slotFlag added in nss-util