summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/softoken
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2021-01-19 08:08:18 +0000
committerMoonchild <moonchild@palemoon.org>2021-01-19 08:08:18 +0000
commitc76214f0b54cf74b69d0fb4afa0d2eca2e898a98 (patch)
tree15ee2e9776727ecabcdc52d06de55dfd576485c1 /security/nss/lib/softoken
parent810c2bf8080da2bc8ec4efb05223fea31817944b (diff)
parent75286e68d703b1d8a4e0a7c72ce45d089024c124 (diff)
downloadUXP-c76214f0b54cf74b69d0fb4afa0d2eca2e898a98.tar
UXP-c76214f0b54cf74b69d0fb4afa0d2eca2e898a98.tar.gz
UXP-c76214f0b54cf74b69d0fb4afa0d2eca2e898a98.tar.lz
UXP-c76214f0b54cf74b69d0fb4afa0d2eca2e898a98.tar.xz
UXP-c76214f0b54cf74b69d0fb4afa0d2eca2e898a98.zip
Master merge
This merges master into release to replace Redwood. # Conflicts: # CLOBBER # build/moz.configure/old.configure # config/milestone.txt # config/moz.build # config/system-headers # dom/abort/AbortController.cpp # dom/abort/AbortController.h # dom/abort/AbortSignal.cpp # dom/abort/AbortSignal.h # dom/abort/moz.build # dom/abort/tests/moz.build # dom/animation/KeyframeEffect.cpp # dom/base/CustomElementRegistry.cpp # dom/base/DocGroup.cpp # dom/base/ResizeObserverController.cpp # dom/base/ResizeObserverController.h # dom/base/nsContentUtils.cpp # dom/base/nsContentUtils.h # dom/base/nsDocument.cpp # dom/base/nsIDocument.h # dom/fetch/FetchObserver.cpp # dom/fetch/FetchObserver.h # dom/heapsnapshot/AutoMemMap.cpp # dom/heapsnapshot/AutoMemMap.h # dom/heapsnapshot/CoreDump.proto # dom/heapsnapshot/HeapSnapshot.cpp # dom/heapsnapshot/HeapSnapshotTempFileHelperChild.h # dom/heapsnapshot/HeapSnapshotTempFileHelperParent.cpp # dom/heapsnapshot/HeapSnapshotTempFileHelperParent.h # dom/heapsnapshot/PHeapSnapshotTempFileHelper.ipdl # dom/heapsnapshot/moz.build # dom/heapsnapshot/tests/gtest/moz.build # dom/html/nsGenericHTMLElement.h # dom/media/platforms/PlatformDecoderModule.h # dom/media/platforms/moz.build # dom/script/ModuleLoadRequest.cpp # dom/script/ModuleLoadRequest.h # dom/script/ModuleScript.cpp # dom/script/ModuleScript.h # dom/script/ScriptElement.cpp # dom/script/ScriptElement.h # dom/script/ScriptLoadHandler.cpp # dom/script/ScriptLoadHandler.h # dom/script/ScriptLoader.cpp # dom/script/ScriptLoader.h # dom/script/ScriptSettings.cpp # dom/script/ScriptSettings.h # dom/script/nsIScriptElement.h # dom/script/nsIScriptLoaderObserver.idl # dom/webidl/HTMLLinkElement.webidl # gfx/gl/moz.build # gfx/graphite2/src/moz.build # gfx/layers/moz.build # js/ductwork/inspector/moz.build # js/ductwork/moz.build # js/src/gc/Heap.h # js/src/moz.build # js/src/vm/UnboxedObject-inl.h # js/src/vm/UnboxedObject.cpp # js/src/vm/UnboxedObject.h # layout/base/crashtests/crashtests.list # layout/build/moz.build # layout/generic/AspectRatio.h # layout/generic/crashtests/crashtests.list # layout/reftests/bidi/reftest-stylo.list # layout/reftests/reftest-stylo.list # layout/reftests/table-bordercollapse/reftest.list # layout/reftests/writing-mode/reftest-stylo.list # layout/style/StyleSheet.cpp # layout/style/nsRuleNode.cpp # layout/style/nsStyleStruct.cpp # layout/style/nsStyleStruct.h # modules/libpref/init/all.js # nsprpub/pr/src/linking/prlink.c # parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/AttributeName.java # parser/html/java/htmlparser/src/nu/validator/htmlparser/impl/ElementName.java # parser/html/nsHtml5AtomList.h # parser/html/nsHtml5AttributeName.cpp # parser/html/nsHtml5AttributeName.h # parser/html/nsHtml5ElementName.cpp # parser/html/nsHtml5ElementName.h # parser/html/nsHtml5TreeBuilderCppSupplement.h # parser/htmlparser/nsElementTable.cpp # parser/htmlparser/nsHTMLTagList.h # security/nss/lib/nss/nss.h # security/nss/lib/softoken/pkcs11.c # security/nss/lib/softoken/softkver.h # security/nss/lib/util/nssutil.h # testing/web-platform/tests/tools/html5lib/html5lib/html5parser.py # testing/web-platform/tests/tools/html5lib/html5lib/treebuilders/_base.py # toolkit/modules/AppConstants.jsm
Diffstat (limited to 'security/nss/lib/softoken')
-rw-r--r--security/nss/lib/softoken/exports.gyp10
-rw-r--r--security/nss/lib/softoken/fipstest.c117
-rw-r--r--security/nss/lib/softoken/fipstokn.c389
-rw-r--r--security/nss/lib/softoken/kbkdf.c1518
-rw-r--r--security/nss/lib/softoken/legacydb/keydb.c6
-rw-r--r--security/nss/lib/softoken/legacydb/lgattr.c8
-rw-r--r--security/nss/lib/softoken/legacydb/lgcreate.c30
-rw-r--r--security/nss/lib/softoken/legacydb/lgdb.h2
-rw-r--r--security/nss/lib/softoken/legacydb/lgfind.c12
-rw-r--r--security/nss/lib/softoken/legacydb/lginit.c8
-rw-r--r--security/nss/lib/softoken/lgglue.c9
-rw-r--r--security/nss/lib/softoken/lowpbe.c422
-rw-r--r--security/nss/lib/softoken/lowpbe.h5
-rw-r--r--security/nss/lib/softoken/manifest.mn12
-rw-r--r--security/nss/lib/softoken/pkcs11.c292
-rw-r--r--security/nss/lib/softoken/pkcs11c.c1153
-rw-r--r--security/nss/lib/softoken/pkcs11i.h79
-rw-r--r--security/nss/lib/softoken/pkcs11u.c127
-rw-r--r--security/nss/lib/softoken/sdb.c411
-rw-r--r--security/nss/lib/softoken/sdb.h4
-rw-r--r--security/nss/lib/softoken/sftkdb.c276
-rw-r--r--security/nss/lib/softoken/sftkdb.h3
-rw-r--r--security/nss/lib/softoken/sftkdbti.h33
-rw-r--r--security/nss/lib/softoken/sftkdhverify.c1282
-rw-r--r--security/nss/lib/softoken/sftkhmac.c12
-rw-r--r--security/nss/lib/softoken/sftkike.c170
-rw-r--r--security/nss/lib/softoken/sftkmessage.c377
-rw-r--r--security/nss/lib/softoken/sftkpwd.c134
-rw-r--r--security/nss/lib/softoken/softkver.h8
-rw-r--r--security/nss/lib/softoken/softoken.gyp11
-rw-r--r--security/nss/lib/softoken/softoken.h17
-rw-r--r--security/nss/lib/softoken/softokn.def11
32 files changed, 6249 insertions, 699 deletions
diff --git a/security/nss/lib/softoken/exports.gyp b/security/nss/lib/softoken/exports.gyp
index d11d8e49a..82b9817e6 100644
--- a/security/nss/lib/softoken/exports.gyp
+++ b/security/nss/lib/softoken/exports.gyp
@@ -19,7 +19,6 @@
},
{
'files': [
- 'lgglue.h',
'pkcs11ni.h',
'sdb.h',
'sftkdbt.h',
@@ -27,7 +26,14 @@
'softoken.h',
'softoknt.h'
],
- 'destination': '<(nss_private_dist_dir)/<(module)'
+ 'destination': '<(nss_private_dist_dir)/<(module)',
+ 'conditions': [
+ [ 'disable_dbm==0', {
+ 'files': [
+ 'lgglue.h',
+ ]
+ }]
+ ]
}
]
}
diff --git a/security/nss/lib/softoken/fipstest.c b/security/nss/lib/softoken/fipstest.c
index e765cde4c..aa4992cd2 100644
--- a/security/nss/lib/softoken/fipstest.c
+++ b/security/nss/lib/softoken/fipstest.c
@@ -13,6 +13,7 @@
#include "secoid.h"
#include "secerr.h"
#include "pkcs11i.h"
+#include "lowpbe.h"
/*
* different platforms have different ways of calling and initial entry point
@@ -581,6 +582,106 @@ rsa_loser:
return (SECFailure);
}
+static SECStatus
+sftk_fips_HKDF_PowerUpSelfTest(void)
+{
+ SECStatus status;
+ static const unsigned char base_key[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
+ };
+ static const unsigned char known_hkdf_sha256_key[] = {
+ 0xdd, 0xdb, 0xeb, 0xe5, 0x6d, 0xd2, 0x96, 0xa4,
+ 0x07, 0xc5, 0x7d, 0xda, 0x31, 0x56, 0x8d, 0xa5,
+ 0x41, 0x3e, 0x90, 0xd4, 0xe6, 0x98, 0xeb, 0xf8,
+ 0x5a, 0x49, 0x7f, 0x38, 0xef, 0x01, 0x8a, 0xe5,
+ 0xda, 0x36, 0xe5, 0xcf, 0x21, 0xe3, 0x9f, 0xc3,
+ 0x32, 0xb3, 0x1e, 0xf6, 0xc5, 0x10, 0x4c, 0x86,
+ 0x53, 0x5e, 0x6f, 0xe0, 0x63, 0x6e, 0x43, 0x33,
+ 0x61, 0x35, 0xf4, 0x17, 0x10, 0x77, 0x75, 0x2a
+ };
+/* current NIST IG's say we only need to test one instance
+ * of kdfs, keep these others around in case the guidance
+ * changes */
+#ifdef NSS_FULL_POST
+ static const unsigned char known_hkdf_sha384_key[] = {
+ 0x35, 0x64, 0xc4, 0xa1, 0xcc, 0xc1, 0xdc, 0xe4,
+ 0xe2, 0xca, 0x51, 0xae, 0xe8, 0x92, 0x88, 0x30,
+ 0x8b, 0xb0, 0x2b, 0xac, 0x00, 0x15, 0xac, 0x15,
+ 0x97, 0xc9, 0xf4, 0x6b, 0xf6, 0x3f, 0x97, 0xea,
+ 0x48, 0x55, 0x38, 0x25, 0x06, 0x5d, 0x91, 0x64,
+ 0xbd, 0x09, 0xf3, 0x44, 0xbc, 0x82, 0xbe, 0xdb,
+ 0x5c, 0xd7, 0xf2, 0x24, 0xa5, 0x55, 0x8d, 0xa9,
+ 0xa8, 0x85, 0xde, 0x8c, 0x33, 0xe0, 0x4d, 0xc3
+ };
+ static const unsigned char known_hkdf_sha512_key[] = {
+ 0x63, 0x4e, 0xbc, 0x42, 0xb3, 0x56, 0x74, 0x7d,
+ 0x1b, 0x55, 0xf0, 0x34, 0x54, 0xcb, 0x6d, 0x58,
+ 0x39, 0x96, 0x10, 0xda, 0x03, 0x20, 0x8f, 0x77,
+ 0x0d, 0xb4, 0xf7, 0xf6, 0x67, 0x0d, 0x5b, 0x6b,
+ 0xd0, 0x30, 0xc4, 0xdd, 0x67, 0x61, 0x5d, 0x9a,
+ 0xf5, 0x18, 0x6e, 0x1b, 0x60, 0x97, 0xc2, 0x4d,
+ 0x23, 0x43, 0x69, 0xe6, 0x3b, 0xa5, 0xdf, 0xe9,
+ 0x7c, 0xf1, 0x87, 0x48, 0x6f, 0xb9, 0xd3, 0x02
+ };
+#endif
+ unsigned char outBytes[64] = { 0 };
+
+ CK_HKDF_PARAMS hkdf_params;
+
+ hkdf_params.bExpand = CK_TRUE;
+ hkdf_params.bExtract = CK_TRUE;
+ hkdf_params.ulSaltType = CKF_HKDF_SALT_DATA;
+ hkdf_params.pSalt = (CK_BYTE_PTR)base_key;
+ hkdf_params.ulSaltLen = sizeof(base_key);
+ hkdf_params.pInfo = (CK_BYTE_PTR)base_key;
+ hkdf_params.ulInfoLen = sizeof(base_key);
+
+ /**************************************************/
+ /* HKDF tests */
+ /**************************************************/
+
+ hkdf_params.prfHashMechanism = CKM_SHA256_HMAC;
+ status = sftk_HKDF(&hkdf_params, CK_INVALID_HANDLE, NULL,
+ base_key, 32, NULL, outBytes, sizeof(outBytes),
+ PR_TRUE, PR_TRUE);
+ if ((status != SECSuccess) ||
+ PORT_Memcmp(outBytes, known_hkdf_sha256_key, sizeof(outBytes)) != 0) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return (SECFailure);
+ }
+
+#ifdef NSS_FULL_POST
+ hkdf_params.prfHashMechanism = CKM_SHA384_HMAC;
+ status = sftk_HKDF(&hkdf_params, CK_INVALID_HANDLE, NULL,
+ base_key, 48, NULL, outBytes, sizeof(outBytes),
+ PR_TRUE, PR_TRUE);
+ if ((status != SECSuccess) ||
+ PORT_Memcmp(outBytes, known_hkdf_sha384_key, sizeof(outBytes)) != 0) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return (SECFailure);
+ }
+
+ hkdf_params.prfHashMechanism = CKM_SHA512_HMAC;
+ status = sftk_HKDF(&hkdf_params, CK_INVALID_HANDLE, NULL,
+ base_key, 64, NULL, outBytes, sizeof(outBytes),
+ PR_TRUE, PR_TRUE);
+ if ((status != SECSuccess) ||
+ PORT_Memcmp(outBytes, known_hkdf_sha512_key, sizeof(outBytes)) != 0) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return (SECFailure);
+ }
+#endif
+
+ return (SECSuccess);
+}
+
static PRBool sftk_self_tests_ran = PR_FALSE;
static PRBool sftk_self_tests_success = PR_FALSE;
@@ -631,6 +732,22 @@ sftk_startup_tests(void)
if (rv != SECSuccess) {
return;
}
+
+ rv = sftk_fips_SP800_108_PowerUpSelfTests();
+ if (rv != SECSuccess) {
+ return;
+ }
+
+ rv = sftk_fips_HKDF_PowerUpSelfTest();
+ if (rv != SECSuccess) {
+ return;
+ }
+
+ rv = sftk_fips_pbkdf_PowerUpSelfTests();
+ if (rv != SECSuccess) {
+ return;
+ }
+
sftk_self_tests_success = PR_TRUE;
}
diff --git a/security/nss/lib/softoken/fipstokn.c b/security/nss/lib/softoken/fipstokn.c
index 166f19de2..6ffec5de1 100644
--- a/security/nss/lib/softoken/fipstokn.c
+++ b/security/nss/lib/softoken/fipstokn.c
@@ -230,6 +230,8 @@ fc_getAttribute(CK_ATTRIBUTE_PTR pTemplate,
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
+#define CK_PKCS11_3_0 1
+
#define CK_PKCS11_FUNCTION_INFO(name) CK_RV __PASTE(NS, name)
#define CK_NEED_ARG_LIST 1
@@ -245,11 +247,37 @@ fc_getAttribute(CK_ATTRIBUTE_PTR pTemplate,
#include "pkcs11f.h"
/* ------------- build the CK_CRYPTO_TABLE ------------------------- */
-static CK_FUNCTION_LIST sftk_fipsTable = {
- { 1, 10 },
+static CK_FUNCTION_LIST_3_0 sftk_fipsTable = {
+ { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ __PASTE(F, name) \
+ ,
+
+#include "pkcs11f.h"
+
+};
+
+/* forward declaration of special GetInfo functions */
+CK_RV FC_GetInfoV2(CK_INFO_PTR pInfo);
+CK_RV NSC_GetInfoV2(CK_INFO_PTR pInfo);
+CK_RV FC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo);
+CK_RV NSC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo);
+
+static CK_FUNCTION_LIST sftk_fipsTable_v2 = {
+ { 2, 40 },
+#undef CK_PKCS11_3_0
+#define CK_PKCS11_2_0_ONLY 1
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
+#define C_GetInfo C_GetInfoV2
+#define C_GetMechanismInfo C_GetMechanismInfoV2
#define CK_PKCS11_FUNCTION_INFO(name) \
__PASTE(F, name) \
@@ -259,11 +287,25 @@ static CK_FUNCTION_LIST sftk_fipsTable = {
};
+#undef C_GetInfo
+#undef C_GetMechanismInfo
#undef CK_NEED_ARG_LIST
#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_PKCS11_2_0_ONLY
#undef __PASTE
+/*
+ * Array is orderd by default first
+ */
+static CK_INTERFACE fips_interfaces[] = {
+ { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable, NSS_INTERFACE_FLAGS },
+ { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_fipsTable_v2, NSS_INTERFACE_FLAGS },
+ { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS }
+};
+/* must match the count of interfaces in fips_interfaces above*/
+#define FIPS_INTERFACE_COUNT 3
+
/* CKO_NOT_A_KEY can be any object class that's not a key object. */
#define CKO_NOT_A_KEY CKO_DATA
@@ -419,10 +461,51 @@ FC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
CHECK_FORK();
- *pFunctionList = &sftk_fipsTable;
+ *pFunctionList = &sftk_fipsTable_v2;
+ return CKR_OK;
+}
+
+CK_RV
+FC_GetInterfaceList(CK_INTERFACE_PTR interfaces, CK_ULONG_PTR pulCount)
+{
+ CK_ULONG count = *pulCount;
+ *pulCount = FIPS_INTERFACE_COUNT;
+ if (interfaces == NULL) {
+ return CKR_OK;
+ }
+ if (count < FIPS_INTERFACE_COUNT) {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ PORT_Memcpy(interfaces, fips_interfaces, sizeof(fips_interfaces));
return CKR_OK;
}
+/*
+ * Get the requested interface, use the fips_interfaces array so we can
+ * easily add new interfaces as they occur.
+ */
+CK_RV
+FC_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion,
+ CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags)
+{
+ int i;
+ for (i = 0; i < FIPS_INTERFACE_COUNT; i++) {
+ CK_INTERFACE_PTR interface = &fips_interfaces[i];
+ if (pInterfaceName && PORT_Strcmp((char *)pInterfaceName, (char *)interface->pInterfaceName) != 0) {
+ continue;
+ }
+ if (pVersion && PORT_Memcmp(pVersion, (CK_VERSION *)interface->pFunctionList, sizeof(CK_VERSION)) != 0) {
+ continue;
+ }
+ if (flags & ((interface->flags & flags) != flags)) {
+ continue;
+ }
+ *ppInterface = interface;
+ return CKR_OK;
+ }
+ return CKR_ARGUMENTS_BAD;
+}
+
/* sigh global so pkcs11 can read it */
PRBool nsf_init = PR_FALSE;
@@ -510,6 +593,15 @@ FC_GetInfo(CK_INFO_PTR pInfo)
return NSC_GetInfo(pInfo);
}
+/* FC_GetInfo returns general information about PKCS #11. */
+CK_RV
+FC_GetInfoV2(CK_INFO_PTR pInfo)
+{
+ CHECK_FORK();
+
+ return NSC_GetInfoV2(pInfo);
+}
+
/* FC_GetSlotList obtains a list of slots in the system. */
CK_RV
FC_GetSlotList(CK_BBOOL tokenPresent,
@@ -540,7 +632,7 @@ FC_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
crv = NSC_GetTokenInfo(slotID, pInfo);
if (crv == CKR_OK) {
- /* use the global database to figure out if we are running in
+ /* 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) {
@@ -581,6 +673,22 @@ FC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
return NSC_GetMechanismInfo(slotID, type, pInfo);
}
+/* FC_GetMechanismInfoV2 same as FC_GetMechanismInfo except the Message
+ * flags have been stripped out */
+CK_RV
+FC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo)
+{
+ CHECK_FORK();
+
+ SFTK_FIPSFATALCHECK();
+ if ((slotID == FIPS_SLOT_ID) || (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID)) {
+ slotID = NETSCAPE_SLOT_ID;
+ }
+ /* FIPS Slots support all functions */
+ return NSC_GetMechanismInfoV2(slotID, type, pInfo);
+}
+
/* FC_InitToken initializes a token. */
CK_RV
FC_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin,
@@ -718,6 +826,16 @@ FC_CloseAllSessions(CK_SLOT_ID slotID)
return NSC_CloseAllSessions(slotID);
}
+CK_RV
+FC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags)
+{
+ SFTK_FIPSFATALCHECK();
+
+ CHECK_FORK();
+
+ return NSC_SessionCancel(hSession, flags);
+}
+
/* FC_GetSessionInfo obtains information about the session. */
CK_RV
FC_GetSessionInfo(CK_SESSION_HANDLE hSession,
@@ -777,6 +895,36 @@ FC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
return rv;
}
+CK_RV
+FC_LoginUser(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
+ CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pUsername,
+ CK_ULONG ulUsernameLen)
+{
+ CK_RV rv;
+ PRBool successful;
+ if (sftk_fatalError)
+ return CKR_DEVICE_ERROR;
+ rv = NSC_LoginUser(hSession, userType, pPin, ulPinLen,
+ pUsername, ulUsernameLen);
+ successful = (rv == CKR_OK) || (rv == CKR_USER_ALREADY_LOGGED_IN);
+ if (successful)
+ isLoggedIn = PR_TRUE;
+ if (sftk_audit_enabled) {
+ char msg[128];
+ char user[61];
+ int len = PR_MIN(ulUsernameLen, sizeof(user) - 1);
+ PORT_Memcpy(user, pUsername, len);
+ user[len] = 0;
+ NSSAuditSeverity severity;
+ severity = successful ? NSS_AUDIT_INFO : NSS_AUDIT_ERROR;
+ PR_snprintf(msg, sizeof msg,
+ "C_LoginUser(hSession=0x%08lX, userType=%lu username=%s)=0x%08lX",
+ (PRUint32)hSession, (PRUint32)userType, user, (PRUint32)rv);
+ sftk_LogAuditMessage(severity, NSS_AUDIT_LOGIN, msg);
+ }
+ return rv;
+}
+
/* FC_Logout logs a user out from a token. */
CK_RV
FC_Logout(CK_SESSION_HANDLE hSession)
@@ -815,7 +963,7 @@ FC_CreateObject(CK_SESSION_HANDLE hSession,
if (classptr == NULL)
return CKR_TEMPLATE_INCOMPLETE;
- if (*classptr == CKO_NETSCAPE_NEWSLOT || *classptr == CKO_NETSCAPE_DELSLOT) {
+ if (*classptr == CKO_NSS_NEWSLOT || *classptr == CKO_NSS_DELSLOT) {
if (sftk_fatalError)
return CKR_DEVICE_ERROR;
} else {
@@ -1691,3 +1839,234 @@ FC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot,
return NSC_WaitForSlotEvent(flags, pSlot, pReserved);
}
+
+CK_RV
+FC_MessageEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+
+ rv = NSC_MessageEncryptInit(hSession, pMechanism, hKey);
+ if (sftk_audit_enabled) {
+ sftk_AuditCryptInit("MessageEncrypt", hSession, pMechanism, hKey, rv);
+ }
+ return rv;
+}
+
+CK_RV
+FC_EncryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pPlaintext,
+ CK_ULONG ulPlaintextLen, CK_BYTE_PTR pCiphertext,
+ CK_ULONG_PTR pulCiphertextLen)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_EncryptMessage(hSession, pParameter, ulParameterLen,
+ pAssociatedData, ulAssociatedDataLen,
+ pPlaintext, ulPlaintextLen, pCiphertext,
+ pulCiphertextLen);
+}
+
+CK_RV
+FC_EncryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_EncryptMessageBegin(hSession, pParameter, ulParameterLen,
+ pAssociatedData, ulAssociatedDataLen);
+}
+
+CK_RV
+FC_EncryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pPlaintextPart,
+ CK_ULONG ulPlaintextPartLen, CK_BYTE_PTR pCiphertextPart,
+ CK_ULONG_PTR pulCiphertextPartLen, CK_FLAGS flags)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_EncryptMessageNext(hSession, pParameter, ulParameterLen,
+ pPlaintextPart, ulPlaintextPartLen,
+ pCiphertextPart, pulCiphertextPartLen, flags);
+}
+
+CK_RV
+FC_MessageEncryptFinal(CK_SESSION_HANDLE hSession)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_MessageEncryptFinal(hSession);
+}
+
+CK_RV
+FC_MessageDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+
+ rv = NSC_MessageDecryptInit(hSession, pMechanism, hKey);
+ if (sftk_audit_enabled) {
+ sftk_AuditCryptInit("MessageDecrypt", hSession, pMechanism, hKey, rv);
+ }
+ return rv;
+}
+
+CK_RV
+FC_DecryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pCiphertext,
+ CK_ULONG ulCiphertextLen, CK_BYTE_PTR pPlaintext,
+ CK_ULONG_PTR pulPlaintextLen)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_DecryptMessage(hSession, pParameter, ulParameterLen,
+ pAssociatedData, ulAssociatedDataLen,
+ pCiphertext, ulCiphertextLen, pPlaintext,
+ pulPlaintextLen);
+}
+
+CK_RV
+FC_DecryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_DecryptMessageBegin(hSession, pParameter, ulParameterLen,
+ pAssociatedData, ulAssociatedDataLen);
+}
+
+CK_RV
+FC_DecryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pCiphertextPart,
+ CK_ULONG ulCiphertextPartLen, CK_BYTE_PTR pPlaintextPart,
+ CK_ULONG_PTR pulPlaintextPartLen, CK_FLAGS flags)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_DecryptMessageNext(hSession, pParameter, ulParameterLen,
+ pCiphertextPart, ulCiphertextPartLen,
+ pPlaintextPart, pulPlaintextPartLen, flags);
+}
+
+CK_RV
+FC_MessageDecryptFinal(CK_SESSION_HANDLE hSession)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_MessageDecryptFinal(hSession);
+}
+
+CK_RV
+FC_MessageSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+
+ rv = NSC_MessageSignInit(hSession, pMechanism, hKey);
+ if (sftk_audit_enabled) {
+ sftk_AuditCryptInit("MessageSign", hSession, pMechanism, hKey, rv);
+ }
+ return rv;
+}
+
+CK_RV
+FC_SignMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_SignMessage(hSession, pParameter, ulParameterLen, pData,
+ ulDataLen, pSignature, pulSignatureLen);
+}
+
+CK_RV
+FC_SignMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_SignMessageBegin(hSession, pParameter, ulParameterLen);
+}
+
+CK_RV
+FC_SignMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_SignMessageNext(hSession, pParameter, ulParameterLen, pData,
+ ulDataLen, pSignature, pulSignatureLen);
+}
+
+CK_RV
+FC_MessageSignFinal(CK_SESSION_HANDLE hSession)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_MessageSignFinal(hSession);
+}
+
+CK_RV
+FC_MessageVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+
+ rv = NSC_MessageVerifyInit(hSession, pMechanism, hKey);
+ if (sftk_audit_enabled) {
+ sftk_AuditCryptInit("MessageVerify", hSession, pMechanism, hKey, rv);
+ }
+ return rv;
+}
+
+CK_RV
+FC_VerifyMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_VerifyMessage(hSession, pParameter, ulParameterLen, pData,
+ ulDataLen, pSignature, ulSignatureLen);
+}
+
+CK_RV
+FC_VerifyMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_VerifyMessageBegin(hSession, pParameter, ulParameterLen);
+}
+
+CK_RV
+FC_VerifyMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_VerifyMessageNext(hSession, pParameter, ulParameterLen,
+ pData, ulDataLen, pSignature, ulSignatureLen);
+}
+
+CK_RV
+FC_MessageVerifyFinal(CK_SESSION_HANDLE hSession)
+{
+ SFTK_FIPSCHECK();
+ CHECK_FORK();
+ return NSC_MessageVerifyFinal(hSession);
+}
diff --git a/security/nss/lib/softoken/kbkdf.c b/security/nss/lib/softoken/kbkdf.c
new file mode 100644
index 000000000..b4544c432
--- /dev/null
+++ b/security/nss/lib/softoken/kbkdf.c
@@ -0,0 +1,1518 @@
+#include "pkcs11i.h"
+#include "blapi.h"
+#include "secerr.h"
+#include "softoken.h"
+
+/* Overview:
+ *
+ * This file contains implementations of the three KDFs from NIST SP800-108
+ * "Recommendation for Key Derivation Using Pseudorandom Functions":
+ *
+ * 1. KDF in Counter Mode (section 5.1)
+ * 2. KDF in Feedback Mode (section 5.2)
+ * 3. KDF in Double-Pipeline Iteration Mode (section 5.3)
+ *
+ * These KDFs are a form of negotiable building blocks for KDFs: protocol
+ * designers can choose various fields, their endianness, and the underlying
+ * PRF. These constructs are generic enough to handle creation of arbitrary,
+ * (but known ahead of time) length outputs.
+ *
+ * The families of PRFs described here are used, among other places, in
+ * Kerberos and GlobalPlatform's Secure Channel Protocol 03. The PKCS#11 v3.0
+ * design for this KDF facilitates a wide range of uses.
+ *
+ * Implementation Details:
+ *
+ * We reuse the new sftk_MACCtx for handling the underlying MACing; with a few
+ * safe restrictions, we can reuse whatever it gives us to use as a PRF.
+ *
+ * We implement the core of the KDF in the *Raw(...) version of the function
+ * call. The PKCS#11 key handling happens in the non-Raw version. This means
+ * we need a single large allocation upfront (large enough to store the entire
+ * key stream), but means we can share key parsing logic and enable the
+ * creation of data objects.
+ */
+
+/* [ section: #define's ] */
+
+#define VALID_CK_BOOL(x) ((x) == CK_TRUE || (x) == CK_FALSE)
+#define IS_COUNTER(_mech) ((_mech) == CKM_SP800_108_COUNTER_KDF || (_mech) == CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA)
+#define DOES_DERIVE_DATA(_mech) ((_mech) == CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA || (_mech) == CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA || (_mech) == CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA)
+
+/* [ section: parameter validation ] */
+
+static CK_RV
+kbkdf_LoadParameters(CK_MECHANISM_TYPE mech, CK_MECHANISM_PTR pMechanism, CK_SP800_108_KDF_PARAMS_PTR kdf_params, CK_BYTE_PTR *initial_value, CK_ULONG_PTR initial_value_length)
+{
+ /* This function loads the parameters for the given mechanism into the
+ * specified kdf_params, splitting off the IV if present. In PKCS#11 v3.0,
+ * CK_SP800_108_FEEDBACK_KDF_PARAMS and CK_SP800_108_KDF_PARAMS have
+ * different ordering of internal parameters, which means that it isn't
+ * easy to reuse feedback parameters in the same functions as non-feedback
+ * parameters. Rather than duplicating the logic, split out the only
+ * Feedback-specific data (the IV) into a separate argument and repack it
+ * into the passed kdf_params struct instead. */
+ PR_ASSERT(pMechanism != NULL && kdf_params != NULL && initial_value != NULL && initial_value_length != NULL);
+
+ CK_SP800_108_KDF_PARAMS_PTR in_params;
+ CK_SP800_108_FEEDBACK_KDF_PARAMS_PTR feedback_params;
+
+ if (mech == CKM_SP800_108_FEEDBACK_KDF || mech == CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA) {
+ if (pMechanism->ulParameterLen != sizeof(CK_SP800_108_FEEDBACK_KDF_PARAMS)) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ feedback_params = (CK_SP800_108_FEEDBACK_KDF_PARAMS *)pMechanism->pParameter;
+
+ if (feedback_params->pIV == NULL && feedback_params->ulIVLen > 0) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ kdf_params->prfType = feedback_params->prfType;
+ kdf_params->ulNumberOfDataParams = feedback_params->ulNumberOfDataParams;
+ kdf_params->pDataParams = feedback_params->pDataParams;
+ kdf_params->ulAdditionalDerivedKeys = feedback_params->ulAdditionalDerivedKeys;
+ kdf_params->pAdditionalDerivedKeys = feedback_params->pAdditionalDerivedKeys;
+
+ *initial_value = feedback_params->pIV;
+ *initial_value_length = feedback_params->ulIVLen;
+ } else {
+ if (pMechanism->ulParameterLen != sizeof(CK_SP800_108_KDF_PARAMS)) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ in_params = (CK_SP800_108_KDF_PARAMS *)pMechanism->pParameter;
+
+ (*kdf_params) = *in_params;
+ }
+
+ return CKR_OK;
+}
+
+static CK_RV
+kbkdf_ValidateParameter(CK_MECHANISM_TYPE mech, const CK_PRF_DATA_PARAM *data)
+{
+ /* This function validates that the passed data parameter (data) conforms
+ * to PKCS#11 v3.0's expectations for KDF parameters. This depends both on
+ * the type of this parameter (data->type) and on the KDF mechanism (mech)
+ * as certain parameters are context dependent (like Iteration Variable).
+ */
+
+ /* If the parameter is missing a value when one is expected, then this
+ * parameter is invalid. */
+ if ((data->pValue == NULL) != (data->ulValueLen == 0)) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ switch (data->type) {
+ case CK_SP800_108_ITERATION_VARIABLE:
+ case CK_SP800_108_OPTIONAL_COUNTER: {
+ if (data->type == CK_SP800_108_ITERATION_VARIABLE && !IS_COUNTER(mech)) {
+ /* In Feedback and Double Pipeline KDFs, PKCS#11 v3.0 connotes the
+ * iteration variable as the chaining value from the previous PRF
+ * invocation. In contrast, counter mode treats this variable as a
+ * COUNTER_FORMAT descriptor. Thus we can skip validation of
+ * iteration variable parameters outside of counter mode. However,
+ * PKCS#11 v3.0 technically mandates that pValue is NULL, so we
+ * still have to validate that. */
+
+ if (data->pValue != NULL) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ return CKR_OK;
+ }
+
+ /* In counter mode, data->pValue should be a pointer to an instance of
+ * CK_SP800_108_COUNTER_FORMAT; validate its length. */
+ if (data->ulValueLen != sizeof(CK_SP800_108_COUNTER_FORMAT)) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ CK_SP800_108_COUNTER_FORMAT_PTR param = (CK_SP800_108_COUNTER_FORMAT_PTR)data->pValue;
+
+ /* Validate the endian parameter. */
+ if (!VALID_CK_BOOL(param->bLittleEndian)) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* Due to restrictions by our underlying hashes, we restrict bit
+ * widths to actually be byte widths by ensuring they're a multiple
+ * of eight. */
+ if ((param->ulWidthInBits % 8) != 0) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* Note that section 5.1 denotes the maximum length of the counter
+ * to be 32. */
+ if (param->ulWidthInBits > 32) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ break;
+ }
+ case CK_SP800_108_DKM_LENGTH: {
+ /* data->pValue should be a pointer to an instance of
+ * CK_SP800_108_DKM_LENGTH_FORMAT; validate its length. */
+ if (data->ulValueLen != sizeof(CK_SP800_108_DKM_LENGTH_FORMAT)) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ CK_SP800_108_DKM_LENGTH_FORMAT_PTR param = (CK_SP800_108_DKM_LENGTH_FORMAT_PTR)data->pValue;
+
+ /* Validate the method parameter. */
+ if (param->dkmLengthMethod != CK_SP800_108_DKM_LENGTH_SUM_OF_KEYS &&
+ param->dkmLengthMethod != CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* Validate the endian parameter. */
+ if (!VALID_CK_BOOL(param->bLittleEndian)) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* Validate the maximum width: we restrict it to being a byte width
+ * instead of a bit width due to restrictions by the underlying
+ * PRFs. */
+ if ((param->ulWidthInBits % 8) != 0) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* Ensure that the width doesn't overflow a 64-bit int. This
+ * restriction is arbitrary but since the counters can't exceed
+ * 32-bits (and most PRFs output at most 1024 bits), you're unlikely
+ * to need all 64-bits of length indicator. */
+ if (param->ulWidthInBits > 64) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ break;
+ }
+ case CK_SP800_108_BYTE_ARRAY:
+ /* There is no additional data to validate for byte arrays; we can
+ * only assume the byte array is of the specified size. */
+ break;
+ default:
+ /* Unexpected parameter type. */
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ return CKR_OK;
+}
+
+static CK_RV
+kbkdf_ValidateDerived(CK_DERIVED_KEY_PTR key)
+{
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ PRUint64 keySize = 0;
+
+ /* The pointer to the key handle shouldn't be NULL. If it is, we can't
+ * do anything else, so exit early. Every other failure case sets the
+ * key->phKey = CK_INVALID_HANDLE, so we can't use `goto failure` here. */
+ if (key->phKey == NULL) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* Validate that we have no attributes if and only if pTemplate is NULL.
+ * Otherwise, there's an inconsistency somewhere. */
+ if ((key->ulAttributeCount == 0) != (key->pTemplate == NULL)) {
+ goto failure;
+ }
+
+ for (size_t offset = 0; offset < key->ulAttributeCount; offset++) {
+ CK_ATTRIBUTE_PTR template = key->pTemplate + offset;
+
+ /* We only look for the CKA_VALUE_LEN and CKA_KEY_TYPE attributes.
+ * Everything else we assume we can set on the key if it is passed
+ * here. However, if we can't inquire as to a length (and barring
+ * that, if we have a key type without a standard length), we're
+ * definitely stuck. This mirrors the logic at the top of
+ * NSC_DeriveKey(...). */
+ if (template->type == CKA_KEY_TYPE) {
+ if (template->ulValueLen != sizeof(CK_KEY_TYPE)) {
+ goto failure;
+ }
+
+ keyType = *(CK_KEY_TYPE *)template->pValue;
+ } else if (template->type == CKA_VALUE_LEN) {
+ if (template->ulValueLen != sizeof(CK_ULONG)) {
+ goto failure;
+ }
+
+ keySize = *(CK_ULONG *)template->pValue;
+ }
+ }
+
+ if (keySize == 0) {
+ /* When we lack a keySize, see if we can infer it from the type of the
+ * passed key. */
+ keySize = sftk_MapKeySize(keyType);
+ }
+
+ /* The main piece of information we validate is that we have a length for
+ * this key. */
+ if (keySize == 0 || keySize >= (1ull << 32ull)) {
+ goto failure;
+ }
+
+ return CKR_OK;
+
+failure:
+ /* PKCS#11 v3.0: If the failure was caused by the content of a specific
+ * key's template (ie the template defined by the content of pTemplate),
+ * the corresponding phKey value will be set to CK_INVALID_HANDLE to
+ * identify the offending template. */
+ *(key->phKey) = CK_INVALID_HANDLE;
+ return CKR_MECHANISM_PARAM_INVALID;
+}
+
+static CK_RV
+kbkdf_ValidateParameters(CK_MECHANISM_TYPE mech, const CK_SP800_108_KDF_PARAMS *params, CK_ULONG keySize)
+{
+ CK_RV ret = CKR_MECHANISM_PARAM_INVALID;
+ int param_type_count[5] = { 0, 0, 0, 0, 0 };
+ size_t offset = 0;
+
+ /* Start with checking the prfType as a mechanism against a list of
+ * PRFs allowed by PKCS#11 v3.0. */
+ if (!(/* The following types aren't defined in NSS yet. */
+ /* params->prfType != CKM_3DES_CMAC && */
+ params->prfType == CKM_AES_CMAC || /* allow */
+ /* We allow any HMAC except MD2 and MD5. */
+ params->prfType != CKM_MD2_HMAC || /* disallow */
+ params->prfType != CKM_MD5_HMAC || /* disallow */
+ sftk_HMACMechanismToHash(params->prfType) != HASH_AlgNULL /* Valid HMAC <-> HASH isn't NULL */
+ )) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* We can't have a null pDataParams pointer: we always need at least one
+ * parameter to succeed. */
+ if (params->pDataParams == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+
+ /* Validate each KDF parameter. */
+ for (offset = 0; offset < params->ulNumberOfDataParams; offset++) {
+ /* Validate this parameter has acceptable values. */
+ ret = kbkdf_ValidateParameter(mech, params->pDataParams + offset);
+ if (ret != CKR_OK) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* Count that we have a parameter of this type. The above logic
+ * in ValidateParameter MUST validate that type is within the
+ * appropriate range. */
+ PR_ASSERT(params->pDataParams[offset].type < sizeof(param_type_count) / sizeof(param_type_count[0]));
+ param_type_count[params->pDataParams[offset].type] += 1;
+ }
+
+ if (IS_COUNTER(mech)) {
+ /* We have to have at least one iteration variable parameter. */
+ if (param_type_count[CK_SP800_108_ITERATION_VARIABLE] == 0) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* We can't have any optional counters parameters -- these belong in
+ * iteration variable parameters instead. */
+ if (param_type_count[CK_SP800_108_OPTIONAL_COUNTER] != 0) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ }
+
+ /* Validate basic assumptions about derived keys:
+ * NULL <-> ulAdditionalDerivedKeys > 0
+ */
+ if ((params->ulAdditionalDerivedKeys == 0) != (params->pAdditionalDerivedKeys == NULL)) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* Validate each derived key. */
+ for (offset = 0; offset < params->ulAdditionalDerivedKeys; offset++) {
+ ret = kbkdf_ValidateDerived(params->pAdditionalDerivedKeys + offset);
+ if (ret != CKR_OK) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ }
+
+ /* Validate the length of our primary key. */
+ if (keySize == 0 || ((PRUint64)keySize) >= (1ull << 32ull)) {
+ return CKR_KEY_SIZE_RANGE;
+ }
+
+ return CKR_OK;
+}
+
+/* [ section: parameter helpers ] */
+
+static CK_VOID_PTR
+kbkdf_FindParameter(const CK_SP800_108_KDF_PARAMS *params, CK_PRF_DATA_TYPE type)
+{
+ for (size_t offset = 0; offset < params->ulNumberOfDataParams; offset++) {
+ if (params->pDataParams[offset].type == type) {
+ return params->pDataParams[offset].pValue;
+ }
+ }
+
+ return NULL;
+}
+
+size_t
+kbkdf_IncrementBuffer(size_t cur_offset, size_t consumed, size_t prf_length)
+{
+ return cur_offset + PR_ROUNDUP(consumed, prf_length);
+}
+
+CK_ULONG
+kbkdf_GetDerivedKeySize(CK_DERIVED_KEY_PTR derived_key)
+{
+ /* Precondition: kbkdf_ValidateDerived(...) returns CKR_OK for this key,
+ * which implies that keySize is defined. */
+
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_ULONG keySize = 0;
+
+ for (size_t offset = 0; offset < derived_key->ulAttributeCount; offset++) {
+ CK_ATTRIBUTE_PTR template = derived_key->pTemplate + offset;
+
+ /* Find the two attributes we care about. */
+ if (template->type == CKA_KEY_TYPE) {
+ keyType = *(CK_KEY_TYPE *)template->pValue;
+ } else if (template->type == CKA_VALUE_LEN) {
+ keySize = *(CK_ULONG *)template->pValue;
+ }
+ }
+
+ /* Prefer keySize, if we have it. */
+ if (keySize > 0) {
+ return keySize;
+ }
+
+ /* Else, fall back to this mapping. We know kbkdf_ValidateDerived(...)
+ * passed, so this should return non-zero. */
+ return sftk_MapKeySize(keyType);
+}
+
+static CK_RV
+kbkdf_CalculateLength(const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, CK_ULONG ret_key_size, PRUint64 *output_bitlen, size_t *buffer_length)
+{
+ /* Two cases: either we have additional derived keys or we don't. In the
+ * case that we don't, the length of the derivation is the size of the
+ * single derived key, and that is the length of the PRF buffer. Otherwise,
+ * we need to use the proper CK_SP800_108_DKM_LENGTH_METHOD to calculate
+ * the length of the output (in bits), with a separate value for the size
+ * of the PRF data buffer. This means that, under PKCS#11 with additional
+ * derived keys, we lie to the KDF about the _actual_ length of the PRF
+ * output.
+ *
+ * Note that *output_bitlen is the L parameter in NIST SP800-108 and is in
+ * bits. However, *buffer_length is in bytes.
+ */
+
+ if (params->ulAdditionalDerivedKeys == 0) {
+ /* When we have no additional derived keys, we get the keySize from
+ * the value passed to one of our KBKDF_* methods. */
+ *output_bitlen = ret_key_size;
+ *buffer_length = ret_key_size;
+ } else {
+ /* Offset in the additional derived keys array. */
+ size_t offset = 0;
+
+ /* Size of the derived key. */
+ CK_ULONG derived_size = 0;
+
+ /* In the below, we place the sum of the keys into *output_bitlen
+ * and the size of the buffer (with padding mandated by PKCS#11 v3.0)
+ * into *buffer_length. If the method is the segment sum, then we
+ * replace *output_bitlen with *buffer_length at the end. This ensures
+ * we always get a output buffer large enough to handle all derived
+ * keys, and *output_bitlen reflects the correct L value. */
+
+ /* Count the initial derived key. */
+ *output_bitlen = ret_key_size;
+ *buffer_length = kbkdf_IncrementBuffer(0, ret_key_size, ctx->mac_size);
+
+ /* Handle n - 1 keys. The last key is special. */
+ for (; offset < params->ulAdditionalDerivedKeys - 1; offset++) {
+ derived_size = kbkdf_GetDerivedKeySize(params->pAdditionalDerivedKeys + offset);
+
+ *output_bitlen += derived_size;
+ *buffer_length = kbkdf_IncrementBuffer(*buffer_length, derived_size, ctx->mac_size);
+ }
+
+ /* Handle the last key. */
+ derived_size = kbkdf_GetDerivedKeySize(params->pAdditionalDerivedKeys + offset);
+
+ *output_bitlen += derived_size;
+ *buffer_length = kbkdf_IncrementBuffer(*buffer_length, derived_size, ctx->mac_size);
+
+ /* Pointer to the DKM method parameter. Note that this implicit cast
+ * is safe since we've assumed we've been validated by
+ * kbkdf_ValidateParameters(...). When kdm_param is NULL, we don't
+ * use the output_bitlen parameter. */
+ CK_SP800_108_DKM_LENGTH_FORMAT_PTR dkm_param = kbkdf_FindParameter(params, CK_SP800_108_DKM_LENGTH);
+ if (dkm_param != NULL) {
+ if (dkm_param->dkmLengthMethod == CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS) {
+ *output_bitlen = *buffer_length;
+ }
+ }
+ }
+
+ /* Note that keySize is the size in bytes and ctx->mac_size is also
+ * the size in bytes. However, output_bitlen needs to be in bits, so
+ * multiply by 8 here. */
+ *output_bitlen *= 8;
+
+ return CKR_OK;
+}
+
+static CK_RV
+kbkdf_CalculateIterations(CK_MECHANISM_TYPE mech, const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, size_t buffer_length, PRUint32 *num_iterations)
+{
+ CK_SP800_108_COUNTER_FORMAT_PTR param_ptr = NULL;
+ PRUint64 iteration_count;
+ PRUint64 r = 32;
+
+ /* We need to know how many full iterations are required. This is done
+ * by rounding up the division of the PRF length into buffer_length.
+ * However, we're not guaranteed that the last output is a full PRF
+ * invocation, so handle that here. */
+ iteration_count = buffer_length + (ctx->mac_size - 1);
+ iteration_count = iteration_count / ctx->mac_size;
+
+ /* NIST SP800-108, section 5.1, process step #2:
+ *
+ * if n > 2^r - 1, then indicate an error and stop.
+ *
+ * In non-counter mode KDFs, r is set at 32, leaving behavior
+ * under-defined when the optional counter is included but fewer than
+ * 32 bits. This implementation assumes r is 32, but if the counter
+ * parameter is included, validates it against that. In counter-mode
+ * KDFs, this is in the ITERATION_VARIABLE parameter; in feedback- or
+ * pipeline-mode KDFs, this is in the COUNTER parameter.
+ *
+ * This is consistent with the supplied sample CAVP tests; none reuses the
+ * same counter value. In some configurations, this could result in
+ * duplicated KDF output. We seek to avoid that from happening.
+ */
+ if (IS_COUNTER(mech)) {
+ param_ptr = kbkdf_FindParameter(params, CK_SP800_108_ITERATION_VARIABLE);
+
+ /* Validated by kbkdf_ValidateParameters(...) above. */
+ PR_ASSERT(param_ptr != NULL);
+
+ r = ((CK_SP800_108_COUNTER_FORMAT_PTR)param_ptr)->ulWidthInBits;
+ } else {
+ param_ptr = kbkdf_FindParameter(params, CK_SP800_108_COUNTER);
+
+ /* Not guaranteed to exist, hence the default value of r=32. */
+ if (param_ptr != NULL) {
+ r = ((CK_SP800_108_COUNTER_FORMAT_PTR)param_ptr)->ulWidthInBits;
+ }
+ }
+
+ if (iteration_count >= (1ull << r) || r > 32) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ *num_iterations = (PRUint32)iteration_count;
+
+ return CKR_OK;
+}
+
+static CK_RV
+kbkdf_AddParameters(CK_MECHANISM_TYPE mech, sftk_MACCtx *ctx, const CK_SP800_108_KDF_PARAMS *params, PRUint32 counter, PRUint64 length, const unsigned char *chaining_prf, size_t chaining_prf_len, CK_PRF_DATA_TYPE exclude)
+{
+ size_t offset = 0;
+ CK_RV ret = CKR_OK;
+
+ for (offset = 0; offset < params->ulNumberOfDataParams; offset++) {
+ CK_PRF_DATA_PARAM_PTR param = params->pDataParams + offset;
+
+ if (param->type == exclude) {
+ /* Necessary for Double Pipeline mode: when constructing the IV,
+ * we skip the optional counter. */
+ continue;
+ }
+
+ switch (param->type) {
+ case CK_SP800_108_ITERATION_VARIABLE: {
+ /* When present in COUNTER mode, this signifies adding the counter
+ * variable to the PRF. Otherwise, it signifies the chaining
+ * value for other KDF modes. */
+ if (IS_COUNTER(mech)) {
+ CK_SP800_108_COUNTER_FORMAT_PTR counter_format = (CK_SP800_108_COUNTER_FORMAT_PTR)param->pValue;
+ CK_BYTE buffer[sizeof(PRUint64)];
+ CK_ULONG num_bytes;
+ sftk_EncodeInteger(counter, counter_format->ulWidthInBits, counter_format->bLittleEndian, buffer, &num_bytes);
+ ret = sftk_MAC_Update(ctx, buffer, num_bytes);
+ } else {
+ ret = sftk_MAC_Update(ctx, chaining_prf, chaining_prf_len);
+ }
+ break;
+ }
+ case CK_SP800_108_COUNTER: {
+ /* Only present in the case when not using COUNTER mode. */
+ PR_ASSERT(!IS_COUNTER(mech));
+
+ /* We should've already validated that this parameter is of
+ * type COUNTER_FORMAT. */
+ CK_SP800_108_COUNTER_FORMAT_PTR counter_format = (CK_SP800_108_COUNTER_FORMAT_PTR)param->pValue;
+ CK_BYTE buffer[sizeof(PRUint64)];
+ CK_ULONG num_bytes;
+ sftk_EncodeInteger(counter, counter_format->ulWidthInBits, counter_format->bLittleEndian, buffer, &num_bytes);
+ ret = sftk_MAC_Update(ctx, buffer, num_bytes);
+ break;
+ }
+ case CK_SP800_108_BYTE_ARRAY:
+ ret = sftk_MAC_Update(ctx, (CK_BYTE_PTR)param->pValue, param->ulValueLen);
+ break;
+ case CK_SP800_108_DKM_LENGTH: {
+ /* We've already done the hard work of calculating the length in
+ * the kbkdf_CalculateIterations function; we merely need to add
+ * the length to the desired point in the input stream. */
+ CK_SP800_108_DKM_LENGTH_FORMAT_PTR length_format = (CK_SP800_108_DKM_LENGTH_FORMAT_PTR)param->pValue;
+ CK_BYTE buffer[sizeof(PRUint64)];
+ CK_ULONG num_bytes;
+ sftk_EncodeInteger(length, length_format->ulWidthInBits, length_format->bLittleEndian, buffer, &num_bytes);
+ ret = sftk_MAC_Update(ctx, buffer, num_bytes);
+ break;
+ }
+ default:
+ /* This should've been caught by kbkdf_ValidateParameters(...). */
+ PR_ASSERT(PR_FALSE);
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ if (ret != CKR_OK) {
+ return ret;
+ }
+ }
+
+ return CKR_OK;
+}
+
+CK_RV
+kbkdf_SaveKey(SFTKObject *key, unsigned char *key_buffer, unsigned int key_len)
+{
+ return sftk_forceAttribute(key, CKA_VALUE, key_buffer, key_len);
+}
+
+CK_RV
+kbkdf_CreateKey(CK_MECHANISM_TYPE kdf_mech, CK_SESSION_HANDLE hSession, CK_DERIVED_KEY_PTR derived_key, SFTKObject **ret_key)
+{
+ /* Largely duplicated from NSC_DeriveKey(...) */
+ CK_RV ret = CKR_HOST_MEMORY;
+ SFTKObject *key = NULL;
+ SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
+ size_t offset = 0;
+
+ /* Slot should be non-NULL because NSC_DeriveKey(...) has already
+ * performed a sftk_SlotFromSessionHandle(...) call on this session
+ * handle. However, Coverity incorrectly flagged this (see 1607955). */
+ PR_ASSERT(slot != NULL);
+ PR_ASSERT(ret_key != NULL);
+ PR_ASSERT(derived_key != NULL);
+ PR_ASSERT(derived_key->phKey != NULL);
+
+ /* Create the new key object for this additional derived key. */
+ key = sftk_NewObject(slot);
+ if (key == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+
+ /* Setup the key from the provided template. */
+ for (offset = 0; offset < derived_key->ulAttributeCount; offset++) {
+ ret = sftk_AddAttributeType(key, sftk_attr_expand(derived_key->pTemplate + offset));
+ if (ret != CKR_OK) {
+ sftk_FreeObject(key);
+ return ret;
+ }
+ }
+
+ /* When using the CKM_SP800_* series of mechanisms, the result must be a
+ * secret key, so its contents can be adequately protected in FIPS mode.
+ * However, when using the special CKM_NSS_SP800_*_DERIVE_DATA series, the
+ * contents need not be protected, so we set CKO_DATA on these "keys". */
+ CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
+ if (DOES_DERIVE_DATA(kdf_mech)) {
+ classType = CKO_DATA;
+ }
+
+ ret = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType));
+ if (ret != CKR_OK) {
+ sftk_FreeObject(key);
+ return ret;
+ }
+
+ *ret_key = key;
+ return CKR_OK;
+}
+
+CK_RV
+kbkdf_FinalizeKey(CK_SESSION_HANDLE hSession, CK_DERIVED_KEY_PTR derived_key, SFTKObject *key)
+{
+ /* Largely duplicated from NSC_DeriveKey(...) */
+ CK_RV ret = CKR_HOST_MEMORY;
+ SFTKSession *session = NULL;
+
+ PR_ASSERT(derived_key != NULL && key != NULL);
+
+ SFTKSessionObject *sessionForKey = sftk_narrowToSessionObject(key);
+ PR_ASSERT(sessionForKey != NULL);
+ sessionForKey->wasDerived = PR_TRUE;
+
+ session = sftk_SessionFromHandle(hSession);
+
+ /* Session should be non-NULL because NSC_DeriveKey(...) has already
+ * performed a sftk_SessionFromHandle(...) call on this session handle. */
+ PR_ASSERT(session != NULL);
+
+ ret = sftk_handleObject(key, session);
+ if (ret != CKR_OK) {
+ goto done;
+ }
+
+ *(derived_key->phKey) = key->handle;
+
+done:
+ /* Guaranteed that key != NULL */
+ sftk_FreeObject(key);
+
+ /* Doesn't do anything. */
+ sftk_FreeSession(session);
+
+ return ret;
+}
+
+CK_RV
+kbkdf_SaveKeys(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE hSession, CK_SP800_108_KDF_PARAMS_PTR params, unsigned char *output_buffer, size_t buffer_len, size_t prf_length, SFTKObject *ret_key, CK_ULONG ret_key_size)
+{
+ CK_RV ret;
+ size_t key_offset = 0;
+ size_t buffer_offset = 0;
+
+ PR_ASSERT(output_buffer != NULL && buffer_len > 0 && ret_key != NULL);
+
+ /* First place key material into the main key. */
+ ret = kbkdf_SaveKey(ret_key, output_buffer + buffer_offset, ret_key_size);
+ if (ret != CKR_OK) {
+ return ret;
+ }
+
+ /* Then increment the offset based on PKCS#11 additional key guidelines:
+ * no two keys may share the key stream from the same PRF invocation. */
+ buffer_offset = kbkdf_IncrementBuffer(buffer_offset, ret_key_size, prf_length);
+
+ if (params->ulAdditionalDerivedKeys > 0) {
+ /* Note that the following code is technically incorrect: PKCS#11 v3.0
+ * says that _no_ key should be set in the event of failure to derive
+ * _any_ key. */
+ for (key_offset = 0; key_offset < params->ulAdditionalDerivedKeys; key_offset++) {
+ CK_DERIVED_KEY_PTR derived_key = params->pAdditionalDerivedKeys + key_offset;
+ SFTKObject *key_obj = NULL;
+ size_t key_size = kbkdf_GetDerivedKeySize(derived_key);
+
+ /* Create a new internal key object for this derived key. */
+ ret = kbkdf_CreateKey(mech, hSession, derived_key, &key_obj);
+ if (ret != CKR_OK) {
+ *(derived_key->phKey) = CK_INVALID_HANDLE;
+ return ret;
+ }
+
+ /* Save the underlying key bytes to the key object. */
+ ret = kbkdf_SaveKey(key_obj, output_buffer + buffer_offset, key_size);
+ if (ret != CKR_OK) {
+ /* When kbkdf_CreateKey(...) exits with an error, it will free
+ * the constructed key object. kbkdf_FinalizeKey(...) also
+ * always frees the key object. In the unlikely event that
+ * kbkdf_SaveKey(...) _does_ fail, we thus need to free it
+ * manually. */
+ sftk_FreeObject(key_obj);
+ *(derived_key->phKey) = CK_INVALID_HANDLE;
+ return ret;
+ }
+
+ /* Handle the increment. */
+ buffer_offset = kbkdf_IncrementBuffer(buffer_offset, key_size, prf_length);
+
+ /* Finalize this key. */
+ ret = kbkdf_FinalizeKey(hSession, derived_key, key_obj);
+ if (ret != CKR_OK) {
+ *(derived_key->phKey) = CK_INVALID_HANDLE;
+ return ret;
+ }
+ }
+ }
+
+ return CKR_OK;
+}
+
+/* [ section: KDFs ] */
+
+static CK_RV
+kbkdf_CounterRaw(const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, unsigned char *ret_buffer, size_t buffer_length, PRUint64 output_bitlen)
+{
+ CK_RV ret = CKR_OK;
+
+ /* Counter variable for this KDF instance. */
+ PRUint32 counter;
+
+ /* Number of iterations required of this PRF necessary to reach the
+ * desired output length. */
+ PRUint32 num_iterations;
+
+ /* Offset in ret_buffer that we're at. */
+ size_t buffer_offset = 0;
+
+ /* Size of this block, in bytes. Defaults to ctx->mac_size except on
+ * the last iteration where it could be a partial block. */
+ size_t block_size = ctx->mac_size;
+
+ /* Calculate the number of iterations required based on the size of the
+ * output buffer. */
+ ret = kbkdf_CalculateIterations(CKM_SP800_108_COUNTER_KDF, params, ctx, buffer_length, &num_iterations);
+ if (ret != CKR_OK) {
+ return ret;
+ }
+
+ /*
+ * 5.1 - [ KDF in Counter Mode ]
+ *
+ * Fixed values:
+ * 1. h - the length of the PRF in bits (ctx->mac_size)
+ * 2. r - the length of the binary representation of the counter i
+ * (params[k: params[k].type == CK_SP800_108_ITERATION_VARIABLE:].data->ulWidthInBits)
+ * Input:
+ * 1. K_I - the key for the PRF (base_key)
+ * 2. label - a binary data field, usually before the separator. Optional.
+ * 3. context - a binary data field, usually after the separator. Optional.
+ * 4. L - length of the output in bits (output_bitlen)
+ *
+ * Process:
+ * 1. n := ceil(L / h) (num_iterations)
+ * 2. if n > 2^r - 1, then indicate an error and stop
+ * 3. result(0) = NULL
+ * 4. for i = 1 to n, do
+ * a. K(i) = PRF(K_I, [i]_2 || Label || 0x00 || Context || [L]_2)
+ * b. result(i) := result(i - 1) || K(i).
+ * 5. return K_O := the leftmost L bits of result(n).
+ */
+ for (counter = 1; counter <= num_iterations; counter++) {
+ if (counter == num_iterations) {
+ block_size = buffer_length - buffer_offset;
+
+ /* Assumption: if we've validated our arguments correctly, this
+ * should always be true. */
+ PR_ASSERT(block_size <= ctx->mac_size);
+ }
+
+ /* Add all parameters required by this instance of the KDF to the
+ * input stream of the underlying PRF. */
+ ret = kbkdf_AddParameters(CKM_SP800_108_COUNTER_KDF, ctx, params, counter, output_bitlen, NULL, 0 /* chaining_prf output */, 0 /* exclude */);
+ if (ret != CKR_OK) {
+ return ret;
+ }
+
+ /* Finalize this iteration of the PRF. */
+ ret = sftk_MAC_Finish(ctx, ret_buffer + buffer_offset, NULL, block_size);
+ if (ret != CKR_OK) {
+ return ret;
+ }
+
+ /* Increment our position in the key material. */
+ buffer_offset += block_size;
+
+ if (counter < num_iterations) {
+ /* Reset the underlying PRF for the next iteration. Only do this
+ * when we have a next iteration since it isn't necessary to do
+ * either before the first iteration (MAC is already initialized)
+ * or after the last iteration (we won't be called again). */
+ ret = sftk_MAC_Reset(ctx);
+ if (ret != CKR_OK) {
+ return ret;
+ }
+ }
+ }
+
+ return CKR_OK;
+}
+
+static CK_RV
+kbkdf_FeedbackRaw(const CK_SP800_108_KDF_PARAMS *params, const unsigned char *initial_value, CK_ULONG initial_value_length, sftk_MACCtx *ctx, unsigned char *ret_buffer, size_t buffer_length, PRUint64 output_bitlen)
+{
+ CK_RV ret = CKR_OK;
+
+ /* Counter variable for this KDF instance. */
+ PRUint32 counter;
+
+ /* Number of iterations required of this PRF necessary to reach the
+ * desired output length. */
+ PRUint32 num_iterations;
+
+ /* Offset in ret_buffer that we're at. */
+ size_t buffer_offset = 0;
+
+ /* Size of this block, in bytes. Defaults to ctx->mac_size except on
+ * the last iteration where it could be a partial block. */
+ size_t block_size = ctx->mac_size;
+
+ /* The last PRF invocation and/or the initial value; used for feedback
+ * chaining in this KDF. Note that we have to make it large enough to
+ * fit the output of the PRF, but we can delay its actual creation until
+ * the first PRF invocation. Until then, point to the IV value. */
+ unsigned char *chaining_value = (unsigned char *)initial_value;
+
+ /* Size of the chaining value discussed above. Defaults to the size of
+ * the IV value. */
+ size_t chaining_length = initial_value_length;
+
+ /* Calculate the number of iterations required based on the size of the
+ * output buffer. */
+ ret = kbkdf_CalculateIterations(CKM_SP800_108_FEEDBACK_KDF, params, ctx, buffer_length, &num_iterations);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /*
+ * 5.2 - [ KDF in Feedback Mode ]
+ *
+ * Fixed values:
+ * 1. h - the length of the PRF in bits (ctx->mac_size)
+ * 2. r - the length of the binary representation of the counter i
+ * (params[k: params[k].type == CK_SP800_108_OPTIONAL_COUNTER:].data->ulWidthInBits)
+ * Note that it is only specified when the optional counter is requested.
+ * Input:
+ * 1. K_I - the key for the PRF (base_key)
+ * 2. label - a binary data field, usually before the separator. Optional.
+ * 3. context - a binary data field, usually after the separator. Optional.
+ * 4. IV - a binary data field, initial PRF value. (params->pIV)
+ * 5. L - length of the output in bits (output_bitlen)
+ *
+ * Process:
+ * 1. n := ceil(L / h) (num_iterations)
+ * 2. if n > 2^32 - 1, then indicate an error and stop
+ * 3. result(0) = NULL, K(0) := IV (chaining_value)
+ * 4. for i = 1 to n, do
+ * a. K(i) = PRF(K_I, K(i-1) {|| [i]_2} || Label || 0x00 || Context || [L]_2)
+ * b. result(i) := result(i - 1) || K(i).
+ * 5. return K_O := the leftmost L bits of result(n).
+ */
+ for (counter = 1; counter <= num_iterations; counter++) {
+ if (counter == num_iterations) {
+ block_size = buffer_length - buffer_offset;
+
+ /* Assumption: if we've validated our arguments correctly, this
+ * should always be true. */
+ PR_ASSERT(block_size <= ctx->mac_size);
+ }
+
+ /* Add all parameters required by this instance of the KDF to the
+ * input stream of the underlying PRF. */
+ ret = kbkdf_AddParameters(CKM_SP800_108_FEEDBACK_KDF, ctx, params, counter, output_bitlen, chaining_value, chaining_length, 0 /* exclude */);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ if (counter == 1) {
+ /* On the first iteration, chaining_value points to the IV from
+ * the caller and chaining_length is the length of that IV. We
+ * now need to allocate a buffer of suitable length to store the
+ * MAC output. */
+ chaining_value = PORT_ZNewArray(unsigned char, ctx->mac_size);
+ chaining_length = ctx->mac_size;
+
+ if (chaining_value == NULL) {
+ ret = CKR_HOST_MEMORY;
+ goto finish;
+ }
+ }
+
+ /* Finalize this iteration of the PRF. Unlike other KDF forms, we
+ * first save this to the chaining value so that we can reuse it
+ * in the next iteration before copying the necessary length to
+ * the output buffer. */
+ ret = sftk_MAC_Finish(ctx, chaining_value, NULL, chaining_length);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /* Save as much of the chaining value as we need for output. */
+ PORT_Memcpy(ret_buffer + buffer_offset, chaining_value, block_size);
+
+ /* Increment our position in the key material. */
+ buffer_offset += block_size;
+
+ if (counter < num_iterations) {
+ /* Reset the underlying PRF for the next iteration. Only do this
+ * when we have a next iteration since it isn't necessary to do
+ * either before the first iteration (MAC is already initialized)
+ * or after the last iteration (we won't be called again). */
+ ret = sftk_MAC_Reset(ctx);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+ }
+ }
+
+finish:
+ if (chaining_value != initial_value && chaining_value != NULL) {
+ PORT_ZFree(chaining_value, chaining_length);
+ }
+
+ return ret;
+}
+
+static CK_RV
+kbkdf_PipelineRaw(const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, unsigned char *ret_buffer, size_t buffer_length, PRUint64 output_bitlen)
+{
+ CK_RV ret = CKR_OK;
+
+ /* Counter variable for this KDF instance. */
+ PRUint32 counter;
+
+ /* Number of iterations required of this PRF necessary to reach the
+ * desired output length. */
+ PRUint32 num_iterations;
+
+ /* Offset in ret_buffer that we're at. */
+ size_t buffer_offset = 0;
+
+ /* Size of this block, in bytes. Defaults to ctx->mac_size except on
+ * the last iteration where it could be a partial block. */
+ size_t block_size = ctx->mac_size;
+
+ /* The last PRF invocation. This is used for the first of the double
+ * PRF invocations this KDF is named after. This defaults to NULL,
+ * signifying that we have to calculate the initial value from params;
+ * when non-NULL, we directly add only this value to the PRF. */
+ unsigned char *chaining_value = NULL;
+
+ /* Size of the chaining value discussed above. Defaults to 0. */
+ size_t chaining_length = 0;
+
+ /* Calculate the number of iterations required based on the size of the
+ * output buffer. */
+ ret = kbkdf_CalculateIterations(CKM_SP800_108_DOUBLE_PIPELINE_KDF, params, ctx, buffer_length, &num_iterations);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /*
+ * 5.3 - [ KDF in Double-Pipeline Iteration Mode ]
+ *
+ * Fixed values:
+ * 1. h - the length of the PRF in bits (ctx->mac_size)
+ * 2. r - the length of the binary representation of the counter i
+ * (params[k: params[k].type == CK_SP800_108_OPTIONAL_COUNTER:].data->ulWidthInBits)
+ * Note that it is only specified when the optional counter is requested.
+ * Input:
+ * 1. K_I - the key for the PRF (base_key)
+ * 2. label - a binary data field, usually before the separator. Optional.
+ * 3. context - a binary data field, usually after the separator. Optional.
+ * 4. L - length of the output in bits (output_bitlen)
+ *
+ * Process:
+ * 1. n := ceil(L / h) (num_iterations)
+ * 2. if n > 2^32 - 1, then indicate an error and stop
+ * 3. result(0) = NULL
+ * 4. A(0) := IV := Label || 0x00 || Context || [L]_2
+ * 5. for i = 1 to n, do
+ * a. A(i) := PRF(K_I, A(i-1))
+ * b. K(i) := PRF(K_I, A(i) {|| [i]_2} || Label || 0x00 || Context || [L]_2
+ * c. result(i) := result(i-1) || K(i)
+ * 6. return K_O := the leftmost L bits of result(n).
+ */
+ for (counter = 1; counter <= num_iterations; counter++) {
+ if (counter == num_iterations) {
+ block_size = buffer_length - buffer_offset;
+
+ /* Assumption: if we've validated our arguments correctly, this
+ * should always be true. */
+ PR_ASSERT(block_size <= ctx->mac_size);
+ }
+
+ /* ===== First pipeline: construct A(i) ===== */
+ if (counter == 1) {
+ /* On the first iteration, we have no chaining value so specify
+ * NULL for the pointer and 0 for the length, and exclude the
+ * optional counter if it exists. This is what NIST specifies as
+ * the IV for the KDF. */
+ ret = kbkdf_AddParameters(CKM_SP800_108_DOUBLE_PIPELINE_KDF, ctx, params, counter, output_bitlen, NULL, 0, CK_SP800_108_OPTIONAL_COUNTER);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /* Allocate the chaining value so we can save the PRF output. */
+ chaining_value = PORT_ZNewArray(unsigned char, ctx->mac_size);
+ chaining_length = ctx->mac_size;
+ if (chaining_value == NULL) {
+ ret = CKR_HOST_MEMORY;
+ goto finish;
+ }
+ } else {
+ /* On all other iterations, the next stage of the first pipeline
+ * comes directly from this stage. */
+ ret = sftk_MAC_Update(ctx, chaining_value, chaining_length);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+ }
+
+ /* Save the PRF output to chaining_value for use in the second
+ * pipeline. */
+ ret = sftk_MAC_Finish(ctx, chaining_value, NULL, chaining_length);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /* Reset the PRF so we can reuse it for the second pipeline. */
+ ret = sftk_MAC_Reset(ctx);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /* ===== Second pipeline: construct K(i) ===== */
+
+ /* Add all parameters required by this instance of the KDF to the
+ * input stream of the underlying PRF. Note that this includes the
+ * chaining value we calculated from the previous pipeline stage. */
+ ret = kbkdf_AddParameters(CKM_SP800_108_FEEDBACK_KDF, ctx, params, counter, output_bitlen, chaining_value, chaining_length, 0 /* exclude */);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /* Finalize this iteration of the PRF directly to the output buffer.
+ * Unlike Feedback mode, this pipeline doesn't influence the previous
+ * stage. */
+ ret = sftk_MAC_Finish(ctx, ret_buffer + buffer_offset, NULL, block_size);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /* Increment our position in the key material. */
+ buffer_offset += block_size;
+
+ if (counter < num_iterations) {
+ /* Reset the underlying PRF for the next iteration. Only do this
+ * when we have a next iteration since it isn't necessary to do
+ * either before the first iteration (MAC is already initialized)
+ * or after the last iteration (we won't be called again). */
+ ret = sftk_MAC_Reset(ctx);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+ }
+ }
+
+finish:
+ PORT_ZFree(chaining_value, chaining_length);
+
+ return ret;
+}
+
+static CK_RV
+kbkdf_RawDispatch(CK_MECHANISM_TYPE mech,
+ const CK_SP800_108_KDF_PARAMS *kdf_params,
+ const CK_BYTE *initial_value,
+ CK_ULONG initial_value_length,
+ SFTKObject *prf_key, const unsigned char *prf_key_bytes,
+ unsigned int prf_key_length, unsigned char **out_key_bytes,
+ size_t *out_key_length, unsigned int *mac_size,
+ CK_ULONG ret_key_size)
+{
+ CK_RV ret;
+ /* Context for our underlying PRF function.
+ *
+ * Zeroing context required unconditional call of sftk_MAC_Destroy.
+ */
+ sftk_MACCtx ctx = { 0 };
+
+ /* We need one buffers large enough to fit the entire KDF key stream for
+ * all iterations of the PRF. This needs only include to the end of the
+ * last key, so it isn't an even multiple of the PRF output size. */
+ unsigned char *output_buffer = NULL;
+
+ /* Size of the above buffer, in bytes. Note that this is technically
+ * separate from the below output_bitlen variable due to the presence
+ * of additional derived keys. See commentary in kbkdf_CalculateLength.
+ */
+ size_t buffer_length = 0;
+
+ /* While NIST specifies a maximum length (in bits) for the counter, they
+ * don't for the maximum length. It is unlikely, but theoretically
+ * possible for output of the PRF to exceed 32 bits while keeping the
+ * counter under 2^32. Thus, use a 64-bit variable for the maximum
+ * output length.
+ *
+ * It is unlikely any caller will request this much data in practice.
+ * 2^32 invocations of the PRF (for a 512-bit PRF) would be 256GB of
+ * data in the KDF key stream alone. The bigger limit is the number of
+ * and size of keys (again, 2^32); this could easily exceed 256GB when
+ * counting the backing softoken key, the key data, template data, and
+ * the input parameters to this KDF.
+ *
+ * This is the L parameter in NIST SP800-108.
+ */
+ PRUint64 output_bitlen = 0;
+
+ /* First validate our passed input parameters against PKCS#11 v3.0
+ * and NIST SP800-108 requirements. */
+ ret = kbkdf_ValidateParameters(mech, kdf_params, ret_key_size);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /* Initialize the underlying PRF state. */
+ if (prf_key) {
+ ret = sftk_MAC_Init(&ctx, kdf_params->prfType, prf_key);
+ } else {
+ ret = sftk_MAC_InitRaw(&ctx, kdf_params->prfType, prf_key_bytes,
+ prf_key_length, PR_TRUE);
+ }
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /* Compute the size of our output buffer based on passed parameters and
+ * the output size of the underlying PRF. */
+ ret = kbkdf_CalculateLength(kdf_params, &ctx, ret_key_size, &output_bitlen, &buffer_length);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /* Allocate memory for the PRF output */
+ output_buffer = PORT_ZNewArray(unsigned char, buffer_length);
+ if (output_buffer == NULL) {
+ ret = CKR_HOST_MEMORY;
+ goto finish;
+ }
+
+ /* Call into the underlying KDF */
+ switch (mech) {
+ case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */
+ case CKM_SP800_108_COUNTER_KDF:
+ ret = kbkdf_CounterRaw(kdf_params, &ctx, output_buffer, buffer_length, output_bitlen);
+ break;
+ case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
+ case CKM_SP800_108_FEEDBACK_KDF:
+ ret = kbkdf_FeedbackRaw(kdf_params, initial_value, initial_value_length, &ctx, output_buffer, buffer_length, output_bitlen);
+ break;
+ case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */
+ case CKM_SP800_108_DOUBLE_PIPELINE_KDF:
+ ret = kbkdf_PipelineRaw(kdf_params, &ctx, output_buffer, buffer_length, output_bitlen);
+ break;
+ default:
+ /* Shouldn't happen unless NIST introduces a new KBKDF type. */
+ PR_ASSERT(PR_FALSE);
+ ret = CKR_FUNCTION_FAILED;
+ }
+
+ /* Validate the above KDF succeeded. */
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ *out_key_bytes = output_buffer;
+ *out_key_length = buffer_length;
+ *mac_size = ctx.mac_size;
+
+ output_buffer = NULL; /* returning the buffer, don't zero and free it */
+
+finish:
+ PORT_ZFree(output_buffer, buffer_length);
+
+ /* Free the PRF. This should handle clearing all sensitive information. */
+ sftk_MAC_Destroy(&ctx, PR_FALSE);
+ return ret;
+}
+
+/* [ section: PKCS#11 entry ] */
+
+CK_RV
+kbkdf_Dispatch(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, SFTKObject *prf_key, SFTKObject *ret_key, CK_ULONG ret_key_size)
+{
+ /* This handles boilerplate common to all KBKDF types. Instead of placing
+ * this in pkcs11c.c, place it here to reduce clutter. */
+
+ CK_RV ret;
+
+ /* Assumptions about our calling environment. */
+ PR_ASSERT(pMechanism != NULL && prf_key != NULL && ret_key != NULL);
+
+ /* Validate that the caller passed parameters. */
+ if (pMechanism->pParameter == NULL) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ /* Create a common set of parameters to use for all KDF types. This
+ * separates out the KDF parameters from the Feedback-specific IV,
+ * allowing us to use a common type for all calls. */
+ CK_SP800_108_KDF_PARAMS kdf_params = { 0 };
+ CK_BYTE_PTR initial_value = NULL;
+ CK_ULONG initial_value_length = 0;
+ unsigned char *output_buffer = NULL;
+ size_t buffer_length = 0;
+ unsigned int mac_size = 0;
+
+ /* Split Feedback-specific IV from remaining KDF parameters. */
+ ret = kbkdf_LoadParameters(mech, pMechanism, &kdf_params, &initial_value, &initial_value_length);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+ /* let rawDispatch handle the rest. We split this out so we could
+ * handle the POST test without accessing pkcs #11 objects. */
+ ret = kbkdf_RawDispatch(mech, &kdf_params, initial_value,
+ initial_value_length, prf_key, NULL, 0,
+ &output_buffer, &buffer_length, &mac_size,
+ ret_key_size);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+ /* Write the output of the PRF into the appropriate keys. */
+ ret = kbkdf_SaveKeys(mech, hSession, &kdf_params, output_buffer, buffer_length, mac_size, ret_key, ret_key_size);
+ if (ret != CKR_OK) {
+ goto finish;
+ }
+
+finish:
+ PORT_ZFree(output_buffer, buffer_length);
+
+ return ret;
+}
+
+struct sftk_SP800_Test_struct {
+ CK_MECHANISM_TYPE mech;
+ CK_SP800_108_KDF_PARAMS kdf_params;
+ unsigned int expected_mac_size;
+ unsigned int ret_key_length;
+ const unsigned char expected_key_bytes[64];
+};
+
+static const CK_SP800_108_COUNTER_FORMAT counter_32 = { 0, 32 };
+static const CK_PRF_DATA_PARAM counter_32_data =
+ { CK_SP800_108_ITERATION_VARIABLE, (CK_VOID_PTR)&counter_32, sizeof(counter_32) };
+
+#ifdef NSS_FULL_POST
+static const CK_SP800_108_COUNTER_FORMAT counter_16 = { 0, 16 };
+static const CK_PRF_DATA_PARAM counter_16_data =
+ { CK_SP800_108_ITERATION_VARIABLE, (CK_VOID_PTR)&counter_16, sizeof(counter_16) };
+static const CK_PRF_DATA_PARAM counter_null_data =
+ { CK_SP800_108_ITERATION_VARIABLE, NULL, 0 };
+#endif
+
+static const struct sftk_SP800_Test_struct sftk_SP800_Tests[] =
+ {
+#ifdef NSS_FULL_POST
+ {
+ CKM_SP800_108_COUNTER_KDF,
+ { CKM_AES_CMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_16_data, 0, NULL },
+ 16,
+ 64,
+ { 0x7b, 0x1c, 0xe7, 0xf3, 0x14, 0x67, 0x15, 0xdd,
+ 0xde, 0x0c, 0x09, 0x46, 0x3f, 0x47, 0x7b, 0xa6,
+ 0xb8, 0xba, 0x40, 0x07, 0x7c, 0xe3, 0x19, 0x53,
+ 0x26, 0xac, 0x4c, 0x2e, 0x2b, 0x37, 0x41, 0xe4,
+ 0x1b, 0x01, 0x3f, 0x2f, 0x2d, 0x16, 0x95, 0xee,
+ 0xeb, 0x7e, 0x72, 0x7d, 0xa4, 0xab, 0x2e, 0x67,
+ 0x1d, 0xef, 0x6f, 0xa2, 0xc6, 0xee, 0x3c, 0xcf,
+ 0xef, 0x88, 0xfd, 0x5c, 0x1d, 0x7b, 0xa0, 0x5a },
+ },
+ {
+ CKM_SP800_108_COUNTER_KDF,
+ { CKM_SHA384_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_32_data, 0, NULL },
+ 48,
+ 64,
+ { 0xe6, 0x62, 0xa4, 0x32, 0x5c, 0xe4, 0xc2, 0x28,
+ 0x73, 0x8a, 0x5d, 0x94, 0xe7, 0x05, 0xe0, 0x5a,
+ 0x71, 0x61, 0xb2, 0x3c, 0x51, 0x28, 0x03, 0x1d,
+ 0xa7, 0xf5, 0x10, 0x83, 0x34, 0xdb, 0x11, 0x73,
+ 0x92, 0xa6, 0x79, 0x74, 0x81, 0x5d, 0x22, 0x7e,
+ 0x8d, 0xf2, 0x59, 0x14, 0x56, 0x60, 0xcf, 0xb2,
+ 0xb3, 0xfd, 0x46, 0xfd, 0x9b, 0x74, 0xfe, 0x4a,
+ 0x09, 0x30, 0x4a, 0xdf, 0x07, 0x43, 0xfe, 0x85 },
+ },
+ {
+ CKM_SP800_108_COUNTER_KDF,
+ { CKM_SHA512_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_32_data, 0, NULL },
+ 64,
+ 64,
+ { 0xb0, 0x78, 0x36, 0xe1, 0x15, 0xd6, 0xf0, 0xac,
+ 0x68, 0x7b, 0x42, 0xd3, 0xb6, 0x82, 0x51, 0xad,
+ 0x95, 0x0a, 0x69, 0x88, 0x84, 0xc2, 0x2e, 0x07,
+ 0x34, 0x62, 0x8d, 0x42, 0x72, 0x0f, 0x22, 0xe6,
+ 0xd5, 0x7f, 0x80, 0x15, 0xe6, 0x84, 0x00, 0x65,
+ 0xef, 0x64, 0x77, 0x29, 0xd6, 0x3b, 0xc7, 0x9a,
+ 0x15, 0x6d, 0x36, 0xf3, 0x96, 0xc9, 0x14, 0x3f,
+ 0x2d, 0x4a, 0x7c, 0xdb, 0xc3, 0x6c, 0x3d, 0x6a },
+ },
+ {
+ CKM_SP800_108_FEEDBACK_KDF,
+ { CKM_AES_CMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
+ 16,
+ 64,
+ { 0xc0, 0xa0, 0x23, 0x96, 0x16, 0x4d, 0xd6, 0xbd,
+ 0x2a, 0x75, 0x8e, 0x72, 0xf5, 0xc3, 0xa0, 0xb8,
+ 0x78, 0x83, 0x15, 0x21, 0x34, 0xd3, 0xd8, 0x71,
+ 0xc9, 0xe7, 0x4b, 0x20, 0xb7, 0x65, 0x5b, 0x13,
+ 0xbc, 0x85, 0x54, 0xe3, 0xb6, 0xee, 0x73, 0xd5,
+ 0xf2, 0xa0, 0x94, 0x1a, 0x79, 0x66, 0x3b, 0x1e,
+ 0x67, 0x3e, 0x69, 0xa4, 0x12, 0x40, 0xa9, 0xda,
+ 0x8d, 0x14, 0xb1, 0xce, 0xf1, 0x4b, 0x79, 0x4e },
+ },
+ {
+ CKM_SP800_108_FEEDBACK_KDF,
+ { CKM_SHA256_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
+ 32,
+ 64,
+ { 0x99, 0x9b, 0x08, 0x79, 0x14, 0x2e, 0x58, 0x34,
+ 0xd7, 0x92, 0xa7, 0x7e, 0x7f, 0xc2, 0xf0, 0x34,
+ 0xa3, 0x4e, 0x33, 0xf0, 0x63, 0x95, 0x2d, 0xad,
+ 0xbf, 0x3b, 0xcb, 0x6d, 0x4e, 0x07, 0xd9, 0xe9,
+ 0xbd, 0xbd, 0x77, 0x54, 0xe1, 0xa3, 0x36, 0x26,
+ 0xcd, 0xb1, 0xf9, 0x2d, 0x80, 0x68, 0xa2, 0x01,
+ 0x4e, 0xbf, 0x35, 0xec, 0x65, 0xae, 0xfd, 0x71,
+ 0xa6, 0xd7, 0x62, 0x26, 0x2c, 0x3f, 0x73, 0x63 },
+ },
+ {
+ CKM_SP800_108_FEEDBACK_KDF,
+ { CKM_SHA384_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
+ 48,
+ 64,
+ { 0xc8, 0x7a, 0xf8, 0xd9, 0x6b, 0x90, 0x82, 0x35,
+ 0xea, 0xf5, 0x2c, 0x8f, 0xce, 0xaa, 0x3b, 0xa5,
+ 0x68, 0xd3, 0x7f, 0xae, 0x31, 0x93, 0xe6, 0x69,
+ 0x0c, 0xd1, 0x74, 0x7f, 0x8f, 0xc2, 0xe2, 0x33,
+ 0x93, 0x45, 0x23, 0xba, 0xb3, 0x73, 0xc9, 0x2c,
+ 0xd6, 0xd2, 0x10, 0x16, 0xe9, 0x9f, 0x9e, 0xe8,
+ 0xc1, 0x0e, 0x29, 0x95, 0x3d, 0x16, 0x68, 0x24,
+ 0x40, 0x4d, 0x40, 0x21, 0x41, 0xa6, 0xc8, 0xdb },
+ },
+ {
+ CKM_SP800_108_FEEDBACK_KDF,
+ { CKM_SHA512_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
+ 64,
+ 64,
+ { 0x81, 0x39, 0x12, 0xc2, 0xf9, 0x31, 0x24, 0x7c,
+ 0x71, 0x12, 0x97, 0x08, 0x82, 0x76, 0x83, 0x55,
+ 0x8c, 0x82, 0xf3, 0x09, 0xd6, 0x1b, 0x7a, 0xa2,
+ 0x6e, 0x71, 0x6b, 0xad, 0x46, 0x57, 0x60, 0x89,
+ 0x38, 0xcf, 0x63, 0xfa, 0xf4, 0x38, 0x27, 0xef,
+ 0xf0, 0xaf, 0x75, 0x4e, 0xc2, 0xe0, 0x31, 0xdb,
+ 0x59, 0x7d, 0x19, 0xc9, 0x6d, 0xbb, 0xed, 0x95,
+ 0xaf, 0x3e, 0xd8, 0x33, 0x76, 0xab, 0xec, 0xfa },
+ },
+ {
+ CKM_SP800_108_DOUBLE_PIPELINE_KDF,
+ { CKM_AES_CMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
+ 16,
+ 64,
+ { 0x3e, 0xa8, 0xbf, 0x77, 0x84, 0x90, 0xb0, 0x3a,
+ 0x89, 0x16, 0x32, 0x01, 0x92, 0xd3, 0x1f, 0x1b,
+ 0xc1, 0x06, 0xc5, 0x32, 0x62, 0x03, 0x50, 0x16,
+ 0x3b, 0xb9, 0xa7, 0xdc, 0xb5, 0x68, 0x6a, 0xbb,
+ 0xbb, 0x7d, 0x63, 0x69, 0x24, 0x6e, 0x09, 0xd6,
+ 0x6f, 0x80, 0x57, 0x65, 0xc5, 0x62, 0x33, 0x96,
+ 0x69, 0xe6, 0xab, 0x65, 0x36, 0xd0, 0xe2, 0x5c,
+ 0xd7, 0xbd, 0xe4, 0x68, 0x13, 0xd6, 0xb1, 0x46 },
+ },
+ {
+ CKM_SP800_108_DOUBLE_PIPELINE_KDF,
+ { CKM_SHA256_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
+ 32,
+ 64,
+ { 0xeb, 0x28, 0xd9, 0x2c, 0x19, 0x33, 0xb9, 0x2a,
+ 0xf9, 0xac, 0x85, 0xbd, 0xf4, 0xdb, 0xfa, 0x88,
+ 0x73, 0xf4, 0x36, 0x08, 0xdb, 0xfe, 0x13, 0xd1,
+ 0x5a, 0xec, 0x7b, 0x68, 0x13, 0x53, 0xb3, 0xd1,
+ 0x31, 0xf2, 0x83, 0xae, 0x9f, 0x75, 0x47, 0xb6,
+ 0x6d, 0x3c, 0x20, 0x16, 0x47, 0x9c, 0x27, 0x66,
+ 0xec, 0xa9, 0xdf, 0x0c, 0xda, 0x2a, 0xf9, 0xf4,
+ 0x55, 0x74, 0xde, 0x9d, 0x3f, 0xe3, 0x5e, 0x14 },
+ },
+ {
+ CKM_SP800_108_DOUBLE_PIPELINE_KDF,
+ { CKM_SHA384_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
+ 48,
+ 64,
+ { 0xa5, 0xca, 0x32, 0x40, 0x00, 0x93, 0xb2, 0xcc,
+ 0x78, 0x3c, 0xa6, 0xc4, 0xaf, 0xa8, 0xb3, 0xd0,
+ 0xa4, 0x6b, 0xb5, 0x31, 0x35, 0x87, 0x33, 0xa2,
+ 0x6a, 0x6b, 0xe1, 0xff, 0xea, 0x1d, 0x6e, 0x9e,
+ 0x0b, 0xde, 0x8b, 0x92, 0x15, 0xd6, 0x56, 0x2f,
+ 0xb6, 0x1a, 0xd7, 0xd2, 0x01, 0x3e, 0x28, 0x2e,
+ 0xfa, 0x84, 0x3c, 0xc0, 0xe8, 0xbe, 0x94, 0xc0,
+ 0x06, 0xbd, 0xbf, 0x87, 0x1f, 0xb8, 0x64, 0xc2 },
+ },
+ {
+ CKM_SP800_108_DOUBLE_PIPELINE_KDF,
+ { CKM_SHA512_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL },
+ 64,
+ 64,
+ { 0x3f, 0xd9, 0x4e, 0x80, 0x58, 0x21, 0xc8, 0xea,
+ 0x22, 0x17, 0xcf, 0x7d, 0xce, 0xfd, 0xec, 0x03,
+ 0xb9, 0xe4, 0xa2, 0xf7, 0xc0, 0xf1, 0x68, 0x81,
+ 0x53, 0x71, 0xb7, 0x42, 0x14, 0x4e, 0x5b, 0x09,
+ 0x05, 0x31, 0xb9, 0x27, 0x18, 0x2d, 0x23, 0xf8,
+ 0x9c, 0x3d, 0x4e, 0xd0, 0xdd, 0xf3, 0x1e, 0x4b,
+ 0xf2, 0xf9, 0x1a, 0x5d, 0x00, 0x66, 0x22, 0x83,
+ 0xae, 0x3c, 0x53, 0xd2, 0x54, 0x4b, 0x06, 0x4c },
+ },
+#endif
+ {
+ CKM_SP800_108_COUNTER_KDF,
+ { CKM_SHA256_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_32_data, 0, NULL },
+ 32,
+ 64,
+ { 0xfb, 0x2b, 0xb5, 0xde, 0xce, 0x5a, 0x2b, 0xdc,
+ 0x25, 0x8f, 0x54, 0x17, 0x4b, 0x5a, 0xa7, 0x90,
+ 0x64, 0x36, 0xeb, 0x43, 0x1f, 0x1d, 0xf9, 0x23,
+ 0xb2, 0x22, 0x29, 0xa0, 0xfa, 0x2e, 0x21, 0xb6,
+ 0xb7, 0xfb, 0x27, 0x0a, 0x1c, 0xa6, 0x58, 0x43,
+ 0xa1, 0x16, 0x44, 0x29, 0x4b, 0x1c, 0xb3, 0x72,
+ 0xd5, 0x98, 0x9d, 0x27, 0xd5, 0x75, 0x25, 0xbf,
+ 0x23, 0x61, 0x40, 0x48, 0xbb, 0x0b, 0x49, 0x8e },
+ }
+ };
+
+SECStatus
+sftk_fips_SP800_108_PowerUpSelfTests(void)
+{
+ int i;
+ CK_RV crv;
+
+ const unsigned char prf_key[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78
+ };
+ for (i = 0; i < PR_ARRAY_SIZE(sftk_SP800_Tests); i++) {
+ const struct sftk_SP800_Test_struct *test = &sftk_SP800_Tests[i];
+ unsigned char *output_buffer;
+ size_t buffer_length;
+ unsigned int mac_size;
+
+ crv = kbkdf_RawDispatch(test->mech, &test->kdf_params,
+ prf_key, test->expected_mac_size,
+ NULL, prf_key, test->expected_mac_size,
+ &output_buffer, &buffer_length, &mac_size,
+ test->ret_key_length);
+ if (crv != CKR_OK) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ if ((mac_size != test->expected_mac_size) ||
+ (buffer_length != test->ret_key_length) ||
+ (output_buffer == NULL) ||
+ (PORT_Memcmp(output_buffer, test->expected_key_bytes, buffer_length) != 0)) {
+ PORT_ZFree(output_buffer, buffer_length);
+ return SECFailure;
+ }
+ PORT_ZFree(output_buffer, buffer_length);
+ }
+ return SECSuccess;
+}
diff --git a/security/nss/lib/softoken/legacydb/keydb.c b/security/nss/lib/softoken/legacydb/keydb.c
index c8c4d07ba..daa0bbd97 100644
--- a/security/nss/lib/softoken/legacydb/keydb.c
+++ b/security/nss/lib/softoken/legacydb/keydb.c
@@ -2252,6 +2252,12 @@ lg_PutMetaData(SDB *sdb, const char *id,
}
CK_RV
+lg_DestroyMetaData(SDB *db, const char *id)
+{
+ return CKR_GENERAL_ERROR; /* no extra data stored */
+}
+
+CK_RV
lg_Reset(SDB *sdb)
{
NSSLOWKEYDBHandle *keydb;
diff --git a/security/nss/lib/softoken/legacydb/lgattr.c b/security/nss/lib/softoken/legacydb/lgattr.c
index c1865a38e..cbc708a3f 100644
--- a/security/nss/lib/softoken/legacydb/lgattr.c
+++ b/security/nss/lib/softoken/legacydb/lgattr.c
@@ -879,7 +879,7 @@ lg_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
return lg_CopyAttributeSigned(attribute, type,
key->u.dsa.params.base.data,
key->u.dsa.params.base.len);
- case CKA_NETSCAPE_DB:
+ case CKA_NSS_DB:
return lg_CopyAttributeSigned(attribute, type,
key->u.dsa.publicValue.data,
key->u.dsa.publicValue.len);
@@ -919,7 +919,7 @@ lg_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
case CKA_BASE:
return lg_CopyAttributeSigned(attribute, type, key->u.dh.base.data,
key->u.dh.base.len);
- case CKA_NETSCAPE_DB:
+ case CKA_NSS_DB:
return lg_CopyAttributeSigned(attribute, type,
key->u.dh.publicValue.data,
key->u.dh.publicValue.len);
@@ -957,7 +957,7 @@ lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
return lg_CopyAttributeSigned(attribute, type,
key->u.ec.ecParams.DEREncoding.data,
key->u.ec.ecParams.DEREncoding.len);
- case CKA_NETSCAPE_DB:
+ case CKA_NSS_DB:
return lg_CopyAttributeSigned(attribute, type,
key->u.ec.publicValue.data,
key->u.ec.publicValue.len);
@@ -1689,7 +1689,7 @@ lg_SetSingleAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr,
CK_ATTRIBUTE attribLocal;
CK_RV crv;
- if ((attr->type == CKA_NETSCAPE_DB) && (obj->objclass == CKO_PRIVATE_KEY)) {
+ if ((attr->type == CKA_NSS_DB) && (obj->objclass == CKO_PRIVATE_KEY)) {
*writePrivate = PR_TRUE;
return CKR_OK;
}
diff --git a/security/nss/lib/softoken/legacydb/lgcreate.c b/security/nss/lib/softoken/legacydb/lgcreate.c
index f2b2aa634..66545a885 100644
--- a/security/nss/lib/softoken/legacydb/lgcreate.c
+++ b/security/nss/lib/softoken/legacydb/lgcreate.c
@@ -574,8 +574,8 @@ lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
&privKey->u.dsa.privateValue, sdb);
if (crv != CKR_OK)
break;
- if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
- crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB, templ, count,
+ if (lg_hasAttribute(CKA_NSS_DB, templ, count)) {
+ crv = lg_Attribute2SSecItem(arena, CKA_NSS_DB, templ, count,
&privKey->u.dsa.publicValue);
/* privKey was zero'd so public value is already set to NULL, 0
* if we don't set it explicitly */
@@ -596,8 +596,8 @@ lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
&privKey->u.dh.privateValue, sdb);
if (crv != CKR_OK)
break;
- if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
- crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB, templ, count,
+ if (lg_hasAttribute(CKA_NSS_DB, templ, count)) {
+ crv = lg_Attribute2SSecItem(arena, CKA_NSS_DB, templ, count,
&privKey->u.dh.publicValue);
/* privKey was zero'd so public value is already set to NULL, 0
* if we don't set it explicitly */
@@ -623,8 +623,8 @@ lg_mkPrivKey(SDB *sdb, const CK_ATTRIBUTE *templ, CK_ULONG count,
&privKey->u.ec.privateValue, sdb);
if (crv != CKR_OK)
break;
- if (lg_hasAttribute(CKA_NETSCAPE_DB, templ, count)) {
- crv = lg_Attribute2SSecItem(arena, CKA_NETSCAPE_DB, templ, count,
+ if (lg_hasAttribute(CKA_NSS_DB, templ, count)) {
+ crv = lg_Attribute2SSecItem(arena, CKA_NSS_DB, templ, count,
&privKey->u.ec.publicValue);
if (crv != CKR_OK)
break;
@@ -672,7 +672,7 @@ lg_createPrivateKeyObject(SDB *sdb, CK_KEY_TYPE key_type,
return crv;
label = lg_getString(CKA_LABEL, templ, count);
- crv = lg_Attribute2SSecItem(NULL, CKA_NETSCAPE_DB, templ, count, &pubKey);
+ crv = lg_Attribute2SSecItem(NULL, CKA_NSS_DB, templ, count, &pubKey);
if (crv != CKR_OK) {
crv = CKR_TEMPLATE_INCOMPLETE;
rv = SECFailure;
@@ -961,6 +961,22 @@ lg_createKeyObject(SDB *sdb, CK_OBJECT_CLASS objclass,
}
/*
+ * return the 'next' key handle
+ */
+CK_RV
+lg_GetNewObjectID(SDB *sdb, CK_OBJECT_HANDLE *handle)
+{
+ /* the upper level needs the Object ID early to populate any
+ * signature attributes. The legacy can't really return a new
+ * handle without the full object template (chicken and egg issue).
+ * Fortunately we can just return a bogus handle because the legacy
+ * database doesn't support meta data and can't store any of the signed
+ * attributes anyway */
+ *handle = CK_INVALID_HANDLE;
+ return CKR_OK;
+}
+
+/*
* Parse the template and create an object stored in the DB that reflects.
* the object specified in the database.
*/
diff --git a/security/nss/lib/softoken/legacydb/lgdb.h b/security/nss/lib/softoken/legacydb/lgdb.h
index ee80f4b77..c28e8a368 100644
--- a/security/nss/lib/softoken/legacydb/lgdb.h
+++ b/security/nss/lib/softoken/legacydb/lgdb.h
@@ -150,6 +150,8 @@ CK_RV lg_Abort(SDB *sdb);
CK_RV lg_GetMetaData(SDB *sdb, const char *id, SECItem *item1, SECItem *item2);
CK_RV lg_PutMetaData(SDB *sdb, const char *id,
const SECItem *item1, const SECItem *item2);
+CK_RV lg_DestroyMetaData(SDB *sdb, const char *id);
+CK_RV lg_GetNewObjectID(SDB *sdb, CK_OBJECT_HANDLE *object_id);
SEC_END_PROTOS
diff --git a/security/nss/lib/softoken/legacydb/lgfind.c b/security/nss/lib/softoken/legacydb/lgfind.c
index 288e56cac..3c18c0ef1 100644
--- a/security/nss/lib/softoken/legacydb/lgfind.c
+++ b/security/nss/lib/softoken/legacydb/lgfind.c
@@ -666,11 +666,11 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
case CKA_LABEL:
copy = &name;
break;
- case CKA_NETSCAPE_EMAIL:
+ case CKA_NSS_EMAIL:
copy = &email;
classFlags &= LG_SMIME | LG_CERT;
break;
- case CKA_NETSCAPE_SMIME_TIMESTAMP:
+ case CKA_NSS_SMIME_TIMESTAMP:
classFlags &= LG_SMIME;
break;
case CKA_CLASS:
@@ -683,13 +683,13 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
case CKO_CERTIFICATE:
classFlags &= LG_CERT;
break;
- case CKO_NETSCAPE_TRUST:
+ case CKO_NSS_TRUST:
classFlags &= LG_TRUST;
break;
- case CKO_NETSCAPE_CRL:
+ case CKO_NSS_CRL:
classFlags &= LG_CRL;
break;
- case CKO_NETSCAPE_SMIME:
+ case CKO_NSS_SMIME:
classFlags &= LG_SMIME;
break;
case CKO_PRIVATE_KEY:
@@ -761,7 +761,7 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
copy = &key_id;
classFlags &= (LG_CERT | LG_PRIVATE | LG_KEY | LG_PUBLIC);
break;
- case CKA_NETSCAPE_KRL:
+ case CKA_NSS_KRL:
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
classFlags = 0;
break;
diff --git a/security/nss/lib/softoken/legacydb/lginit.c b/security/nss/lib/softoken/legacydb/lginit.c
index 4f0b53f52..d3b4ff32f 100644
--- a/security/nss/lib/softoken/legacydb/lginit.c
+++ b/security/nss/lib/softoken/legacydb/lginit.c
@@ -341,7 +341,7 @@ lg_OpenCertDB(const char *configdir, const char *prefix, PRBool readOnly,
NSSLOWCERTCertDBHandle **certdbPtr)
{
NSSLOWCERTCertDBHandle *certdb = NULL;
- CK_RV crv = CKR_NETSCAPE_CERTDB_FAILED;
+ CK_RV crv = CKR_NSS_CERTDB_FAILED;
SECStatus rv;
char *name = NULL;
char *appName = NULL;
@@ -401,7 +401,7 @@ lg_OpenKeyDB(const char *configdir, const char *prefix, PRBool readOnly,
if (appName)
PORT_Free(appName);
if (keydb == NULL)
- return CKR_NETSCAPE_KEYDB_FAILED;
+ return CKR_NSS_KEYDB_FAILED;
*keydbPtr = keydb;
return CKR_OK;
@@ -519,7 +519,7 @@ lg_init(SDB **pSdb, int flags, NSSLOWCERTCertDBHandle *certdbPtr,
}
sdb->private = lgdb_p;
- sdb->version = 0;
+ sdb->version = 1;
sdb->sdb_flags = flags;
sdb->app_private = NULL;
sdb->sdb_FindObjectsInit = lg_FindObjectsInit;
@@ -531,12 +531,14 @@ lg_init(SDB **pSdb, int flags, NSSLOWCERTCertDBHandle *certdbPtr,
sdb->sdb_DestroyObject = lg_DestroyObject;
sdb->sdb_GetMetaData = lg_GetMetaData;
sdb->sdb_PutMetaData = lg_PutMetaData;
+ sdb->sdb_DestroyMetaData = lg_DestroyMetaData;
sdb->sdb_Begin = lg_Begin;
sdb->sdb_Commit = lg_Commit;
sdb->sdb_Abort = lg_Abort;
sdb->sdb_Reset = lg_Reset;
sdb->sdb_Close = lg_Close;
sdb->sdb_SetForkState = lg_SetForkState;
+ sdb->sdb_GetNewObjectID = lg_GetNewObjectID;
*pSdb = sdb;
return CKR_OK;
diff --git a/security/nss/lib/softoken/lgglue.c b/security/nss/lib/softoken/lgglue.c
index 8cfb4ec56..461e9a3cd 100644
--- a/security/nss/lib/softoken/lgglue.c
+++ b/security/nss/lib/softoken/lgglue.c
@@ -205,7 +205,8 @@ sftkdb_encrypt_stub(PLArenaPool *arena, SDB *sdb, SECItem *plainText,
iterationCount = 1;
}
- rv = sftkdb_EncryptAttribute(arena, key, iterationCount,
+ rv = sftkdb_EncryptAttribute(arena, handle, sdb, key, iterationCount,
+ CK_INVALID_HANDLE, CKT_INVALID_TYPE,
plainText, cipherText);
PZ_Unlock(handle->passwordLock);
@@ -227,7 +228,7 @@ sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText, SECItem **plainText)
return SECFailure;
}
- /* if we aren't th handle, try the other handle */
+ /* if we aren't the key handle, try the other handle */
oldKey = handle->oldKey;
if (handle->type != SFTK_KEYDB_TYPE) {
handle = handle->peerDB;
@@ -244,7 +245,9 @@ sftkdb_decrypt_stub(SDB *sdb, SECItem *cipherText, SECItem **plainText)
/* PORT_SetError */
return SECFailure;
}
- rv = sftkdb_DecryptAttribute(oldKey ? oldKey : &handle->passwordKey,
+ rv = sftkdb_DecryptAttribute(NULL, oldKey ? oldKey : &handle->passwordKey,
+ CK_INVALID_HANDLE,
+ CKT_INVALID_TYPE,
cipherText, plainText);
PZ_Unlock(handle->passwordLock);
diff --git a/security/nss/lib/softoken/lowpbe.c b/security/nss/lib/softoken/lowpbe.c
index 55808f0f7..0d8e02ddf 100644
--- a/security/nss/lib/softoken/lowpbe.c
+++ b/security/nss/lib/softoken/lowpbe.c
@@ -22,6 +22,9 @@
SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
+/* how much a crypto encrypt/decryption may expand a buffer */
+#define MAX_CRYPTO_EXPANSION 64
+
/* template for PKCS 5 PBE Parameter. This template has been expanded
* based upon the additions in PKCS 12. This should eventually be moved
* if RSA updates PKCS 5.
@@ -604,6 +607,7 @@ sftk_clearPBECommonCacheItemsLocked(KDFCacheItem *item)
}
}
+static void
sftk_setPBECommonCacheItemsKDFLocked(KDFCacheItem *cacheItem,
const SECItem *hash,
const NSSPKCS5PBEParameter *pbe_param,
@@ -623,12 +627,14 @@ sftk_setPBECacheKDF2(const SECItem *hash,
const SECItem *pwItem)
{
PZ_Lock(PBECache.lock);
+
sftk_clearPBECommonCacheItemsLocked(&PBECache.cacheKDF2.common);
+
sftk_setPBECommonCacheItemsKDFLocked(&PBECache.cacheKDF2.common,
hash, pbe_param, pwItem);
PZ_Unlock(PBECache.lock);
-}
+}
static void
sftk_setPBECacheKDF1(const SECItem *hash,
@@ -698,7 +704,6 @@ sftk_getPBECacheKDF1(const NSSPKCS5PBEParameter *pbe_param,
return result;
}
-
void
sftk_PBELockShutdown(void)
{
@@ -808,11 +813,49 @@ loser:
return NULL;
}
+#define MAX_IV_LENGTH 64
+/* get a random IV into the parameters */
+static SECStatus
+nsspkcs5_SetIVParam(NSSPKCS5PBEParameter *pbe_param, int ivLen)
+{
+ SECStatus rv;
+ SECItem derIV;
+ SECItem iv;
+ SECItem *dummy = NULL;
+ unsigned char ivData[MAX_IV_LENGTH];
+
+ PORT_Assert(ivLen <= MAX_IV_LENGTH);
+
+ /* Because of a bug in the decode section, the IV's not are expected
+ * to be der encoded, but still need to parse as if they were der data.
+ * because we want to be compatible with existing versions of nss that
+ * have that bug, create an IV that looks like der data. That still
+ * leaves 14 bytes of entropy in the IV */
+ rv = RNG_GenerateGlobalRandomBytes(ivData, ivLen - 2);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ derIV.data = NULL;
+ derIV.len = 0;
+ iv.data = ivData;
+ iv.len = ivLen - 2;
+ dummy = SEC_ASN1EncodeItem(pbe_param->poolp, &derIV, &iv,
+ SEC_ASN1_GET(SEC_OctetStringTemplate));
+ if (dummy == NULL) {
+ return SECFailure;
+ }
+ pbe_param->ivData = derIV.data;
+ pbe_param->ivLen = derIV.len;
+ PORT_Assert(pbe_param->ivLen == ivLen);
+ return SECSuccess;
+}
+
static SECStatus
nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
NSSPKCS5PBEParameter *pbe_param)
{
PRBool skipType = PR_FALSE;
+ SECStatus rv;
pbe_param->keyLen = 5;
pbe_param->ivLen = 8;
@@ -846,6 +889,7 @@ nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
pbe_param->encAlg = SEC_OID_DES_CBC;
break;
+#ifndef NSS_DISABLE_DEPRECATED_RC2
/* RC2 Algorithms */
case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
pbe_param->keyLen = 16;
@@ -858,6 +902,7 @@ nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
/* fall through */
case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
break;
+#endif
/* RC4 algorithms */
case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
@@ -885,11 +930,68 @@ nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
pbe_param->encAlg = SEC_OID_PKCS5_PBKDF2;
pbe_param->keyLen = 0; /* needs to be set by caller after return */
break;
+ /* AES uses PBKDF2 */
+ case SEC_OID_AES_128_CBC:
+ rv = nsspkcs5_SetIVParam(pbe_param, 16);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ pbe_param->ivLen = 16;
+ pbe_param->pbeType = NSSPKCS5_PBKDF2;
+ pbe_param->encAlg = algorithm;
+ pbe_param->keyLen = 128 / 8;
+ break;
+ case SEC_OID_AES_192_CBC:
+ rv = nsspkcs5_SetIVParam(pbe_param, 16);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ pbe_param->pbeType = NSSPKCS5_PBKDF2;
+ pbe_param->encAlg = algorithm;
+ pbe_param->keyLen = 192 / 8;
+ break;
+ case SEC_OID_AES_256_CBC:
+ rv = nsspkcs5_SetIVParam(pbe_param, 16);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ pbe_param->pbeType = NSSPKCS5_PBKDF2;
+ pbe_param->encAlg = algorithm;
+ pbe_param->keyLen = 256 / 8;
+ break;
+ case SEC_OID_AES_128_KEY_WRAP:
+ pbe_param->ivLen = 0;
+ pbe_param->pbeType = NSSPKCS5_PBKDF2;
+ pbe_param->encAlg = algorithm;
+ pbe_param->keyLen = 128 / 8;
+ break;
+ case SEC_OID_AES_192_KEY_WRAP:
+ pbe_param->ivLen = 0;
+ pbe_param->pbeType = NSSPKCS5_PBKDF2;
+ pbe_param->encAlg = algorithm;
+ pbe_param->keyLen = 192 / 8;
+ break;
+ case SEC_OID_AES_256_KEY_WRAP:
+ pbe_param->ivLen = 0;
+ pbe_param->pbeType = NSSPKCS5_PBKDF2;
+ pbe_param->encAlg = algorithm;
+ pbe_param->keyLen = 256 / 8;
+ break;
default:
return SECFailure;
}
-
+ if (pbe_param->pbeType == NSSPKCS5_PBKDF2) {
+ SECOidTag prfAlg = HASH_HMACOidFromHash(pbe_param->hashType);
+ if (prfAlg == SEC_OID_UNKNOWN) {
+ return SECFailure;
+ }
+ rv = SECOID_SetAlgorithmID(pbe_param->poolp, &pbe_param->prfAlg,
+ prfAlg, NULL);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ }
return SECSuccess;
}
@@ -962,6 +1064,29 @@ HASH_FromHMACOid(SECOidTag hmac)
return HASH_AlgNULL;
}
+SECOidTag
+HASH_HMACOidFromHash(HASH_HashType hashType)
+{
+ switch (hashType) {
+ case HASH_AlgSHA1:
+ return SEC_OID_HMAC_SHA1;
+ case HASH_AlgSHA256:
+ return SEC_OID_HMAC_SHA256;
+ case HASH_AlgSHA384:
+ return SEC_OID_HMAC_SHA384;
+ case HASH_AlgSHA512:
+ return SEC_OID_HMAC_SHA512;
+ case HASH_AlgSHA224:
+ return SEC_OID_HMAC_SHA224;
+ case HASH_AlgMD2:
+ case HASH_AlgMD5:
+ case HASH_AlgTOTAL:
+ default:
+ break;
+ }
+ return SEC_OID_UNKNOWN;
+}
+
/* decode the algid and generate a PKCS 5 parameter from it
*/
NSSPKCS5PBEParameter *
@@ -1066,11 +1191,16 @@ sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
{
SECItem *dest;
SECItem *dup_src;
+ CK_RV crv = CKR_DEVICE_ERROR;
+ int error;
SECStatus rv = SECFailure;
- int pad;
+ DESContext *ctxt;
+ unsigned int pad;
- if ((src == NULL) || (key == NULL) || (iv == NULL))
+ if ((src == NULL) || (key == NULL) || (iv == NULL)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
+ }
dup_src = SECITEM_DupItem(src);
if (dup_src == NULL) {
@@ -1081,7 +1211,7 @@ sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
void *dummy;
dummy = CBC_PadBuffer(NULL, dup_src->data,
- dup_src->len, &dup_src->len, 8 /* DES_BLOCK_SIZE */);
+ dup_src->len, &dup_src->len, DES_BLOCK_SIZE);
if (dummy == NULL) {
SECITEM_FreeItem(dup_src, PR_TRUE);
return NULL;
@@ -1089,42 +1219,33 @@ sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
dup_src->data = (unsigned char *)dummy;
}
- dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if (dest != NULL) {
- /* allocate with over flow */
- dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
- if (dest->data != NULL) {
- DESContext *ctxt;
- ctxt = DES_CreateContext(key->data, iv->data,
- (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC),
- encrypt);
+ dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
+ if (dest == NULL) {
+ goto loser;
+ }
+ ctxt = DES_CreateContext(key->data, iv->data,
+ (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC),
+ encrypt);
+ if (ctxt == NULL) {
+ goto loser;
+ }
+ rv = (encrypt ? DES_Encrypt : DES_Decrypt)(
+ ctxt, dest->data, &dest->len,
+ dest->len, dup_src->data, dup_src->len);
- if (ctxt != NULL) {
- rv = (encrypt ? DES_Encrypt : DES_Decrypt)(
- ctxt, dest->data, &dest->len,
- dup_src->len + 64, dup_src->data, dup_src->len);
+ crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
+ error = PORT_GetError();
- /* remove padding -- assumes 64 bit blocks */
- if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
- pad = dest->data[dest->len - 1];
- if ((pad > 0) && (pad <= 8)) {
- if (dest->data[dest->len - pad] != pad) {
- rv = SECFailure;
- PORT_SetError(SEC_ERROR_BAD_PASSWORD);
- } else {
- dest->len -= pad;
- }
- } else {
- rv = SECFailure;
- PORT_SetError(SEC_ERROR_BAD_PASSWORD);
- }
- }
- DES_DestroyContext(ctxt, PR_TRUE);
- }
- }
+ /* remove padding */
+ if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
+ crv = sftk_CheckCBCPadding(dest->data, dest->len, DES_BLOCK_SIZE, &pad);
+ dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
+ PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
}
+ DES_DestroyContext(ctxt, PR_TRUE);
- if (rv == SECFailure) {
+loser:
+ if (crv != CKR_OK) {
if (dest != NULL) {
SECITEM_FreeItem(dest, PR_TRUE);
}
@@ -1146,11 +1267,16 @@ sec_pkcs5_aes(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
{
SECItem *dest;
SECItem *dup_src;
+ CK_RV crv = CKR_DEVICE_ERROR;
+ int error;
SECStatus rv = SECFailure;
- int pad;
+ AESContext *ctxt;
+ unsigned int pad;
- if ((src == NULL) || (key == NULL) || (iv == NULL))
+ if ((src == NULL) || (key == NULL) || (iv == NULL)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
+ }
dup_src = SECITEM_DupItem(src);
if (dup_src == NULL) {
@@ -1169,41 +1295,108 @@ sec_pkcs5_aes(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
dup_src->data = (unsigned char *)dummy;
}
- dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
- if (dest != NULL) {
- /* allocate with over flow */
- dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
- if (dest->data != NULL) {
- AESContext *ctxt;
- ctxt = AES_CreateContext(key->data, iv->data,
- NSS_AES_CBC, encrypt, key->len, 16);
+ dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
+ if (dest == NULL) {
+ goto loser;
+ }
+ ctxt = AES_CreateContext(key->data, iv->data, NSS_AES_CBC,
+ encrypt, key->len, AES_BLOCK_SIZE);
+ if (ctxt == NULL) {
+ goto loser;
+ }
+ rv = (encrypt ? AES_Encrypt : AES_Decrypt)(
+ ctxt, dest->data, &dest->len,
+ dest->len, dup_src->data, dup_src->len);
- if (ctxt != NULL) {
- rv = (encrypt ? AES_Encrypt : AES_Decrypt)(
- ctxt, dest->data, &dest->len,
- dup_src->len + 64, dup_src->data, dup_src->len);
+ crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
+ error = PORT_GetError();
- /* remove padding -- assumes 64 bit blocks */
- if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
- pad = dest->data[dest->len - 1];
- if ((pad > 0) && (pad <= 16)) {
- if (dest->data[dest->len - pad] != pad) {
- rv = SECFailure;
- PORT_SetError(SEC_ERROR_BAD_PASSWORD);
- } else {
- dest->len -= pad;
- }
- } else {
- rv = SECFailure;
- PORT_SetError(SEC_ERROR_BAD_PASSWORD);
- }
- }
- AES_DestroyContext(ctxt, PR_TRUE);
- }
+ /* remove padding */
+ if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
+ crv = sftk_CheckCBCPadding(dest->data, dest->len, AES_BLOCK_SIZE, &pad);
+ dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
+ PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
+ }
+ AES_DestroyContext(ctxt, PR_TRUE);
+
+loser:
+ if (crv != CKR_OK) {
+ if (dest != NULL) {
+ SECITEM_FreeItem(dest, PR_TRUE);
}
+ dest = NULL;
+ }
+
+ if (dup_src != NULL) {
+ SECITEM_FreeItem(dup_src, PR_TRUE);
}
- if (rv == SECFailure) {
+ return dest;
+}
+
+/* perform aes encryption/decryption if an error occurs, NULL is returned
+ */
+static SECItem *
+sec_pkcs5_aes_key_wrap(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
+ PRBool encrypt)
+{
+ SECItem *dest;
+ SECItem *dup_src;
+ CK_RV crv = CKR_DEVICE_ERROR;
+ int error;
+ SECStatus rv = SECFailure;
+ AESKeyWrapContext *ctxt;
+ unsigned int pad;
+
+ if ((src == NULL) || (key == NULL) || (iv == NULL)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ dup_src = SECITEM_DupItem(src);
+ if (dup_src == NULL) {
+ return NULL;
+ }
+
+ if (encrypt != PR_FALSE) {
+ void *dummy;
+
+ dummy = CBC_PadBuffer(NULL, dup_src->data,
+ dup_src->len, &dup_src->len, AES_BLOCK_SIZE);
+ if (dummy == NULL) {
+ SECITEM_FreeItem(dup_src, PR_TRUE);
+ return NULL;
+ }
+ dup_src->data = (unsigned char *)dummy;
+ }
+
+ dest = SECITEM_AllocItem(NULL, NULL, dup_src->len + MAX_CRYPTO_EXPANSION);
+ if (dest == NULL) {
+ goto loser;
+ }
+ ctxt = AESKeyWrap_CreateContext(key->data, iv->data, encrypt,
+ key->len);
+
+ if (ctxt == NULL) {
+ goto loser;
+ }
+ rv = (encrypt ? AESKeyWrap_Encrypt : AESKeyWrap_Decrypt)(
+ ctxt, dest->data, &dest->len,
+ dest->len, dup_src->data, dup_src->len);
+
+ crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
+ error = PORT_GetError();
+
+ /* remove padding */
+ if ((encrypt == PR_FALSE) && (rv == SECSuccess)) {
+ crv = sftk_CheckCBCPadding(dest->data, dest->len, AES_BLOCK_SIZE, &pad);
+ dest->len = PORT_CT_SEL(sftk_CKRVToMask(crv), dest->len - pad, dest->len);
+ PORT_SetError(PORT_CT_SEL(sftk_CKRVToMask(crv), error, SEC_ERROR_BAD_PASSWORD));
+ }
+ AESKeyWrap_DestroyContext(ctxt, PR_TRUE);
+
+loser:
+ if (crv != CKR_OK) {
if (dest != NULL) {
SECITEM_FreeItem(dest, PR_TRUE);
}
@@ -1217,6 +1410,7 @@ sec_pkcs5_aes(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
return dest;
}
+#ifndef NSS_DISABLE_DEPRECATED_RC2
/* perform rc2 encryption/decryption if an error occurs, NULL is returned
*/
static SECItem *
@@ -1229,6 +1423,7 @@ sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy,
int pad;
if ((src == NULL) || (key == NULL) || (iv == NULL)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
@@ -1293,6 +1488,7 @@ sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy,
return dest;
}
+#endif /* NSS_DISABLE_DEPRECATED_RC2 */
/* perform rc4 encryption and decryption */
static SECItem *
@@ -1303,6 +1499,7 @@ sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op,
SECStatus rv = SECFailure;
if ((src == NULL) || (key == NULL) || (iv == NULL)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
@@ -1357,6 +1554,7 @@ nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
}
if ((pwitem == NULL) || (src == NULL)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
@@ -1368,6 +1566,11 @@ nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
switch (pbe_param->encAlg) {
/* PKCS 5 v2 only */
+ case SEC_OID_AES_128_KEY_WRAP:
+ case SEC_OID_AES_192_KEY_WRAP:
+ case SEC_OID_AES_256_KEY_WRAP:
+ cryptof = sec_pkcs5_aes_key_wrap;
+ break;
case SEC_OID_AES_128_CBC:
case SEC_OID_AES_192_CBC:
case SEC_OID_AES_256_CBC:
@@ -1381,9 +1584,11 @@ nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
cryptof = sec_pkcs5_des;
tripleDES = PR_FALSE;
break;
+#ifndef NSS_DISABLE_DEPRECATED_RC2
case SEC_OID_RC2_CBC:
cryptof = sec_pkcs5_rc2;
break;
+#endif
case SEC_OID_RC4:
cryptof = sec_pkcs5_rc4;
break;
@@ -1405,8 +1610,8 @@ nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
* The case can only happen on decrypted of a
* SEC_OID_DES_EDE3_CBD.
*/
- if ((dest == NULL) && (encrypt == PR_FALSE) &&
- (pbe_param->encAlg == SEC_OID_DES_EDE3_CBC)) {
+ if ((pbe_param->encAlg == SEC_OID_DES_EDE3_CBC) &&
+ (dest == NULL) && (encrypt == PR_FALSE)) {
dest = (*cryptof)(key, &iv, src, PR_FALSE, encrypt);
if (update && (dest != NULL))
*update = PR_TRUE;
@@ -1496,10 +1701,19 @@ nsspkcs5_CreateAlgorithmID(PLArenaPool *arena, SECOidTag algorithm,
rv = SECOID_SetAlgorithmID(arena, &pkcs5v2_param.algParams,
pbe_param->encAlg, pbe_param->ivLen ? &der_param : NULL);
if (rv != SECSuccess) {
+ dummy = NULL;
break;
}
+ der_param.data = NULL;
+ der_param.len = 0;
dummy = SEC_ASN1EncodeItem(arena, &der_param, &pkcs5v2_param,
NSSPKCS5V2PBES2ParameterTemplate);
+ /* If the algorithm was set to some encryption oid, set it
+ * to PBES2 */
+ if ((algorithm != SEC_OID_PKCS5_PBKDF2) &&
+ (algorithm != SEC_OID_PKCS5_PBMAC1)) {
+ algorithm = SEC_OID_PKCS5_PBES2;
+ }
break;
default:
break;
@@ -1529,3 +1743,67 @@ loser:
return ret_algid;
}
+
+#define TEST_KEY "pbkdf test key"
+SECStatus
+sftk_fips_pbkdf_PowerUpSelfTests(void)
+{
+ SECItem *result;
+ SECItem inKey;
+ NSSPKCS5PBEParameter pbe_params;
+ unsigned char iteration_count = 5;
+ unsigned char keyLen = 64;
+ char *inKeyData = TEST_KEY;
+ static const unsigned char saltData[] =
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
+ static const unsigned char pbkdf_known_answer[] = {
+ 0x31, 0xf0, 0xe5, 0x39, 0x9f, 0x39, 0xb9, 0x29,
+ 0x68, 0xac, 0xf2, 0xe9, 0x53, 0x9b, 0xb4, 0x9c,
+ 0x28, 0x59, 0x8b, 0x5c, 0xd8, 0xd4, 0x02, 0x37,
+ 0x18, 0x22, 0xc1, 0x92, 0xd0, 0xfa, 0x72, 0x90,
+ 0x2c, 0x8d, 0x19, 0xd4, 0x56, 0xfb, 0x16, 0xfa,
+ 0x8d, 0x5c, 0x06, 0x33, 0xd1, 0x5f, 0x17, 0xb1,
+ 0x22, 0xd9, 0x9c, 0xaf, 0x5e, 0x3f, 0xf3, 0x66,
+ 0xc6, 0x14, 0xfe, 0x83, 0xfa, 0x1a, 0x2a, 0xc5
+ };
+
+ sftk_PBELockInit();
+
+ inKey.data = (unsigned char *)inKeyData;
+ inKey.len = sizeof(TEST_KEY) - 1;
+
+ pbe_params.salt.data = (unsigned char *)saltData;
+ pbe_params.salt.len = sizeof(saltData);
+ /* the interation and keyLength are used as intermediate
+ * values when decoding the Algorithm ID, set them for completeness,
+ * but they are not used */
+ pbe_params.iteration.data = &iteration_count;
+ pbe_params.iteration.len = 1;
+ pbe_params.keyLength.data = &keyLen;
+ pbe_params.keyLength.len = 1;
+ /* pkcs5v2 stores the key in the AlgorithmID, so we don't need to
+ * generate it here */
+ pbe_params.ivLen = 0;
+ pbe_params.ivData = NULL;
+ /* keyID is only used by pkcs12 extensions to pkcs5v1 */
+ pbe_params.keyID = pbeBitGenCipherKey;
+ /* Algorithm is used by the decryption code after get get our key */
+ pbe_params.encAlg = SEC_OID_AES_256_CBC;
+ /* these are the fields actually used in nsspkcs5_ComputeKeyAndIV
+ * for NSSPKCS5_PBKDF2 */
+ pbe_params.iter = iteration_count;
+ pbe_params.keyLen = keyLen;
+ pbe_params.hashType = HASH_AlgSHA256;
+ pbe_params.pbeType = NSSPKCS5_PBKDF2;
+ pbe_params.is2KeyDES = PR_FALSE;
+
+ result = nsspkcs5_ComputeKeyAndIV(&pbe_params, &inKey, NULL, PR_FALSE);
+ if ((result == NULL) || (result->len != sizeof(pbkdf_known_answer)) ||
+ (PORT_Memcmp(result->data, pbkdf_known_answer, sizeof(pbkdf_known_answer)) != 0)) {
+ SECITEM_FreeItem(result, PR_TRUE);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ SECITEM_FreeItem(result, PR_TRUE);
+ return SECSuccess;
+}
diff --git a/security/nss/lib/softoken/lowpbe.h b/security/nss/lib/softoken/lowpbe.h
index 208013818..b567c5968 100644
--- a/security/nss/lib/softoken/lowpbe.h
+++ b/security/nss/lib/softoken/lowpbe.h
@@ -101,6 +101,11 @@ extern void
nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *param);
HASH_HashType HASH_FromHMACOid(SECOidTag oid);
+SECOidTag HASH_HMACOidFromHash(HASH_HashType);
+
+/* fips selftest */
+extern SECStatus
+sftk_fips_pbkdf_PowerUpSelfTests(void);
SEC_END_PROTOS
diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn
index f25b97730..a8513800f 100644
--- a/security/nss/lib/softoken/manifest.mn
+++ b/security/nss/lib/softoken/manifest.mn
@@ -5,7 +5,9 @@
CORE_DEPTH = ../..
MODULE = nss
+ifndef NSS_DISABLE_DBM
DIRS = legacydb
+endif
LIBRARY_NAME = softokn
LIBRARY_VERSION = 3
@@ -23,7 +25,6 @@ EXPORTS = \
$(NULL)
PRIVATE_EXPORTS = \
- lgglue.h \
pkcs11ni.h \
softoken.h \
softoknt.h \
@@ -36,7 +37,7 @@ CSRCS = \
fipsaudt.c \
fipstest.c \
fipstokn.c \
- lgglue.c \
+ kbkdf.c \
lowkey.c \
lowpbe.c \
padbuf.c \
@@ -45,8 +46,10 @@ CSRCS = \
pkcs11u.c \
sdb.c \
sftkdb.c \
+ sftkdhverify.c \
sftkhmac.c \
sftkike.c \
+ sftkmessage.c \
sftkpars.c \
sftkpwd.c \
softkver.c \
@@ -54,6 +57,11 @@ CSRCS = \
jpakesftk.c \
$(NULL)
+ifndef NSS_DISABLE_DBM
+PRIVATE_EXPORTS += lgglue.h
+CSRCS += lgglue.c
+endif
+
ifdef SQLITE_UNSAFE_THREADS
DEFINES += -DSQLITE_UNSAFE_THREADS
endif
diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c
index 116a34890..216c5ac18 100644
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -86,6 +86,7 @@ static PRUint32 minSessionObjectHandle = 1U;
#undef CK_PKCS11_FUNCTION_INFO
#undef CK_NEED_ARG_LIST
+#define CK_PKCS11_3_0 1
#define CK_EXTERN extern
#define CK_PKCS11_FUNCTION_INFO(func) \
CK_RV __PASTE(NS, func)
@@ -94,8 +95,8 @@ static PRUint32 minSessionObjectHandle = 1U;
#include "pkcs11f.h"
/* build the crypto module table */
-static const CK_FUNCTION_LIST sftk_funcList = {
- { 1, 10 },
+static CK_FUNCTION_LIST_3_0 sftk_funcList = {
+ { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
#undef CK_PKCS11_FUNCTION_INFO
#undef CK_NEED_ARG_LIST
@@ -107,11 +108,54 @@ static const CK_FUNCTION_LIST sftk_funcList = {
};
+/* need a special version of get info for version 2 which returns the version
+ * 2.4 version number */
+CK_RV NSC_GetInfoV2(CK_INFO_PTR pInfo);
+CK_RV NSC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo);
+
+/* build the crypto module table */
+static CK_FUNCTION_LIST sftk_funcList_v2 = {
+ { 2, 40 },
+
+#undef CK_PKCS11_3_0
+#define CK_PKCS_11_2_0_ONLY 1
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+#define C_GetInfo C_GetInfoV2
+#define C_GetMechanismInfo C_GetMechanismInfoV2
+
+#define CK_PKCS11_FUNCTION_INFO(func) \
+ __PASTE(NS, func) \
+ ,
+#include "pkcs11f.h"
+
+};
+
+#undef C_GetInfo
+#undef C_GetMechanismInfo
+#undef CK_PKCS_11_2_0_ONLY
#undef CK_PKCS11_FUNCTION_INFO
#undef CK_NEED_ARG_LIST
#undef __PASTE
+CK_NSS_MODULE_FUNCTIONS sftk_module_funcList = {
+ { 1, 0 },
+ NSC_ModuleDBFunc
+};
+
+/*
+ * Array is orderd by default first
+ */
+static CK_INTERFACE nss_interfaces[] = {
+ { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList, NSS_INTERFACE_FLAGS },
+ { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList_v2, NSS_INTERFACE_FLAGS },
+ { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS }
+};
+/* must match the count of interfaces in nss_interfaces above */
+#define NSS_INTERFACE_COUNT 3
+
/* List of DES Weak Keys */
typedef unsigned char desKey[8];
static const desKey sftk_desWeakTable[] = {
@@ -223,12 +267,13 @@ struct mechanismList {
#define CKF_WR_UN CKF_WRAP | CKF_UNWRAP
#define CKF_SN_VR CKF_SIGN | CKF_VERIFY
#define CKF_SN_RE CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER
+#define CKF_EN_DE_MSG CKF_ENCRYPT | CKF_DECRYPT | CKF_MESSAGE_ENCRYPT | CKF_MESSAGE_DECRYPT
#define CKF_EN_DE_WR_UN CKF_EN_DE | CKF_WR_UN
#define CKF_SN_VR_RE CKF_SN_VR | CKF_SN_RE
#define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE
-#define CKF_EC_PNU CKF_EC_FP | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS
+#define CKF_EC_PNU CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS
#define CKF_EC_BPNU CKF_EC_F_2M | CKF_EC_PNU
@@ -278,6 +323,10 @@ static const struct mechanismList mechanisms[] = {
{ CKM_DSA, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
{ CKM_DSA_PARAMETER_GEN, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_GENERATE }, PR_TRUE },
{ CKM_DSA_SHA1, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
+ { CKM_DSA_SHA224, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
+ { CKM_DSA_SHA256, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
+ { CKM_DSA_SHA384, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
+ { CKM_DSA_SHA512, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
/* -------------------- Diffie Hellman Operations --------------------- */
/* no diffie hellman yet */
{ CKM_DH_PKCS_KEY_PAIR_GEN, { DH_MIN_P_BITS, DH_MAX_P_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
@@ -287,6 +336,10 @@ static const struct mechanismList mechanisms[] = {
{ CKM_ECDH1_DERIVE, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_DERIVE | CKF_EC_BPNU }, PR_TRUE },
{ CKM_ECDSA, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
{ CKM_ECDSA_SHA1, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
+ { CKM_ECDSA_SHA224, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
+ { CKM_ECDSA_SHA256, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
+ { CKM_ECDSA_SHA384, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
+ { CKM_ECDSA_SHA512, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
/* ------------------------- RC2 Operations --------------------------- */
{ CKM_RC2_KEY_GEN, { 1, 128, CKF_GENERATE }, PR_TRUE },
{ CKM_RC2_ECB, { 1, 128, CKF_EN_DE_WR_UN }, PR_TRUE },
@@ -329,8 +382,8 @@ static const struct mechanismList mechanisms[] = {
{ CKM_AES_CBC_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
{ CKM_AES_CTS, { 16, 32, CKF_EN_DE }, PR_TRUE },
{ CKM_AES_CTR, { 16, 32, CKF_EN_DE }, PR_TRUE },
- { CKM_AES_GCM, { 16, 32, CKF_EN_DE }, PR_TRUE },
- { CKM_AES_XCBC_MAC_96, { 16, 16, CKF_SN_VR }, PR_TRUE },
+ { CKM_AES_GCM, { 16, 32, CKF_EN_DE_MSG }, PR_TRUE },
+ { CKM_AES_XCBC_MAC_96, { 12, 12, CKF_SN_VR }, PR_TRUE },
{ CKM_AES_XCBC_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE },
/* ------------------------- Camellia Operations --------------------- */
{ CKM_CAMELLIA_KEY_GEN, { 16, 32, CKF_GENERATE }, PR_TRUE },
@@ -339,18 +392,22 @@ static const struct mechanismList mechanisms[] = {
{ CKM_CAMELLIA_MAC, { 16, 32, CKF_SN_VR }, PR_TRUE },
{ CKM_CAMELLIA_MAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE },
{ CKM_CAMELLIA_CBC_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
- /* ------------------------- SEED Operations --------------------------- */
+/* ------------------------- SEED Operations --------------------------- */
+#ifndef NSS_DISABLE_DEPRECATED_SEED
{ CKM_SEED_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
{ CKM_SEED_ECB, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
{ CKM_SEED_CBC, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
{ CKM_SEED_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE },
{ CKM_SEED_MAC_GENERAL, { 16, 16, CKF_SN_VR }, PR_TRUE },
{ CKM_SEED_CBC_PAD, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
+#endif
+/* ------------------------- ChaCha20 Operations ---------------------- */
#ifndef NSS_DISABLE_CHACHAPOLY
- /* ------------------------- ChaCha20 Operations ---------------------- */
{ CKM_NSS_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
{ CKM_NSS_CHACHA20_POLY1305, { 32, 32, CKF_EN_DE }, PR_TRUE },
{ CKM_NSS_CHACHA20_CTR, { 32, 32, CKF_EN_DE }, PR_TRUE },
+ { CKM_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
+ { CKM_CHACHA20_POLY1305, { 32, 32, CKF_EN_DE_MSG }, PR_TRUE },
#endif /* NSS_DISABLE_CHACHAPOLY */
/* ------------------------- Hashing Operations ----------------------- */
{ CKM_MD2, { 0, 0, CKF_DIGEST }, PR_FALSE },
@@ -380,6 +437,9 @@ static const struct mechanismList mechanisms[] = {
{ 0, 512, CKF_SN_VR },
PR_FALSE },
/* ------------------------- HKDF Operations -------------------------- */
+ { CKM_HKDF_DERIVE, { 1, 255 * 64, CKF_DERIVE }, PR_TRUE },
+ { CKM_HKDF_DATA, { 1, 255 * 64, CKF_DERIVE }, PR_TRUE },
+ { CKM_HKDF_KEY_GEN, { 20, 64, CKF_GENERATE }, PR_TRUE },
{ CKM_NSS_HKDF_SHA1, { 1, 128, CKF_DERIVE }, PR_TRUE },
{ CKM_NSS_HKDF_SHA256, { 1, 128, CKF_DERIVE }, PR_TRUE },
{ CKM_NSS_HKDF_SHA384, { 1, 128, CKF_DERIVE }, PR_TRUE },
@@ -437,9 +497,10 @@ static const struct mechanismList mechanisms[] = {
{ 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 },
+#ifndef NSS_DISABLE_DEPRECATED_SEED
{ CKM_SEED_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
{ CKM_SEED_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
-
+#endif
/* ---------------------- 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 },
@@ -478,9 +539,9 @@ static const struct mechanismList mechanisms[] = {
/* ---------------------- PBE Key Derivations ------------------------ */
{ CKM_PBE_MD2_DES_CBC, { 8, 8, CKF_DERIVE }, PR_TRUE },
{ CKM_PBE_MD5_DES_CBC, { 8, 8, CKF_DERIVE }, PR_TRUE },
- /* ------------------ NETSCAPE PBE Key Derivations ------------------- */
- { CKM_NETSCAPE_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE }, PR_TRUE },
- { CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, { 24, 24, CKF_GENERATE }, PR_TRUE },
+ /* ------------------ NSS PBE Key Derivations ------------------- */
+ { CKM_NSS_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE }, PR_TRUE },
+ { CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC, { 24, 24, CKF_GENERATE }, PR_TRUE },
{ CKM_PBE_SHA1_DES3_EDE_CBC, { 24, 24, CKF_GENERATE }, PR_TRUE },
{ CKM_PBE_SHA1_DES2_EDE_CBC, { 24, 24, CKF_GENERATE }, PR_TRUE },
{ CKM_PBE_SHA1_RC2_40_CBC, { 40, 40, CKF_GENERATE }, PR_TRUE },
@@ -489,16 +550,26 @@ static const struct mechanismList mechanisms[] = {
{ CKM_PBE_SHA1_RC4_128, { 128, 128, CKF_GENERATE }, PR_TRUE },
{ CKM_PBA_SHA1_WITH_SHA1_HMAC, { 20, 20, CKF_GENERATE }, PR_TRUE },
{ CKM_PKCS5_PBKD2, { 1, 256, CKF_GENERATE }, PR_TRUE },
- { CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, { 20, 20, CKF_GENERATE }, PR_TRUE },
- { CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
- { CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
+ { CKM_NSS_PBE_SHA1_HMAC_KEY_GEN, { 20, 20, CKF_GENERATE }, PR_TRUE },
+ { CKM_NSS_PBE_MD5_HMAC_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
+ { CKM_NSS_PBE_MD2_HMAC_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
{ CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN, { 28, 28, CKF_GENERATE }, PR_TRUE },
{ CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
{ CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN, { 48, 48, CKF_GENERATE }, PR_TRUE },
{ CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN, { 64, 64, CKF_GENERATE }, PR_TRUE },
+ /* ------------------ NIST 800-108 Key Derivations ------------------- */
+ { CKM_SP800_108_COUNTER_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
+ { CKM_SP800_108_FEEDBACK_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
+ { CKM_SP800_108_DOUBLE_PIPELINE_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
+ { CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
+ { CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
+ { CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
/* ------------------ AES Key Wrap (also encrypt) ------------------- */
- { CKM_NETSCAPE_AES_KEY_WRAP, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
- { CKM_NETSCAPE_AES_KEY_WRAP_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+ { CKM_NSS_AES_KEY_WRAP, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+ { CKM_NSS_AES_KEY_WRAP_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+ { CKM_AES_KEY_WRAP, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+ { CKM_AES_KEY_WRAP_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
+ { CKM_AES_KEY_WRAP_KWP, { 1, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
/* --------------------------- J-PAKE -------------------------------- */
{ CKM_NSS_JPAKE_ROUND1_SHA1, { 0, 0, CKF_GENERATE }, PR_TRUE },
{ CKM_NSS_JPAKE_ROUND1_SHA256, { 0, 0, CKF_GENERATE }, PR_TRUE },
@@ -518,7 +589,8 @@ static const struct mechanismList mechanisms[] = {
/* --------------------IPSEC ----------------------- */
{ CKM_NSS_IKE_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE },
{ CKM_NSS_IKE_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
- { CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE }
+ { CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
+ { CKM_NSS_IKE1_APP_B_PRF_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE }
};
static const CK_ULONG mechanismCount = sizeof(mechanisms) / sizeof(mechanisms[0]);
@@ -814,7 +886,7 @@ sftk_handleSMimeObject(SFTKSession *session, SFTKObject *object)
if (!sftk_hasAttribute(object, CKA_SUBJECT)) {
return CKR_TEMPLATE_INCOMPLETE;
}
- if (!sftk_hasAttribute(object, CKA_NETSCAPE_EMAIL)) {
+ if (!sftk_hasAttribute(object, CKA_NSS_EMAIL)) {
return CKR_TEMPLATE_INCOMPLETE;
}
@@ -1097,7 +1169,7 @@ sftk_handlePrivateKeyObject(SFTKSession *session, SFTKObject *object, CK_KEY_TYP
crv = sftk_Attribute2SSecItem(NULL, &mod, object, CKA_MODULUS);
if (crv != CKR_OK)
return crv;
- crv = sftk_forceAttribute(object, CKA_NETSCAPE_DB,
+ crv = sftk_forceAttribute(object, CKA_NSS_DB,
sftk_item_expand(&mod));
if (mod.data)
PORT_Free(mod.data);
@@ -1124,6 +1196,11 @@ sftk_handlePrivateKeyObject(SFTKSession *session, SFTKObject *object, CK_KEY_TYP
if (!sftk_hasAttribute(object, CKA_VALUE)) {
return CKR_TEMPLATE_INCOMPLETE;
}
+ /* allow subprime to be set after the fact */
+ crv = sftk_defaultAttribute(object, CKA_SUBPRIME, NULL, 0);
+ if (crv != CKR_OK) {
+ return crv;
+ }
encrypt = CK_FALSE;
recover = CK_FALSE;
wrap = CK_FALSE;
@@ -1479,7 +1556,7 @@ sftk_handleDSAParameterObject(SFTKSession *session, SFTKObject *object)
* them. */
}
- attribute = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_COUNTER);
+ attribute = sftk_FindAttribute(object, CKA_NSS_PQG_COUNTER);
if (attribute != NULL) {
vfy.counter = *(CK_ULONG *)attribute->attrib.pValue;
sftk_FreeAttribute(attribute);
@@ -1488,7 +1565,7 @@ sftk_handleDSAParameterObject(SFTKSession *session, SFTKObject *object)
vfy.counter = -1;
}
- hAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_H);
+ hAttr = sftk_FindAttribute(object, CKA_NSS_PQG_H);
if (hAttr != NULL) {
vfy.h.data = hAttr->attrib.pValue;
vfy.h.len = hAttr->attrib.ulValueLen;
@@ -1497,7 +1574,7 @@ sftk_handleDSAParameterObject(SFTKSession *session, SFTKObject *object)
vfy.h.data = NULL;
vfy.h.len = 0;
}
- seedAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_SEED);
+ seedAttr = sftk_FindAttribute(object, CKA_NSS_PQG_SEED);
if (seedAttr != NULL) {
vfy.seed.data = seedAttr->attrib.pValue;
vfy.seed.len = seedAttr->attrib.ulValueLen;
@@ -1662,13 +1739,13 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session)
case CKO_CERTIFICATE:
crv = sftk_handleCertObject(session, object);
break;
- case CKO_NETSCAPE_TRUST:
+ case CKO_NSS_TRUST:
crv = sftk_handleTrustObject(session, object);
break;
- case CKO_NETSCAPE_CRL:
+ case CKO_NSS_CRL:
crv = sftk_handleCrlObject(session, object);
break;
- case CKO_NETSCAPE_SMIME:
+ case CKO_NSS_SMIME:
crv = sftk_handleSMimeObject(session, object);
break;
case CKO_PRIVATE_KEY:
@@ -1676,7 +1753,7 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session)
case CKO_SECRET_KEY:
crv = sftk_handleKeyObject(session, object);
break;
- case CKO_KG_PARAMETERS:
+ case CKO_DOMAIN_PARAMETERS:
crv = sftk_handleKeyParameterObject(session, object);
break;
default:
@@ -1981,9 +2058,9 @@ sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp)
if (crv != CKR_OK)
break;
- if (sftk_hasAttribute(object, CKA_NETSCAPE_DB)) {
+ if (sftk_hasAttribute(object, CKA_NSS_DB)) {
crv = sftk_Attribute2SSecItem(arena, &privKey->u.ec.publicValue,
- object, CKA_NETSCAPE_DB);
+ object, CKA_NSS_DB);
if (crv != CKR_OK)
break;
/* privKey was zero'd so public value is already set to NULL, 0
@@ -2398,7 +2475,7 @@ sftk_IsWeakKey(unsigned char *key, CK_KEY_TYPE key_type)
CK_RV
NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
{
- *pFunctionList = (CK_FUNCTION_LIST_PTR)&sftk_funcList;
+ *pFunctionList = (CK_FUNCTION_LIST_PTR)&sftk_funcList_v2;
return CKR_OK;
}
@@ -2409,6 +2486,60 @@ C_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
return NSC_GetFunctionList(pFunctionList);
}
+CK_RV
+NSC_GetInterfaceList(CK_INTERFACE_PTR interfaces, CK_ULONG_PTR pulCount)
+{
+ CK_ULONG count = *pulCount;
+ *pulCount = NSS_INTERFACE_COUNT;
+ if (interfaces == NULL) {
+ return CKR_OK;
+ }
+ if (count < NSS_INTERFACE_COUNT) {
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ PORT_Memcpy(interfaces, nss_interfaces, sizeof(nss_interfaces));
+ return CKR_OK;
+}
+
+CK_RV
+C_GetInterfaceList(CK_INTERFACE_PTR interfaces, CK_ULONG_PTR pulCount)
+{
+ return NSC_GetInterfaceList(interfaces, pulCount);
+}
+
+/*
+ * Get the requested interface, use the nss_interfaces array so we can
+ * easily add new interfaces as they occur.
+ */
+CK_RV
+NSC_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion,
+ CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags)
+{
+ int i;
+ for (i = 0; i < NSS_INTERFACE_COUNT; i++) {
+ CK_INTERFACE_PTR interface = &nss_interfaces[i];
+ if (pInterfaceName && PORT_Strcmp((char *)pInterfaceName, (char *)interface->pInterfaceName) != 0) {
+ continue;
+ }
+ if (pVersion && PORT_Memcmp(pVersion, (CK_VERSION *)interface->pFunctionList, sizeof(CK_VERSION)) != 0) {
+ continue;
+ }
+ if (flags & ((interface->flags & flags) != flags)) {
+ continue;
+ }
+ *ppInterface = interface;
+ return CKR_OK;
+ }
+ return CKR_ARGUMENTS_BAD;
+}
+
+CK_RV
+C_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion,
+ CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags)
+{
+ return NSC_GetInterface(pInterfaceName, pVersion, ppInterface, flags);
+}
+
static PLHashNumber
sftk_HashNumber(const void *key)
{
@@ -2482,7 +2613,7 @@ SFTKSlot *
sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all)
{
SFTKSlot *slot;
- int index = sftk_GetModuleIndex(slotID);
+ unsigned int index = sftk_GetModuleIndex(slotID);
if (nscSlotHashTable[index] == NULL)
return NULL;
@@ -2513,7 +2644,7 @@ sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle)
}
static CK_RV
-sftk_RegisterSlot(SFTKSlot *slot, int moduleIndex)
+sftk_RegisterSlot(SFTKSlot *slot, unsigned int moduleIndex)
{
PLHashEntry *entry;
unsigned int index;
@@ -2589,7 +2720,8 @@ sftk_RegisterSlot(SFTKSlot *slot, int moduleIndex)
*/
CK_RV
SFTK_SlotReInit(SFTKSlot *slot, char *configdir, char *updatedir,
- char *updateID, sftk_token_parameters *params, int moduleIndex)
+ char *updateID, sftk_token_parameters *params,
+ unsigned int moduleIndex)
{
PRBool needLogin = !params->noKeyDB;
CK_RV crv;
@@ -2665,7 +2797,7 @@ loser:
*/
CK_RV
SFTK_SlotInit(char *configdir, char *updatedir, char *updateID,
- sftk_token_parameters *params, int moduleIndex)
+ sftk_token_parameters *params, unsigned int moduleIndex)
{
unsigned int i;
CK_SLOT_ID slotID = params->slotID;
@@ -2930,12 +3062,14 @@ SFTK_DestroySlotData(SFTKSlot *slot)
char **
NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args)
{
+#ifndef NSS_DISABLE_DBM
char *secmod = NULL;
char *appName = NULL;
char *filename = NULL;
NSSDBType dbType = NSS_DB_TYPE_NONE;
PRBool rw;
static char *success = "Success";
+#endif /* NSS_DISABLE_DBM */
char **rvstr = NULL;
rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args);
@@ -2947,6 +3081,7 @@ NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args)
return NULL;
}
+#ifndef NSS_DISABLE_DBM
/* The legacy database uses the old dbm, which is only linked with the
* legacy DB handler, which is only callable from softoken */
@@ -3038,11 +3173,12 @@ loser:
PORT_Free(appName);
if (filename)
PORT_Free(filename);
+#endif /* NSS_DISABLE_DBM */
return rvstr;
}
static void
-nscFreeAllSlots(int moduleIndex)
+nscFreeAllSlots(unsigned int moduleIndex)
{
/* free all the slots */
SFTKSlot *slot = NULL;
@@ -3086,7 +3222,7 @@ sftk_closePeer(PRBool isFIPS)
{
CK_SLOT_ID slotID = isFIPS ? PRIVATE_KEY_SLOT_ID : FIPS_SLOT_ID;
SFTKSlot *slot;
- int moduleIndex = isFIPS ? NSC_NON_FIPS_MODULE : NSC_FIPS_MODULE;
+ unsigned int moduleIndex = isFIPS ? NSC_NON_FIPS_MODULE : NSC_FIPS_MODULE;
PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex];
slot = (SFTKSlot *)PL_HashTableLookup(tmpSlotHashTable, (void *)slotID);
@@ -3108,7 +3244,7 @@ nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
SECStatus rv;
CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *)pReserved;
int i;
- int moduleIndex = isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE;
+ unsigned int moduleIndex = isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE;
if (isFIPS) {
loginWaitTime = PR_SecondsToInterval(1);
@@ -3305,6 +3441,7 @@ nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS)
nsc_init = PR_FALSE;
+#ifndef NO_FORK_CHECK
#ifdef CHECK_FORK_MIXED
if (!usePthread_atfork) {
myPid = 0; /* allow CHECK_FORK in the next softoken initialization to
@@ -3317,6 +3454,7 @@ nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS)
#elif defined(CHECK_FORK_PTHREAD)
forked = PR_FALSE; /* allow reinitialization */
#endif
+#endif
return CKR_OK;
}
@@ -3381,8 +3519,24 @@ NSC_GetInfo(CK_INFO_PTR pInfo)
CHECK_FORK();
+ pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
+ pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
+ PORT_Memcpy(pInfo->manufacturerID, manufacturerID, 32);
+ pInfo->libraryVersion.major = SOFTOKEN_VMAJOR;
+ pInfo->libraryVersion.minor = SOFTOKEN_VMINOR;
+ PORT_Memcpy(pInfo->libraryDescription, libraryDescription, 32);
+ pInfo->flags = 0;
+ return CKR_OK;
+}
+
+/* NSC_GetInfo returns general information about Cryptoki. */
+CK_RV
+NSC_GetInfoV2(CK_INFO_PTR pInfo)
+{
+ CHECK_FORK();
+
pInfo->cryptokiVersion.major = 2;
- pInfo->cryptokiVersion.minor = 20;
+ pInfo->cryptokiVersion.minor = 40;
PORT_Memcpy(pInfo->manufacturerID, manufacturerID, 32);
pInfo->libraryVersion.major = SOFTOKEN_VMAJOR;
pInfo->libraryVersion.minor = SOFTOKEN_VMINOR;
@@ -3394,7 +3548,8 @@ NSC_GetInfo(CK_INFO_PTR pInfo)
/* NSC_GetSlotList obtains a list of slots in the system. */
CK_RV
nsc_CommonGetSlotList(CK_BBOOL tokenPresent,
- CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex)
+ CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount,
+ unsigned int moduleIndex)
{
*pulCount = nscSlotCount[moduleIndex];
if (pSlotList != NULL) {
@@ -3512,11 +3667,11 @@ NSC_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
PORT_Memcpy(pInfo->serialNumber, "0000000000000000", 16);
PORT_Memcpy(pInfo->utcTime, "0000000000000000", 16);
pInfo->ulMaxSessionCount = 0; /* arbitrarily large */
- pInfo->ulMaxRwSessionCount = 0; /* arbitrarily large */
+ pInfo->ulMaxRwSessionCount = 0; /* arbitarily large */
PZ_Lock(slot->slotLock); /* Protect sessionCount / rwSessioncount */
pInfo->ulSessionCount = slot->sessionCount;
pInfo->ulRwSessionCount = slot->rwSessionCount;
- PZ_Unlock(slot->slotLock); /* Unlock before sftk_getKeyDB */
+ PZ_Unlock(slot->slotLock); /* Unlock before sftk_getKeyDB */
pInfo->firmwareVersion.major = 0;
pInfo->firmwareVersion.minor = 0;
PORT_Memcpy(pInfo->label, slot->tokDescription, sizeof(pInfo->label));
@@ -3666,6 +3821,22 @@ NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
return CKR_MECHANISM_INVALID;
}
+/*
+ * If we are using the V2 interface, strip out the message flags
+ */
+#define SFTK_MESSAGE_FLAGS (CKF_MESSAGE_ENCRYPT | CKF_MESSAGE_DECRYPT | CKF_MESSAGE_SIGN | CKF_MESSAGE_VERIFY)
+CK_RV
+NSC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo)
+{
+ CK_RV crv;
+ crv = NSC_GetMechanismInfo(slotID, type, pInfo);
+ if (crv == CKR_OK) {
+ pInfo->flags = pInfo->flags & ~SFTK_MESSAGE_FLAGS;
+ }
+ return crv;
+}
+
CK_RV
sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op)
{
@@ -3700,6 +3871,18 @@ sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op)
case CKA_DERIVE:
flags = CKF_DERIVE;
break;
+ case CKA_NSS_MESSAGE | CKA_ENCRYPT:
+ flags = CKF_MESSAGE_ENCRYPT;
+ break;
+ case CKA_NSS_MESSAGE | CKA_DECRYPT:
+ flags = CKF_MESSAGE_DECRYPT;
+ break;
+ case CKA_NSS_MESSAGE | CKA_SIGN:
+ flags = CKF_MESSAGE_SIGN;
+ break;
+ case CKA_NSS_MESSAGE | CKA_VERIFY:
+ flags = CKF_MESSAGE_VERIFY;
+ break;
default:
return CKR_ARGUMENTS_BAD;
}
@@ -4245,6 +4428,15 @@ done:
return crv;
}
+CK_RV
+NSC_LoginUser(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
+ CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pUsername,
+ CK_ULONG ulUsernameLen)
+{
+ /* softoken currently does not support additional users */
+ return CKR_OPERATION_NOT_INITIALIZED;
+}
+
/* NSC_Logout logs a user out from a token. */
CK_RV
NSC_Logout(CK_SESSION_HANDLE hSession)
@@ -4299,7 +4491,7 @@ sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class,
PRBool isValidFIPSUserSlot = PR_FALSE;
PRBool isValidSlot = PR_FALSE;
PRBool isFIPS = PR_FALSE;
- unsigned long moduleIndex = NSC_NON_FIPS_MODULE;
+ unsigned int moduleIndex = NSC_NON_FIPS_MODULE;
SFTKAttribute *attribute;
sftk_parameters paramStrings;
char *paramString;
@@ -4307,13 +4499,13 @@ sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class,
SFTKSlot *newSlot = NULL;
CK_RV crv = CKR_OK;
- if (class != CKO_NETSCAPE_DELSLOT && class != CKO_NETSCAPE_NEWSLOT) {
+ if (class != CKO_NSS_DELSLOT && class != CKO_NSS_NEWSLOT) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
- if (class == CKO_NETSCAPE_NEWSLOT && slot->slotID == FIPS_SLOT_ID) {
+ if (class == CKO_NSS_NEWSLOT && slot->slotID == FIPS_SLOT_ID) {
isFIPS = PR_TRUE;
}
- attribute = sftk_FindAttribute(object, CKA_NETSCAPE_MODULE_SPEC);
+ attribute = sftk_FindAttribute(object, CKA_NSS_MODULE_SPEC);
if (attribute == NULL) {
return CKR_TEMPLATE_INCOMPLETE;
}
@@ -4337,7 +4529,7 @@ sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class,
isValidFIPSUserSlot = (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID &&
slotID <= SFTK_MAX_FIPS_USER_SLOT_ID);
- if (class == CKO_NETSCAPE_DELSLOT) {
+ if (class == CKO_NSS_DELSLOT) {
if (slot->slotID == slotID) {
isValidSlot = isValidUserSlot || isValidFIPSUserSlot;
}
@@ -4367,7 +4559,7 @@ sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class,
}
/* if we were just planning on deleting the slot, then do so now */
- if (class == CKO_NETSCAPE_DELSLOT) {
+ if (class == CKO_NSS_DELSLOT) {
/* sort of a unconventional use of this error code, be we are
* overusing CKR_ATTRIBUTE_VALUE_INVALID, and it does apply */
crv = newSlot ? CKR_OK : CKR_SLOT_ID_INVALID;
@@ -4400,7 +4592,7 @@ NSC_CreateObject(CK_SESSION_HANDLE hSession,
SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
SFTKSession *session;
SFTKObject *object;
- /* make sure class isn't randomly CKO_NETSCAPE_NEWSLOT or
+ /* make sure class isn't randomly CKO_NSS_NEWSLOT or
* CKO_NETSCPE_DELSLOT. */
CK_OBJECT_CLASS class = CKO_VENDOR_DEFINED;
CK_RV crv;
@@ -4445,7 +4637,7 @@ NSC_CreateObject(CK_SESSION_HANDLE hSession,
/*
* handle pseudo objects (CKO_NEWSLOT)
*/
- if ((class == CKO_NETSCAPE_NEWSLOT) || (class == CKO_NETSCAPE_DELSLOT)) {
+ if ((class == CKO_NSS_NEWSLOT) || (class == CKO_NSS_DELSLOT)) {
crv = sftk_CreateNewSlot(slot, class, object);
goto done;
}
@@ -4821,7 +5013,7 @@ sftk_emailhack(SFTKSlot *slot, SFTKDBHandle *handle,
unsigned int i;
SFTKSearchResults smime_search;
CK_ATTRIBUTE smime_template[2];
- CK_OBJECT_CLASS smime_class = CKO_NETSCAPE_SMIME;
+ CK_OBJECT_CLASS smime_class = CKO_NSS_SMIME;
SFTKAttribute *attribute = NULL;
SFTKObject *object = NULL;
CK_RV crv = CKR_OK;
@@ -4838,7 +5030,7 @@ sftk_emailhack(SFTKSlot *slot, SFTKDBHandle *handle,
break;
}
isCert = PR_TRUE;
- } else if (pTemplate[i].type == CKA_NETSCAPE_EMAIL) {
+ } else if (pTemplate[i].type == CKA_NSS_EMAIL) {
emailIndex = i;
}
if (isCert && (emailIndex != -1))
diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c
index 6bc5cc939..b54d28de9 100644
--- a/security/nss/lib/softoken/pkcs11c.c
+++ b/security/nss/lib/softoken/pkcs11c.c
@@ -48,6 +48,8 @@
#undef CK_PKCS11_FUNCTION_INFO
#undef CK_NEED_ARG_LIST
+#define CK_PKCS11_3_0 1
+
#define CK_EXTERN extern
#define CK_PKCS11_FUNCTION_INFO(func) \
CK_RV __PASTE(NS, func)
@@ -96,38 +98,6 @@ sftk_Space(void *data, PRBool freeit)
}
/*
- * map all the SEC_ERROR_xxx error codes that may be returned by freebl
- * functions to CKR_xxx. Most of the mapping is done in
- * sftk_mapCryptError (now in pkcs11u.c). The next two functions adjust
- * that mapping based for different contexts (Decrypt or Verify).
- */
-
-/* used by Decrypt and UnwrapKey (indirectly) */
-static CK_RV
-sftk_MapDecryptError(int error)
-{
- switch (error) {
- case SEC_ERROR_BAD_DATA:
- return CKR_ENCRYPTED_DATA_INVALID;
- default:
- return sftk_MapCryptError(error);
- }
-}
-
-/*
- * return CKR_SIGNATURE_INVALID instead of CKR_DEVICE_ERROR by default for
- * backward compatibilty.
- */
-static CK_RV
-sftk_MapVerifyError(int error)
-{
- CK_RV crv = sftk_MapCryptError(error);
- if (crv == CKR_DEVICE_ERROR)
- crv = CKR_SIGNATURE_INVALID;
- return crv;
-}
-
-/*
* turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
* Deprecating a full des key to 40 bit key strenth.
*/
@@ -321,6 +291,8 @@ sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
switch (type) {
case SFTK_ENCRYPT:
case SFTK_DECRYPT:
+ case SFTK_MESSAGE_ENCRYPT:
+ case SFTK_MESSAGE_DECRYPT:
return session->enc_context;
case SFTK_HASH:
return session->hash_context;
@@ -328,6 +300,8 @@ sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
case SFTK_SIGN_RECOVER:
case SFTK_VERIFY:
case SFTK_VERIFY_RECOVER:
+ case SFTK_MESSAGE_SIGN:
+ case SFTK_MESSAGE_VERIFY:
return session->hash_context;
}
return NULL;
@@ -343,6 +317,8 @@ sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
switch (type) {
case SFTK_ENCRYPT:
case SFTK_DECRYPT:
+ case SFTK_MESSAGE_ENCRYPT:
+ case SFTK_MESSAGE_DECRYPT:
session->enc_context = context;
break;
case SFTK_HASH:
@@ -352,6 +328,8 @@ sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
case SFTK_SIGN_RECOVER:
case SFTK_VERIFY:
case SFTK_VERIFY_RECOVER:
+ case SFTK_MESSAGE_SIGN:
+ case SFTK_MESSAGE_VERIFY:
session->hash_context = context;
break;
}
@@ -365,7 +343,7 @@ sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
* and optionally returns the session pointer (if sessionPtr != NULL) if session
* pointer is returned, the caller is responsible for freeing it.
*/
-static CK_RV
+CK_RV
sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr,
SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr)
{
@@ -393,7 +371,7 @@ sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr,
/** Terminate operation (in the PKCS#11 spec sense).
* Intuitive name for FreeContext/SetNullContext pair.
*/
-static void
+void
sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype,
SFTKSessionContext *context)
{
@@ -409,7 +387,7 @@ sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype,
* All the NSC_InitXXX functions have a set of common checks and processing they
* all need to do at the beginning. This is done here.
*/
-static CK_RV
+CK_RV
sftk_InitGeneric(SFTKSession *session, SFTKSessionContext **contextPtr,
SFTKContextType ctype, SFTKObject **keyPtr,
CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
@@ -761,7 +739,7 @@ sftk_ChaCha20Ctr_DestroyContext(SFTKChaCha20CtrInfo *ctx,
* Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block
* ciphers MAC'ing.
*/
-static CK_RV
+CK_RV
sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
CK_OBJECT_HANDLE hKey,
CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage,
@@ -771,14 +749,20 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
SFTKObject *key;
SFTKSessionContext *context;
SFTKAttribute *att;
+#ifndef NSS_DISABLE_DEPRECATED_RC2
CK_RC2_CBC_PARAMS *rc2_param;
+ unsigned effectiveKeyLength;
+#endif
#if NSS_SOFTOKEN_DOES_RC5
CK_RC5_CBC_PARAMS *rc5_param;
SECItem rc5Key;
#endif
+ CK_NSS_GCM_PARAMS nss_gcm_param;
+ void *aes_param;
+ CK_NSS_AEAD_PARAMS nss_aead_params;
+ CK_NSS_AEAD_PARAMS *nss_aead_params_ptr = NULL;
CK_KEY_TYPE key_type;
CK_RV crv = CKR_OK;
- unsigned effectiveKeyLength;
unsigned char newdeskey[24];
PRBool useNewKey = PR_FALSE;
int t;
@@ -885,6 +869,7 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
}
context->destroy = (SFTKDestroy)sftk_Space;
break;
+#ifndef NSS_DISABLE_DEPRECATED_RC2
case CKM_RC2_CBC_PAD:
context->doPad = PR_TRUE;
/* fall thru */
@@ -919,6 +904,8 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
context->update = (SFTKCipher)(isEncrypt ? RC2_Encrypt : RC2_Decrypt);
context->destroy = (SFTKDestroy)RC2_DestroyContext;
break;
+#endif /* NSS_DISABLE_DEPRECATED_RC2 */
+
#if NSS_SOFTOKEN_DOES_RC5
case CKM_RC5_CBC_PAD:
context->doPad = PR_TRUE;
@@ -1002,10 +989,6 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
crv = CKR_KEY_TYPE_INCONSISTENT;
break;
}
- if (pMechanism->ulParameterLen < 8) {
- crv = CKR_DOMAIN_PARAMS_INVALID;
- break;
- }
t = NSS_DES_CBC;
goto finish_des;
case CKM_DES3_ECB:
@@ -1023,12 +1006,13 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
crv = CKR_KEY_TYPE_INCONSISTENT;
break;
}
- if (pMechanism->ulParameterLen < 8) {
+ t = NSS_DES_EDE3_CBC;
+ finish_des:
+ if ((t != NSS_DES && t != NSS_DES_EDE3) && (pMechanism->pParameter == NULL ||
+ pMechanism->ulParameterLen < 8)) {
crv = CKR_DOMAIN_PARAMS_INVALID;
break;
}
- t = NSS_DES_EDE3_CBC;
- finish_des:
context->blockSize = 8;
att = sftk_FindAttribute(key, CKA_VALUE);
if (att == NULL) {
@@ -1062,6 +1046,7 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
context->update = (SFTKCipher)(isEncrypt ? DES_Encrypt : DES_Decrypt);
context->destroy = (SFTKDestroy)DES_DestroyContext;
break;
+#ifndef NSS_DISABLE_DEPRECATED_SEED
case CKM_SEED_CBC_PAD:
context->doPad = PR_TRUE;
/* fall thru */
@@ -1096,7 +1081,7 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt);
context->destroy = (SFTKDestroy)SEED_DestroyContext;
break;
-
+#endif /* NSS_DISABLE_DEPRECATED_SEED */
case CKM_CAMELLIA_CBC_PAD:
context->doPad = PR_TRUE;
/* fall thru */
@@ -1144,9 +1129,52 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
case CKM_AES_CTS:
case CKM_AES_CTR:
case CKM_AES_GCM:
- if ((pMechanism->mechanism == CKM_AES_GCM && BAD_PARAM_CAST(pMechanism, sizeof(CK_GCM_PARAMS))) ||
- (pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) ||
- ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) {
+ aes_param = pMechanism->pParameter;
+ /*
+ * Due to a mismatch between the documentation and the header
+ * file, two different definitions for CK_GCM_PARAMS exist.
+ * The header file is normative according to Oasis, but NSS used
+ * the documentation. In PKCS #11 v3.0, this was reconciled in
+ * favor of the header file definition. To maintain binary
+ * compatibility, NSS now defines CK_GCM_PARAMS_V3 as the official
+ * version v3 (V2.4 header file) and CK_NSS_GCM_PARAMS as the
+ * legacy (V2.4 documentation, NSS version). CK_GCM_PARAMS
+ * is defined as CK_GCM_PARAMS_V3 if NSS_PKCS11_2_0_COMPAT is not
+ * defined and CK_NSS_GCM_PARAMS if it is. Internally
+ * softoken continues to use the legacy version. The code below
+ * automatically detects which parameter was passed in and
+ * converts CK_GCM_PARAMS_V3 to the CK_NSS_GCM_PARAMS (legacy
+ * version) on the fly. NSS proper will eventually start
+ * using the CK_GCM_PARAMS_V3 version and fall back to the
+ * CK_NSS_GCM_PARAMS if the CK_GCM_PARAMS_V3 version fails with
+ * CKR_MECHANISM_PARAM_INVALID.
+ */
+ if (pMechanism->mechanism == CKM_AES_GCM) {
+ if (!aes_param) {
+ crv = CKR_MECHANISM_PARAM_INVALID;
+ break;
+ }
+ if (pMechanism->ulParameterLen == sizeof(CK_GCM_PARAMS_V3)) {
+ /* convert the true V3 parameters into the old NSS parameters */
+ CK_GCM_PARAMS_V3 *gcm_params = (CK_GCM_PARAMS_V3 *)aes_param;
+ if (gcm_params->ulIvLen * 8 != gcm_params->ulIvBits) {
+ /* only support byte aligned IV lengths */
+ crv = CKR_MECHANISM_PARAM_INVALID;
+ break;
+ }
+ aes_param = (void *)&nss_gcm_param;
+ nss_gcm_param.pIv = gcm_params->pIv;
+ nss_gcm_param.ulIvLen = gcm_params->ulIvLen;
+ nss_gcm_param.pAAD = gcm_params->pAAD;
+ nss_gcm_param.ulAADLen = gcm_params->ulAADLen;
+ nss_gcm_param.ulTagBits = gcm_params->ulTagBits;
+ } else if (pMechanism->ulParameterLen != sizeof(CK_NSS_GCM_PARAMS)) {
+ /* neither old nor new style params, must be invalid */
+ crv = CKR_MECHANISM_PARAM_INVALID;
+ break;
+ }
+ } else if ((pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) ||
+ ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) {
crv = CKR_MECHANISM_PARAM_INVALID;
break;
}
@@ -1165,7 +1193,7 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
}
context->cipherInfo = AES_CreateContext(
(unsigned char *)att->attrib.pValue,
- (unsigned char *)pMechanism->pParameter,
+ (unsigned char *)aes_param,
sftk_aes_mode(pMechanism->mechanism),
isEncrypt, att->attrib.ulValueLen, 16);
sftk_FreeAttribute(att);
@@ -1178,12 +1206,34 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
break;
case CKM_NSS_CHACHA20_POLY1305:
- if (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS)) {
- crv = CKR_MECHANISM_PARAM_INVALID;
- break;
+ case CKM_CHACHA20_POLY1305:
+ if (pMechanism->mechanism == CKM_NSS_CHACHA20_POLY1305) {
+ if ((pMechanism->pParameter == NULL) ||
+ (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS))) {
+ crv = CKR_MECHANISM_PARAM_INVALID;
+ break;
+ }
+ nss_aead_params_ptr = (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter;
+ } else {
+ CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR chacha_poly_params;
+ if ((pMechanism->pParameter == NULL) ||
+ (pMechanism->ulParameterLen !=
+ sizeof(CK_SALSA20_CHACHA20_POLY1305_PARAMS))) {
+ crv = CKR_MECHANISM_PARAM_INVALID;
+ break;
+ }
+ chacha_poly_params = (CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR)
+ pMechanism->pParameter;
+ nss_aead_params_ptr = &nss_aead_params;
+ nss_aead_params.pNonce = chacha_poly_params->pNonce;
+ nss_aead_params.ulNonceLen = chacha_poly_params->ulNonceLen;
+ nss_aead_params.pAAD = chacha_poly_params->pAAD;
+ nss_aead_params.ulAADLen = chacha_poly_params->ulAADLen;
+ nss_aead_params.ulTagLen = 16; /* Poly1305 is always 16 */
}
+
context->multi = PR_FALSE;
- if (key_type != CKK_NSS_CHACHA20) {
+ if ((key_type != CKK_NSS_CHACHA20) && (key_type != CKK_CHACHA20)) {
crv = CKR_KEY_TYPE_INCONSISTENT;
break;
}
@@ -1194,7 +1244,7 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
}
context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext(
(unsigned char *)att->attrib.pValue, att->attrib.ulValueLen,
- (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter);
+ nss_aead_params_ptr);
sftk_FreeAttribute(att);
if (context->cipherInfo == NULL) {
crv = sftk_MapCryptError(PORT_GetError());
@@ -1204,14 +1254,47 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
context->destroy = (SFTKDestroy)sftk_ChaCha20Poly1305_DestroyContext;
break;
- case CKM_NSS_CHACHA20_CTR:
- if (key_type != CKK_NSS_CHACHA20) {
- crv = CKR_KEY_TYPE_INCONSISTENT;
- break;
- }
- if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) {
- crv = CKR_MECHANISM_PARAM_INVALID;
- break;
+ case CKM_NSS_CHACHA20_CTR: /* old NSS private version */
+ case CKM_CHACHA20: /* PKCS #11 v3 version */
+ {
+ unsigned char *counter;
+ unsigned char *nonce;
+ unsigned long counter_len;
+ unsigned long nonce_len;
+ context->multi = PR_FALSE;
+ if (pMechanism->mechanism == CKM_NSS_CHACHA20_CTR) {
+ if (key_type != CKK_NSS_CHACHA20) {
+ crv = CKR_KEY_TYPE_INCONSISTENT;
+ break;
+ }
+ if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) {
+ crv = CKR_MECHANISM_PARAM_INVALID;
+ break;
+ }
+ counter_len = 4;
+ counter = pMechanism->pParameter;
+ nonce = counter + 4;
+ nonce_len = 12;
+ } else {
+ CK_CHACHA20_PARAMS_PTR chacha20_param_ptr;
+ if (key_type != CKK_CHACHA20) {
+ crv = CKR_KEY_TYPE_INCONSISTENT;
+ break;
+ }
+ if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != sizeof(CK_CHACHA20_PARAMS)) {
+ crv = CKR_MECHANISM_PARAM_INVALID;
+ break;
+ }
+ chacha20_param_ptr = (CK_CHACHA20_PARAMS_PTR)pMechanism->pParameter;
+ if ((chacha20_param_ptr->blockCounterBits != 32) &&
+ (chacha20_param_ptr->blockCounterBits != 64)) {
+ crv = CKR_MECHANISM_PARAM_INVALID;
+ break;
+ }
+ counter_len = chacha20_param_ptr->blockCounterBits / PR_BITS_PER_BYTE;
+ counter = chacha20_param_ptr->pBlockCounter;
+ nonce = chacha20_param_ptr->pNonce;
+ nonce_len = chacha20_param_ptr->ulNonceBits / PR_BITS_PER_BYTE;
}
att = sftk_FindAttribute(key, CKA_VALUE);
@@ -1234,24 +1317,35 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen);
sftk_FreeAttribute(att);
+ /* make sure we don't overflow our parameters */
+ if ((sizeof(ctx->counter) < counter_len) ||
+ (sizeof(ctx->nonce) < nonce_len)) {
+ PORT_Free(ctx);
+ crv = CKR_MECHANISM_PARAM_INVALID;
+ break;
+ }
+
/* The counter is little endian. */
- PRUint8 *param = pMechanism->pParameter;
int i = 0;
- for (; i < 4; ++i) {
- ctx->counter |= param[i] << (i * 8);
+ for (; i < counter_len; ++i) {
+ ctx->counter |= (PRUint32)counter[i] << (i * 8);
}
- memcpy(ctx->nonce, param + 4, 12);
+ memcpy(ctx->nonce, nonce, nonce_len);
context->cipherInfo = ctx;
context->update = (SFTKCipher)sftk_ChaCha20Ctr;
context->destroy = (SFTKDestroy)sftk_ChaCha20Ctr_DestroyContext;
break;
+ }
case CKM_NSS_AES_KEY_WRAP_PAD:
+ case CKM_AES_KEY_WRAP_PAD:
context->doPad = PR_TRUE;
/* fall thru */
case CKM_NSS_AES_KEY_WRAP:
- context->multi = PR_FALSE;
+ case CKM_AES_KEY_WRAP:
context->blockSize = 8;
+ case CKM_AES_KEY_WRAP_KWP:
+ context->multi = PR_FALSE;
if (key_type != CKK_AES) {
crv = CKR_KEY_TYPE_INCONSISTENT;
break;
@@ -1270,8 +1364,13 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
crv = CKR_HOST_MEMORY;
break;
}
- context->update = (SFTKCipher)(isEncrypt ? AESKeyWrap_Encrypt
- : AESKeyWrap_Decrypt);
+ if (pMechanism->mechanism == CKM_AES_KEY_WRAP_KWP) {
+ context->update = (SFTKCipher)(isEncrypt ? AESKeyWrap_EncryptKWP
+ : AESKeyWrap_DecryptKWP);
+ } else {
+ context->update = (SFTKCipher)(isEncrypt ? AESKeyWrap_Encrypt
+ : AESKeyWrap_Decrypt);
+ }
context->destroy = (SFTKDestroy)AESKeyWrap_DestroyContext;
break;
@@ -1613,68 +1712,6 @@ NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
return CKR_OK;
}
-/* From ssl3con.c: Constant-time helper macro that copies the MSB of x to all
- * other bits. */
-#define DUPLICATE_MSB_TO_ALL(x) ((unsigned int)((int)(x) >> (sizeof(int) * 8 - 1)))
-/* CK_RVToMask returns, in constant time, a mask value of
- * all ones if rv == CKR_OK. Otherwise it returns zero. */
-static unsigned int
-CK_RVToMask(CK_RV rv)
-{
- unsigned int good;
- /* rv ^ CKR_OK is zero iff rv == CKR_OK. Subtracting one results
- * in the MSB being set to one iff it was zero before. */
- good = rv ^ CKR_OK;
- good--;
- return DUPLICATE_MSB_TO_ALL(good);
-}
-/* Constant-time helper macro that selects l or r depending on all-1 or all-0
- * mask m */
-#define CT_SEL(m, l, r) (((m) & (l)) | (~(m) & (r)))
-/* Constant-time helper macro that returns all-1s if x is not 0; and all-0s
- * otherwise. */
-#define CT_NOT_ZERO(x) (DUPLICATE_MSB_TO_ALL(((x) | (0 - x))))
-
-/* sftk_CheckCBCPadding checks, in constant time, the padding validity and
- * accordingly sets the pad length. */
-static CK_RV
-sftk_CheckCBCPadding(CK_BYTE_PTR pLastPart,
- unsigned int blockSize, unsigned int *outPadSize)
-{
- PORT_Assert(outPadSize);
-
- unsigned int padSize = (unsigned int)pLastPart[blockSize - 1];
-
- /* If padSize <= blockSize, set goodPad to all-1s and all-0s otherwise.*/
- unsigned int goodPad = DUPLICATE_MSB_TO_ALL(~(blockSize - padSize));
- /* padSize should not be 0 */
- goodPad &= CT_NOT_ZERO(padSize);
-
- unsigned int i;
- for (i = 0; i < blockSize; i++) {
- /* If i < padSize, set loopMask to all-1s and all-0s otherwise.*/
- unsigned int loopMask = DUPLICATE_MSB_TO_ALL(~(padSize - 1 - i));
- /* Get the padding value (should be padSize) from buffer */
- unsigned int padVal = pLastPart[blockSize - 1 - i];
- /* Update goodPad only if i < padSize */
- goodPad &= CT_SEL(loopMask, ~(padVal ^ padSize), goodPad);
- }
-
- /* If any of the final padding bytes had the wrong value, one or more
- * of the lower eight bits of |goodPad| will be cleared. We AND the
- * bottom 8 bits together and duplicate the result to all the bits. */
- goodPad &= goodPad >> 4;
- goodPad &= goodPad >> 2;
- goodPad &= goodPad >> 1;
- goodPad <<= sizeof(goodPad) * 8 - 1;
- goodPad = DUPLICATE_MSB_TO_ALL(goodPad);
-
- /* Set outPadSize to padSize or 0 */
- *outPadSize = CT_SEL(goodPad, padSize, 0);
- /* Return OK if the pad is valid */
- return CT_SEL(goodPad, CKR_OK, CKR_ENCRYPTED_DATA_INVALID);
-}
-
/* NSC_DecryptFinal finishes a multiple-part decryption operation. */
CK_RV
NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
@@ -1714,9 +1751,10 @@ NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
crv = sftk_MapDecryptError(PORT_GetError());
} else {
unsigned int padSize = 0;
- crv = sftk_CheckCBCPadding(&pLastPart[outlen - context->blockSize], context->blockSize, &padSize);
+ crv = sftk_CheckCBCPadding(pLastPart, outlen,
+ context->blockSize, &padSize);
/* Update pulLastPartLen, in constant time, if crv is OK */
- *pulLastPartLen = CT_SEL(CK_RVToMask(crv), outlen - padSize, *pulLastPartLen);
+ *pulLastPartLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulLastPartLen);
}
}
}
@@ -1768,7 +1806,7 @@ NSC_Decrypt(CK_SESSION_HANDLE hSession,
finalLen = maxoutlen;
crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
if (crv == CKR_OK) {
- *pulDataLen = CT_SEL(CK_RVToMask(crv2), updateLen + finalLen, *pulDataLen);
+ *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv2), updateLen + finalLen, *pulDataLen);
return crv2;
} else {
return crv;
@@ -1782,9 +1820,10 @@ NSC_Decrypt(CK_SESSION_HANDLE hSession,
if (rv == SECSuccess) {
if (context->doPad) {
unsigned int padSize = 0;
- crv = sftk_CheckCBCPadding(&pData[outlen - context->blockSize], context->blockSize, &padSize);
+ crv = sftk_CheckCBCPadding(pData, outlen, context->blockSize,
+ &padSize);
/* Update pulDataLen, in constant time, if crv is OK */
- *pulDataLen = CT_SEL(CK_RVToMask(crv), outlen - padSize, *pulDataLen);
+ *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulDataLen);
} else {
*pulDataLen = (CK_ULONG)outlen;
}
@@ -2195,7 +2234,9 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
{
CK_MECHANISM cbc_mechanism;
CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
+#ifndef NSS_DISABLE_DEPRECATED_RC2
CK_RC2_CBC_PARAMS rc2_params;
+#endif
#if NSS_SOFTOKEN_DOES_RC5
CK_RC5_CBC_PARAMS rc5_params;
CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
@@ -2213,6 +2254,7 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
}
switch (pMechanism->mechanism) {
+#ifndef NSS_DISABLE_DEPRECATED_RC2
case CKM_RC2_MAC_GENERAL:
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) {
return CKR_MECHANISM_PARAM_INVALID;
@@ -2232,6 +2274,8 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
cbc_mechanism.ulParameterLen = sizeof(rc2_params);
blockSize = 8;
break;
+#endif /* NSS_DISABLE_DEPRECATED_RC2 */
+
#if NSS_SOFTOKEN_DOES_RC5
case CKM_RC5_MAC_GENERAL:
if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
@@ -2290,6 +2334,7 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
cbc_mechanism.pParameter = &ivBlock;
cbc_mechanism.ulParameterLen = blockSize;
break;
+#ifndef NSS_DISABLE_DEPRECATED_SEED
case CKM_SEED_MAC_GENERAL:
mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
/* fall through */
@@ -2300,6 +2345,7 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
cbc_mechanism.pParameter = &ivBlock;
cbc_mechanism.ulParameterLen = blockSize;
break;
+#endif /* NSS_DISABLE_DEPRECATED_SEED */
case CKM_CAMELLIA_MAC_GENERAL:
mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
/* fall through */
@@ -2757,13 +2803,20 @@ NSC_SignInit(CK_SESSION_HANDLE hSession,
context->maxLen = nsslowkey_PrivateModulusLen(info->key);
break;
- case CKM_DSA_SHA1:
- context->multi = PR_TRUE;
- crv = sftk_doSubSHA1(context);
- if (crv != CKR_OK)
- break;
- /* fall through */
+#define INIT_DSA_SIGN_MECH(mmm) \
+ case CKM_DSA_##mmm: \
+ context->multi = PR_TRUE; \
+ crv = sftk_doSub##mmm(context); \
+ if (crv != CKR_OK) \
+ break; \
+ goto finish_dsa;
+ INIT_DSA_SIGN_MECH(SHA1)
+ INIT_DSA_SIGN_MECH(SHA224)
+ INIT_DSA_SIGN_MECH(SHA256)
+ INIT_DSA_SIGN_MECH(SHA384)
+ INIT_DSA_SIGN_MECH(SHA512)
case CKM_DSA:
+ finish_dsa:
if (key_type != CKK_DSA) {
crv = CKR_KEY_TYPE_INCONSISTENT;
break;
@@ -2779,13 +2832,20 @@ NSC_SignInit(CK_SESSION_HANDLE hSession,
break;
- case CKM_ECDSA_SHA1:
- context->multi = PR_TRUE;
- crv = sftk_doSubSHA1(context);
- if (crv != CKR_OK)
- break;
- /* fall through */
+#define INIT_ECDSA_SIGN_MECH(mmm) \
+ case CKM_ECDSA_##mmm: \
+ context->multi = PR_TRUE; \
+ crv = sftk_doSub##mmm(context); \
+ if (crv != CKR_OK) \
+ break; \
+ goto finish_ecdsa;
+ INIT_ECDSA_SIGN_MECH(SHA1)
+ INIT_ECDSA_SIGN_MECH(SHA224)
+ INIT_ECDSA_SIGN_MECH(SHA256)
+ INIT_ECDSA_SIGN_MECH(SHA384)
+ INIT_ECDSA_SIGN_MECH(SHA512)
case CKM_ECDSA:
+ finish_ecdsa:
if (key_type != CKK_EC) {
crv = CKR_KEY_TYPE_INCONSISTENT;
break;
@@ -2878,7 +2938,7 @@ NSC_SignInit(CK_SESSION_HANDLE hSession,
break;
}
tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter;
- if (tls12_mac_params->prfMechanism == CKM_TLS_PRF) {
+ if (tls12_mac_params->prfHashMechanism == CKM_TLS_PRF) {
/* The TLS 1.0 and 1.1 PRF */
tlsPrfHash = HASH_AlgNULL;
if (tls12_mac_params->ulMacLength != 12) {
@@ -2888,7 +2948,7 @@ NSC_SignInit(CK_SESSION_HANDLE hSession,
} else {
/* The hash function for the TLS 1.2 PRF */
tlsPrfHash =
- GetHashTypeFromMechanism(tls12_mac_params->prfMechanism);
+ GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism);
if (tlsPrfHash == HASH_AlgNULL ||
tls12_mac_params->ulMacLength < 12) {
crv = CKR_MECHANISM_PARAM_INVALID;
@@ -3105,6 +3165,62 @@ NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN);
}
+struct SFTK_SESSION_FLAGS {
+ CK_FLAGS flag;
+ SFTKContextType type;
+};
+
+const static struct SFTK_SESSION_FLAGS sftk_session_flags[] = {
+ { CKF_ENCRYPT, SFTK_ENCRYPT },
+ { CKF_DECRYPT, SFTK_DECRYPT },
+ { CKF_DIGEST, SFTK_HASH },
+ { CKF_SIGN, SFTK_SIGN },
+ { CKF_SIGN_RECOVER, SFTK_SIGN_RECOVER },
+ { CKF_VERIFY, SFTK_VERIFY },
+ { CKF_VERIFY_RECOVER, SFTK_VERIFY_RECOVER },
+ { CKF_MESSAGE_ENCRYPT, SFTK_MESSAGE_ENCRYPT },
+ { CKF_MESSAGE_DECRYPT, SFTK_MESSAGE_DECRYPT },
+ { CKF_MESSAGE_SIGN, SFTK_MESSAGE_SIGN },
+ { CKF_MESSAGE_VERIFY, SFTK_MESSAGE_VERIFY },
+};
+const static int sftk_flag_count = PR_ARRAY_SIZE(sftk_session_flags);
+
+/*
+ * Cancel one or more operations running on the existing session.
+ */
+CK_RV
+NSC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags)
+{
+ SFTKSession *session;
+ SFTKSessionContext *context;
+ CK_RV gcrv = CKR_OK;
+ CK_RV crv;
+ int i;
+
+ for (i = 0; i < sftk_flag_count; i++) {
+ if (flags & sftk_session_flags[i].flag) {
+ flags &= ~sftk_session_flags[i].flag;
+ crv = sftk_GetContext(hSession, &context, sftk_session_flags[i].type, PR_TRUE, &session);
+ if (crv != CKR_OK) {
+ gcrv = CKR_OPERATION_CANCEL_FAILED;
+ continue;
+ }
+ sftk_TerminateOp(session, sftk_session_flags[i].type, context);
+ }
+ }
+ if (flags & CKF_FIND_OBJECTS) {
+ flags &= ~CKF_FIND_OBJECTS;
+ crv = NSC_FindObjectsFinal(hSession);
+ if (crv != CKR_OK) {
+ gcrv = CKR_OPERATION_CANCEL_FAILED;
+ }
+ }
+ if (flags) {
+ gcrv = CKR_OPERATION_CANCEL_FAILED;
+ }
+ return gcrv;
+}
+
/* NSC_SignFinal finishes a multiple-part signature operation,
* returning the signature. */
CK_RV
@@ -4072,11 +4188,13 @@ nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
CK_RV crv = CKR_OK;
switch (mechanism) {
+#ifndef NSS_DISABLE_DEPRECATED_RC2
case CKM_RC2_KEY_GEN:
*key_type = CKK_RC2;
if (*key_length == 0)
crv = CKR_TEMPLATE_INCOMPLETE;
break;
+#endif /* NSS_DISABLE_DEPRECATED_RC2 */
#if NSS_SOFTOKEN_DOES_RC5
case CKM_RC5_KEY_GEN:
*key_type = CKK_RC5;
@@ -4110,10 +4228,12 @@ nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
*key_type = CKK_DES3;
*key_length = 24;
break;
+#ifndef NSS_DISABLE_DEPRECATED_SEED
case CKM_SEED_KEY_GEN:
*key_type = CKK_SEED;
*key_length = 16;
break;
+#endif /* NSS_DISABLE_DEPRECATED_SEED */
case CKM_CAMELLIA_KEY_GEN:
*key_type = CKK_CAMELLIA;
if (*key_length == 0)
@@ -4126,6 +4246,14 @@ nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
break;
case CKM_NSS_CHACHA20_KEY_GEN:
*key_type = CKK_NSS_CHACHA20;
+ *key_length = 32;
+ break;
+ case CKM_CHACHA20_KEY_GEN:
+ *key_type = CKK_CHACHA20;
+ *key_length = 32;
+ break;
+ case CKM_HKDF_KEY_GEN:
+ *key_type = CKK_HKDF;
if (*key_length == 0)
crv = CKR_TEMPLATE_INCOMPLETE;
break;
@@ -4184,16 +4312,16 @@ nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
return CKR_HOST_MEMORY;
}
switch (pMechanism->mechanism) {
- case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
+ case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
case CKM_PBA_SHA1_WITH_SHA1_HMAC:
params->hashType = HASH_AlgSHA1;
params->keyLen = 20;
break;
- case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
+ case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
params->hashType = HASH_AlgMD5;
params->keyLen = 16;
break;
- case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
+ case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
params->hashType = HASH_AlgMD2;
params->keyLen = 16;
break;
@@ -4295,10 +4423,12 @@ nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
*key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3;
*key_length = params->keyLen;
break;
+#ifndef NSS_DISABLE_DEPRECATED_RC2
case SEC_OID_RC2_CBC:
*key_type = CKK_RC2;
*key_length = params->keyLen;
break;
+#endif /* NSS_DISABLE_DEPRECATED_RC2 */
case SEC_OID_RC4:
*key_type = CKK_RC4;
*key_length = params->keyLen;
@@ -4346,6 +4476,7 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
CK_RV crv = CKR_OK;
CK_BBOOL cktrue = CK_TRUE;
+ NSSPKCS5PBEParameter *pbe_param = NULL;
int i;
SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
unsigned char buf[MAX_KEY_LEN];
@@ -4354,7 +4485,6 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
nsc_bulk,
nsc_param,
nsc_jpake } key_gen_type;
- NSSPKCS5PBEParameter *pbe_param;
SSL3RSAPreMasterSecret *rsa_pms;
CK_VERSION *version;
/* in very old versions of NSS, there were implementation errors with key
@@ -4413,14 +4543,19 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
case CKM_DES2_KEY_GEN:
case CKM_DES3_KEY_GEN:
checkWeak = PR_TRUE;
- /* fall through */
+/* fall through */
+#ifndef NSS_DISABLE_DEPRECATED_RC2
case CKM_RC2_KEY_GEN:
+#endif
case CKM_RC4_KEY_GEN:
case CKM_GENERIC_SECRET_KEY_GEN:
+#ifndef NSS_DISABLE_DEPRECATED_SEED
case CKM_SEED_KEY_GEN:
+#endif
case CKM_CAMELLIA_KEY_GEN:
case CKM_AES_KEY_GEN:
case CKM_NSS_CHACHA20_KEY_GEN:
+ case CKM_CHACHA20_KEY_GEN:
#if NSS_SOFTOKEN_DOES_RC5
case CKM_RC5_KEY_GEN:
#endif
@@ -4432,9 +4567,9 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
key_gen_type = nsc_ssl;
break;
case CKM_PBA_SHA1_WITH_SHA1_HMAC:
- case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
- case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
- case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
+ case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
+ case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
+ case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
@@ -4443,19 +4578,21 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
key_type = CKK_GENERIC_SECRET;
crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param);
break;
- case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
+ case CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC:
faultyPBE3DES = PR_TRUE;
/* fall through */
- case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:
- case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
- case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
- case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC:
- case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4:
- case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4:
- case CKM_PBE_SHA1_DES3_EDE_CBC:
- case CKM_PBE_SHA1_DES2_EDE_CBC:
+ case CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC:
+#ifndef NSS_DISABLE_DEPRECATED_RC2
+ case CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC:
+ case CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC:
case CKM_PBE_SHA1_RC2_128_CBC:
case CKM_PBE_SHA1_RC2_40_CBC:
+#endif
+ case CKM_NSS_PBE_SHA1_DES_CBC:
+ case CKM_NSS_PBE_SHA1_40_BIT_RC4:
+ case CKM_NSS_PBE_SHA1_128_BIT_RC4:
+ case CKM_PBE_SHA1_DES3_EDE_CBC:
+ case CKM_PBE_SHA1_DES2_EDE_CBC:
case CKM_PBE_SHA1_RC4_128:
case CKM_PBE_SHA1_RC4_40:
case CKM_PBE_MD5_DES_CBC:
@@ -4467,7 +4604,7 @@ NSC_GenerateKey(CK_SESSION_HANDLE hSession,
case CKM_DSA_PARAMETER_GEN:
key_gen_type = nsc_param;
key_type = CKK_DSA;
- objclass = CKO_KG_PARAMETERS;
+ objclass = CKO_DOMAIN_PARAMETERS;
crv = CKR_OK;
break;
case CKM_NSS_JPAKE_ROUND1_SHA1:
@@ -4622,7 +4759,7 @@ loser:
* performed, for example, CKR_HOST_MEMORY.
*/
static CK_RV
-sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
+sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, SFTKSlot *slot,
SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType)
{
/*
@@ -4637,6 +4774,12 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
* others => CKM_INVALID_MECHANISM
*
* None of these mechanisms has a parameter.
+ *
+ * For derive CKK_DH => CKM_DH_PKCS_DERIVE
+ * CKK_EC => CKM_ECDH1_DERIVE
+ * others => CKM_INVALID_MECHANISM
+ *
+ * The parameters for these mechanisms is the public key.
*/
CK_MECHANISM mech = { 0, NULL, 0 };
@@ -4896,24 +5039,106 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
isDerivable = sftk_isTrue(privateKey, CKA_DERIVE);
if (isDerivable) {
- /*
- * We are not doing consistency check for Diffie-Hellman Key -
- * otherwise it would be here
- * This is also true for Elliptic Curve Diffie-Hellman keys
- * NOTE: EC keys are currently subjected to pairwise
- * consistency check for signing/verification.
- */
- /*
- * FIPS 140-2 had the following pairwise consistency test for
- * public and private keys used for key agreement:
- * If the keys are used to perform key agreement, then the
- * cryptographic module shall create a second, compatible
- * key pair. The cryptographic module shall perform both
- * sides of the key agreement algorithm and shall compare
- * the resulting shared values. If the shared values are
- * not equal, the test shall fail.
- * This test was removed in Change Notice 3.
- */
+ SFTKAttribute *pubAttribute = NULL;
+ CK_OBJECT_HANDLE newKey;
+ PRBool isFIPS = (slot->slotID == FIPS_SLOT_ID);
+ CK_RV crv2;
+ CK_OBJECT_CLASS secret = CKO_SECRET_KEY;
+ CK_KEY_TYPE generic = CKK_GENERIC_SECRET;
+ CK_ULONG keyLen = 128;
+ CK_BBOOL ckTrue = CK_TRUE;
+ CK_ATTRIBUTE template[] = {
+ { CKA_CLASS, &secret, sizeof(secret) },
+ { CKA_KEY_TYPE, &generic, sizeof(generic) },
+ { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) },
+ { CKA_DERIVE, &ckTrue, sizeof(ckTrue) }
+ };
+ CK_ULONG templateCount = PR_ARRAY_SIZE(template);
+ CK_ECDH1_DERIVE_PARAMS ecParams;
+
+ crv = CKR_OK; /*paranoia, already get's set before we drop to the end */
+ /* FIPS 140-2 requires we verify that the resulting key is a valid key.
+ * The easiest way to do this is to do a derive operation, which checks
+ * the validity of the key */
+
+ switch (keyType) {
+ case CKK_DH:
+ mech.mechanism = CKM_DH_PKCS_DERIVE;
+ pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE);
+ if (pubAttribute == NULL) {
+ return CKR_DEVICE_ERROR;
+ }
+ mech.pParameter = pubAttribute->attrib.pValue;
+ mech.ulParameterLen = pubAttribute->attrib.ulValueLen;
+ break;
+ case CKK_EC:
+ mech.mechanism = CKM_ECDH1_DERIVE;
+ pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT);
+ if (pubAttribute == NULL) {
+ return CKR_DEVICE_ERROR;
+ }
+ ecParams.kdf = CKD_NULL;
+ ecParams.ulSharedDataLen = 0;
+ ecParams.pSharedData = NULL;
+ ecParams.ulPublicDataLen = pubAttribute->attrib.ulValueLen;
+ ecParams.pPublicData = pubAttribute->attrib.pValue;
+ mech.pParameter = &ecParams;
+ mech.ulParameterLen = sizeof(ecParams);
+ break;
+ default:
+ return CKR_DEVICE_ERROR;
+ }
+
+ crv = NSC_DeriveKey(hSession, &mech, privateKey->handle, template, templateCount, &newKey);
+ if (crv != CKR_OK) {
+ sftk_FreeAttribute(pubAttribute);
+ return crv;
+ }
+ /* FIPS requires full validation, but in fipx mode NSC_Derive
+ * only does partial validation with approved primes, now handle
+ * full validation */
+ if (isFIPS && keyType == CKK_DH) {
+ SECItem pubKey;
+ SECItem prime;
+ SECItem subPrime;
+ const SECItem *subPrimePtr = &subPrime;
+
+ pubKey.data = pubAttribute->attrib.pValue;
+ pubKey.len = pubAttribute->attrib.ulValueLen;
+ prime.data = subPrime.data = NULL;
+ prime.len = subPrime.len = 0;
+ crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
+ if (crv != CKR_OK) {
+ goto done;
+ }
+ crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
+ /* we ignore the return code an only look at the length */
+ if (subPrime.len == 0) {
+ /* subprime not supplied, In this case look it up.
+ * This only works with approved primes, but in FIPS mode
+ * that's the only kine of prime that will get here */
+ subPrimePtr = sftk_VerifyDH_Prime(&prime);
+ if (subPrimePtr == NULL) {
+ crv = CKR_GENERAL_ERROR;
+ goto done;
+ }
+ }
+ if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) {
+ crv = CKR_GENERAL_ERROR;
+ }
+ done:
+ PORT_Free(subPrime.data);
+ PORT_Free(prime.data);
+ }
+ /* clean up before we return */
+ sftk_FreeAttribute(pubAttribute);
+ crv2 = NSC_DestroyObject(hSession, newKey);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+ if (crv2 != CKR_OK) {
+ return crv2;
+ }
}
return CKR_OK;
@@ -5027,7 +5252,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
case CKM_RSA_PKCS_KEY_PAIR_GEN:
/* format the keys */
sftk_DeleteAttributeType(publicKey, CKA_MODULUS);
- sftk_DeleteAttributeType(privateKey, CKA_NETSCAPE_DB);
+ sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
sftk_DeleteAttributeType(privateKey, CKA_MODULUS);
sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT);
sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT);
@@ -5082,7 +5307,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
if (crv != CKR_OK)
goto kpg_done;
/* now fill in the RSA dependent paramenters in the private key */
- crv = sftk_AddAttributeType(privateKey, CKA_NETSCAPE_DB,
+ crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
sftk_item_expand(&rsaPriv->modulus));
if (crv != CKR_OK)
goto kpg_done;
@@ -5118,7 +5343,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
break;
case CKM_DSA_KEY_PAIR_GEN:
sftk_DeleteAttributeType(publicKey, CKA_VALUE);
- sftk_DeleteAttributeType(privateKey, CKA_NETSCAPE_DB);
+ sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
sftk_DeleteAttributeType(privateKey, CKA_PRIME);
sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME);
sftk_DeleteAttributeType(privateKey, CKA_BASE);
@@ -5216,7 +5441,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
goto dsagn_done;
/* now fill in the RSA dependent paramenters in the private key */
- crv = sftk_AddAttributeType(privateKey, CKA_NETSCAPE_DB,
+ crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
sftk_item_expand(&dsaPriv->publicValue));
if (crv != CKR_OK)
goto dsagn_done;
@@ -5232,7 +5457,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
sftk_DeleteAttributeType(privateKey, CKA_PRIME);
sftk_DeleteAttributeType(privateKey, CKA_BASE);
sftk_DeleteAttributeType(privateKey, CKA_VALUE);
- sftk_DeleteAttributeType(privateKey, CKA_NETSCAPE_DB);
+ sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
key_type = CKK_DH;
/* extract the necessary parameters and copy them to private keys */
@@ -5290,7 +5515,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
if (crv != CKR_OK)
goto dhgn_done;
- crv = sftk_AddAttributeType(privateKey, CKA_NETSCAPE_DB,
+ crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
sftk_item_expand(&dhPriv->publicValue));
if (crv != CKR_OK)
goto dhgn_done;
@@ -5306,7 +5531,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
case CKM_EC_KEY_PAIR_GEN:
sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS);
sftk_DeleteAttributeType(privateKey, CKA_VALUE);
- sftk_DeleteAttributeType(privateKey, CKA_NETSCAPE_DB);
+ sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
key_type = CKK_EC;
/* extract the necessary parameters and copy them to private keys */
@@ -5365,7 +5590,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
if (crv != CKR_OK)
goto ecgn_done;
- crv = sftk_AddAttributeType(privateKey, CKA_NETSCAPE_DB,
+ crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
sftk_item_expand(&ecPriv->publicValue));
ecgn_done:
/* should zeroize, since this function doesn't. */
@@ -5457,7 +5682,7 @@ NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
if (crv == CKR_OK) {
/* Perform FIPS 140-2 pairwise consistency check. */
- crv = sftk_PairwiseConsistencyCheck(hSession,
+ crv = sftk_PairwiseConsistencyCheck(hSession, slot,
publicKey, privateKey, key_type);
if (crv != CKR_OK) {
if (sftk_audit_enabled) {
@@ -5936,8 +6161,8 @@ sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
switch (lpk->keyType) {
case NSSLOWKEYRSAKey:
keyType = CKK_RSA;
- if (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) {
- sftk_DeleteAttributeType(key, CKA_NETSCAPE_DB);
+ if (sftk_hasAttribute(key, CKA_NSS_DB)) {
+ sftk_DeleteAttributeType(key, CKA_NSS_DB);
}
crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
sizeof(keyType));
@@ -5992,7 +6217,7 @@ sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
break;
case NSSLOWKEYDSAKey:
keyType = CKK_DSA;
- crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
+ crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
if (crv != CKR_OK)
break;
crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
@@ -6034,7 +6259,7 @@ sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
/* what about fortezza??? */
case NSSLOWKEYECKey:
keyType = CKK_EC;
- crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
+ crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
if (crv != CKR_OK)
break;
crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
@@ -6356,14 +6581,42 @@ sftk_freeSSLKeys(CK_SESSION_HANDLE session,
* semantics.
*/
static CK_RV
-sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey)
+sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey,
+ PRBool canBeData)
{
PRBool hasSensitive;
PRBool sensitive = PR_FALSE;
+ CK_BBOOL bFalse = CK_FALSE;
PRBool hasExtractable;
PRBool extractable = PR_TRUE;
+ CK_BBOOL bTrue = CK_TRUE;
CK_RV crv = CKR_OK;
SFTKAttribute *att;
+ PRBool isData = PR_TRUE;
+
+ if (canBeData) {
+ CK_OBJECT_CLASS objClass;
+
+ /* if the target key is actually data, don't set the unexpected
+ * attributes */
+ crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+ if (objClass == CKO_DATA) {
+ return CKR_OK;
+ }
+
+ /* if the base key is data, it doesn't have sensitive attributes,
+ * allow the destKey to get it's own */
+ crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+ if (objClass == CKO_DATA) {
+ isData = PR_TRUE;
+ }
+ }
hasSensitive = PR_FALSE;
att = sftk_FindAttribute(destKey, CKA_SENSITIVE);
@@ -6394,19 +6647,31 @@ sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey)
/* inherit parent's sensitivity */
if (!hasSensitive) {
att = sftk_FindAttribute(baseKey, CKA_SENSITIVE);
- if (att == NULL)
+ if (att != NULL) {
+ crv = sftk_defaultAttribute(destKey,
+ sftk_attr_expand(&att->attrib));
+ sftk_FreeAttribute(att);
+ } else if (isData) {
+ crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE,
+ &bFalse, sizeof(bFalse));
+ } else {
return CKR_KEY_TYPE_INCONSISTENT;
- crv = sftk_defaultAttribute(destKey, sftk_attr_expand(&att->attrib));
- sftk_FreeAttribute(att);
+ }
if (crv != CKR_OK)
return crv;
}
if (!hasExtractable) {
att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE);
- if (att == NULL)
+ if (att != NULL) {
+ crv = sftk_defaultAttribute(destKey,
+ sftk_attr_expand(&att->attrib));
+ sftk_FreeAttribute(att);
+ } else if (isData) {
+ crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE,
+ &bTrue, sizeof(bTrue));
+ } else {
return CKR_KEY_TYPE_INCONSISTENT;
- crv = sftk_defaultAttribute(destKey, sftk_attr_expand(&att->attrib));
- sftk_FreeAttribute(att);
+ }
if (crv != CKR_OK)
return crv;
}
@@ -6589,6 +6854,185 @@ sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo,
return crv;
}
+CK_RV
+sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession,
+ SFTKObject *sourceKey, const unsigned char *sourceKeyBytes,
+ int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes,
+ int keySize, PRBool canBeData, PRBool isFIPS)
+{
+ SFTKSession *session;
+ SFTKAttribute *saltKey_att = NULL;
+ const SECHashObject *rawHash;
+ unsigned hashLen;
+ unsigned genLen = 0;
+ unsigned char hashbuf[HASH_LENGTH_MAX];
+ unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH];
+ unsigned char *keyBlockAlloc = NULL; /* allocated keyBlock */
+ unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */
+ const unsigned char *prk; /* psuedo-random key */
+ CK_ULONG prkLen;
+ const unsigned char *okm; /* output keying material */
+ HASH_HashType hashType = GetHashTypeFromMechanism(params->prfHashMechanism);
+ SFTKObject *saltKey = NULL;
+ CK_RV crv = CKR_OK;
+
+ /* Spec says it should be the base hash, but also accept the HMAC */
+ if (hashType == HASH_AlgNULL) {
+ hashType = sftk_HMACMechanismToHash(params->prfHashMechanism);
+ }
+ rawHash = HASH_GetRawHashObject(hashType);
+ if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) {
+ return CKR_MECHANISM_INVALID;
+ }
+ hashLen = rawHash->length;
+
+ if ((!params->bExpand && !params->bExtract) ||
+ (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
+ (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ if ((params->bExpand && keySize == 0) ||
+ (!params->bExpand && keySize > hashLen) ||
+ (params->bExpand && keySize > 255 * hashLen)) {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ /* sourceKey is NULL if we are called from the POST, skip the
+ * sensitiveCheck */
+ if (sourceKey != NULL) {
+ crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData);
+ if (crv != CKR_OK)
+ return crv;
+ }
+
+ /* HKDF-Extract(salt, base key value) */
+ if (params->bExtract) {
+ CK_BYTE *salt;
+ CK_ULONG saltLen;
+ HMACContext *hmac;
+ unsigned int bufLen;
+
+ switch (params->ulSaltType) {
+ case CKF_HKDF_SALT_NULL:
+ saltLen = hashLen;
+ salt = hashbuf;
+ memset(salt, 0, saltLen);
+ break;
+ case CKF_HKDF_SALT_DATA:
+ salt = params->pSalt;
+ saltLen = params->ulSaltLen;
+ if ((salt == NULL) || (params->ulSaltLen == 0)) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+ break;
+ case CKF_HKDF_SALT_KEY:
+ /* lookup key */
+ session = sftk_SessionFromHandle(hSession);
+ if (session == NULL) {
+ return CKR_SESSION_HANDLE_INVALID;
+ }
+
+ saltKey = sftk_ObjectFromHandle(params->hSaltKey, session);
+ sftk_FreeSession(session);
+ if (saltKey == NULL) {
+ return CKR_KEY_HANDLE_INVALID;
+ }
+ saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
+ if (saltKey_att == NULL) {
+ sftk_FreeObject(saltKey);
+ return CKR_KEY_HANDLE_INVALID;
+ }
+ /* save the resulting salt */
+ salt = saltKey_att->attrib.pValue;
+ saltLen = saltKey_att->attrib.ulValueLen;
+ break;
+ default:
+ return CKR_MECHANISM_PARAM_INVALID;
+ break;
+ }
+
+ hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
+ if (saltKey_att) {
+ sftk_FreeAttribute(saltKey_att);
+ }
+ if (saltKey) {
+ sftk_FreeObject(saltKey);
+ }
+ if (!hmac) {
+ return CKR_HOST_MEMORY;
+ }
+ HMAC_Begin(hmac);
+ HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen);
+ HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf));
+ HMAC_Destroy(hmac, PR_TRUE);
+ PORT_Assert(bufLen == rawHash->length);
+ prk = hashbuf;
+ prkLen = bufLen;
+ } else {
+ /* PRK = base key value */
+ prk = sourceKeyBytes;
+ prkLen = sourceKeyLen;
+ }
+
+ /* HKDF-Expand */
+ if (!params->bExpand) {
+ okm = prk;
+ keySize = genLen = hashLen;
+ } else {
+ /* T(1) = HMAC-Hash(prk, "" | info | 0x01)
+ * T(n) = HMAC-Hash(prk, T(n-1) | info | n
+ * key material = T(1) | ... | T(n)
+ */
+ HMACContext *hmac;
+ CK_BYTE bi;
+ unsigned iterations;
+
+ genLen = PR_ROUNDUP(keySize, hashLen);
+ iterations = genLen / hashLen;
+
+ if (genLen > sizeof(keyBlock)) {
+ keyBlockAlloc = PORT_Alloc(genLen);
+ if (keyBlockAlloc == NULL) {
+ return CKR_HOST_MEMORY;
+ }
+ keyBlockData = keyBlockAlloc;
+ }
+ hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
+ if (hmac == NULL) {
+ PORT_Free(keyBlockAlloc);
+ return CKR_HOST_MEMORY;
+ }
+ for (bi = 1; bi <= iterations && bi > 0; ++bi) {
+ unsigned len;
+ HMAC_Begin(hmac);
+ if (bi > 1) {
+ HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen);
+ }
+ if (params->ulInfoLen != 0) {
+ HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
+ }
+ HMAC_Update(hmac, &bi, 1);
+ HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len,
+ hashLen);
+ PORT_Assert(len == hashLen);
+ }
+ HMAC_Destroy(hmac, PR_TRUE);
+ okm = &keyBlockData[0];
+ }
+ /* key material = okm */
+ crv = CKR_OK;
+ if (key) {
+ crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
+ } else {
+ PORT_Assert(outKeyBytes != NULL);
+ PORT_Memcpy(outKeyBytes, okm, keySize);
+ }
+ PORT_Memset(keyBlockData, 0, genLen);
+ PORT_Memset(hashbuf, 0, sizeof(hashbuf));
+ PORT_Free(keyBlockAlloc);
+ return crv;
+}
+
/*
* SSL Key generation given pre master secret
*/
@@ -6644,7 +7088,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH];
PRBool isFIPS;
HASH_HashType hashType;
+ CK_MECHANISM_TYPE hashMech;
PRBool extractValue = PR_TRUE;
+ CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS ikeAppB;
+ CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *pIkeAppB;
CHECK_FORK();
@@ -6704,6 +7151,12 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
extractValue = PR_FALSE;
classType = CKO_PUBLIC_KEY;
break;
+ case CKM_HKDF_DATA: /* fall through */
+ case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */
+ case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
+ case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA:
+ classType = CKO_DATA;
+ break;
case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */
case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
@@ -6793,14 +7246,22 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
key, keySize);
break;
case CKM_NSS_IKE1_APP_B_PRF_DERIVE:
- if (pMechanism->ulParameterLen !=
+ pIkeAppB = (CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *)pMechanism->pParameter;
+ if (pMechanism->ulParameterLen ==
sizeof(CK_MECHANISM_TYPE)) {
+ ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter;
+ ikeAppB.bHasKeygxy = PR_FALSE;
+ ikeAppB.hKeygxy = CK_INVALID_HANDLE;
+ ikeAppB.pExtraData = NULL;
+ ikeAppB.ulExtraDataLen = 0;
+ pIkeAppB = &ikeAppB;
+ } else if (pMechanism->ulParameterLen !=
+ sizeof(CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS)) {
crv = CKR_MECHANISM_PARAM_INVALID;
break;
}
- crv = sftk_ike1_appendix_b_prf(hSession, att,
- (CK_MECHANISM_TYPE *)pMechanism->pParameter,
- key, keySize);
+ crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key,
+ keySize);
break;
case CKM_NSS_IKE_PRF_PLUS_DERIVE:
if (pMechanism->ulParameterLen !=
@@ -7119,7 +7580,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
isTLS = PR_TRUE;
}
- crv = sftk_DeriveSensitiveCheck(sourceKey, key);
+ crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
if (crv != CKR_OK)
break;
@@ -7484,6 +7945,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
break;
}
+#ifndef NSS_DISABLE_DEPRECATED_SEED
case CKM_SEED_ECB_ENCRYPT_DATA:
case CKM_SEED_CBC_ENCRYPT_DATA: {
void *cipherInfo;
@@ -7530,11 +7992,12 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
SEED_DestroyContext(cipherInfo, PR_TRUE);
break;
}
+#endif /* NSS_DISABLE_DEPRECATED_SEED */
case CKM_CONCATENATE_BASE_AND_KEY: {
SFTKObject *newKey;
- crv = sftk_DeriveSensitiveCheck(sourceKey, key);
+ crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
if (crv != CKR_OK)
break;
@@ -7597,7 +8060,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
}
case CKM_CONCATENATE_BASE_AND_DATA:
- crv = sftk_DeriveSensitiveCheck(sourceKey, key);
+ crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
if (crv != CKR_OK)
break;
@@ -7627,7 +8090,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
PORT_ZFree(buf, tmpKeySize);
break;
case CKM_CONCATENATE_DATA_AND_BASE:
- crv = sftk_DeriveSensitiveCheck(sourceKey, key);
+ crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
if (crv != CKR_OK)
break;
@@ -7657,7 +8120,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
PORT_ZFree(buf, tmpKeySize);
break;
case CKM_XOR_BASE_AND_DATA:
- crv = sftk_DeriveSensitiveCheck(sourceKey, key);
+ crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
if (crv != CKR_OK)
break;
@@ -7698,7 +8161,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
- crv = sftk_DeriveSensitiveCheck(sourceKey, key);
+ crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
if (crv != CKR_OK)
break;
@@ -7833,40 +8296,101 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
case CKM_DH_PKCS_DERIVE: {
SECItem derived, dhPublic;
- SECItem dhPrime, dhSubPrime, dhValue;
+ SECItem dhPrime, dhValue;
+ const SECItem *subPrime;
/* sourceKey - values for the local existing low key */
/* get prime and value attributes */
crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
if (crv != CKR_OK)
break;
- crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
- if (crv != CKR_OK) {
- PORT_Free(dhPrime.data);
- break;
- }
dhPublic.data = pMechanism->pParameter;
dhPublic.len = pMechanism->ulParameterLen;
- /* If the caller bothered to provide Q, use Q to validate
- * the public key. */
- crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, sourceKey, CKA_SUBPRIME);
- if (crv == CKR_OK) {
- rv = KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime);
- PORT_Free(dhSubPrime.data);
- if (rv != SECSuccess) {
+ /* if the prime is an approved prime, we can skip all the other
+ * checks. */
+ subPrime = sftk_VerifyDH_Prime(&dhPrime);
+ if (subPrime == NULL) {
+ SECItem dhSubPrime;
+ /* If the caller set the subprime value, it means that
+ * either the caller knows the subprime value and wants us
+ * to validate the key against the subprime, or that the
+ * caller wants us to verify that the prime is a safe prime
+ * by passing in subprime = (prime-1)/2 */
+ dhSubPrime.data = NULL;
+ dhSubPrime.len = 0;
+ crv = sftk_Attribute2SecItem(NULL, &dhSubPrime,
+ sourceKey, CKA_SUBPRIME);
+ /* we ignore the value of crv here, We treat a valid
+ * return of len = 0 and a failure to find a subrime the same
+ * NOTE: we free the subprime in both cases depending on
+ * PORT_Free of NULL to be a noop */
+ if (dhSubPrime.len != 0) {
+ PRBool isSafe = PR_FALSE;
+
+ /* Callers can set dhSubPrime to q=(p-1)/2 to force
+ * checks for safe primes. If so we only need to check
+ * q and p for primality and skip the group test. */
+ rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe);
+ if (rv != SECSuccess) {
+ /* either p or q was even and therefore not prime,
+ * we can stop processing here and fail now */
+ crv = CKR_ARGUMENTS_BAD;
+ PORT_Free(dhPrime.data);
+ PORT_Free(dhSubPrime.data);
+ break;
+ }
+
+ /* first make sure the primes are really prime */
+ if (!KEA_PrimeCheck(&dhPrime)) {
+ crv = CKR_ARGUMENTS_BAD;
+ PORT_Free(dhPrime.data);
+ PORT_Free(dhSubPrime.data);
+ break;
+ }
+ if (!KEA_PrimeCheck(&dhSubPrime)) {
+ crv = CKR_ARGUMENTS_BAD;
+ PORT_Free(dhPrime.data);
+ PORT_Free(dhSubPrime.data);
+ break;
+ }
+ if (isFIPS || !isSafe) {
+ /* With safe primes, there is only one other small
+ * subgroup. As long as y isn't 0, 1, or -1 mod p,
+ * any other y is safe. Only do the full check for
+ * non-safe primes, except in FIPS mode we need
+ * to do this check on all primes in which
+ * we receive the subprime value */
+ if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) {
+ crv = CKR_ARGUMENTS_BAD;
+ PORT_Free(dhPrime.data);
+ PORT_Free(dhSubPrime.data);
+ break;
+ }
+ }
+ } else if (isFIPS) {
+ /* In FIPS mode we only accept approved primes, or
+ * primes with the full subprime value */
crv = CKR_ARGUMENTS_BAD;
PORT_Free(dhPrime.data);
- PORT_Free(dhValue.data);
break;
}
+ /* checks are complete, no need for the subPrime any longer */
+ PORT_Free(dhSubPrime.data);
+ }
+
+ /* now that the prime is validated, get the private value */
+ crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
+ if (crv != CKR_OK) {
+ PORT_Free(dhPrime.data);
+ break;
}
/* calculate private value - oct */
rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
PORT_Free(dhPrime.data);
- PORT_Free(dhValue.data);
+ PORT_ZFree(dhValue.data, dhValue.len);
if (rv == SECSuccess) {
sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
@@ -8017,142 +8541,58 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
}
break;
}
-
/* See RFC 5869 and CK_NSS_HKDFParams for documentation. */
case CKM_NSS_HKDF_SHA1:
- hashType = HASH_AlgSHA1;
+ hashMech = CKM_SHA_1;
goto hkdf;
case CKM_NSS_HKDF_SHA256:
- hashType = HASH_AlgSHA256;
+ hashMech = CKM_SHA256;
goto hkdf;
case CKM_NSS_HKDF_SHA384:
- hashType = HASH_AlgSHA384;
+ hashMech = CKM_SHA384;
goto hkdf;
case CKM_NSS_HKDF_SHA512:
- hashType = HASH_AlgSHA512;
+ hashMech = CKM_SHA512;
goto hkdf;
hkdf : {
const CK_NSS_HKDFParams *params =
(const CK_NSS_HKDFParams *)pMechanism->pParameter;
- const SECHashObject *rawHash;
- unsigned hashLen;
- CK_BYTE hashbuf[HASH_LENGTH_MAX];
- CK_BYTE *prk; /* psuedo-random key */
- CK_ULONG prkLen;
- CK_BYTE *okm; /* output keying material */
- unsigned allocated_space = 0; /* If we need more work space, track it */
- unsigned char *key_buf = &key_block[0];
-
- rawHash = HASH_GetRawHashObject(hashType);
- if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) {
- crv = CKR_FUNCTION_FAILED;
- break;
- }
- hashLen = rawHash->length;
+ CK_HKDF_PARAMS hkdfParams;
- if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams) ||
- !params || (!params->bExpand && !params->bExtract) ||
- (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
- (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
+ if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) {
crv = CKR_MECHANISM_PARAM_INVALID;
break;
}
- if (keySize == 0 ||
- (!params->bExpand && keySize > hashLen) ||
- (params->bExpand && keySize > 255 * hashLen)) {
- crv = CKR_TEMPLATE_INCONSISTENT;
- break;
- }
- crv = sftk_DeriveSensitiveCheck(sourceKey, key);
- if (crv != CKR_OK)
- break;
-
- /* HKDF-Extract(salt, base key value) */
- if (params->bExtract) {
- CK_BYTE *salt;
- CK_ULONG saltLen;
- HMACContext *hmac;
- unsigned int bufLen;
-
- salt = params->pSalt;
- saltLen = params->ulSaltLen;
- if (salt == NULL) {
- saltLen = hashLen;
- salt = hashbuf;
- memset(salt, 0, saltLen);
- }
- hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
- if (!hmac) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- HMAC_Begin(hmac);
- HMAC_Update(hmac, (const unsigned char *)att->attrib.pValue,
- att->attrib.ulValueLen);
- HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf));
- HMAC_Destroy(hmac, PR_TRUE);
- PORT_Assert(bufLen == rawHash->length);
- prk = hashbuf;
- prkLen = bufLen;
- } else {
- /* PRK = base key value */
- prk = (CK_BYTE *)att->attrib.pValue;
- prkLen = att->attrib.ulValueLen;
- }
-
- /* HKDF-Expand */
- if (!params->bExpand) {
- okm = prk;
+ hkdfParams.bExtract = params->bExtract;
+ hkdfParams.bExpand = params->bExpand;
+ if (params->pSalt) {
+ hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA;
} else {
- /* T(1) = HMAC-Hash(prk, "" | info | 0x01)
- * T(n) = HMAC-Hash(prk, T(n-1) | info | n
- * key material = T(1) | ... | T(n)
- *
- * If the requested output length does not fit
- * within |key_block|, allocate space for expansion.
- */
- HMACContext *hmac;
- CK_BYTE bi;
- unsigned n_bytes = PR_ROUNDUP(keySize, hashLen);
- unsigned iterations = n_bytes / hashLen;
- hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
- if (hmac == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- if (n_bytes > sizeof(key_block)) {
- key_buf = PORT_Alloc(n_bytes);
- if (key_buf == NULL) {
- crv = CKR_HOST_MEMORY;
- break;
- }
- allocated_space = n_bytes;
- }
- for (bi = 1; bi <= iterations && bi > 0; ++bi) {
- unsigned len;
- HMAC_Begin(hmac);
- if (bi > 1) {
- HMAC_Update(hmac, key_buf + ((bi - 2) * hashLen), hashLen);
- }
- if (params->ulInfoLen != 0) {
- HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
- }
- HMAC_Update(hmac, &bi, 1);
- HMAC_Finish(hmac, key_buf + ((bi - 1) * hashLen), &len,
- hashLen);
- PORT_Assert(len == hashLen);
- }
- HMAC_Destroy(hmac, PR_TRUE);
- okm = key_buf;
- }
- /* key material = prk */
- crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
- if (allocated_space) {
- PORT_ZFree(key_buf, allocated_space);
+ hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL;
+ }
+ hkdfParams.pSalt = params->pSalt;
+ hkdfParams.ulSaltLen = params->ulSaltLen;
+ hkdfParams.hSaltKey = CK_INVALID_HANDLE;
+ hkdfParams.pInfo = params->pInfo;
+ hkdfParams.ulInfoLen = params->ulInfoLen;
+ hkdfParams.prfHashMechanism = hashMech;
+
+ crv = sftk_HKDF(&hkdfParams, hSession, sourceKey,
+ att->attrib.pValue, att->attrib.ulValueLen,
+ key, NULL, keySize, PR_FALSE, isFIPS);
+ } break;
+ case CKM_HKDF_DERIVE:
+ case CKM_HKDF_DATA: /* only difference is the class of key */
+ if ((pMechanism->pParameter == NULL) ||
+ (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) {
+ crv = CKR_MECHANISM_PARAM_INVALID;
+ break;
}
+ crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter,
+ hSession, sourceKey, att->attrib.pValue,
+ att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE,
+ isFIPS);
break;
- } /* end of CKM_NSS_HKDF_* */
-
case CKM_NSS_JPAKE_ROUND2_SHA1:
hashType = HASH_AlgSHA1;
goto jpake2;
@@ -8172,7 +8612,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN))
crv = CKR_TEMPLATE_INCONSISTENT;
if (crv == CKR_OK)
- crv = sftk_DeriveSensitiveCheck(sourceKey, key);
+ crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
if (crv == CKR_OK)
crv = jpake_Round2(hashType,
(CK_NSS_JPAKERound2Params *)pMechanism->pParameter,
@@ -8208,6 +8648,19 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
sourceKey, key);
break;
+ case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */
+ case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
+ case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */
+ case CKM_SP800_108_COUNTER_KDF: /* fall through */
+ case CKM_SP800_108_FEEDBACK_KDF: /* fall through */
+ case CKM_SP800_108_DOUBLE_PIPELINE_KDF:
+ crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
+ if (crv != CKR_OK) {
+ break;
+ }
+
+ crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize);
+ break;
default:
crv = CKR_MECHANISM_INVALID;
}
diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h
index 51127a32a..2aabb37e4 100644
--- a/security/nss/lib/softoken/pkcs11i.h
+++ b/security/nss/lib/softoken/pkcs11i.h
@@ -117,6 +117,9 @@ typedef void (*SFTKDestroy)(void *, PRBool);
typedef void (*SFTKBegin)(void *);
typedef SECStatus (*SFTKCipher)(void *, void *, unsigned int *, unsigned int,
void *, unsigned int);
+typedef SECStatus (*SFTKAEADCipher)(void *, void *, unsigned int *,
+ unsigned int, void *, unsigned int,
+ void *, unsigned int, void *, unsigned int);
typedef SECStatus (*SFTKVerify)(void *, void *, unsigned int, void *, unsigned int);
typedef void (*SFTKHash)(void *, const void *, unsigned int);
typedef void (*SFTKEnd)(void *, void *, unsigned int *, unsigned int);
@@ -235,7 +238,11 @@ typedef enum {
SFTK_SIGN,
SFTK_SIGN_RECOVER,
SFTK_VERIFY,
- SFTK_VERIFY_RECOVER
+ SFTK_VERIFY_RECOVER,
+ SFTK_MESSAGE_ENCRYPT,
+ SFTK_MESSAGE_DECRYPT,
+ SFTK_MESSAGE_SIGN,
+ SFTK_MESSAGE_VERIFY
} SFTKContextType;
/** max block size of supported block ciphers */
@@ -272,6 +279,7 @@ struct SFTKSessionContextStr {
unsigned int cipherInfoLen;
CK_MECHANISM_TYPE currentMech;
SFTKCipher update;
+ SFTKAEADCipher aeadUpdate;
SFTKHash hashUpdate;
SFTKEnd end;
SFTKDestroy destroy;
@@ -665,6 +673,8 @@ struct sftk_MACCtxStr {
};
typedef struct sftk_MACCtxStr sftk_MACCtx;
+extern CK_NSS_MODULE_FUNCTIONS sftk_module_funcList;
+
SEC_BEGIN_PROTOS
/* shared functions between pkcs11.c and fipstokn.c */
@@ -673,20 +683,26 @@ extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS);
extern CK_RV nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS);
extern PRBool sftk_ForkReset(CK_VOID_PTR pReserved, CK_RV *crv);
extern CK_RV nsc_CommonGetSlotList(CK_BBOOL tokPresent,
- CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex);
+ CK_SLOT_ID_PTR pSlotList,
+ CK_ULONG_PTR pulCount,
+ unsigned int moduleIndex);
/* slot initialization, reinit, shutdown and destruction */
extern CK_RV SFTK_SlotInit(char *configdir, char *updatedir, char *updateID,
- sftk_token_parameters *params, int moduleIndex);
+ sftk_token_parameters *params,
+ unsigned int moduleIndex);
extern CK_RV SFTK_SlotReInit(SFTKSlot *slot, char *configdir,
char *updatedir, char *updateID,
- sftk_token_parameters *params, int moduleIndex);
+ sftk_token_parameters *params,
+ unsigned int moduleIndex);
extern CK_RV SFTK_DestroySlotData(SFTKSlot *slot);
extern CK_RV SFTK_ShutdownSlot(SFTKSlot *slot);
extern CK_RV sftk_CloseAllSessions(SFTKSlot *slot, PRBool logout);
/* internal utility functions used by pkcs11.c */
extern CK_RV sftk_MapCryptError(int error);
+extern CK_RV sftk_MapDecryptError(int error);
+extern CK_RV sftk_MapVerifyError(int error);
extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object,
CK_ATTRIBUTE_TYPE type);
extern void sftk_FreeAttribute(SFTKAttribute *attribute);
@@ -757,10 +773,28 @@ extern SFTKSession *sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify,
CK_VOID_PTR pApplication, CK_FLAGS flags);
extern void sftk_update_state(SFTKSlot *slot, SFTKSession *session);
extern void sftk_update_all_states(SFTKSlot *slot);
-extern void sftk_FreeContext(SFTKSessionContext *context);
extern void sftk_InitFreeLists(void);
extern void sftk_CleanupFreeLists(void);
+/*
+ * Helper functions to handle the session crypto contexts
+ */
+extern CK_RV sftk_InitGeneric(SFTKSession *session,
+ SFTKSessionContext **contextPtr,
+ SFTKContextType ctype, SFTKObject **keyPtr,
+ CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
+ CK_OBJECT_CLASS pubKeyType,
+ CK_ATTRIBUTE_TYPE operation);
+void sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
+ SFTKSessionContext *context);
+extern CK_RV sftk_GetContext(CK_SESSION_HANDLE handle,
+ SFTKSessionContext **contextPtr,
+ SFTKContextType type, PRBool needMulti,
+ SFTKSession **sessionPtr);
+extern void sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype,
+ SFTKSessionContext *context);
+extern void sftk_FreeContext(SFTKSessionContext *context);
+
extern NSSLOWKEYPublicKey *sftk_GetPubKey(SFTKObject *object,
CK_KEY_TYPE key_type, CK_RV *crvp);
extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object,
@@ -770,6 +804,8 @@ extern CK_RV sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privKey, CK_KEY_T
extern void sftk_FormatDESKey(unsigned char *key, int length);
extern PRBool sftk_CheckDESKey(unsigned char *key);
extern PRBool sftk_IsWeakKey(unsigned char *key, CK_KEY_TYPE key_type);
+extern void sftk_EncodeInteger(PRUint64 integer, CK_ULONG num_bits, CK_BBOOL littleEndian,
+ CK_BYTE_PTR output, CK_ULONG_PTR output_len);
/* ike and xcbc helpers */
extern CK_RV sftk_ike_prf(CK_SESSION_HANDLE hSession,
@@ -781,7 +817,8 @@ extern CK_RV sftk_ike1_prf(CK_SESSION_HANDLE hSession,
unsigned int keySize);
extern CK_RV sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession,
const SFTKAttribute *inKey,
- const CK_MECHANISM_TYPE *params, SFTKObject *outKey,
+ const CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *params,
+ SFTKObject *outKey,
unsigned int keySize);
extern CK_RV sftk_ike_prf_plus(CK_SESSION_HANDLE hSession,
const SFTKAttribute *inKey,
@@ -791,7 +828,7 @@ extern CK_RV sftk_aes_xcbc_new_keys(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE_PTR phKey,
unsigned char *k2, unsigned char *k3);
extern CK_RV sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen,
- int blockSize, const unsigned char *k2,
+ unsigned int blockSize, const unsigned char *k2,
const unsigned char *k3);
extern SECStatus sftk_fips_IKE_PowerUpSelfTests(void);
@@ -859,14 +896,40 @@ sftk_TLSPRFInit(SFTKSessionContext *context,
/* PKCS#11 MAC implementation. See sftk_MACCtxStr declaration above for
* calling semantics for these functions. */
+HASH_HashType sftk_HMACMechanismToHash(CK_MECHANISM_TYPE mech);
CK_RV sftk_MAC_Create(CK_MECHANISM_TYPE mech, SFTKObject *key, sftk_MACCtx **ret_ctx);
CK_RV sftk_MAC_Init(sftk_MACCtx *ctx, CK_MECHANISM_TYPE mech, SFTKObject *key);
CK_RV sftk_MAC_InitRaw(sftk_MACCtx *ctx, CK_MECHANISM_TYPE mech, const unsigned char *key, unsigned int key_len, PRBool isFIPS);
-CK_RV sftk_MAC_Update(sftk_MACCtx *ctx, CK_BYTE_PTR data, unsigned int data_len);
+CK_RV sftk_MAC_Update(sftk_MACCtx *ctx, const CK_BYTE *data, unsigned int data_len);
CK_RV sftk_MAC_Finish(sftk_MACCtx *ctx, CK_BYTE_PTR result, unsigned int *result_len, unsigned int max_result_len);
CK_RV sftk_MAC_Reset(sftk_MACCtx *ctx);
void sftk_MAC_Destroy(sftk_MACCtx *ctx, PRBool free_it);
+/* constant time helpers */
+unsigned int sftk_CKRVToMask(CK_RV rv);
+CK_RV sftk_CheckCBCPadding(CK_BYTE_PTR pBuf, unsigned int bufLen,
+ unsigned int blockSize, unsigned int *outPadSize);
+
+/* NIST 800-108 (kbkdf.c) implementations */
+extern CK_RV kbkdf_Dispatch(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, SFTKObject *base_key, SFTKObject *ret_key, CK_ULONG keySize);
+extern SECStatus sftk_fips_SP800_108_PowerUpSelfTests(void);
+
+/* export the HKDF function for use in PowerupSelfTests */
+CK_RV sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession,
+ SFTKObject *sourceKey, const unsigned char *sourceKeyBytes,
+ int sourceKeyLen, SFTKObject *key,
+ unsigned char *outKeyBytes, int keySize,
+ PRBool canBeData, PRBool isFIPS);
+
+char **NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args);
+
+/* dh verify functions */
+/* verify that dhPrime matches one of our known primes, and if so return
+ * it's subprime value */
+const SECItem *sftk_VerifyDH_Prime(SECItem *dhPrime);
+/* check if dhSubPrime claims dhPrime is a safe prime. */
+SECStatus sftk_IsSafePrime(SECItem *dhPrime, SECItem *dhSubPrime, PRBool *isSafe);
+
SEC_END_PROTOS
#endif /* _PKCS11I_H_ */
diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c
index 1f66e6f61..7d969a1bc 100644
--- a/security/nss/lib/softoken/pkcs11u.c
+++ b/security/nss/lib/softoken/pkcs11u.c
@@ -55,6 +55,38 @@ sftk_MapCryptError(int error)
}
return CKR_DEVICE_ERROR;
}
+
+/*
+ * functions which adjust the mapping based on different contexts
+ * (Decrypt or Verify).
+ */
+
+/* used by Decrypt and UnwrapKey (indirectly) and Decrypt message */
+CK_RV
+sftk_MapDecryptError(int error)
+{
+ switch (error) {
+ /* usually a padding error, or aead tag mismatch */
+ case SEC_ERROR_BAD_DATA:
+ return CKR_ENCRYPTED_DATA_INVALID;
+ default:
+ return sftk_MapCryptError(error);
+ }
+}
+
+/*
+ * return CKR_SIGNATURE_INVALID instead of CKR_DEVICE_ERROR by default for
+ * backward compatibilty.
+ */
+CK_RV
+sftk_MapVerifyError(int error)
+{
+ CK_RV crv = sftk_MapCryptError(error);
+ if (crv == CKR_DEVICE_ERROR)
+ crv = CKR_SIGNATURE_INVALID;
+ return crv;
+}
+
/*
* ******************** Attribute Utilities *******************************
*/
@@ -684,7 +716,6 @@ sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
case CKA_PUBLIC_EXPONENT:
case CKA_PRIVATE_EXPONENT:
case CKA_PRIME:
- case CKA_SUBPRIME:
case CKA_BASE:
case CKA_PRIME_1:
case CKA_PRIME_2:
@@ -694,7 +725,7 @@ sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
case CKA_VALUE_LEN:
case CKA_ALWAYS_SENSITIVE:
case CKA_NEVER_EXTRACTABLE:
- case CKA_NETSCAPE_DB:
+ case CKA_NSS_DB:
mtype = SFTK_NEVER;
break;
@@ -735,6 +766,11 @@ sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
mtype = (inClass == CKO_DATA) ? SFTK_ALWAYS : SFTK_NEVER;
break;
+ case CKA_SUBPRIME:
+ /* allow the CKA_SUBPRIME to be added to dh private keys */
+ mtype = (inClass == CKO_PRIVATE_KEY) ? SFTK_ALWAYS : SFTK_NEVER;
+ break;
+
case CKA_SUBJECT:
mtype = (inClass == CKO_CERTIFICATE) ? SFTK_NEVER : SFTK_ALWAYS;
break;
@@ -1249,7 +1285,7 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
SFTKTokenObject *to = sftk_narrowToTokenObject(object);
PORT_Assert(to);
#endif
- crv = sftkdb_DestroyObject(handle, object->handle);
+ crv = sftkdb_DestroyObject(handle, object->handle, object->objclass);
sftk_freeDB(handle);
}
return crv;
@@ -1310,7 +1346,7 @@ static const CK_ULONG ecPubKeyAttrsCount =
static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = {
CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT,
- CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB, CKA_PUBLIC_KEY_INFO
+ CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NSS_DB, CKA_PUBLIC_KEY_INFO
};
static const CK_ULONG commonPrivKeyAttrsCount =
sizeof(commonPrivKeyAttrs) / sizeof(commonPrivKeyAttrs[0]);
@@ -1354,13 +1390,13 @@ static const CK_ULONG trustAttrsCount =
sizeof(trustAttrs) / sizeof(trustAttrs[0]);
static const CK_ATTRIBUTE_TYPE smimeAttrs[] = {
- CKA_SUBJECT, CKA_NETSCAPE_EMAIL, CKA_NETSCAPE_SMIME_TIMESTAMP, CKA_VALUE
+ CKA_SUBJECT, CKA_NSS_EMAIL, CKA_NSS_SMIME_TIMESTAMP, CKA_VALUE
};
static const CK_ULONG smimeAttrsCount =
sizeof(smimeAttrs) / sizeof(smimeAttrs[0]);
static const CK_ATTRIBUTE_TYPE crlAttrs[] = {
- CKA_SUBJECT, CKA_VALUE, CKA_NETSCAPE_URL, CKA_NETSCAPE_KRL
+ CKA_SUBJECT, CKA_VALUE, CKA_NSS_URL, CKA_NSS_KRL
};
static const CK_ULONG crlAttrsCount =
sizeof(crlAttrs) / sizeof(crlAttrs[0]);
@@ -1554,15 +1590,15 @@ sftk_CopyTokenObject(SFTKObject *destObject, SFTKObject *srcObject)
crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs,
certAttrsCount);
break;
- case CKO_NETSCAPE_TRUST:
+ case CKO_NSS_TRUST:
crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs,
trustAttrsCount);
break;
- case CKO_NETSCAPE_SMIME:
+ case CKO_NSS_SMIME:
crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs,
smimeAttrsCount);
break;
- case CKO_NETSCAPE_CRL:
+ case CKO_NSS_CRL:
crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs,
crlAttrsCount);
break;
@@ -2010,3 +2046,76 @@ sftk_narrowToTokenObject(SFTKObject *obj)
{
return sftk_isToken(obj->handle) ? (SFTKTokenObject *)obj : NULL;
}
+
+/* Constant time helper functions */
+
+/* sftk_CKRVToMask returns, in constant time, a mask value of
+ * all ones if rv == CKR_OK. Otherwise it returns zero. */
+unsigned int
+sftk_CKRVToMask(CK_RV rv)
+{
+ PR_STATIC_ASSERT(CKR_OK == 0);
+ return ~PORT_CT_NOT_ZERO(rv);
+}
+
+/* sftk_CheckCBCPadding checks, in constant time, the padding validity and
+ * accordingly sets the pad length. */
+CK_RV
+sftk_CheckCBCPadding(CK_BYTE_PTR pBuf, unsigned int bufLen,
+ unsigned int blockSize, unsigned int *outPadSize)
+{
+ PORT_Assert(outPadSize);
+
+ unsigned int padSize = (unsigned int)pBuf[bufLen - 1];
+
+ /* If padSize <= blockSize, set goodPad to all-1s and all-0s otherwise.*/
+ unsigned int goodPad = PORT_CT_DUPLICATE_MSB_TO_ALL(~(blockSize - padSize));
+ /* padSize should not be 0 */
+ goodPad &= PORT_CT_NOT_ZERO(padSize);
+
+ unsigned int i;
+ for (i = 0; i < blockSize; i++) {
+ /* If i < padSize, set loopMask to all-1s and all-0s otherwise.*/
+ unsigned int loopMask = PORT_CT_DUPLICATE_MSB_TO_ALL(~(padSize - 1 - i));
+ /* Get the padding value (should be padSize) from buffer */
+ unsigned int padVal = pBuf[bufLen - 1 - i];
+ /* Update goodPad only if i < padSize */
+ goodPad &= PORT_CT_SEL(loopMask, ~(padVal ^ padSize), goodPad);
+ }
+
+ /* If any of the final padding bytes had the wrong value, one or more
+ * of the lower eight bits of |goodPad| will be cleared. We AND the
+ * bottom 8 bits together and duplicate the result to all the bits. */
+ goodPad &= goodPad >> 4;
+ goodPad &= goodPad >> 2;
+ goodPad &= goodPad >> 1;
+ goodPad <<= sizeof(goodPad) * 8 - 1;
+ goodPad = PORT_CT_DUPLICATE_MSB_TO_ALL(goodPad);
+
+ /* Set outPadSize to padSize or 0 */
+ *outPadSize = PORT_CT_SEL(goodPad, padSize, 0);
+ /* Return OK if the pad is valid */
+ return PORT_CT_SEL(goodPad, CKR_OK, CKR_ENCRYPTED_DATA_INVALID);
+}
+
+void
+sftk_EncodeInteger(PRUint64 integer, CK_ULONG num_bits, CK_BBOOL littleEndian,
+ CK_BYTE_PTR output, CK_ULONG_PTR output_len)
+{
+ if (output_len) {
+ *output_len = (num_bits / 8);
+ }
+
+ PR_ASSERT(num_bits > 0 && num_bits <= 64 && (num_bits % 8) == 0);
+
+ if (littleEndian == CK_TRUE) {
+ for (size_t offset = 0; offset < num_bits / 8; offset++) {
+ output[offset] = (unsigned char)((integer >> (offset * 8)) & 0xFF);
+ }
+ } else {
+ for (size_t offset = 0; offset < num_bits / 8; offset++) {
+ PRUint64 shift = num_bits - (offset + 1) * 8;
+ output[offset] = (unsigned char)((integer >> shift) & 0xFF);
+ }
+ }
+}
diff --git a/security/nss/lib/softoken/sdb.c b/security/nss/lib/softoken/sdb.c
index c84476100..50625ab94 100644
--- a/security/nss/lib/softoken/sdb.c
+++ b/security/nss/lib/softoken/sdb.c
@@ -90,6 +90,49 @@ typedef enum {
#define SDB_MAX_BUSY_RETRIES 10
/*
+ * known attributes
+ */
+static const CK_ATTRIBUTE_TYPE known_attributes[] = {
+ CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_APPLICATION,
+ CKA_VALUE, CKA_OBJECT_ID, CKA_CERTIFICATE_TYPE, CKA_ISSUER,
+ CKA_SERIAL_NUMBER, CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES, CKA_TRUSTED,
+ CKA_CERTIFICATE_CATEGORY, CKA_JAVA_MIDP_SECURITY_DOMAIN, CKA_URL,
+ CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CKA_HASH_OF_ISSUER_PUBLIC_KEY,
+ CKA_CHECK_VALUE, CKA_KEY_TYPE, CKA_SUBJECT, CKA_ID, CKA_SENSITIVE,
+ CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SIGN, CKA_SIGN_RECOVER,
+ CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE,
+ CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT,
+ CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT,
+ CKA_PUBLIC_KEY_INFO, CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS,
+ CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE,
+ CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE,
+ CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS,
+ CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_HW_FEATURE_TYPE,
+ CKA_RESET_ON_INIT, CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y,
+ CKA_RESOLUTION, CKA_CHAR_ROWS, CKA_CHAR_COLUMNS, CKA_COLOR,
+ CKA_BITS_PER_PIXEL, CKA_CHAR_SETS, CKA_ENCODING_METHODS, CKA_MIME_TYPES,
+ CKA_MECHANISM_TYPE, CKA_REQUIRED_CMS_ATTRIBUTES,
+ CKA_DEFAULT_CMS_ATTRIBUTES, CKA_SUPPORTED_CMS_ATTRIBUTES,
+ CKA_WRAP_TEMPLATE, CKA_UNWRAP_TEMPLATE, CKA_NSS_TRUST, CKA_NSS_URL,
+ CKA_NSS_EMAIL, CKA_NSS_SMIME_INFO, CKA_NSS_SMIME_TIMESTAMP,
+ CKA_NSS_PKCS8_SALT, CKA_NSS_PASSWORD_CHECK, CKA_NSS_EXPIRES,
+ CKA_NSS_KRL, CKA_NSS_PQG_COUNTER, CKA_NSS_PQG_SEED,
+ CKA_NSS_PQG_H, CKA_NSS_PQG_SEED_BITS, CKA_NSS_MODULE_SPEC,
+ CKA_NSS_OVERRIDE_EXTENSIONS, CKA_NSS_SERVER_DISTRUST_AFTER,
+ CKA_NSS_EMAIL_DISTRUST_AFTER, CKA_TRUST_DIGITAL_SIGNATURE,
+ CKA_TRUST_NON_REPUDIATION, CKA_TRUST_KEY_ENCIPHERMENT,
+ CKA_TRUST_DATA_ENCIPHERMENT, CKA_TRUST_KEY_AGREEMENT,
+ CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN, CKA_TRUST_SERVER_AUTH,
+ CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING, CKA_TRUST_EMAIL_PROTECTION,
+ CKA_TRUST_IPSEC_END_SYSTEM, CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER,
+ CKA_TRUST_TIME_STAMPING, CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH,
+ CKA_CERT_MD5_HASH, CKA_NSS_DB
+};
+
+static const int known_attributes_size = PR_ARRAY_SIZE(known_attributes);
+
+/*
* Note on use of sqlReadDB: Only one thread at a time may have an actual
* operation going on given sqlite3 * database. An operation is defined as
* the time from a sqlite3_prepare() until the sqlite3_finalize().
@@ -103,68 +146,26 @@ typedef enum {
* other operations like NSC_GetAttributeValue */
struct SDBPrivateStr {
- char *sqlDBName; /* invariant, path to this database */
- sqlite3 *sqlXactDB; /* access protected by dbMon, use protected
+ char *sqlDBName; /* invariant, path to this database */
+ sqlite3 *sqlXactDB; /* access protected by dbMon, use protected
* by the transaction. Current transaction db*/
- PRThread *sqlXactThread; /* protected by dbMon,
+ PRThread *sqlXactThread; /* protected by dbMon,
* current transaction thread */
- sqlite3 *sqlReadDB; /* use protected by dbMon, value invariant */
- PRIntervalTime lastUpdateTime; /* last time the cache was updated */
- PRIntervalTime updateInterval; /* how long the cache can go before it
+ sqlite3 *sqlReadDB; /* use protected by dbMon, value invariant */
+ PRIntervalTime lastUpdateTime; /* last time the cache was updated */
+ PRIntervalTime updateInterval; /* how long the cache can go before it
* must be updated again */
- sdbDataType type; /* invariant, database type */
- char *table; /* invariant, SQL table which contains the db */
- char *cacheTable; /* invariant, SQL table cache of db */
- PRMonitor *dbMon; /* invariant, monitor to protect
+ sdbDataType type; /* invariant, database type */
+ char *table; /* invariant, SQL table which contains the db */
+ char *cacheTable; /* invariant, SQL table cache of db */
+ PRMonitor *dbMon; /* invariant, monitor to protect
* sqlXact* fields, and use of the sqlReadDB */
+ CK_ATTRIBUTE_TYPE *schemaAttrs; /* Attribute columns that exist in the table. */
+ unsigned int numSchemaAttrs;
};
typedef struct SDBPrivateStr SDBPrivate;
-/*
- * known attributes
- */
-static const CK_ATTRIBUTE_TYPE known_attributes[] = {
- CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_APPLICATION,
- CKA_VALUE, CKA_OBJECT_ID, CKA_CERTIFICATE_TYPE, CKA_ISSUER,
- CKA_SERIAL_NUMBER, CKA_AC_ISSUER, CKA_OWNER, CKA_ATTR_TYPES, CKA_TRUSTED,
- CKA_CERTIFICATE_CATEGORY, CKA_JAVA_MIDP_SECURITY_DOMAIN, CKA_URL,
- CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CKA_HASH_OF_ISSUER_PUBLIC_KEY,
- CKA_CHECK_VALUE, CKA_KEY_TYPE, CKA_SUBJECT, CKA_ID, CKA_SENSITIVE,
- CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, CKA_SIGN, CKA_SIGN_RECOVER,
- CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_DERIVE, CKA_START_DATE, CKA_END_DATE,
- CKA_MODULUS, CKA_MODULUS_BITS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT,
- CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT,
- CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_PRIME_BITS,
- CKA_SUB_PRIME_BITS, CKA_VALUE_BITS, CKA_VALUE_LEN, CKA_EXTRACTABLE,
- CKA_LOCAL, CKA_NEVER_EXTRACTABLE, CKA_ALWAYS_SENSITIVE,
- CKA_KEY_GEN_MECHANISM, CKA_MODIFIABLE, CKA_EC_PARAMS,
- CKA_EC_POINT, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
- CKA_ALWAYS_AUTHENTICATE, CKA_WRAP_WITH_TRUSTED, CKA_WRAP_TEMPLATE,
- CKA_UNWRAP_TEMPLATE, CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT,
- CKA_HAS_RESET, CKA_PIXEL_X, CKA_PIXEL_Y, CKA_RESOLUTION, CKA_CHAR_ROWS,
- CKA_CHAR_COLUMNS, CKA_COLOR, CKA_BITS_PER_PIXEL, CKA_CHAR_SETS,
- CKA_ENCODING_METHODS, CKA_MIME_TYPES, CKA_MECHANISM_TYPE,
- CKA_REQUIRED_CMS_ATTRIBUTES, CKA_DEFAULT_CMS_ATTRIBUTES,
- CKA_SUPPORTED_CMS_ATTRIBUTES, CKA_NETSCAPE_URL, CKA_NETSCAPE_EMAIL,
- CKA_NETSCAPE_SMIME_INFO, CKA_NETSCAPE_SMIME_TIMESTAMP,
- CKA_NETSCAPE_PKCS8_SALT, CKA_NETSCAPE_PASSWORD_CHECK, CKA_NETSCAPE_EXPIRES,
- CKA_NETSCAPE_KRL, CKA_NETSCAPE_PQG_COUNTER, CKA_NETSCAPE_PQG_SEED,
- CKA_NETSCAPE_PQG_H, CKA_NETSCAPE_PQG_SEED_BITS, CKA_NETSCAPE_MODULE_SPEC,
- CKA_TRUST_DIGITAL_SIGNATURE, CKA_TRUST_NON_REPUDIATION,
- CKA_TRUST_KEY_ENCIPHERMENT, CKA_TRUST_DATA_ENCIPHERMENT,
- CKA_TRUST_KEY_AGREEMENT, CKA_TRUST_KEY_CERT_SIGN, CKA_TRUST_CRL_SIGN,
- CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_CODE_SIGNING,
- CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM,
- CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING,
- CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
- CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS,
- CKA_PUBLIC_KEY_INFO, CKA_NSS_SERVER_DISTRUST_AFTER, CKA_NSS_EMAIL_DISTRUST_AFTER
-};
-
-static int known_attributes_size = sizeof(known_attributes) /
- sizeof(known_attributes[0]);
-
/* Magic for an explicit NULL. NOTE: ideally this should be
* out of band data. Since it's not completely out of band, pick
* a value that has no meaning to any existing PKCS #11 attributes.
@@ -362,7 +363,7 @@ sdb_mapSQLError(sdbDataType type, int sqlerr)
case SQLITE_CANTOPEN:
case SQLITE_NOTFOUND:
/* NSS distiguishes between failure to open the cert and the key db */
- return type == SDB_CERT ? CKR_NETSCAPE_CERTDB_FAILED : CKR_NETSCAPE_KEYDB_FAILED;
+ return type == SDB_CERT ? CKR_NSS_CERTDB_FAILED : CKR_NSS_KEYDB_FAILED;
case SQLITE_IOERR:
return CKR_DEVICE_ERROR;
default:
@@ -400,8 +401,20 @@ sdb_measureAccess(const char *directory)
PRIntervalTime duration = PR_MillisecondsToInterval(33);
const char *doesntExistName = "_dOeSnotExist_.db";
char *temp, *tempStartOfFilename;
- size_t maxTempLen, maxFileNameLen, directoryLength;
-
+ size_t maxTempLen, maxFileNameLen, directoryLength, tmpdirLength = 0;
+#ifdef SDB_MEASURE_USE_TEMP_DIR
+ /*
+ * on some OS's and Filesystems, creating a bunch of files and deleting
+ * them messes up the systems's caching, but if we create the files in
+ * a temp directory which we later delete, then the cache gets cleared
+ * up. This code uses several OS dependent calls, and it's not clear
+ * that temp directory use won't mess up other filesystems and OS caching,
+ * so if you need this for your OS, you can turn on the
+ * 'SDB_MEASURE_USE_TEMP_DIR' define in coreconf
+ */
+ const char template[] = "dbTemp.XXXXXX";
+ tmpdirLength = sizeof(template);
+#endif
/* no directory, just return one */
if (directory == NULL) {
return 1;
@@ -412,24 +425,39 @@ sdb_measureAccess(const char *directory)
directoryLength = strlen(directory);
- maxTempLen = directoryLength + strlen(doesntExistName) + 1 /* potential additional separator char */
- + 11 /* max chars for 32 bit int plus potential sign */
- + 1; /* zero terminator */
+ maxTempLen = directoryLength + 1 /* dirname + / */
+ + tmpdirLength /* tmpdirname includes / */
+ + strlen(doesntExistName) /* filename base */
+ + 11 /* max chars for 32 bit int plus potential sign */
+ + 1; /* zero terminator */
- temp = PORT_Alloc(maxTempLen);
+ temp = PORT_ZAlloc(maxTempLen);
if (!temp) {
return 1;
}
/* We'll copy directory into temp just once, then ensure it ends
- * with the directory separator, then remember the position after
- * the separator, and calculate the number of remaining bytes. */
+ * with the directory separator. */
strcpy(temp, directory);
if (directory[directoryLength - 1] != PR_GetDirectorySeparator()) {
temp[directoryLength++] = PR_GetDirectorySeparator();
}
- tempStartOfFilename = temp + directoryLength;
+
+#ifdef SDB_MEASURE_USE_TEMP_DIR
+ /* add the template for a temporary subdir, and create it */
+ strcat(temp, template);
+ if (!mkdtemp(temp)) {
+ PORT_Free(temp);
+ return 1;
+ }
+ /* and terminate that tmp subdir with a / */
+ strcat(temp, "/");
+#endif
+
+ /* Remember the position after the last separator, and calculate the
+ * number of remaining bytes. */
+ tempStartOfFilename = temp + directoryLength + tmpdirLength;
maxFileNameLen = maxTempLen - directoryLength;
/* measure number of Access operations that can be done in 33 milliseconds
@@ -453,6 +481,12 @@ sdb_measureAccess(const char *directory)
break;
}
+#ifdef SDB_MEASURE_USE_TEMP_DIR
+ /* turn temp back into our tmpdir path by removing doesntExistName, and
+ * remove the tmp dir */
+ *tempStartOfFilename = '\0';
+ (void)rmdir(temp);
+#endif
PORT_Free(temp);
/* always return 1 or greater */
@@ -858,9 +892,9 @@ sdb_FindObjectsFinal(SDB *sdb, SDBFind *sdbFind)
return sdb_mapSQLError(sdb_p->type, sqlerr);
}
-CK_RV
-sdb_GetAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
- CK_ATTRIBUTE *template, CK_ULONG count)
+static CK_RV
+sdb_GetValidAttributeValueNoLock(SDB *sdb, CK_OBJECT_HANDLE object_id,
+ CK_ATTRIBUTE *template, CK_ULONG count)
{
SDBPrivate *sdb_p = sdb->private;
sqlite3 *sqlDB = NULL;
@@ -992,19 +1026,109 @@ loser:
return error;
}
+/* NOTE: requires sdb_p->schemaAttrs to be sorted asc. */
+inline static PRBool
+sdb_attributeExists(SDB *sdb, CK_ATTRIBUTE_TYPE attr)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ int first = 0;
+ int last = (int)sdb_p->numSchemaAttrs - 1;
+ while (last >= first) {
+ int mid = first + (last - first) / 2;
+ if (sdb_p->schemaAttrs[mid] == attr) {
+ return PR_TRUE;
+ }
+ if (attr > sdb_p->schemaAttrs[mid]) {
+ first = mid + 1;
+ } else {
+ last = mid - 1;
+ }
+ }
+
+ return PR_FALSE;
+}
+
CK_RV
sdb_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE object_id,
CK_ATTRIBUTE *template, CK_ULONG count)
{
- CK_RV crv;
+ CK_RV crv = CKR_OK;
+ unsigned int tmplIdx;
+ unsigned int resIdx = 0;
+ unsigned int validCount = 0;
+ unsigned int i;
if (count == 0) {
- return CKR_OK;
+ return crv;
+ }
+
+ CK_ATTRIBUTE *validTemplate;
+ PRBool invalidExists = PR_FALSE;
+ for (tmplIdx = 0; tmplIdx < count; tmplIdx++) {
+ if (!sdb_attributeExists(sdb, template[tmplIdx].type)) {
+ template[tmplIdx].ulValueLen = -1;
+ crv = CKR_ATTRIBUTE_TYPE_INVALID;
+ invalidExists = PR_TRUE;
+ break;
+ }
+ }
+
+ if (!invalidExists) {
+ validTemplate = template;
+ validCount = count;
+ } else {
+ /* Create a new template containing only the valid subset of
+ * input |template|, and query with that. */
+ validCount = tmplIdx;
+ validTemplate = malloc(sizeof(CK_ATTRIBUTE) * count);
+ if (!validTemplate) {
+ return CKR_HOST_MEMORY;
+ }
+ /* Copy in what we already know is valid. */
+ for (i = 0; i < validCount; i++) {
+ validTemplate[i] = template[i];
+ }
+
+ /* tmplIdx was left at the index of the first invalid
+ * attribute, which has been handled. We only need to
+ * deal with the remainder. */
+ tmplIdx++;
+ for (; tmplIdx < count; tmplIdx++) {
+ if (sdb_attributeExists(sdb, template[tmplIdx].type)) {
+ validTemplate[validCount++] = template[tmplIdx];
+ } else {
+ template[tmplIdx].ulValueLen = -1;
+ }
+ }
+ }
+
+ if (validCount) {
+ LOCK_SQLITE()
+ CK_RV crv2 = sdb_GetValidAttributeValueNoLock(sdb, object_id, validTemplate, validCount);
+ UNLOCK_SQLITE()
+
+ /* If an invalid attribute was removed above, let
+ * the caller know. Any other error from the actual
+ * query should propogate. */
+ crv = (crv2 == CKR_OK) ? crv : crv2;
+ }
+
+ if (invalidExists) {
+ /* Copy out valid lengths. */
+ tmplIdx = 0;
+ for (resIdx = 0; resIdx < validCount; resIdx++) {
+ for (; tmplIdx < count; tmplIdx++) {
+ if (template[tmplIdx].type != validTemplate[resIdx].type) {
+ continue;
+ }
+ template[tmplIdx].ulValueLen = validTemplate[resIdx].ulValueLen;
+ tmplIdx++;
+ break;
+ }
+ }
+ free(validTemplate);
}
- LOCK_SQLITE()
- crv = sdb_GetAttributeValueNoLock(sdb, object_id, template, count);
- UNLOCK_SQLITE()
return crv;
}
@@ -1115,7 +1239,7 @@ sdb_objectExists(SDB *sdb, CK_OBJECT_HANDLE candidate)
CK_RV crv;
CK_ATTRIBUTE template = { CKA_LABEL, NULL, 0 };
- crv = sdb_GetAttributeValueNoLock(sdb, candidate, &template, 1);
+ crv = sdb_GetValidAttributeValueNoLock(sdb, candidate, &template, 1);
if (crv == CKR_OBJECT_HANDLE_INVALID) {
return PR_FALSE;
}
@@ -1161,6 +1285,19 @@ sdb_getObjectId(SDB *sdb)
return CK_INVALID_HANDLE;
}
+CK_RV
+sdb_GetNewObjectID(SDB *sdb, CK_OBJECT_HANDLE *object)
+{
+ CK_OBJECT_HANDLE id;
+
+ id = sdb_getObjectId(sdb);
+ if (id == CK_INVALID_HANDLE) {
+ return CKR_DEVICE_MEMORY; /* basically we ran out of resources */
+ }
+ *object = id;
+ return CKR_OK;
+}
+
static const char CREATE_CMD[] = "INSERT INTO %s (id%s) VALUES($ID%s);";
CK_RV
sdb_CreateObject(SDB *sdb, CK_OBJECT_HANDLE *object_id,
@@ -1268,10 +1405,13 @@ loser:
return error;
}
+/*
+ * Generic destroy that can destroy metadata or objects
+ */
static const char DESTROY_CMD[] = "DELETE FROM %s WHERE (id=$ID);";
-
CK_RV
-sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
+sdb_destroyAnyObject(SDB *sdb, const char *table,
+ CK_OBJECT_HANDLE object_id, const char *string_id)
{
SDBPrivate *sdb_p = sdb->private;
sqlite3 *sqlDB = NULL;
@@ -1290,7 +1430,7 @@ sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
if (error != CKR_OK) {
goto loser;
}
- newStr = sqlite3_mprintf(DESTROY_CMD, sdb_p->table);
+ newStr = sqlite3_mprintf(DESTROY_CMD, table);
if (newStr == NULL) {
error = CKR_HOST_MEMORY;
goto loser;
@@ -1299,7 +1439,12 @@ sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
sqlite3_free(newStr);
if (sqlerr != SQLITE_OK)
goto loser;
- sqlerr = sqlite3_bind_int(stmt, 1, object_id);
+ if (string_id == NULL) {
+ sqlerr = sqlite3_bind_int(stmt, 1, object_id);
+ } else {
+ sqlerr = sqlite3_bind_text(stmt, 1, string_id,
+ PORT_Strlen(string_id), SQLITE_STATIC);
+ }
if (sqlerr != SQLITE_OK)
goto loser;
@@ -1328,6 +1473,19 @@ loser:
return error;
}
+CK_RV
+sdb_DestroyObject(SDB *sdb, CK_OBJECT_HANDLE object_id)
+{
+ SDBPrivate *sdb_p = sdb->private;
+ return sdb_destroyAnyObject(sdb, sdb_p->table, object_id, NULL);
+}
+
+CK_RV
+sdb_DestroyMetaData(SDB *sdb, const char *id)
+{
+ return sdb_destroyAnyObject(sdb, "metaData", 0, id);
+}
+
static const char BEGIN_CMD[] = "BEGIN IMMEDIATE TRANSACTION;";
/*
@@ -1725,6 +1883,7 @@ sdb_Close(SDB *sdb)
if (sdb_p->dbMon) {
PR_DestroyMonitor(sdb_p->dbMon);
}
+ free(sdb_p->schemaAttrs);
free(sdb_p);
free(sdb);
return sdb_mapSQLError(type, sqlerr);
@@ -1762,6 +1921,18 @@ sdb_SetForkState(PRBool forked)
* interface, we will need to set it and reset it from here */
}
+static int
+sdb_attributeComparator(const void *a, const void *b)
+{
+ if (*(CK_ATTRIBUTE_TYPE *)a < *(CK_ATTRIBUTE_TYPE *)b) {
+ return -1;
+ }
+ if (*(CK_ATTRIBUTE_TYPE *)a > *(CK_ATTRIBUTE_TYPE *)b) {
+ return 1;
+ }
+ return 0;
+}
+
/*
* initialize a single database
*/
@@ -1775,6 +1946,7 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
int i;
char *initStr = NULL;
char *newStr;
+ char *queryStr = NULL;
int inTransaction = 0;
SDB *sdb = NULL;
SDBPrivate *sdb_p = NULL;
@@ -2028,7 +2200,85 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
}
sdb = (SDB *)malloc(sizeof(SDB));
+ if (!sdb) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
sdb_p = (SDBPrivate *)malloc(sizeof(SDBPrivate));
+ if (!sdb_p) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+
+ /* Cache the attributes that are held in the table, so we can later check
+ * that queried attributes actually exist. We don't assume the schema
+ * to be exactly |known_attributes|, as it may change over time. */
+ sdb_p->schemaAttrs = NULL;
+ if (!PORT_Strcmp("nssPublic", table) ||
+ !PORT_Strcmp("nssPrivate", table)) {
+ sqlite3_stmt *stmt = NULL;
+ int retry = 0;
+ unsigned int backedAttrs = 0;
+
+ /* Can't bind parameters to a PRAGMA. */
+ queryStr = sqlite3_mprintf("PRAGMA table_info(%s);", table);
+ if (queryStr == NULL) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ sqlerr = sqlite3_prepare_v2(sqlDB, queryStr, -1, &stmt, NULL);
+ sqlite3_free(queryStr);
+ queryStr = NULL;
+ if (sqlerr != SQLITE_OK) {
+ goto loser;
+ }
+ unsigned int schemaAttrsCapacity = known_attributes_size;
+ sdb_p->schemaAttrs = malloc(schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE));
+ if (!sdb_p->schemaAttrs) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ do {
+ sqlerr = sqlite3_step(stmt);
+ if (sqlerr == SQLITE_BUSY) {
+ PR_Sleep(SDB_BUSY_RETRY_TIME);
+ }
+ if (sqlerr == SQLITE_ROW) {
+ if (backedAttrs == schemaAttrsCapacity) {
+ schemaAttrsCapacity += known_attributes_size;
+ sdb_p->schemaAttrs = realloc(sdb_p->schemaAttrs,
+ schemaAttrsCapacity * sizeof(CK_ATTRIBUTE_TYPE));
+ if (!sdb_p->schemaAttrs) {
+ error = CKR_HOST_MEMORY;
+ goto loser;
+ }
+ }
+ /* Record the ULONG attribute value. */
+ char *val = (char *)sqlite3_column_text(stmt, 1);
+ if (val && val[0] == 'a') {
+ CK_ATTRIBUTE_TYPE attr = strtoul(&val[1], NULL, 16);
+ sdb_p->schemaAttrs[backedAttrs++] = attr;
+ }
+ }
+ } while (!sdb_done(sqlerr, &retry));
+ if (sqlerr != SQLITE_DONE) {
+ goto loser;
+ }
+ sqlerr = sqlite3_reset(stmt);
+ if (sqlerr != SQLITE_OK) {
+ goto loser;
+ }
+ sqlerr = sqlite3_finalize(stmt);
+ if (sqlerr != SQLITE_OK) {
+ goto loser;
+ }
+
+ sdb_p->numSchemaAttrs = backedAttrs;
+
+ /* Sort these once so we can shortcut invalid attribute searches. */
+ qsort(sdb_p->schemaAttrs, sdb_p->numSchemaAttrs,
+ sizeof(CK_ATTRIBUTE_TYPE), sdb_attributeComparator);
+ }
/* invariant fields */
sdb_p->sqlDBName = PORT_Strdup(dbname);
@@ -2044,7 +2294,7 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
sdb_p->sqlXactDB = NULL;
sdb_p->sqlXactThread = NULL;
sdb->private = sdb_p;
- sdb->version = 0;
+ sdb->version = 1;
sdb->sdb_flags = inFlags | SDB_HAS_META;
sdb->app_private = NULL;
sdb->sdb_FindObjectsInit = sdb_FindObjectsInit;
@@ -2056,12 +2306,14 @@ sdb_init(char *dbname, char *table, sdbDataType type, int *inUpdate,
sdb->sdb_DestroyObject = sdb_DestroyObject;
sdb->sdb_GetMetaData = sdb_GetMetaData;
sdb->sdb_PutMetaData = sdb_PutMetaData;
+ sdb->sdb_DestroyMetaData = sdb_DestroyMetaData;
sdb->sdb_Begin = sdb_Begin;
sdb->sdb_Commit = sdb_Commit;
sdb->sdb_Abort = sdb_Abort;
sdb->sdb_Reset = sdb_Reset;
sdb->sdb_Close = sdb_Close;
sdb->sdb_SetForkState = sdb_SetForkState;
+ sdb->sdb_GetNewObjectID = sdb_GetNewObjectID;
if (inTransaction) {
sqlerr = sqlite3_exec(sqlDB, COMMIT_CMD, NULL, 0, NULL);
@@ -2087,6 +2339,9 @@ loser:
free(sdb);
}
if (sdb_p) {
+ if (sdb_p->schemaAttrs) {
+ free(sdb_p->schemaAttrs);
+ }
free(sdb_p);
}
if (sqlDB) {
diff --git a/security/nss/lib/softoken/sdb.h b/security/nss/lib/softoken/sdb.h
index 8ff254bf7..931be826c 100644
--- a/security/nss/lib/softoken/sdb.h
+++ b/security/nss/lib/softoken/sdb.h
@@ -75,6 +75,10 @@ struct SDBStr {
CK_RV(*sdb_Close)
(SDB *sdb);
void (*sdb_SetForkState)(PRBool forked);
+ CK_RV(*sdb_GetNewObjectID)
+ (SDB *db, CK_OBJECT_HANDLE *object);
+ CK_RV(*sdb_DestroyMetaData)
+ (SDB *db, const char *id);
};
CK_RV s_open(const char *directory, const char *certPrefix,
diff --git a/security/nss/lib/softoken/sftkdb.c b/security/nss/lib/softoken/sftkdb.c
index 61cb2ce8b..a1a723fe8 100644
--- a/security/nss/lib/softoken/sftkdb.c
+++ b/security/nss/lib/softoken/sftkdb.c
@@ -245,21 +245,44 @@ sftkdb_TypeString(SFTKDBHandle *handle)
* function will fail with CKR_BUFFER_TOO_SMALL.
*/
static CK_RV
-sftkdb_getAttributeSignature(SFTKDBHandle *handle, SFTKDBHandle *keyHandle,
+sftkdb_getRawAttributeSignature(SFTKDBHandle *handle, SDB *db,
+ CK_OBJECT_HANDLE objectID,
+ CK_ATTRIBUTE_TYPE type,
+ SECItem *signText)
+{
+ char id[30];
+ CK_RV crv;
+
+ sprintf(id, SFTKDB_META_SIG_TEMPLATE,
+ sftkdb_TypeString(handle),
+ (unsigned int)objectID, (unsigned int)type);
+
+ crv = (*db->sdb_GetMetaData)(db, id, signText, NULL);
+ return crv;
+}
+
+CK_RV
+sftkdb_GetAttributeSignature(SFTKDBHandle *handle, SFTKDBHandle *keyHandle,
CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE type,
SECItem *signText)
{
- SDB *db;
+ SDB *db = SFTK_GET_SDB(keyHandle);
+ return sftkdb_getRawAttributeSignature(handle, db, objectID, type, signText);
+}
+
+CK_RV
+sftkdb_DestroyAttributeSignature(SFTKDBHandle *handle, SDB *db,
+ CK_OBJECT_HANDLE objectID,
+ CK_ATTRIBUTE_TYPE type)
+{
char id[30];
CK_RV crv;
- db = SFTK_GET_SDB(keyHandle);
-
sprintf(id, SFTKDB_META_SIG_TEMPLATE,
sftkdb_TypeString(handle),
(unsigned int)objectID, (unsigned int)type);
- crv = (*db->sdb_GetMetaData)(db, id, signText, NULL);
+ crv = (*db->sdb_DestroyMetaData)(db, id);
return crv;
}
@@ -363,7 +386,10 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
crv = CKR_USER_NOT_LOGGED_IN;
continue;
}
- rv = sftkdb_DecryptAttribute(&handle->passwordKey,
+ rv = sftkdb_DecryptAttribute(handle,
+ &handle->passwordKey,
+ objectID,
+ ntemplate[i].type,
&cipherText, &plainText);
PZ_Unlock(handle->passwordLock);
if (rv != SECSuccess) {
@@ -389,6 +415,7 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
/* make sure signed attributes are valid */
if (checkSig && sftkdb_isAuthenticatedAttribute(ntemplate[i].type)) {
SECStatus rv;
+ CK_RV local_crv;
SECItem signText;
SECItem plainText;
unsigned char signData[SDB_MAX_META_DATA_LEN];
@@ -396,12 +423,17 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
signText.data = signData;
signText.len = sizeof(signData);
- rv = sftkdb_getAttributeSignature(handle, keyHandle,
- objectID, ntemplate[i].type, &signText);
- if (rv != SECSuccess) {
+ /* Use a local variable so that we don't clobber any already
+ * set error. This function returns either CKR_OK or the last
+ * found error in the template */
+ local_crv = sftkdb_GetAttributeSignature(handle, keyHandle,
+ objectID,
+ ntemplate[i].type,
+ &signText);
+ if (local_crv != CKR_OK) {
PORT_Memset(template[i].pValue, 0, template[i].ulValueLen);
template[i].ulValueLen = -1;
- crv = CKR_DATA_INVALID; /* better error code? */
+ crv = local_crv;
continue;
}
@@ -421,7 +453,8 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *template, CK_OBJECT_HANDLE objectID,
continue;
}
- rv = sftkdb_VerifyAttribute(&keyHandle->passwordKey,
+ rv = sftkdb_VerifyAttribute(keyHandle,
+ &keyHandle->passwordKey,
objectID, ntemplate[i].type,
&plainText, &signText);
PZ_Unlock(keyHandle->passwordLock);
@@ -529,7 +562,8 @@ sftk_signTemplate(PLArenaPool *arena, SFTKDBHandle *handle,
crv = CKR_USER_NOT_LOGGED_IN;
goto loser;
}
- rv = sftkdb_SignAttribute(arena, &keyHandle->passwordKey,
+ rv = sftkdb_SignAttribute(arena, keyHandle, keyTarget,
+ &keyHandle->passwordKey,
keyHandle->defaultIterationCount,
objectID, template[i].type,
&plainText, &signText);
@@ -538,10 +572,9 @@ sftk_signTemplate(PLArenaPool *arena, SFTKDBHandle *handle,
crv = CKR_GENERAL_ERROR; /* better error code here? */
goto loser;
}
- rv = sftkdb_PutAttributeSignature(handle, keyTarget,
- objectID, template[i].type, signText);
- if (rv != SECSuccess) {
- crv = CKR_GENERAL_ERROR; /* better error code here? */
+ crv = sftkdb_PutAttributeSignature(handle, keyTarget, objectID,
+ template[i].type, signText);
+ if (crv != CKR_OK) {
goto loser;
}
}
@@ -586,10 +619,56 @@ loser:
return crv;
}
+static CK_RV
+sftkdb_fixupSignatures(SFTKDBHandle *handle,
+ SDB *db, CK_OBJECT_HANDLE oldID, CK_OBJECT_HANDLE newID,
+ CK_ATTRIBUTE *ptemplate, CK_ULONG max_attributes)
+{
+ unsigned int i;
+ CK_RV crv = CKR_OK;
+
+ /* if we don't have a meta table, we didn't write any signature objects */
+ if ((db->sdb_flags & SDB_HAS_META) == 0) {
+ return CKR_OK;
+ }
+ for (i = 0; i < max_attributes; i++) {
+ CK_ATTRIBUTE *att = &ptemplate[i];
+ CK_ATTRIBUTE_TYPE type = att->type;
+ if (sftkdb_isPrivateAttribute(type)) {
+ /* move the signature from one object handle to another and delete
+ * the old entry */
+ SECItem signature;
+ unsigned char signData[SDB_MAX_META_DATA_LEN];
+
+ signature.data = signData;
+ signature.len = sizeof(signData);
+ crv = sftkdb_getRawAttributeSignature(handle, db, oldID, type,
+ &signature);
+ if (crv != CKR_OK) {
+ /* NOTE: if we ever change our default write from AES_CBC
+ * to AES_KW, We'll need to change this to a continue as
+ * we won't need the integrity record for AES_KW */
+ break;
+ }
+ crv = sftkdb_PutAttributeSignature(handle, db, newID, type,
+ &signature);
+ if (crv != CKR_OK) {
+ break;
+ }
+ /* now get rid of the old one */
+ crv = sftkdb_DestroyAttributeSignature(handle, db, oldID, type);
+ if (crv != CKR_OK) {
+ break;
+ }
+ }
+ }
+ return crv;
+}
+
CK_ATTRIBUTE *
sftk_ExtractTemplate(PLArenaPool *arena, SFTKObject *object,
- SFTKDBHandle *handle, CK_ULONG *pcount,
- CK_RV *crv)
+ SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID,
+ SDB *db, CK_ULONG *pcount, CK_RV *crv)
{
unsigned int count;
CK_ATTRIBUTE *template;
@@ -663,8 +742,11 @@ sftk_ExtractTemplate(PLArenaPool *arena, SFTKObject *object,
*crv = CKR_USER_NOT_LOGGED_IN;
break;
}
- rv = sftkdb_EncryptAttribute(arena, &handle->passwordKey,
+ rv = sftkdb_EncryptAttribute(arena, handle, db,
+ &handle->passwordKey,
handle->defaultIterationCount,
+ objectID,
+ tp->type,
&plainText, &cipherText);
PZ_Unlock(handle->passwordLock);
if (rv == SECSuccess) {
@@ -1111,7 +1193,7 @@ sftkdb_write(SFTKDBHandle *handle, SFTKObject *object,
CK_RV crv;
SDB *db;
PRBool inTransaction = PR_FALSE;
- CK_OBJECT_HANDLE id;
+ CK_OBJECT_HANDLE id, candidateID;
*objectID = CK_INVALID_HANDLE;
@@ -1136,16 +1218,21 @@ sftkdb_write(SFTKDBHandle *handle, SFTKObject *object,
return CKR_HOST_MEMORY;
}
- template = sftk_ExtractTemplate(arena, object, handle, &count, &crv);
- if (!template) {
+ crv = (*db->sdb_Begin)(db);
+ if (crv != CKR_OK) {
goto loser;
}
+ inTransaction = PR_TRUE;
- crv = (*db->sdb_Begin)(db);
+ crv = (*db->sdb_GetNewObjectID)(db, &candidateID);
if (crv != CKR_OK) {
goto loser;
}
- inTransaction = PR_TRUE;
+
+ template = sftk_ExtractTemplate(arena, object, handle, candidateID, db, &count, &crv);
+ if (!template) {
+ goto loser;
+ }
/*
* We want to make the base database as free from object specific knowledge
@@ -1174,16 +1261,23 @@ sftkdb_write(SFTKDBHandle *handle, SFTKObject *object,
goto loser;
}
if (id == CK_INVALID_HANDLE) {
+ *objectID = candidateID;
crv = sftkdb_CreateObject(arena, handle, db, objectID, template, count);
} else {
/* object already exists, modify it's attributes */
*objectID = id;
+ /* The object ID changed from our candidate, we need to move any
+ * signature attribute signatures to the new object ID. */
+ crv = sftkdb_fixupSignatures(handle, db, candidateID, id,
+ template, count);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
crv = sftkdb_setAttributeValue(arena, handle, db, id, template, count);
}
if (crv != CKR_OK) {
goto loser;
}
-
crv = (*db->sdb_Commit)(db);
inTransaction = PR_FALSE;
@@ -1413,7 +1507,8 @@ loser:
}
CK_RV
-sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID)
+sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID,
+ CK_OBJECT_CLASS objclass)
{
CK_RV crv = CKR_OK;
SDB *db;
@@ -1423,6 +1518,7 @@ sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID)
}
db = SFTK_GET_SDB(handle);
objectID &= SFTK_OBJ_ID_MASK;
+
crv = (*db->sdb_Begin)(db);
if (crv != CKR_OK) {
goto loser;
@@ -1431,6 +1527,51 @@ sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE objectID)
if (crv != CKR_OK) {
goto loser;
}
+ /* if the database supports meta data, delete any old signatures
+ * that we may have added */
+ if ((db->sdb_flags & SDB_HAS_META) == SDB_HAS_META) {
+ SDB *keydb = db;
+ if (handle->type == SFTK_KEYDB_TYPE) {
+ /* delete any private attribute signatures that might exist */
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_VALUE);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_PRIVATE_EXPONENT);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_PRIME_1);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_PRIME_2);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_EXPONENT_1);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_EXPONENT_2);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_COEFFICIENT);
+ } else {
+ keydb = SFTK_GET_SDB(handle->peerDB);
+ }
+ /* now destroy any authenticated attributes that may exist */
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_MODULUS);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_PUBLIC_EXPONENT);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_CERT_SHA1_HASH);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_CERT_MD5_HASH);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_TRUST_SERVER_AUTH);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_TRUST_CLIENT_AUTH);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_TRUST_EMAIL_PROTECTION);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_TRUST_CODE_SIGNING);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_TRUST_STEP_UP_APPROVED);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_NSS_OVERRIDE_EXTENSIONS);
+ }
crv = (*db->sdb_Commit)(db);
loser:
if (crv != CKR_OK) {
@@ -1593,7 +1734,7 @@ static const CK_ATTRIBUTE_TYPE known_attributes[] = {
CKA_TRUST_EMAIL_PROTECTION, CKA_TRUST_IPSEC_END_SYSTEM,
CKA_TRUST_IPSEC_TUNNEL, CKA_TRUST_IPSEC_USER, CKA_TRUST_TIME_STAMPING,
CKA_TRUST_STEP_UP_APPROVED, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
- CKA_NETSCAPE_DB, CKA_NETSCAPE_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS,
+ CKA_NSS_DB, CKA_NSS_TRUST, CKA_NSS_OVERRIDE_EXTENSIONS,
CKA_PUBLIC_KEY_INFO
};
@@ -2144,6 +2285,56 @@ sftkdb_updateObjectTemplate(PLArenaPool *arena, SDB *db,
return SFTKDB_ADD_OBJECT;
}
+static CK_RV
+sftkdb_updateIntegrity(PLArenaPool *arena, SFTKDBHandle *handle,
+ SDB *source, CK_OBJECT_HANDLE sourceID,
+ SDB *target, CK_OBJECT_HANDLE targetID,
+ CK_ATTRIBUTE *ptemplate, CK_ULONG max_attributes)
+{
+ unsigned int i;
+ CK_RV global_crv = CKR_OK;
+
+ /* if the target doesn't have META data, don't need to do anything */
+ if ((target->sdb_flags & SDB_HAS_META) == 0) {
+ return CKR_OK;
+ }
+ /* if the source doesn't have meta data, then the record won't require
+ * integrity */
+ if ((source->sdb_flags & SDB_HAS_META) == 0) {
+ return CKR_OK;
+ }
+ for (i = 0; i < max_attributes; i++) {
+ CK_ATTRIBUTE *att = &ptemplate[i];
+ CK_ATTRIBUTE_TYPE type = att->type;
+ if (sftkdb_isPrivateAttribute(type)) {
+ /* copy integrity signatures associated with this record (if any) */
+ SECItem signature;
+ unsigned char signData[SDB_MAX_META_DATA_LEN];
+ CK_RV crv;
+
+ signature.data = signData;
+ signature.len = sizeof(signData);
+ crv = sftkdb_getRawAttributeSignature(handle, source, sourceID, type,
+ &signature);
+ if (crv != CKR_OK) {
+ /* old databases don't have signature IDs because they are
+ * 3DES encrypted. Since we know not to look for integrity
+ * for 3DES records it's OK not to find one here. A new record
+ * will be created when we reencrypt using AES CBC */
+ continue;
+ }
+ crv = sftkdb_PutAttributeSignature(handle, target, targetID, type,
+ &signature);
+ if (crv != CKR_OK) {
+ /* we had a signature in the source db, but we couldn't store
+ * it in the target, remember the error so we can report it. */
+ global_crv = crv;
+ }
+ }
+ }
+ return global_crv;
+}
+
#define MAX_ATTRIBUTES 500
static CK_RV
sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
@@ -2156,6 +2347,7 @@ sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
SDB *source = handle->update;
SDB *target = handle->db;
unsigned int i;
+ CK_OBJECT_HANDLE newID = CK_INVALID_HANDLE;
CK_RV crv;
PLArenaPool *arena = NULL;
@@ -2202,20 +2394,20 @@ sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
* database.
*/
if (!handle->updateID) {
- crv = sftkdb_CreateObject(arena, handle, target, &id,
+ crv = sftkdb_CreateObject(arena, handle, target, &newID,
ptemplate, max_attributes);
} else {
sftkdbUpdateStatus update_status;
update_status = sftkdb_updateObjectTemplate(arena, target,
- objectType, ptemplate, &max_attributes, &id);
+ objectType, ptemplate, &max_attributes, &newID);
switch (update_status) {
case SFTKDB_ADD_OBJECT:
- crv = sftkdb_CreateObject(arena, handle, target, &id,
+ crv = sftkdb_CreateObject(arena, handle, target, &newID,
ptemplate, max_attributes);
break;
case SFTKDB_MODIFY_OBJECT:
crv = sftkdb_setAttributeValue(arena, handle, target,
- id, ptemplate, max_attributes);
+ newID, ptemplate, max_attributes);
break;
case SFTKDB_DO_NOTHING:
case SFTKDB_DROP_ATTRIBUTE:
@@ -2223,6 +2415,13 @@ sftkdb_mergeObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE id,
}
}
+ /* if keyDB copy any meta data hashes to target, Update for the new
+ * object ID */
+ if (crv == CKR_OK) {
+ crv = sftkdb_updateIntegrity(arena, handle, source, id, target, newID,
+ ptemplate, max_attributes);
+ }
+
loser:
if (arena) {
PORT_FreeArena(arena, PR_TRUE);
@@ -2251,7 +2450,6 @@ sftkdb_Update(SFTKDBHandle *handle, SECItem *key)
if (handle->update == NULL) {
return CKR_OK;
}
-
/*
* put the whole update under a transaction. This allows us to handle
* any possible race conditions between with the updateID check.
@@ -2495,6 +2693,7 @@ sftkdb_ResetKeyDB(SFTKDBHandle *handle)
return SECSuccess;
}
+#ifndef NSS_DISABLE_DBM
static PRBool
sftk_oldVersionExists(const char *dir, int version)
{
@@ -2598,6 +2797,7 @@ sftk_hasLegacyDB(const char *confdir, const char *certPrefix,
PR_smprintf_free(dir);
return exists;
}
+#endif /* NSS_DISABLE_DBM */
/*
* initialize certificate and key database handles as a pair.
@@ -2621,7 +2821,9 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
CK_RV crv = CKR_OK;
int flags = SDB_RDONLY;
PRBool newInit = PR_FALSE;
+#ifndef NSS_DISABLE_DBM
PRBool needUpdate = PR_FALSE;
+#endif /* NSS_DISABLE_DBM */
char *nconfdir = NULL;
PRBool legacy = PR_TRUE;
@@ -2644,6 +2846,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
* now initialize the appropriate database
*/
switch (dbType) {
+#ifndef NSS_DISABLE_DBM
case NSS_DB_TYPE_LEGACY:
crv = sftkdbCall_open(confdir, certPrefix, keyPrefix, 8, 3, flags,
noCertDB ? NULL : &certSDB, noKeyDB ? NULL : &keySDB);
@@ -2652,10 +2855,13 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
crv = sftkdbCall_open(configdir, certPrefix, keyPrefix, 8, 3, flags,
noCertDB ? NULL : &certSDB, noKeyDB ? NULL : &keySDB);
break;
+#endif /* NSS_DISABLE_DBM */
case NSS_DB_TYPE_SQL:
case NSS_DB_TYPE_EXTERN: /* SHOULD open a loadable db */
crv = s_open(confdir, certPrefix, keyPrefix, 9, 4, flags,
noCertDB ? NULL : &certSDB, noKeyDB ? NULL : &keySDB, &newInit);
+
+#ifndef NSS_DISABLE_DBM
legacy = PR_FALSE;
/*
@@ -2707,6 +2913,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
needUpdate = PR_TRUE;
}
}
+#endif /* NSS_DISABLE_DBM */
break;
default:
crv = CKR_GENERAL_ERROR; /* can't happen, EvaluationConfigDir MUST
@@ -2735,6 +2942,7 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
(*keyDB)->peerDB = *certDB;
}
+#ifndef NSS_DISABLE_DBM
/*
* if we need to update, open the legacy database and
* mark the handle as needing update.
@@ -2772,6 +2980,8 @@ sftk_DBInit(const char *configdir, const char *certPrefix,
}
}
}
+#endif /* NSS_DISABLE_DBM */
+
done:
if (appName) {
PORT_Free(appName);
@@ -2786,6 +2996,8 @@ CK_RV
sftkdb_Shutdown(void)
{
s_shutdown();
+#ifndef NSS_DISABLE_DBM
sftkdbCall_Shutdown();
+#endif /* NSS_DISABLE_DBM */
return CKR_OK;
}
diff --git a/security/nss/lib/softoken/sftkdb.h b/security/nss/lib/softoken/sftkdb.h
index bce39dc92..a8c289d4d 100644
--- a/security/nss/lib/softoken/sftkdb.h
+++ b/security/nss/lib/softoken/sftkdb.h
@@ -17,7 +17,8 @@ CK_RV sftkdb_GetAttributeValue(SFTKDBHandle *handle,
CK_OBJECT_HANDLE object_id, CK_ATTRIBUTE *template, CK_ULONG count);
CK_RV sftkdb_SetAttributeValue(SFTKDBHandle *handle, SFTKObject *object,
const CK_ATTRIBUTE *template, CK_ULONG count);
-CK_RV sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id);
+CK_RV sftkdb_DestroyObject(SFTKDBHandle *handle, CK_OBJECT_HANDLE object_id,
+ CK_OBJECT_CLASS objclass);
CK_RV sftkdb_closeDB(SFTKDBHandle *handle);
/* keydb functions */
diff --git a/security/nss/lib/softoken/sftkdbti.h b/security/nss/lib/softoken/sftkdbti.h
index a3a19414e..eea52c81d 100644
--- a/security/nss/lib/softoken/sftkdbti.h
+++ b/security/nss/lib/softoken/sftkdbti.h
@@ -39,16 +39,26 @@ struct SFTKDBHandleStr {
#define SFTK_GET_SDB(handle) \
((handle)->update ? (handle)->update : (handle)->db)
-SECStatus sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText,
- SECItem **plainText);
-SECStatus sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey,
- int iterationCount, SECItem *plainText,
- SECItem **cipherText);
-SECStatus sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey,
+SECStatus sftkdb_DecryptAttribute(SFTKDBHandle *handle,
+ SECItem *passKey,
+ CK_OBJECT_HANDLE id,
+ CK_ATTRIBUTE_TYPE attrType,
+ SECItem *cipherText, SECItem **plainText);
+SECStatus sftkdb_EncryptAttribute(PLArenaPool *arena,
+ SFTKDBHandle *handle, SDB *db,
+ SECItem *passKey,
+ int iterationCount,
+ CK_OBJECT_HANDLE id,
+ CK_ATTRIBUTE_TYPE attrType,
+ SECItem *plainText, SECItem **cipherText);
+SECStatus sftkdb_SignAttribute(PLArenaPool *arena,
+ SFTKDBHandle *handle, SDB *db,
+ SECItem *passKey,
int iterationCount, CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE attrType,
SECItem *plainText, SECItem **sigText);
-SECStatus sftkdb_VerifyAttribute(SECItem *passKey,
+SECStatus sftkdb_VerifyAttribute(SFTKDBHandle *handle,
+ SECItem *passKey,
CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE attrType,
SECItem *plainText, SECItem *sigText);
@@ -59,5 +69,14 @@ CK_RV sftkdb_Update(SFTKDBHandle *handle, SECItem *key);
CK_RV sftkdb_PutAttributeSignature(SFTKDBHandle *handle,
SDB *keyTarget, CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE type, SECItem *signText);
+CK_RV sftkdb_GetAttributeSignature(SFTKDBHandle *handle,
+ SFTKDBHandle *keyHandle,
+ CK_OBJECT_HANDLE objectID,
+ CK_ATTRIBUTE_TYPE type,
+ SECItem *signText);
+CK_RV
+sftkdb_DestroyAttributeSignature(SFTKDBHandle *handle, SDB *db,
+ CK_OBJECT_HANDLE objectID,
+ CK_ATTRIBUTE_TYPE type);
#endif
diff --git a/security/nss/lib/softoken/sftkdhverify.c b/security/nss/lib/softoken/sftkdhverify.c
new file mode 100644
index 000000000..d85fba94f
--- /dev/null
+++ b/security/nss/lib/softoken/sftkdhverify.c
@@ -0,0 +1,1282 @@
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * This file makes sure a prime given to us matches one of the known
+ * approved primes for diffie-helman.
+ *
+ * It also checks if a prime is a safe prime for the case
+ * where we don't match an approved prime.
+ */
+#include "seccomon.h"
+#include "secitem.h"
+#include "secerr.h"
+#include "blapi.h"
+
+/* IKE 1536 prime is: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } */
+static const unsigned char prime_ike_1536[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* IKE 2048 prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 */
+static const unsigned char prime_ike_2048[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* TLS 2048 prime is: 2^2048 - 2^1984 + {[2^1918 * e] + 560316 } * 2^64 - 1 */
+static const unsigned char prime_tls_2048[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0xF8, 0x54, 0x58,
+ 0xA2, 0xBB, 0x4A, 0x9A, 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
+ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, 0xA9, 0xE1, 0x36, 0x41,
+ 0x14, 0x64, 0x33, 0xFB, 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
+ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, 0xF6, 0x81, 0xB2, 0x02,
+ 0xAE, 0xC4, 0x61, 0x7A, 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
+ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, 0x85, 0x63, 0x65, 0x55,
+ 0x3D, 0xED, 0x1A, 0xF3, 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
+ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, 0xE2, 0xA6, 0x89, 0xDA,
+ 0xF3, 0xEF, 0xE8, 0x72, 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
+ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, 0xBC, 0x0A, 0xB1, 0x82,
+ 0xB3, 0x24, 0xFB, 0x61, 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
+ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, 0x1D, 0x4F, 0x42, 0xA3,
+ 0xDE, 0x39, 0x4D, 0xF4, 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
+ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, 0x9E, 0x02, 0xFC, 0xE1,
+ 0xCD, 0xF7, 0xE2, 0xEC, 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
+ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, 0x8E, 0x4F, 0x12, 0x32,
+ 0xEE, 0xF2, 0x81, 0x83, 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
+ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, 0xC5, 0x8E, 0xF1, 0x83,
+ 0x7D, 0x16, 0x83, 0xB2, 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
+ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* IKE 3072 prime is: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } */
+static const unsigned char prime_ike_3072[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+ 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+ 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+ 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+ 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+ 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+ 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* TLS 3072 prime is: 2^3072 - 2^3008 + {[2^2942 * e] + 2625351} * 2^64 - 1 */
+static const unsigned char prime_tls_3072[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0xF8, 0x54, 0x58,
+ 0xA2, 0xBB, 0x4A, 0x9A, 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
+ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, 0xA9, 0xE1, 0x36, 0x41,
+ 0x14, 0x64, 0x33, 0xFB, 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
+ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, 0xF6, 0x81, 0xB2, 0x02,
+ 0xAE, 0xC4, 0x61, 0x7A, 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
+ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, 0x85, 0x63, 0x65, 0x55,
+ 0x3D, 0xED, 0x1A, 0xF3, 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
+ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, 0xE2, 0xA6, 0x89, 0xDA,
+ 0xF3, 0xEF, 0xE8, 0x72, 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
+ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, 0xBC, 0x0A, 0xB1, 0x82,
+ 0xB3, 0x24, 0xFB, 0x61, 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
+ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, 0x1D, 0x4F, 0x42, 0xA3,
+ 0xDE, 0x39, 0x4D, 0xF4, 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
+ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, 0x9E, 0x02, 0xFC, 0xE1,
+ 0xCD, 0xF7, 0xE2, 0xEC, 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
+ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, 0x8E, 0x4F, 0x12, 0x32,
+ 0xEE, 0xF2, 0x81, 0x83, 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
+ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, 0xC5, 0x8E, 0xF1, 0x83,
+ 0x7D, 0x16, 0x83, 0xB2, 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
+ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, 0xDE, 0x35, 0x5B, 0x3B,
+ 0x65, 0x19, 0x03, 0x5B, 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
+ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, 0x7A, 0xD9, 0x1D, 0x26,
+ 0x91, 0xF7, 0xF7, 0xEE, 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
+ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xB4, 0x13, 0x0C, 0x93,
+ 0xBC, 0x43, 0x79, 0x44, 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
+ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, 0x5C, 0xAE, 0x82, 0xAB,
+ 0x9C, 0x9D, 0xF6, 0x9E, 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
+ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, 0x1D, 0xBF, 0x9A, 0x42,
+ 0xD5, 0xC4, 0x48, 0x4E, 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
+ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, 0x25, 0xE4, 0x1D, 0x2B,
+ 0x66, 0xC6, 0x2E, 0x37, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* IKE 4096 prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } */
+static const unsigned char prime_ike_4096[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+ 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+ 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+ 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+ 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+ 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+ 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
+ 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
+ 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
+ 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
+ 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
+ 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* TLS 4096 prime is: 2^4096 - 2^4032 + {[2^3966 * e] + 5736041} * 2^64 - 1 */
+static const unsigned char prime_tls_4096[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0xF8, 0x54, 0x58,
+ 0xA2, 0xBB, 0x4A, 0x9A, 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
+ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, 0xA9, 0xE1, 0x36, 0x41,
+ 0x14, 0x64, 0x33, 0xFB, 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
+ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, 0xF6, 0x81, 0xB2, 0x02,
+ 0xAE, 0xC4, 0x61, 0x7A, 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
+ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, 0x85, 0x63, 0x65, 0x55,
+ 0x3D, 0xED, 0x1A, 0xF3, 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
+ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, 0xE2, 0xA6, 0x89, 0xDA,
+ 0xF3, 0xEF, 0xE8, 0x72, 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
+ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, 0xBC, 0x0A, 0xB1, 0x82,
+ 0xB3, 0x24, 0xFB, 0x61, 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
+ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, 0x1D, 0x4F, 0x42, 0xA3,
+ 0xDE, 0x39, 0x4D, 0xF4, 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
+ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, 0x9E, 0x02, 0xFC, 0xE1,
+ 0xCD, 0xF7, 0xE2, 0xEC, 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
+ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, 0x8E, 0x4F, 0x12, 0x32,
+ 0xEE, 0xF2, 0x81, 0x83, 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
+ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, 0xC5, 0x8E, 0xF1, 0x83,
+ 0x7D, 0x16, 0x83, 0xB2, 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
+ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, 0xDE, 0x35, 0x5B, 0x3B,
+ 0x65, 0x19, 0x03, 0x5B, 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
+ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, 0x7A, 0xD9, 0x1D, 0x26,
+ 0x91, 0xF7, 0xF7, 0xEE, 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
+ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xB4, 0x13, 0x0C, 0x93,
+ 0xBC, 0x43, 0x79, 0x44, 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
+ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, 0x5C, 0xAE, 0x82, 0xAB,
+ 0x9C, 0x9D, 0xF6, 0x9E, 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
+ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, 0x1D, 0xBF, 0x9A, 0x42,
+ 0xD5, 0xC4, 0x48, 0x4E, 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
+ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, 0x25, 0xE4, 0x1D, 0x2B,
+ 0x66, 0x9E, 0x1E, 0xF1, 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
+ 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, 0xAC, 0x7D, 0x5F, 0x42,
+ 0xD6, 0x9F, 0x6D, 0x18, 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
+ 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, 0x71, 0x35, 0xC8, 0x86,
+ 0xEF, 0xB4, 0x31, 0x8A, 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
+ 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, 0x6D, 0xC7, 0x78, 0xF9,
+ 0x71, 0xAD, 0x00, 0x38, 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
+ 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, 0x2A, 0x4E, 0xCE, 0xA9,
+ 0xF9, 0x8D, 0x0A, 0xCC, 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
+ 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, 0x4D, 0xB5, 0xA8, 0x51,
+ 0xF4, 0x41, 0x82, 0xE1, 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* IKE 6144 prime is: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } */
+static const unsigned char prime_ike_6144[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+ 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+ 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+ 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+ 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+ 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+ 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
+ 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
+ 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
+ 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
+ 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
+ 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
+ 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2,
+ 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
+ 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F,
+ 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
+ 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB,
+ 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
+ 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51,
+ 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
+ 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15,
+ 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
+ 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31,
+ 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
+ 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7,
+ 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
+ 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2,
+ 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
+ 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D,
+ 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
+ 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7,
+ 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
+ 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E,
+ 0x6D, 0xCC, 0x40, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* TLS 6144 prime is: 2^6144 - 2^6080 + {[2^6014 * e] + 15705020} * 2^64 - 1 */
+static const unsigned char prime_tls_6144[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0xF8, 0x54, 0x58,
+ 0xA2, 0xBB, 0x4A, 0x9A, 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
+ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, 0xA9, 0xE1, 0x36, 0x41,
+ 0x14, 0x64, 0x33, 0xFB, 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
+ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, 0xF6, 0x81, 0xB2, 0x02,
+ 0xAE, 0xC4, 0x61, 0x7A, 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
+ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, 0x85, 0x63, 0x65, 0x55,
+ 0x3D, 0xED, 0x1A, 0xF3, 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
+ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, 0xE2, 0xA6, 0x89, 0xDA,
+ 0xF3, 0xEF, 0xE8, 0x72, 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
+ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, 0xBC, 0x0A, 0xB1, 0x82,
+ 0xB3, 0x24, 0xFB, 0x61, 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
+ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, 0x1D, 0x4F, 0x42, 0xA3,
+ 0xDE, 0x39, 0x4D, 0xF4, 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
+ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, 0x9E, 0x02, 0xFC, 0xE1,
+ 0xCD, 0xF7, 0xE2, 0xEC, 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
+ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, 0x8E, 0x4F, 0x12, 0x32,
+ 0xEE, 0xF2, 0x81, 0x83, 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
+ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, 0xC5, 0x8E, 0xF1, 0x83,
+ 0x7D, 0x16, 0x83, 0xB2, 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
+ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, 0xDE, 0x35, 0x5B, 0x3B,
+ 0x65, 0x19, 0x03, 0x5B, 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
+ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, 0x7A, 0xD9, 0x1D, 0x26,
+ 0x91, 0xF7, 0xF7, 0xEE, 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
+ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xB4, 0x13, 0x0C, 0x93,
+ 0xBC, 0x43, 0x79, 0x44, 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
+ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, 0x5C, 0xAE, 0x82, 0xAB,
+ 0x9C, 0x9D, 0xF6, 0x9E, 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
+ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, 0x1D, 0xBF, 0x9A, 0x42,
+ 0xD5, 0xC4, 0x48, 0x4E, 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
+ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, 0x25, 0xE4, 0x1D, 0x2B,
+ 0x66, 0x9E, 0x1E, 0xF1, 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
+ 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, 0xAC, 0x7D, 0x5F, 0x42,
+ 0xD6, 0x9F, 0x6D, 0x18, 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
+ 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, 0x71, 0x35, 0xC8, 0x86,
+ 0xEF, 0xB4, 0x31, 0x8A, 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
+ 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, 0x6D, 0xC7, 0x78, 0xF9,
+ 0x71, 0xAD, 0x00, 0x38, 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
+ 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, 0x2A, 0x4E, 0xCE, 0xA9,
+ 0xF9, 0x8D, 0x0A, 0xCC, 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
+ 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, 0x4D, 0xB5, 0xA8, 0x51,
+ 0xF4, 0x41, 0x82, 0xE1, 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02,
+ 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, 0x4E, 0x67, 0x7D, 0x2C,
+ 0x38, 0x53, 0x2A, 0x3A, 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6,
+ 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, 0x91, 0x7B, 0xDD, 0x64,
+ 0xB1, 0xC0, 0xFD, 0x4C, 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A,
+ 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, 0x9B, 0x1F, 0x5C, 0x3E,
+ 0x4E, 0x46, 0x04, 0x1F, 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77,
+ 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, 0xB8, 0x55, 0x32, 0x2E,
+ 0xDB, 0x63, 0x40, 0xD8, 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3,
+ 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, 0x7F, 0xB2, 0x9F, 0x8C,
+ 0x18, 0x30, 0x23, 0xC3, 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4,
+ 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, 0x94, 0xC6, 0x65, 0x1E,
+ 0x77, 0xCA, 0xF9, 0x92, 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6,
+ 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, 0x0A, 0xE8, 0xDB, 0x58,
+ 0x47, 0xA6, 0x7C, 0xBE, 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C,
+ 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, 0x62, 0x29, 0x2C, 0x31,
+ 0x15, 0x62, 0xA8, 0x46, 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A,
+ 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, 0x8C, 0xCF, 0x2D, 0xD5,
+ 0xCA, 0xCE, 0xF4, 0x03, 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04,
+ 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, 0x3F, 0xDD, 0x4A, 0x8E,
+ 0x9A, 0xDB, 0x1E, 0x69, 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1,
+ 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, 0xA4, 0x0E, 0x32, 0x9C,
+ 0xD0, 0xE4, 0x0E, 0x65, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* IKE 8192 prime is: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } */
+static const unsigned char prime_ike_8192[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
+ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
+ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
+ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
+ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
+ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
+ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
+ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
+ 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
+ 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
+ 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
+ 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
+ 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
+ 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
+ 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
+ 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
+ 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
+ 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
+ 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
+ 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
+ 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
+ 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
+ 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2,
+ 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
+ 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F,
+ 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
+ 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB,
+ 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
+ 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51,
+ 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
+ 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15,
+ 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
+ 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31,
+ 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
+ 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7,
+ 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
+ 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2,
+ 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
+ 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D,
+ 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
+ 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7,
+ 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
+ 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E,
+ 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
+ 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0,
+ 0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
+ 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93,
+ 0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
+ 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB,
+ 0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
+ 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8,
+ 0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
+ 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F,
+ 0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
+ 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8,
+ 0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
+ 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5,
+ 0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
+ 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3,
+ 0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
+ 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E,
+ 0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
+ 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2,
+ 0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
+ 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* TLS 8192 prime is: 2^8192 - 2^8128 + {[2^8062 * e] + 10965728} * 2^64 - 1 */
+static const unsigned char prime_tls_8192[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0xF8, 0x54, 0x58,
+ 0xA2, 0xBB, 0x4A, 0x9A, 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1,
+ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, 0xA9, 0xE1, 0x36, 0x41,
+ 0x14, 0x64, 0x33, 0xFB, 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9,
+ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, 0xF6, 0x81, 0xB2, 0x02,
+ 0xAE, 0xC4, 0x61, 0x7A, 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61,
+ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, 0x85, 0x63, 0x65, 0x55,
+ 0x3D, 0xED, 0x1A, 0xF3, 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35,
+ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, 0xE2, 0xA6, 0x89, 0xDA,
+ 0xF3, 0xEF, 0xE8, 0x72, 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35,
+ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, 0xBC, 0x0A, 0xB1, 0x82,
+ 0xB3, 0x24, 0xFB, 0x61, 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB,
+ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, 0x1D, 0x4F, 0x42, 0xA3,
+ 0xDE, 0x39, 0x4D, 0xF4, 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19,
+ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, 0x9E, 0x02, 0xFC, 0xE1,
+ 0xCD, 0xF7, 0xE2, 0xEC, 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61,
+ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, 0x8E, 0x4F, 0x12, 0x32,
+ 0xEE, 0xF2, 0x81, 0x83, 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73,
+ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, 0xC5, 0x8E, 0xF1, 0x83,
+ 0x7D, 0x16, 0x83, 0xB2, 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA,
+ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, 0xDE, 0x35, 0x5B, 0x3B,
+ 0x65, 0x19, 0x03, 0x5B, 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38,
+ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, 0x7A, 0xD9, 0x1D, 0x26,
+ 0x91, 0xF7, 0xF7, 0xEE, 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C,
+ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, 0xB4, 0x13, 0x0C, 0x93,
+ 0xBC, 0x43, 0x79, 0x44, 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3,
+ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, 0x5C, 0xAE, 0x82, 0xAB,
+ 0x9C, 0x9D, 0xF6, 0x9E, 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D,
+ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, 0x1D, 0xBF, 0x9A, 0x42,
+ 0xD5, 0xC4, 0x48, 0x4E, 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF,
+ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, 0x25, 0xE4, 0x1D, 0x2B,
+ 0x66, 0x9E, 0x1E, 0xF1, 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB,
+ 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, 0xAC, 0x7D, 0x5F, 0x42,
+ 0xD6, 0x9F, 0x6D, 0x18, 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04,
+ 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, 0x71, 0x35, 0xC8, 0x86,
+ 0xEF, 0xB4, 0x31, 0x8A, 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32,
+ 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, 0x6D, 0xC7, 0x78, 0xF9,
+ 0x71, 0xAD, 0x00, 0x38, 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A,
+ 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, 0x2A, 0x4E, 0xCE, 0xA9,
+ 0xF9, 0x8D, 0x0A, 0xCC, 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF,
+ 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, 0x4D, 0xB5, 0xA8, 0x51,
+ 0xF4, 0x41, 0x82, 0xE1, 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02,
+ 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, 0x4E, 0x67, 0x7D, 0x2C,
+ 0x38, 0x53, 0x2A, 0x3A, 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6,
+ 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, 0x91, 0x7B, 0xDD, 0x64,
+ 0xB1, 0xC0, 0xFD, 0x4C, 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A,
+ 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, 0x9B, 0x1F, 0x5C, 0x3E,
+ 0x4E, 0x46, 0x04, 0x1F, 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77,
+ 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, 0xB8, 0x55, 0x32, 0x2E,
+ 0xDB, 0x63, 0x40, 0xD8, 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3,
+ 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, 0x7F, 0xB2, 0x9F, 0x8C,
+ 0x18, 0x30, 0x23, 0xC3, 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4,
+ 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, 0x94, 0xC6, 0x65, 0x1E,
+ 0x77, 0xCA, 0xF9, 0x92, 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6,
+ 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, 0x0A, 0xE8, 0xDB, 0x58,
+ 0x47, 0xA6, 0x7C, 0xBE, 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C,
+ 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, 0x62, 0x29, 0x2C, 0x31,
+ 0x15, 0x62, 0xA8, 0x46, 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A,
+ 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, 0x8C, 0xCF, 0x2D, 0xD5,
+ 0xCA, 0xCE, 0xF4, 0x03, 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04,
+ 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, 0x3F, 0xDD, 0x4A, 0x8E,
+ 0x9A, 0xDB, 0x1E, 0x69, 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1,
+ 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, 0xA4, 0x0E, 0x32, 0x9C,
+ 0xCF, 0xF4, 0x6A, 0xAA, 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38,
+ 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, 0xFD, 0xB2, 0x3F, 0xCE,
+ 0xC9, 0x50, 0x9D, 0x43, 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E,
+ 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, 0x86, 0xB6, 0x31, 0x42,
+ 0xA3, 0xAB, 0x88, 0x29, 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65,
+ 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, 0x29, 0x38, 0x88, 0x39,
+ 0xD2, 0xAF, 0x05, 0xE4, 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82,
+ 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, 0x59, 0x16, 0x0C, 0xC0,
+ 0x46, 0xFD, 0x82, 0x51, 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22,
+ 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, 0x51, 0xA8, 0xA9, 0x31,
+ 0x09, 0x70, 0x3F, 0xEE, 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C,
+ 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, 0x99, 0xE9, 0xE3, 0x16,
+ 0x50, 0xC1, 0x21, 0x7B, 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9,
+ 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, 0xA1, 0xFE, 0x30, 0x75,
+ 0xA5, 0x77, 0xE2, 0x31, 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57,
+ 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, 0xB6, 0x85, 0x5D, 0xFE,
+ 0x72, 0xB0, 0xA6, 0x6E, 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30,
+ 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, 0x2F, 0x74, 0x1E, 0xF8,
+ 0xC1, 0xFE, 0x86, 0xFE, 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D,
+ 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, 0x08, 0x22, 0xE5, 0x06,
+ 0xA9, 0xF4, 0x61, 0x4E, 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C,
+ 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* q=(p-1)/2 for prime prime_ike_1536 */
+static const unsigned char subprime_ike_1536_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x87, 0xed, 0x51,
+ 0x10, 0xb4, 0x61, 0x1a, 0x62, 0x63, 0x31, 0x45, 0xc0, 0x6e, 0x0e, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xe6, 0x3a, 0x01, 0x05, 0xdf, 0x53,
+ 0x1d, 0x89, 0xcd, 0x91, 0x28, 0xa5, 0x04, 0x3c, 0xc7, 0x1a, 0x02, 0x6e,
+ 0xf7, 0xca, 0x8c, 0xd9, 0xe6, 0x9d, 0x21, 0x8d, 0x98, 0x15, 0x85, 0x36,
+ 0xf9, 0x2f, 0x8a, 0x1b, 0xa7, 0xf0, 0x9a, 0xb6, 0xb6, 0xa8, 0xe1, 0x22,
+ 0xf2, 0x42, 0xda, 0xbb, 0x31, 0x2f, 0x3f, 0x63, 0x7a, 0x26, 0x21, 0x74,
+ 0xd3, 0x1b, 0xf6, 0xb5, 0x85, 0xff, 0xae, 0x5b, 0x7a, 0x03, 0x5b, 0xf6,
+ 0xf7, 0x1c, 0x35, 0xfd, 0xad, 0x44, 0xcf, 0xd2, 0xd7, 0x4f, 0x92, 0x08,
+ 0xbe, 0x25, 0x8f, 0xf3, 0x24, 0x94, 0x33, 0x28, 0xf6, 0x72, 0x2d, 0x9e,
+ 0xe1, 0x00, 0x3e, 0x5c, 0x50, 0xb1, 0xdf, 0x82, 0xcc, 0x6d, 0x24, 0x1b,
+ 0x0e, 0x2a, 0xe9, 0xcd, 0x34, 0x8b, 0x1f, 0xd4, 0x7e, 0x92, 0x67, 0xaf,
+ 0xc1, 0xb2, 0xae, 0x91, 0xee, 0x51, 0xd6, 0xcb, 0x0e, 0x31, 0x79, 0xab,
+ 0x10, 0x42, 0xa9, 0x5d, 0xcf, 0x6a, 0x94, 0x83, 0xb8, 0x4b, 0x4b, 0x36,
+ 0xb3, 0x86, 0x1a, 0xa7, 0x25, 0x5e, 0x4c, 0x02, 0x78, 0xba, 0x36, 0x04,
+ 0x65, 0x11, 0xb9, 0x93, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* q=(p-1)/2 for prime prime_ike_2048 */
+static const unsigned char subprime_ike_2048_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x87, 0xed, 0x51,
+ 0x10, 0xb4, 0x61, 0x1a, 0x62, 0x63, 0x31, 0x45, 0xc0, 0x6e, 0x0e, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xe6, 0x3a, 0x01, 0x05, 0xdf, 0x53,
+ 0x1d, 0x89, 0xcd, 0x91, 0x28, 0xa5, 0x04, 0x3c, 0xc7, 0x1a, 0x02, 0x6e,
+ 0xf7, 0xca, 0x8c, 0xd9, 0xe6, 0x9d, 0x21, 0x8d, 0x98, 0x15, 0x85, 0x36,
+ 0xf9, 0x2f, 0x8a, 0x1b, 0xa7, 0xf0, 0x9a, 0xb6, 0xb6, 0xa8, 0xe1, 0x22,
+ 0xf2, 0x42, 0xda, 0xbb, 0x31, 0x2f, 0x3f, 0x63, 0x7a, 0x26, 0x21, 0x74,
+ 0xd3, 0x1b, 0xf6, 0xb5, 0x85, 0xff, 0xae, 0x5b, 0x7a, 0x03, 0x5b, 0xf6,
+ 0xf7, 0x1c, 0x35, 0xfd, 0xad, 0x44, 0xcf, 0xd2, 0xd7, 0x4f, 0x92, 0x08,
+ 0xbe, 0x25, 0x8f, 0xf3, 0x24, 0x94, 0x33, 0x28, 0xf6, 0x72, 0x2d, 0x9e,
+ 0xe1, 0x00, 0x3e, 0x5c, 0x50, 0xb1, 0xdf, 0x82, 0xcc, 0x6d, 0x24, 0x1b,
+ 0x0e, 0x2a, 0xe9, 0xcd, 0x34, 0x8b, 0x1f, 0xd4, 0x7e, 0x92, 0x67, 0xaf,
+ 0xc1, 0xb2, 0xae, 0x91, 0xee, 0x51, 0xd6, 0xcb, 0x0e, 0x31, 0x79, 0xab,
+ 0x10, 0x42, 0xa9, 0x5d, 0xcf, 0x6a, 0x94, 0x83, 0xb8, 0x4b, 0x4b, 0x36,
+ 0xb3, 0x86, 0x1a, 0xa7, 0x25, 0x5e, 0x4c, 0x02, 0x78, 0xba, 0x36, 0x04,
+ 0x65, 0x0c, 0x10, 0xbe, 0x19, 0x48, 0x2f, 0x23, 0x17, 0x1b, 0x67, 0x1d,
+ 0xf1, 0xcf, 0x3b, 0x96, 0x0c, 0x07, 0x43, 0x01, 0xcd, 0x93, 0xc1, 0xd1,
+ 0x76, 0x03, 0xd1, 0x47, 0xda, 0xe2, 0xae, 0xf8, 0x37, 0xa6, 0x29, 0x64,
+ 0xef, 0x15, 0xe5, 0xfb, 0x4a, 0xac, 0x0b, 0x8c, 0x1c, 0xca, 0xa4, 0xbe,
+ 0x75, 0x4a, 0xb5, 0x72, 0x8a, 0xe9, 0x13, 0x0c, 0x4c, 0x7d, 0x02, 0x88,
+ 0x0a, 0xb9, 0x47, 0x2d, 0x45, 0x56, 0x55, 0x34, 0x7f, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+};
+
+/* q=(p-1)/2 for prime prime_tls_2048 */
+static const unsigned char subprime_tls_2048_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xfc, 0x2a, 0x2c,
+ 0x51, 0x5d, 0xa5, 0x4d, 0x57, 0xee, 0x2b, 0x10, 0x13, 0x9e, 0x9e, 0x78,
+ 0xec, 0x5c, 0xe2, 0xc1, 0xe7, 0x16, 0x9b, 0x4a, 0xd4, 0xf0, 0x9b, 0x20,
+ 0x8a, 0x32, 0x19, 0xfd, 0xe6, 0x49, 0xce, 0xe7, 0x12, 0x4d, 0x9f, 0x7c,
+ 0xbe, 0x97, 0xf1, 0xb1, 0xb1, 0x86, 0x3a, 0xec, 0x7b, 0x40, 0xd9, 0x01,
+ 0x57, 0x62, 0x30, 0xbd, 0x69, 0xef, 0x8f, 0x6a, 0xea, 0xfe, 0xb2, 0xb0,
+ 0x92, 0x19, 0xfa, 0x8f, 0xaf, 0x83, 0x37, 0x68, 0x42, 0xb1, 0xb2, 0xaa,
+ 0x9e, 0xf6, 0x8d, 0x79, 0xda, 0xab, 0x89, 0xaf, 0x3f, 0xab, 0xe4, 0x9a,
+ 0xcc, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xbb, 0xf1, 0x53, 0x44, 0xed,
+ 0x79, 0xf7, 0xf4, 0x39, 0x0e, 0xf8, 0xac, 0x50, 0x9b, 0x56, 0xf3, 0x9a,
+ 0x98, 0x56, 0x65, 0x27, 0xa4, 0x1d, 0x3c, 0xbd, 0x5e, 0x05, 0x58, 0xc1,
+ 0x59, 0x92, 0x7d, 0xb0, 0xe8, 0x84, 0x54, 0xa5, 0xd9, 0x64, 0x71, 0xfd,
+ 0xdc, 0xb5, 0x6d, 0x5b, 0xb0, 0x6b, 0xfa, 0x34, 0x0e, 0xa7, 0xa1, 0x51,
+ 0xef, 0x1c, 0xa6, 0xfa, 0x57, 0x2b, 0x76, 0xf3, 0xb1, 0xb9, 0x5d, 0x8c,
+ 0x85, 0x83, 0xd3, 0xe4, 0x77, 0x05, 0x36, 0xb8, 0x4f, 0x01, 0x7e, 0x70,
+ 0xe6, 0xfb, 0xf1, 0x76, 0x60, 0x1a, 0x02, 0x66, 0x94, 0x1a, 0x17, 0xb0,
+ 0xc8, 0xb9, 0x7f, 0x4e, 0x74, 0xc2, 0xc1, 0xff, 0xc7, 0x27, 0x89, 0x19,
+ 0x77, 0x79, 0x40, 0xc1, 0xe1, 0xff, 0x1d, 0x8d, 0xa6, 0x37, 0xd6, 0xb9,
+ 0x9d, 0xda, 0xfe, 0x5e, 0x17, 0x61, 0x10, 0x02, 0xe2, 0xc7, 0x78, 0xc1,
+ 0xbe, 0x8b, 0x41, 0xd9, 0x63, 0x79, 0xa5, 0x13, 0x60, 0xd9, 0x77, 0xfd,
+ 0x44, 0x35, 0xa1, 0x1c, 0x30, 0x94, 0x2e, 0x4b, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+};
+
+/* q=(p-1)/2 for prime prime_ike_3072 */
+static const unsigned char subprime_ike_3072_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x87, 0xed, 0x51,
+ 0x10, 0xb4, 0x61, 0x1a, 0x62, 0x63, 0x31, 0x45, 0xc0, 0x6e, 0x0e, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xe6, 0x3a, 0x01, 0x05, 0xdf, 0x53,
+ 0x1d, 0x89, 0xcd, 0x91, 0x28, 0xa5, 0x04, 0x3c, 0xc7, 0x1a, 0x02, 0x6e,
+ 0xf7, 0xca, 0x8c, 0xd9, 0xe6, 0x9d, 0x21, 0x8d, 0x98, 0x15, 0x85, 0x36,
+ 0xf9, 0x2f, 0x8a, 0x1b, 0xa7, 0xf0, 0x9a, 0xb6, 0xb6, 0xa8, 0xe1, 0x22,
+ 0xf2, 0x42, 0xda, 0xbb, 0x31, 0x2f, 0x3f, 0x63, 0x7a, 0x26, 0x21, 0x74,
+ 0xd3, 0x1b, 0xf6, 0xb5, 0x85, 0xff, 0xae, 0x5b, 0x7a, 0x03, 0x5b, 0xf6,
+ 0xf7, 0x1c, 0x35, 0xfd, 0xad, 0x44, 0xcf, 0xd2, 0xd7, 0x4f, 0x92, 0x08,
+ 0xbe, 0x25, 0x8f, 0xf3, 0x24, 0x94, 0x33, 0x28, 0xf6, 0x72, 0x2d, 0x9e,
+ 0xe1, 0x00, 0x3e, 0x5c, 0x50, 0xb1, 0xdf, 0x82, 0xcc, 0x6d, 0x24, 0x1b,
+ 0x0e, 0x2a, 0xe9, 0xcd, 0x34, 0x8b, 0x1f, 0xd4, 0x7e, 0x92, 0x67, 0xaf,
+ 0xc1, 0xb2, 0xae, 0x91, 0xee, 0x51, 0xd6, 0xcb, 0x0e, 0x31, 0x79, 0xab,
+ 0x10, 0x42, 0xa9, 0x5d, 0xcf, 0x6a, 0x94, 0x83, 0xb8, 0x4b, 0x4b, 0x36,
+ 0xb3, 0x86, 0x1a, 0xa7, 0x25, 0x5e, 0x4c, 0x02, 0x78, 0xba, 0x36, 0x04,
+ 0x65, 0x0c, 0x10, 0xbe, 0x19, 0x48, 0x2f, 0x23, 0x17, 0x1b, 0x67, 0x1d,
+ 0xf1, 0xcf, 0x3b, 0x96, 0x0c, 0x07, 0x43, 0x01, 0xcd, 0x93, 0xc1, 0xd1,
+ 0x76, 0x03, 0xd1, 0x47, 0xda, 0xe2, 0xae, 0xf8, 0x37, 0xa6, 0x29, 0x64,
+ 0xef, 0x15, 0xe5, 0xfb, 0x4a, 0xac, 0x0b, 0x8c, 0x1c, 0xca, 0xa4, 0xbe,
+ 0x75, 0x4a, 0xb5, 0x72, 0x8a, 0xe9, 0x13, 0x0c, 0x4c, 0x7d, 0x02, 0x88,
+ 0x0a, 0xb9, 0x47, 0x2d, 0x45, 0x55, 0x62, 0x16, 0xd6, 0x99, 0x8b, 0x86,
+ 0x82, 0x28, 0x3d, 0x19, 0xd4, 0x2a, 0x90, 0xd5, 0xef, 0x8e, 0x5d, 0x32,
+ 0x76, 0x7d, 0xc2, 0x82, 0x2c, 0x6d, 0xf7, 0x85, 0x45, 0x75, 0x38, 0xab,
+ 0xae, 0x83, 0x06, 0x3e, 0xd9, 0xcb, 0x87, 0xc2, 0xd3, 0x70, 0xf2, 0x63,
+ 0xd5, 0xfa, 0xd7, 0x46, 0x6d, 0x84, 0x99, 0xeb, 0x8f, 0x46, 0x4a, 0x70,
+ 0x25, 0x12, 0xb0, 0xce, 0xe7, 0x71, 0xe9, 0x13, 0x0d, 0x69, 0x77, 0x35,
+ 0xf8, 0x97, 0xfd, 0x03, 0x6c, 0xc5, 0x04, 0x32, 0x6c, 0x3b, 0x01, 0x39,
+ 0x9f, 0x64, 0x35, 0x32, 0x29, 0x0f, 0x95, 0x8c, 0x0b, 0xbd, 0x90, 0x06,
+ 0x5d, 0xf0, 0x8b, 0xab, 0xbd, 0x30, 0xae, 0xb6, 0x3b, 0x84, 0xc4, 0x60,
+ 0x5d, 0x6c, 0xa3, 0x71, 0x04, 0x71, 0x27, 0xd0, 0x3a, 0x72, 0xd5, 0x98,
+ 0xa1, 0xed, 0xad, 0xfe, 0x70, 0x7e, 0x88, 0x47, 0x25, 0xc1, 0x68, 0x90,
+ 0x54, 0x9d, 0x69, 0x65, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* q=(p-1)/2 for prime prime_tls_3072 */
+static const unsigned char subprime_tls_3072_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xfc, 0x2a, 0x2c,
+ 0x51, 0x5d, 0xa5, 0x4d, 0x57, 0xee, 0x2b, 0x10, 0x13, 0x9e, 0x9e, 0x78,
+ 0xec, 0x5c, 0xe2, 0xc1, 0xe7, 0x16, 0x9b, 0x4a, 0xd4, 0xf0, 0x9b, 0x20,
+ 0x8a, 0x32, 0x19, 0xfd, 0xe6, 0x49, 0xce, 0xe7, 0x12, 0x4d, 0x9f, 0x7c,
+ 0xbe, 0x97, 0xf1, 0xb1, 0xb1, 0x86, 0x3a, 0xec, 0x7b, 0x40, 0xd9, 0x01,
+ 0x57, 0x62, 0x30, 0xbd, 0x69, 0xef, 0x8f, 0x6a, 0xea, 0xfe, 0xb2, 0xb0,
+ 0x92, 0x19, 0xfa, 0x8f, 0xaf, 0x83, 0x37, 0x68, 0x42, 0xb1, 0xb2, 0xaa,
+ 0x9e, 0xf6, 0x8d, 0x79, 0xda, 0xab, 0x89, 0xaf, 0x3f, 0xab, 0xe4, 0x9a,
+ 0xcc, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xbb, 0xf1, 0x53, 0x44, 0xed,
+ 0x79, 0xf7, 0xf4, 0x39, 0x0e, 0xf8, 0xac, 0x50, 0x9b, 0x56, 0xf3, 0x9a,
+ 0x98, 0x56, 0x65, 0x27, 0xa4, 0x1d, 0x3c, 0xbd, 0x5e, 0x05, 0x58, 0xc1,
+ 0x59, 0x92, 0x7d, 0xb0, 0xe8, 0x84, 0x54, 0xa5, 0xd9, 0x64, 0x71, 0xfd,
+ 0xdc, 0xb5, 0x6d, 0x5b, 0xb0, 0x6b, 0xfa, 0x34, 0x0e, 0xa7, 0xa1, 0x51,
+ 0xef, 0x1c, 0xa6, 0xfa, 0x57, 0x2b, 0x76, 0xf3, 0xb1, 0xb9, 0x5d, 0x8c,
+ 0x85, 0x83, 0xd3, 0xe4, 0x77, 0x05, 0x36, 0xb8, 0x4f, 0x01, 0x7e, 0x70,
+ 0xe6, 0xfb, 0xf1, 0x76, 0x60, 0x1a, 0x02, 0x66, 0x94, 0x1a, 0x17, 0xb0,
+ 0xc8, 0xb9, 0x7f, 0x4e, 0x74, 0xc2, 0xc1, 0xff, 0xc7, 0x27, 0x89, 0x19,
+ 0x77, 0x79, 0x40, 0xc1, 0xe1, 0xff, 0x1d, 0x8d, 0xa6, 0x37, 0xd6, 0xb9,
+ 0x9d, 0xda, 0xfe, 0x5e, 0x17, 0x61, 0x10, 0x02, 0xe2, 0xc7, 0x78, 0xc1,
+ 0xbe, 0x8b, 0x41, 0xd9, 0x63, 0x79, 0xa5, 0x13, 0x60, 0xd9, 0x77, 0xfd,
+ 0x44, 0x35, 0xa1, 0x1c, 0x30, 0x8f, 0xe7, 0xee, 0x6f, 0x1a, 0xad, 0x9d,
+ 0xb2, 0x8c, 0x81, 0xad, 0xde, 0x1a, 0x7a, 0x6f, 0x7c, 0xce, 0x01, 0x1c,
+ 0x30, 0xda, 0x37, 0xe4, 0xeb, 0x73, 0x64, 0x83, 0xbd, 0x6c, 0x8e, 0x93,
+ 0x48, 0xfb, 0xfb, 0xf7, 0x2c, 0xc6, 0x58, 0x7d, 0x60, 0xc3, 0x6c, 0x8e,
+ 0x57, 0x7f, 0x09, 0x84, 0xc2, 0x89, 0xc9, 0x38, 0x5a, 0x09, 0x86, 0x49,
+ 0xde, 0x21, 0xbc, 0xa2, 0x7a, 0x7e, 0xa2, 0x29, 0x71, 0x6b, 0xa6, 0xe9,
+ 0xb2, 0x79, 0x71, 0x0f, 0x38, 0xfa, 0xa5, 0xff, 0xae, 0x57, 0x41, 0x55,
+ 0xce, 0x4e, 0xfb, 0x4f, 0x74, 0x36, 0x95, 0xe2, 0x91, 0x1b, 0x1d, 0x06,
+ 0xd5, 0xe2, 0x90, 0xcb, 0xcd, 0x86, 0xf5, 0x6d, 0x0e, 0xdf, 0xcd, 0x21,
+ 0x6a, 0xe2, 0x24, 0x27, 0x05, 0x5e, 0x68, 0x35, 0xfd, 0x29, 0xee, 0xf7,
+ 0x9e, 0x0d, 0x90, 0x77, 0x1f, 0xea, 0xce, 0xbe, 0x12, 0xf2, 0x0e, 0x95,
+ 0xb3, 0x63, 0x17, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* q=(p-1)/2 for prime prime_ike_4096 */
+static const unsigned char subprime_ike_4096_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x87, 0xed, 0x51,
+ 0x10, 0xb4, 0x61, 0x1a, 0x62, 0x63, 0x31, 0x45, 0xc0, 0x6e, 0x0e, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xe6, 0x3a, 0x01, 0x05, 0xdf, 0x53,
+ 0x1d, 0x89, 0xcd, 0x91, 0x28, 0xa5, 0x04, 0x3c, 0xc7, 0x1a, 0x02, 0x6e,
+ 0xf7, 0xca, 0x8c, 0xd9, 0xe6, 0x9d, 0x21, 0x8d, 0x98, 0x15, 0x85, 0x36,
+ 0xf9, 0x2f, 0x8a, 0x1b, 0xa7, 0xf0, 0x9a, 0xb6, 0xb6, 0xa8, 0xe1, 0x22,
+ 0xf2, 0x42, 0xda, 0xbb, 0x31, 0x2f, 0x3f, 0x63, 0x7a, 0x26, 0x21, 0x74,
+ 0xd3, 0x1b, 0xf6, 0xb5, 0x85, 0xff, 0xae, 0x5b, 0x7a, 0x03, 0x5b, 0xf6,
+ 0xf7, 0x1c, 0x35, 0xfd, 0xad, 0x44, 0xcf, 0xd2, 0xd7, 0x4f, 0x92, 0x08,
+ 0xbe, 0x25, 0x8f, 0xf3, 0x24, 0x94, 0x33, 0x28, 0xf6, 0x72, 0x2d, 0x9e,
+ 0xe1, 0x00, 0x3e, 0x5c, 0x50, 0xb1, 0xdf, 0x82, 0xcc, 0x6d, 0x24, 0x1b,
+ 0x0e, 0x2a, 0xe9, 0xcd, 0x34, 0x8b, 0x1f, 0xd4, 0x7e, 0x92, 0x67, 0xaf,
+ 0xc1, 0xb2, 0xae, 0x91, 0xee, 0x51, 0xd6, 0xcb, 0x0e, 0x31, 0x79, 0xab,
+ 0x10, 0x42, 0xa9, 0x5d, 0xcf, 0x6a, 0x94, 0x83, 0xb8, 0x4b, 0x4b, 0x36,
+ 0xb3, 0x86, 0x1a, 0xa7, 0x25, 0x5e, 0x4c, 0x02, 0x78, 0xba, 0x36, 0x04,
+ 0x65, 0x0c, 0x10, 0xbe, 0x19, 0x48, 0x2f, 0x23, 0x17, 0x1b, 0x67, 0x1d,
+ 0xf1, 0xcf, 0x3b, 0x96, 0x0c, 0x07, 0x43, 0x01, 0xcd, 0x93, 0xc1, 0xd1,
+ 0x76, 0x03, 0xd1, 0x47, 0xda, 0xe2, 0xae, 0xf8, 0x37, 0xa6, 0x29, 0x64,
+ 0xef, 0x15, 0xe5, 0xfb, 0x4a, 0xac, 0x0b, 0x8c, 0x1c, 0xca, 0xa4, 0xbe,
+ 0x75, 0x4a, 0xb5, 0x72, 0x8a, 0xe9, 0x13, 0x0c, 0x4c, 0x7d, 0x02, 0x88,
+ 0x0a, 0xb9, 0x47, 0x2d, 0x45, 0x55, 0x62, 0x16, 0xd6, 0x99, 0x8b, 0x86,
+ 0x82, 0x28, 0x3d, 0x19, 0xd4, 0x2a, 0x90, 0xd5, 0xef, 0x8e, 0x5d, 0x32,
+ 0x76, 0x7d, 0xc2, 0x82, 0x2c, 0x6d, 0xf7, 0x85, 0x45, 0x75, 0x38, 0xab,
+ 0xae, 0x83, 0x06, 0x3e, 0xd9, 0xcb, 0x87, 0xc2, 0xd3, 0x70, 0xf2, 0x63,
+ 0xd5, 0xfa, 0xd7, 0x46, 0x6d, 0x84, 0x99, 0xeb, 0x8f, 0x46, 0x4a, 0x70,
+ 0x25, 0x12, 0xb0, 0xce, 0xe7, 0x71, 0xe9, 0x13, 0x0d, 0x69, 0x77, 0x35,
+ 0xf8, 0x97, 0xfd, 0x03, 0x6c, 0xc5, 0x04, 0x32, 0x6c, 0x3b, 0x01, 0x39,
+ 0x9f, 0x64, 0x35, 0x32, 0x29, 0x0f, 0x95, 0x8c, 0x0b, 0xbd, 0x90, 0x06,
+ 0x5d, 0xf0, 0x8b, 0xab, 0xbd, 0x30, 0xae, 0xb6, 0x3b, 0x84, 0xc4, 0x60,
+ 0x5d, 0x6c, 0xa3, 0x71, 0x04, 0x71, 0x27, 0xd0, 0x3a, 0x72, 0xd5, 0x98,
+ 0xa1, 0xed, 0xad, 0xfe, 0x70, 0x7e, 0x88, 0x47, 0x25, 0xc1, 0x68, 0x90,
+ 0x54, 0x90, 0x84, 0x00, 0x8d, 0x39, 0x1e, 0x09, 0x53, 0xc3, 0xf3, 0x6b,
+ 0xc4, 0x38, 0xcd, 0x08, 0x5e, 0xdd, 0x2d, 0x93, 0x4c, 0xe1, 0x93, 0x8c,
+ 0x35, 0x7a, 0x71, 0x1e, 0x0d, 0x4a, 0x34, 0x1a, 0x5b, 0x0a, 0x85, 0xed,
+ 0x12, 0xc1, 0xf4, 0xe5, 0x15, 0x6a, 0x26, 0x74, 0x6d, 0xdd, 0xe1, 0x6d,
+ 0x82, 0x6f, 0x47, 0x7c, 0x97, 0x47, 0x7e, 0x0a, 0x0f, 0xdf, 0x65, 0x53,
+ 0x14, 0x3e, 0x2c, 0xa3, 0xa7, 0x35, 0xe0, 0x2e, 0xcc, 0xd9, 0x4b, 0x27,
+ 0xd0, 0x48, 0x61, 0xd1, 0x11, 0x9d, 0xd0, 0xc3, 0x28, 0xad, 0xf3, 0xf6,
+ 0x8f, 0xb0, 0x94, 0xb8, 0x67, 0x71, 0x6b, 0xd7, 0xdc, 0x0d, 0xee, 0xbb,
+ 0x10, 0xb8, 0x24, 0x0e, 0x68, 0x03, 0x48, 0x93, 0xea, 0xd8, 0x2d, 0x54,
+ 0xc9, 0xda, 0x75, 0x4c, 0x46, 0xc7, 0xee, 0xe0, 0xc3, 0x7f, 0xdb, 0xee,
+ 0x48, 0x53, 0x60, 0x47, 0xa6, 0xfa, 0x1a, 0xe4, 0x9a, 0x03, 0x18, 0xcc,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* q=(p-1)/2 for prime prime_tls_4096 */
+static const unsigned char subprime_tls_4096_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xfc, 0x2a, 0x2c,
+ 0x51, 0x5d, 0xa5, 0x4d, 0x57, 0xee, 0x2b, 0x10, 0x13, 0x9e, 0x9e, 0x78,
+ 0xec, 0x5c, 0xe2, 0xc1, 0xe7, 0x16, 0x9b, 0x4a, 0xd4, 0xf0, 0x9b, 0x20,
+ 0x8a, 0x32, 0x19, 0xfd, 0xe6, 0x49, 0xce, 0xe7, 0x12, 0x4d, 0x9f, 0x7c,
+ 0xbe, 0x97, 0xf1, 0xb1, 0xb1, 0x86, 0x3a, 0xec, 0x7b, 0x40, 0xd9, 0x01,
+ 0x57, 0x62, 0x30, 0xbd, 0x69, 0xef, 0x8f, 0x6a, 0xea, 0xfe, 0xb2, 0xb0,
+ 0x92, 0x19, 0xfa, 0x8f, 0xaf, 0x83, 0x37, 0x68, 0x42, 0xb1, 0xb2, 0xaa,
+ 0x9e, 0xf6, 0x8d, 0x79, 0xda, 0xab, 0x89, 0xaf, 0x3f, 0xab, 0xe4, 0x9a,
+ 0xcc, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xbb, 0xf1, 0x53, 0x44, 0xed,
+ 0x79, 0xf7, 0xf4, 0x39, 0x0e, 0xf8, 0xac, 0x50, 0x9b, 0x56, 0xf3, 0x9a,
+ 0x98, 0x56, 0x65, 0x27, 0xa4, 0x1d, 0x3c, 0xbd, 0x5e, 0x05, 0x58, 0xc1,
+ 0x59, 0x92, 0x7d, 0xb0, 0xe8, 0x84, 0x54, 0xa5, 0xd9, 0x64, 0x71, 0xfd,
+ 0xdc, 0xb5, 0x6d, 0x5b, 0xb0, 0x6b, 0xfa, 0x34, 0x0e, 0xa7, 0xa1, 0x51,
+ 0xef, 0x1c, 0xa6, 0xfa, 0x57, 0x2b, 0x76, 0xf3, 0xb1, 0xb9, 0x5d, 0x8c,
+ 0x85, 0x83, 0xd3, 0xe4, 0x77, 0x05, 0x36, 0xb8, 0x4f, 0x01, 0x7e, 0x70,
+ 0xe6, 0xfb, 0xf1, 0x76, 0x60, 0x1a, 0x02, 0x66, 0x94, 0x1a, 0x17, 0xb0,
+ 0xc8, 0xb9, 0x7f, 0x4e, 0x74, 0xc2, 0xc1, 0xff, 0xc7, 0x27, 0x89, 0x19,
+ 0x77, 0x79, 0x40, 0xc1, 0xe1, 0xff, 0x1d, 0x8d, 0xa6, 0x37, 0xd6, 0xb9,
+ 0x9d, 0xda, 0xfe, 0x5e, 0x17, 0x61, 0x10, 0x02, 0xe2, 0xc7, 0x78, 0xc1,
+ 0xbe, 0x8b, 0x41, 0xd9, 0x63, 0x79, 0xa5, 0x13, 0x60, 0xd9, 0x77, 0xfd,
+ 0x44, 0x35, 0xa1, 0x1c, 0x30, 0x8f, 0xe7, 0xee, 0x6f, 0x1a, 0xad, 0x9d,
+ 0xb2, 0x8c, 0x81, 0xad, 0xde, 0x1a, 0x7a, 0x6f, 0x7c, 0xce, 0x01, 0x1c,
+ 0x30, 0xda, 0x37, 0xe4, 0xeb, 0x73, 0x64, 0x83, 0xbd, 0x6c, 0x8e, 0x93,
+ 0x48, 0xfb, 0xfb, 0xf7, 0x2c, 0xc6, 0x58, 0x7d, 0x60, 0xc3, 0x6c, 0x8e,
+ 0x57, 0x7f, 0x09, 0x84, 0xc2, 0x89, 0xc9, 0x38, 0x5a, 0x09, 0x86, 0x49,
+ 0xde, 0x21, 0xbc, 0xa2, 0x7a, 0x7e, 0xa2, 0x29, 0x71, 0x6b, 0xa6, 0xe9,
+ 0xb2, 0x79, 0x71, 0x0f, 0x38, 0xfa, 0xa5, 0xff, 0xae, 0x57, 0x41, 0x55,
+ 0xce, 0x4e, 0xfb, 0x4f, 0x74, 0x36, 0x95, 0xe2, 0x91, 0x1b, 0x1d, 0x06,
+ 0xd5, 0xe2, 0x90, 0xcb, 0xcd, 0x86, 0xf5, 0x6d, 0x0e, 0xdf, 0xcd, 0x21,
+ 0x6a, 0xe2, 0x24, 0x27, 0x05, 0x5e, 0x68, 0x35, 0xfd, 0x29, 0xee, 0xf7,
+ 0x9e, 0x0d, 0x90, 0x77, 0x1f, 0xea, 0xce, 0xbe, 0x12, 0xf2, 0x0e, 0x95,
+ 0xb3, 0x4f, 0x0f, 0x78, 0xb7, 0x37, 0xa9, 0x61, 0x8b, 0x26, 0xfa, 0x7d,
+ 0xbc, 0x98, 0x74, 0xf2, 0x72, 0xc4, 0x2b, 0xdb, 0x56, 0x3e, 0xaf, 0xa1,
+ 0x6b, 0x4f, 0xb6, 0x8c, 0x3b, 0xb1, 0xe7, 0x8e, 0xaa, 0x81, 0xa0, 0x02,
+ 0x43, 0xfa, 0xad, 0xd2, 0xbf, 0x18, 0xe6, 0x3d, 0x38, 0x9a, 0xe4, 0x43,
+ 0x77, 0xda, 0x18, 0xc5, 0x76, 0xb5, 0x0f, 0x00, 0x96, 0xcf, 0x34, 0x19,
+ 0x54, 0x83, 0xb0, 0x05, 0x48, 0xc0, 0x98, 0x62, 0x36, 0xe3, 0xbc, 0x7c,
+ 0xb8, 0xd6, 0x80, 0x1c, 0x04, 0x94, 0xcc, 0xd1, 0x99, 0xe5, 0xc5, 0xbd,
+ 0x0d, 0x0e, 0xdc, 0x9e, 0xb8, 0xa0, 0x00, 0x1e, 0x15, 0x27, 0x67, 0x54,
+ 0xfc, 0xc6, 0x85, 0x66, 0x05, 0x41, 0x48, 0xe6, 0xe7, 0x64, 0xbe, 0xe7,
+ 0xc7, 0x64, 0xda, 0xad, 0x3f, 0xc4, 0x52, 0x35, 0xa6, 0xda, 0xd4, 0x28,
+ 0xfa, 0x20, 0xc1, 0x70, 0xe3, 0x45, 0x00, 0x3f, 0x2f, 0x32, 0xaf, 0xb5,
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* q=(p-1)/2 for prime prime_ike_6144 */
+static const unsigned char subprime_ike_6144_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x87, 0xed, 0x51,
+ 0x10, 0xb4, 0x61, 0x1a, 0x62, 0x63, 0x31, 0x45, 0xc0, 0x6e, 0x0e, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xe6, 0x3a, 0x01, 0x05, 0xdf, 0x53,
+ 0x1d, 0x89, 0xcd, 0x91, 0x28, 0xa5, 0x04, 0x3c, 0xc7, 0x1a, 0x02, 0x6e,
+ 0xf7, 0xca, 0x8c, 0xd9, 0xe6, 0x9d, 0x21, 0x8d, 0x98, 0x15, 0x85, 0x36,
+ 0xf9, 0x2f, 0x8a, 0x1b, 0xa7, 0xf0, 0x9a, 0xb6, 0xb6, 0xa8, 0xe1, 0x22,
+ 0xf2, 0x42, 0xda, 0xbb, 0x31, 0x2f, 0x3f, 0x63, 0x7a, 0x26, 0x21, 0x74,
+ 0xd3, 0x1b, 0xf6, 0xb5, 0x85, 0xff, 0xae, 0x5b, 0x7a, 0x03, 0x5b, 0xf6,
+ 0xf7, 0x1c, 0x35, 0xfd, 0xad, 0x44, 0xcf, 0xd2, 0xd7, 0x4f, 0x92, 0x08,
+ 0xbe, 0x25, 0x8f, 0xf3, 0x24, 0x94, 0x33, 0x28, 0xf6, 0x72, 0x2d, 0x9e,
+ 0xe1, 0x00, 0x3e, 0x5c, 0x50, 0xb1, 0xdf, 0x82, 0xcc, 0x6d, 0x24, 0x1b,
+ 0x0e, 0x2a, 0xe9, 0xcd, 0x34, 0x8b, 0x1f, 0xd4, 0x7e, 0x92, 0x67, 0xaf,
+ 0xc1, 0xb2, 0xae, 0x91, 0xee, 0x51, 0xd6, 0xcb, 0x0e, 0x31, 0x79, 0xab,
+ 0x10, 0x42, 0xa9, 0x5d, 0xcf, 0x6a, 0x94, 0x83, 0xb8, 0x4b, 0x4b, 0x36,
+ 0xb3, 0x86, 0x1a, 0xa7, 0x25, 0x5e, 0x4c, 0x02, 0x78, 0xba, 0x36, 0x04,
+ 0x65, 0x0c, 0x10, 0xbe, 0x19, 0x48, 0x2f, 0x23, 0x17, 0x1b, 0x67, 0x1d,
+ 0xf1, 0xcf, 0x3b, 0x96, 0x0c, 0x07, 0x43, 0x01, 0xcd, 0x93, 0xc1, 0xd1,
+ 0x76, 0x03, 0xd1, 0x47, 0xda, 0xe2, 0xae, 0xf8, 0x37, 0xa6, 0x29, 0x64,
+ 0xef, 0x15, 0xe5, 0xfb, 0x4a, 0xac, 0x0b, 0x8c, 0x1c, 0xca, 0xa4, 0xbe,
+ 0x75, 0x4a, 0xb5, 0x72, 0x8a, 0xe9, 0x13, 0x0c, 0x4c, 0x7d, 0x02, 0x88,
+ 0x0a, 0xb9, 0x47, 0x2d, 0x45, 0x55, 0x62, 0x16, 0xd6, 0x99, 0x8b, 0x86,
+ 0x82, 0x28, 0x3d, 0x19, 0xd4, 0x2a, 0x90, 0xd5, 0xef, 0x8e, 0x5d, 0x32,
+ 0x76, 0x7d, 0xc2, 0x82, 0x2c, 0x6d, 0xf7, 0x85, 0x45, 0x75, 0x38, 0xab,
+ 0xae, 0x83, 0x06, 0x3e, 0xd9, 0xcb, 0x87, 0xc2, 0xd3, 0x70, 0xf2, 0x63,
+ 0xd5, 0xfa, 0xd7, 0x46, 0x6d, 0x84, 0x99, 0xeb, 0x8f, 0x46, 0x4a, 0x70,
+ 0x25, 0x12, 0xb0, 0xce, 0xe7, 0x71, 0xe9, 0x13, 0x0d, 0x69, 0x77, 0x35,
+ 0xf8, 0x97, 0xfd, 0x03, 0x6c, 0xc5, 0x04, 0x32, 0x6c, 0x3b, 0x01, 0x39,
+ 0x9f, 0x64, 0x35, 0x32, 0x29, 0x0f, 0x95, 0x8c, 0x0b, 0xbd, 0x90, 0x06,
+ 0x5d, 0xf0, 0x8b, 0xab, 0xbd, 0x30, 0xae, 0xb6, 0x3b, 0x84, 0xc4, 0x60,
+ 0x5d, 0x6c, 0xa3, 0x71, 0x04, 0x71, 0x27, 0xd0, 0x3a, 0x72, 0xd5, 0x98,
+ 0xa1, 0xed, 0xad, 0xfe, 0x70, 0x7e, 0x88, 0x47, 0x25, 0xc1, 0x68, 0x90,
+ 0x54, 0x90, 0x84, 0x00, 0x8d, 0x39, 0x1e, 0x09, 0x53, 0xc3, 0xf3, 0x6b,
+ 0xc4, 0x38, 0xcd, 0x08, 0x5e, 0xdd, 0x2d, 0x93, 0x4c, 0xe1, 0x93, 0x8c,
+ 0x35, 0x7a, 0x71, 0x1e, 0x0d, 0x4a, 0x34, 0x1a, 0x5b, 0x0a, 0x85, 0xed,
+ 0x12, 0xc1, 0xf4, 0xe5, 0x15, 0x6a, 0x26, 0x74, 0x6d, 0xdd, 0xe1, 0x6d,
+ 0x82, 0x6f, 0x47, 0x7c, 0x97, 0x47, 0x7e, 0x0a, 0x0f, 0xdf, 0x65, 0x53,
+ 0x14, 0x3e, 0x2c, 0xa3, 0xa7, 0x35, 0xe0, 0x2e, 0xcc, 0xd9, 0x4b, 0x27,
+ 0xd0, 0x48, 0x61, 0xd1, 0x11, 0x9d, 0xd0, 0xc3, 0x28, 0xad, 0xf3, 0xf6,
+ 0x8f, 0xb0, 0x94, 0xb8, 0x67, 0x71, 0x6b, 0xd7, 0xdc, 0x0d, 0xee, 0xbb,
+ 0x10, 0xb8, 0x24, 0x0e, 0x68, 0x03, 0x48, 0x93, 0xea, 0xd8, 0x2d, 0x54,
+ 0xc9, 0xda, 0x75, 0x4c, 0x46, 0xc7, 0xee, 0xe0, 0xc3, 0x7f, 0xdb, 0xee,
+ 0x48, 0x53, 0x60, 0x47, 0xa6, 0xfa, 0x1a, 0xe4, 0x9a, 0x01, 0x42, 0x49,
+ 0x1b, 0x61, 0xfd, 0x5a, 0x69, 0x3e, 0x38, 0x13, 0x60, 0xea, 0x6e, 0x59,
+ 0x30, 0x13, 0x23, 0x6f, 0x64, 0xba, 0x8f, 0x3b, 0x1e, 0xdd, 0x1b, 0xde,
+ 0xfc, 0x7f, 0xca, 0x03, 0x56, 0xcf, 0x29, 0x87, 0x72, 0xed, 0x9c, 0x17,
+ 0xa0, 0x98, 0x00, 0xd7, 0x58, 0x35, 0x29, 0xf6, 0xc8, 0x13, 0xec, 0x18,
+ 0x8b, 0xcb, 0x93, 0xd8, 0x43, 0x2d, 0x44, 0x8c, 0x6d, 0x1f, 0x6d, 0xf5,
+ 0xe7, 0xcd, 0x8a, 0x76, 0xa2, 0x67, 0x36, 0x5d, 0x67, 0x6a, 0x5d, 0x8d,
+ 0xed, 0xbf, 0x8a, 0x23, 0xf3, 0x66, 0x12, 0xa5, 0x99, 0x90, 0x28, 0xa8,
+ 0x95, 0xeb, 0xd7, 0xa1, 0x37, 0xdc, 0x7a, 0x00, 0x9b, 0xc6, 0x69, 0x5f,
+ 0xac, 0xc1, 0xe5, 0x00, 0xe3, 0x25, 0xc9, 0x76, 0x78, 0x19, 0x75, 0x0a,
+ 0xe8, 0xb9, 0x0e, 0x81, 0xfa, 0x41, 0x6b, 0xe7, 0x37, 0x3a, 0x7f, 0x7b,
+ 0x6a, 0xaf, 0x38, 0x17, 0xa3, 0x4c, 0x06, 0x41, 0x5a, 0xd4, 0x20, 0x18,
+ 0xc8, 0x05, 0x8e, 0x4f, 0x2c, 0xf3, 0xe4, 0xbf, 0xdf, 0x63, 0xf4, 0x79,
+ 0x91, 0xd4, 0xbd, 0x3f, 0x1b, 0x66, 0x44, 0x5f, 0x07, 0x8e, 0xa2, 0xdb,
+ 0xff, 0xac, 0x2d, 0x62, 0xa5, 0xea, 0x03, 0xd9, 0x15, 0xa0, 0xaa, 0x55,
+ 0x66, 0x47, 0xb6, 0xbf, 0x5f, 0xa4, 0x70, 0xec, 0x0a, 0x66, 0x2f, 0x69,
+ 0x07, 0xc0, 0x1b, 0xf0, 0x53, 0xcb, 0x8a, 0xf7, 0x79, 0x4d, 0xf1, 0x94,
+ 0x03, 0x50, 0xea, 0xc5, 0xdb, 0xe2, 0xed, 0x3b, 0x7a, 0xa8, 0x55, 0x1e,
+ 0xc5, 0x0f, 0xdf, 0xf8, 0x75, 0x8c, 0xe6, 0x58, 0xd1, 0x89, 0xea, 0xae,
+ 0x6d, 0x2b, 0x64, 0xf6, 0x17, 0x79, 0x4b, 0x19, 0x1c, 0x3f, 0xf4, 0x6b,
+ 0xb7, 0x1e, 0x02, 0x34, 0x02, 0x1f, 0x47, 0xb3, 0x1f, 0xa4, 0x30, 0x77,
+ 0x09, 0x5f, 0x96, 0xad, 0x85, 0xba, 0x3a, 0x6b, 0x73, 0x4a, 0x7c, 0x8f,
+ 0x36, 0xe6, 0x20, 0x12, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* q=(p-1)/2 for prime prime_tls_6144 */
+static const unsigned char subprime_tls_6144_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xfc, 0x2a, 0x2c,
+ 0x51, 0x5d, 0xa5, 0x4d, 0x57, 0xee, 0x2b, 0x10, 0x13, 0x9e, 0x9e, 0x78,
+ 0xec, 0x5c, 0xe2, 0xc1, 0xe7, 0x16, 0x9b, 0x4a, 0xd4, 0xf0, 0x9b, 0x20,
+ 0x8a, 0x32, 0x19, 0xfd, 0xe6, 0x49, 0xce, 0xe7, 0x12, 0x4d, 0x9f, 0x7c,
+ 0xbe, 0x97, 0xf1, 0xb1, 0xb1, 0x86, 0x3a, 0xec, 0x7b, 0x40, 0xd9, 0x01,
+ 0x57, 0x62, 0x30, 0xbd, 0x69, 0xef, 0x8f, 0x6a, 0xea, 0xfe, 0xb2, 0xb0,
+ 0x92, 0x19, 0xfa, 0x8f, 0xaf, 0x83, 0x37, 0x68, 0x42, 0xb1, 0xb2, 0xaa,
+ 0x9e, 0xf6, 0x8d, 0x79, 0xda, 0xab, 0x89, 0xaf, 0x3f, 0xab, 0xe4, 0x9a,
+ 0xcc, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xbb, 0xf1, 0x53, 0x44, 0xed,
+ 0x79, 0xf7, 0xf4, 0x39, 0x0e, 0xf8, 0xac, 0x50, 0x9b, 0x56, 0xf3, 0x9a,
+ 0x98, 0x56, 0x65, 0x27, 0xa4, 0x1d, 0x3c, 0xbd, 0x5e, 0x05, 0x58, 0xc1,
+ 0x59, 0x92, 0x7d, 0xb0, 0xe8, 0x84, 0x54, 0xa5, 0xd9, 0x64, 0x71, 0xfd,
+ 0xdc, 0xb5, 0x6d, 0x5b, 0xb0, 0x6b, 0xfa, 0x34, 0x0e, 0xa7, 0xa1, 0x51,
+ 0xef, 0x1c, 0xa6, 0xfa, 0x57, 0x2b, 0x76, 0xf3, 0xb1, 0xb9, 0x5d, 0x8c,
+ 0x85, 0x83, 0xd3, 0xe4, 0x77, 0x05, 0x36, 0xb8, 0x4f, 0x01, 0x7e, 0x70,
+ 0xe6, 0xfb, 0xf1, 0x76, 0x60, 0x1a, 0x02, 0x66, 0x94, 0x1a, 0x17, 0xb0,
+ 0xc8, 0xb9, 0x7f, 0x4e, 0x74, 0xc2, 0xc1, 0xff, 0xc7, 0x27, 0x89, 0x19,
+ 0x77, 0x79, 0x40, 0xc1, 0xe1, 0xff, 0x1d, 0x8d, 0xa6, 0x37, 0xd6, 0xb9,
+ 0x9d, 0xda, 0xfe, 0x5e, 0x17, 0x61, 0x10, 0x02, 0xe2, 0xc7, 0x78, 0xc1,
+ 0xbe, 0x8b, 0x41, 0xd9, 0x63, 0x79, 0xa5, 0x13, 0x60, 0xd9, 0x77, 0xfd,
+ 0x44, 0x35, 0xa1, 0x1c, 0x30, 0x8f, 0xe7, 0xee, 0x6f, 0x1a, 0xad, 0x9d,
+ 0xb2, 0x8c, 0x81, 0xad, 0xde, 0x1a, 0x7a, 0x6f, 0x7c, 0xce, 0x01, 0x1c,
+ 0x30, 0xda, 0x37, 0xe4, 0xeb, 0x73, 0x64, 0x83, 0xbd, 0x6c, 0x8e, 0x93,
+ 0x48, 0xfb, 0xfb, 0xf7, 0x2c, 0xc6, 0x58, 0x7d, 0x60, 0xc3, 0x6c, 0x8e,
+ 0x57, 0x7f, 0x09, 0x84, 0xc2, 0x89, 0xc9, 0x38, 0x5a, 0x09, 0x86, 0x49,
+ 0xde, 0x21, 0xbc, 0xa2, 0x7a, 0x7e, 0xa2, 0x29, 0x71, 0x6b, 0xa6, 0xe9,
+ 0xb2, 0x79, 0x71, 0x0f, 0x38, 0xfa, 0xa5, 0xff, 0xae, 0x57, 0x41, 0x55,
+ 0xce, 0x4e, 0xfb, 0x4f, 0x74, 0x36, 0x95, 0xe2, 0x91, 0x1b, 0x1d, 0x06,
+ 0xd5, 0xe2, 0x90, 0xcb, 0xcd, 0x86, 0xf5, 0x6d, 0x0e, 0xdf, 0xcd, 0x21,
+ 0x6a, 0xe2, 0x24, 0x27, 0x05, 0x5e, 0x68, 0x35, 0xfd, 0x29, 0xee, 0xf7,
+ 0x9e, 0x0d, 0x90, 0x77, 0x1f, 0xea, 0xce, 0xbe, 0x12, 0xf2, 0x0e, 0x95,
+ 0xb3, 0x4f, 0x0f, 0x78, 0xb7, 0x37, 0xa9, 0x61, 0x8b, 0x26, 0xfa, 0x7d,
+ 0xbc, 0x98, 0x74, 0xf2, 0x72, 0xc4, 0x2b, 0xdb, 0x56, 0x3e, 0xaf, 0xa1,
+ 0x6b, 0x4f, 0xb6, 0x8c, 0x3b, 0xb1, 0xe7, 0x8e, 0xaa, 0x81, 0xa0, 0x02,
+ 0x43, 0xfa, 0xad, 0xd2, 0xbf, 0x18, 0xe6, 0x3d, 0x38, 0x9a, 0xe4, 0x43,
+ 0x77, 0xda, 0x18, 0xc5, 0x76, 0xb5, 0x0f, 0x00, 0x96, 0xcf, 0x34, 0x19,
+ 0x54, 0x83, 0xb0, 0x05, 0x48, 0xc0, 0x98, 0x62, 0x36, 0xe3, 0xbc, 0x7c,
+ 0xb8, 0xd6, 0x80, 0x1c, 0x04, 0x94, 0xcc, 0xd1, 0x99, 0xe5, 0xc5, 0xbd,
+ 0x0d, 0x0e, 0xdc, 0x9e, 0xb8, 0xa0, 0x00, 0x1e, 0x15, 0x27, 0x67, 0x54,
+ 0xfc, 0xc6, 0x85, 0x66, 0x05, 0x41, 0x48, 0xe6, 0xe7, 0x64, 0xbe, 0xe7,
+ 0xc7, 0x64, 0xda, 0xad, 0x3f, 0xc4, 0x52, 0x35, 0xa6, 0xda, 0xd4, 0x28,
+ 0xfa, 0x20, 0xc1, 0x70, 0xe3, 0x45, 0x00, 0x3f, 0x2f, 0x06, 0xec, 0x81,
+ 0x05, 0xfe, 0xb2, 0x5b, 0x22, 0x81, 0xb6, 0x3d, 0x27, 0x33, 0xbe, 0x96,
+ 0x1c, 0x29, 0x95, 0x1d, 0x11, 0xdd, 0x22, 0x21, 0x65, 0x7a, 0x9f, 0x53,
+ 0x1d, 0xda, 0x2a, 0x19, 0x4d, 0xbb, 0x12, 0x64, 0x48, 0xbd, 0xee, 0xb2,
+ 0x58, 0xe0, 0x7e, 0xa6, 0x59, 0xc7, 0x46, 0x19, 0xa6, 0x38, 0x0e, 0x1d,
+ 0x66, 0xd6, 0x83, 0x2b, 0xfe, 0x67, 0xf6, 0x38, 0xcd, 0x8f, 0xae, 0x1f,
+ 0x27, 0x23, 0x02, 0x0f, 0x9c, 0x40, 0xa3, 0xfd, 0xa6, 0x7e, 0xda, 0x3b,
+ 0xd2, 0x92, 0x38, 0xfb, 0xd4, 0xd4, 0xb4, 0x88, 0x5c, 0x2a, 0x99, 0x17,
+ 0x6d, 0xb1, 0xa0, 0x6c, 0x50, 0x07, 0x78, 0x49, 0x1a, 0x82, 0x88, 0xf1,
+ 0x85, 0x5f, 0x60, 0xff, 0xfc, 0xf1, 0xd1, 0x37, 0x3f, 0xd9, 0x4f, 0xc6,
+ 0x0c, 0x18, 0x11, 0xe1, 0xac, 0x3f, 0x1c, 0x6d, 0x00, 0x3b, 0xec, 0xda,
+ 0x3b, 0x1f, 0x27, 0x25, 0xca, 0x59, 0x5d, 0xe0, 0xca, 0x63, 0x32, 0x8f,
+ 0x3b, 0xe5, 0x7c, 0xc9, 0x77, 0x55, 0x60, 0x11, 0x95, 0x14, 0x0d, 0xfb,
+ 0x59, 0xd3, 0x9c, 0xe0, 0x91, 0x30, 0x8b, 0x41, 0x05, 0x74, 0x6d, 0xac,
+ 0x23, 0xd3, 0x3e, 0x5f, 0x7c, 0xe4, 0x84, 0x8d, 0xa3, 0x16, 0xa9, 0xc6,
+ 0x6b, 0x95, 0x81, 0xba, 0x35, 0x73, 0xbf, 0xaf, 0x31, 0x14, 0x96, 0x18,
+ 0x8a, 0xb1, 0x54, 0x23, 0x28, 0x2e, 0xe4, 0x16, 0xdc, 0x2a, 0x19, 0xc5,
+ 0x72, 0x4f, 0xa9, 0x1a, 0xe4, 0xad, 0xc8, 0x8b, 0xc6, 0x67, 0x96, 0xea,
+ 0xe5, 0x67, 0x7a, 0x01, 0xf6, 0x4e, 0x8c, 0x08, 0x63, 0x13, 0x95, 0x82,
+ 0x2d, 0x9d, 0xb8, 0xfc, 0xee, 0x35, 0xc0, 0x6b, 0x1f, 0xee, 0xa5, 0x47,
+ 0x4d, 0x6d, 0x8f, 0x34, 0xb1, 0x53, 0x4a, 0x93, 0x6a, 0x18, 0xb0, 0xe0,
+ 0xd2, 0x0e, 0xab, 0x86, 0xbc, 0x9c, 0x6d, 0x6a, 0x52, 0x07, 0x19, 0x4e,
+ 0x68, 0x72, 0x07, 0x32, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/* q=(p-1)/2 for prime prime_ike_8192 */
+static const unsigned char subprime_ike_8192_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x87, 0xed, 0x51,
+ 0x10, 0xb4, 0x61, 0x1a, 0x62, 0x63, 0x31, 0x45, 0xc0, 0x6e, 0x0e, 0x68,
+ 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xe6, 0x3a, 0x01, 0x05, 0xdf, 0x53,
+ 0x1d, 0x89, 0xcd, 0x91, 0x28, 0xa5, 0x04, 0x3c, 0xc7, 0x1a, 0x02, 0x6e,
+ 0xf7, 0xca, 0x8c, 0xd9, 0xe6, 0x9d, 0x21, 0x8d, 0x98, 0x15, 0x85, 0x36,
+ 0xf9, 0x2f, 0x8a, 0x1b, 0xa7, 0xf0, 0x9a, 0xb6, 0xb6, 0xa8, 0xe1, 0x22,
+ 0xf2, 0x42, 0xda, 0xbb, 0x31, 0x2f, 0x3f, 0x63, 0x7a, 0x26, 0x21, 0x74,
+ 0xd3, 0x1b, 0xf6, 0xb5, 0x85, 0xff, 0xae, 0x5b, 0x7a, 0x03, 0x5b, 0xf6,
+ 0xf7, 0x1c, 0x35, 0xfd, 0xad, 0x44, 0xcf, 0xd2, 0xd7, 0x4f, 0x92, 0x08,
+ 0xbe, 0x25, 0x8f, 0xf3, 0x24, 0x94, 0x33, 0x28, 0xf6, 0x72, 0x2d, 0x9e,
+ 0xe1, 0x00, 0x3e, 0x5c, 0x50, 0xb1, 0xdf, 0x82, 0xcc, 0x6d, 0x24, 0x1b,
+ 0x0e, 0x2a, 0xe9, 0xcd, 0x34, 0x8b, 0x1f, 0xd4, 0x7e, 0x92, 0x67, 0xaf,
+ 0xc1, 0xb2, 0xae, 0x91, 0xee, 0x51, 0xd6, 0xcb, 0x0e, 0x31, 0x79, 0xab,
+ 0x10, 0x42, 0xa9, 0x5d, 0xcf, 0x6a, 0x94, 0x83, 0xb8, 0x4b, 0x4b, 0x36,
+ 0xb3, 0x86, 0x1a, 0xa7, 0x25, 0x5e, 0x4c, 0x02, 0x78, 0xba, 0x36, 0x04,
+ 0x65, 0x0c, 0x10, 0xbe, 0x19, 0x48, 0x2f, 0x23, 0x17, 0x1b, 0x67, 0x1d,
+ 0xf1, 0xcf, 0x3b, 0x96, 0x0c, 0x07, 0x43, 0x01, 0xcd, 0x93, 0xc1, 0xd1,
+ 0x76, 0x03, 0xd1, 0x47, 0xda, 0xe2, 0xae, 0xf8, 0x37, 0xa6, 0x29, 0x64,
+ 0xef, 0x15, 0xe5, 0xfb, 0x4a, 0xac, 0x0b, 0x8c, 0x1c, 0xca, 0xa4, 0xbe,
+ 0x75, 0x4a, 0xb5, 0x72, 0x8a, 0xe9, 0x13, 0x0c, 0x4c, 0x7d, 0x02, 0x88,
+ 0x0a, 0xb9, 0x47, 0x2d, 0x45, 0x55, 0x62, 0x16, 0xd6, 0x99, 0x8b, 0x86,
+ 0x82, 0x28, 0x3d, 0x19, 0xd4, 0x2a, 0x90, 0xd5, 0xef, 0x8e, 0x5d, 0x32,
+ 0x76, 0x7d, 0xc2, 0x82, 0x2c, 0x6d, 0xf7, 0x85, 0x45, 0x75, 0x38, 0xab,
+ 0xae, 0x83, 0x06, 0x3e, 0xd9, 0xcb, 0x87, 0xc2, 0xd3, 0x70, 0xf2, 0x63,
+ 0xd5, 0xfa, 0xd7, 0x46, 0x6d, 0x84, 0x99, 0xeb, 0x8f, 0x46, 0x4a, 0x70,
+ 0x25, 0x12, 0xb0, 0xce, 0xe7, 0x71, 0xe9, 0x13, 0x0d, 0x69, 0x77, 0x35,
+ 0xf8, 0x97, 0xfd, 0x03, 0x6c, 0xc5, 0x04, 0x32, 0x6c, 0x3b, 0x01, 0x39,
+ 0x9f, 0x64, 0x35, 0x32, 0x29, 0x0f, 0x95, 0x8c, 0x0b, 0xbd, 0x90, 0x06,
+ 0x5d, 0xf0, 0x8b, 0xab, 0xbd, 0x30, 0xae, 0xb6, 0x3b, 0x84, 0xc4, 0x60,
+ 0x5d, 0x6c, 0xa3, 0x71, 0x04, 0x71, 0x27, 0xd0, 0x3a, 0x72, 0xd5, 0x98,
+ 0xa1, 0xed, 0xad, 0xfe, 0x70, 0x7e, 0x88, 0x47, 0x25, 0xc1, 0x68, 0x90,
+ 0x54, 0x90, 0x84, 0x00, 0x8d, 0x39, 0x1e, 0x09, 0x53, 0xc3, 0xf3, 0x6b,
+ 0xc4, 0x38, 0xcd, 0x08, 0x5e, 0xdd, 0x2d, 0x93, 0x4c, 0xe1, 0x93, 0x8c,
+ 0x35, 0x7a, 0x71, 0x1e, 0x0d, 0x4a, 0x34, 0x1a, 0x5b, 0x0a, 0x85, 0xed,
+ 0x12, 0xc1, 0xf4, 0xe5, 0x15, 0x6a, 0x26, 0x74, 0x6d, 0xdd, 0xe1, 0x6d,
+ 0x82, 0x6f, 0x47, 0x7c, 0x97, 0x47, 0x7e, 0x0a, 0x0f, 0xdf, 0x65, 0x53,
+ 0x14, 0x3e, 0x2c, 0xa3, 0xa7, 0x35, 0xe0, 0x2e, 0xcc, 0xd9, 0x4b, 0x27,
+ 0xd0, 0x48, 0x61, 0xd1, 0x11, 0x9d, 0xd0, 0xc3, 0x28, 0xad, 0xf3, 0xf6,
+ 0x8f, 0xb0, 0x94, 0xb8, 0x67, 0x71, 0x6b, 0xd7, 0xdc, 0x0d, 0xee, 0xbb,
+ 0x10, 0xb8, 0x24, 0x0e, 0x68, 0x03, 0x48, 0x93, 0xea, 0xd8, 0x2d, 0x54,
+ 0xc9, 0xda, 0x75, 0x4c, 0x46, 0xc7, 0xee, 0xe0, 0xc3, 0x7f, 0xdb, 0xee,
+ 0x48, 0x53, 0x60, 0x47, 0xa6, 0xfa, 0x1a, 0xe4, 0x9a, 0x01, 0x42, 0x49,
+ 0x1b, 0x61, 0xfd, 0x5a, 0x69, 0x3e, 0x38, 0x13, 0x60, 0xea, 0x6e, 0x59,
+ 0x30, 0x13, 0x23, 0x6f, 0x64, 0xba, 0x8f, 0x3b, 0x1e, 0xdd, 0x1b, 0xde,
+ 0xfc, 0x7f, 0xca, 0x03, 0x56, 0xcf, 0x29, 0x87, 0x72, 0xed, 0x9c, 0x17,
+ 0xa0, 0x98, 0x00, 0xd7, 0x58, 0x35, 0x29, 0xf6, 0xc8, 0x13, 0xec, 0x18,
+ 0x8b, 0xcb, 0x93, 0xd8, 0x43, 0x2d, 0x44, 0x8c, 0x6d, 0x1f, 0x6d, 0xf5,
+ 0xe7, 0xcd, 0x8a, 0x76, 0xa2, 0x67, 0x36, 0x5d, 0x67, 0x6a, 0x5d, 0x8d,
+ 0xed, 0xbf, 0x8a, 0x23, 0xf3, 0x66, 0x12, 0xa5, 0x99, 0x90, 0x28, 0xa8,
+ 0x95, 0xeb, 0xd7, 0xa1, 0x37, 0xdc, 0x7a, 0x00, 0x9b, 0xc6, 0x69, 0x5f,
+ 0xac, 0xc1, 0xe5, 0x00, 0xe3, 0x25, 0xc9, 0x76, 0x78, 0x19, 0x75, 0x0a,
+ 0xe8, 0xb9, 0x0e, 0x81, 0xfa, 0x41, 0x6b, 0xe7, 0x37, 0x3a, 0x7f, 0x7b,
+ 0x6a, 0xaf, 0x38, 0x17, 0xa3, 0x4c, 0x06, 0x41, 0x5a, 0xd4, 0x20, 0x18,
+ 0xc8, 0x05, 0x8e, 0x4f, 0x2c, 0xf3, 0xe4, 0xbf, 0xdf, 0x63, 0xf4, 0x79,
+ 0x91, 0xd4, 0xbd, 0x3f, 0x1b, 0x66, 0x44, 0x5f, 0x07, 0x8e, 0xa2, 0xdb,
+ 0xff, 0xac, 0x2d, 0x62, 0xa5, 0xea, 0x03, 0xd9, 0x15, 0xa0, 0xaa, 0x55,
+ 0x66, 0x47, 0xb6, 0xbf, 0x5f, 0xa4, 0x70, 0xec, 0x0a, 0x66, 0x2f, 0x69,
+ 0x07, 0xc0, 0x1b, 0xf0, 0x53, 0xcb, 0x8a, 0xf7, 0x79, 0x4d, 0xf1, 0x94,
+ 0x03, 0x50, 0xea, 0xc5, 0xdb, 0xe2, 0xed, 0x3b, 0x7a, 0xa8, 0x55, 0x1e,
+ 0xc5, 0x0f, 0xdf, 0xf8, 0x75, 0x8c, 0xe6, 0x58, 0xd1, 0x89, 0xea, 0xae,
+ 0x6d, 0x2b, 0x64, 0xf6, 0x17, 0x79, 0x4b, 0x19, 0x1c, 0x3f, 0xf4, 0x6b,
+ 0xb7, 0x1e, 0x02, 0x34, 0x02, 0x1f, 0x47, 0xb3, 0x1f, 0xa4, 0x30, 0x77,
+ 0x09, 0x5f, 0x96, 0xad, 0x85, 0xba, 0x3a, 0x6b, 0x73, 0x4a, 0x7c, 0x8f,
+ 0x36, 0xdf, 0x08, 0xac, 0xba, 0x51, 0xc9, 0x37, 0x89, 0x7f, 0x72, 0xf2,
+ 0x1c, 0x3b, 0xbe, 0x5b, 0x54, 0x99, 0x6f, 0xc6, 0x6c, 0x5f, 0x62, 0x68,
+ 0x39, 0xdc, 0x98, 0xdd, 0x1d, 0xe4, 0x19, 0x5b, 0x46, 0xce, 0xe9, 0x80,
+ 0x3a, 0x0f, 0xd3, 0xdf, 0xc5, 0x7e, 0x23, 0xf6, 0x92, 0xbb, 0x7b, 0x49,
+ 0xb5, 0xd2, 0x12, 0x33, 0x1d, 0x55, 0xb1, 0xce, 0x2d, 0x72, 0x7a, 0xb4,
+ 0x1a, 0x11, 0xda, 0x3a, 0x15, 0xf8, 0xe4, 0xbc, 0x11, 0xc7, 0x8b, 0x65,
+ 0xf1, 0xce, 0xb2, 0x96, 0xf1, 0xfe, 0xdc, 0x5f, 0x7e, 0x42, 0x45, 0x6c,
+ 0x91, 0x11, 0x17, 0x02, 0x52, 0x01, 0xbe, 0x03, 0x89, 0xf5, 0xab, 0xd4,
+ 0x0d, 0x11, 0xf8, 0x63, 0x9a, 0x39, 0xfe, 0x32, 0x36, 0x75, 0x18, 0x35,
+ 0xa5, 0xe5, 0xe4, 0x43, 0x17, 0xc1, 0xc2, 0xee, 0xfd, 0x4e, 0xa5, 0xbf,
+ 0xd1, 0x60, 0x43, 0xf4, 0x3c, 0xb4, 0x19, 0x81, 0xf6, 0xad, 0xee, 0x9d,
+ 0x03, 0x15, 0x9e, 0x7a, 0xd9, 0xd1, 0x3c, 0x53, 0x36, 0x95, 0x09, 0xfc,
+ 0x1f, 0xa2, 0x7c, 0x16, 0xef, 0x98, 0x87, 0x70, 0x3a, 0x55, 0xb5, 0x1b,
+ 0x22, 0xcb, 0xf4, 0x4c, 0xd0, 0x12, 0xae, 0xe0, 0xb2, 0x79, 0x8e, 0x62,
+ 0x84, 0x23, 0x42, 0x8e, 0xfc, 0xd5, 0xa4, 0x0c, 0xae, 0xf6, 0xbf, 0x50,
+ 0xd8, 0xea, 0x88, 0x5e, 0xbf, 0x73, 0xa6, 0xb9, 0xfd, 0x79, 0xb5, 0xe1,
+ 0x8f, 0x67, 0xd1, 0x34, 0x1a, 0xc8, 0x23, 0x7a, 0x75, 0xc3, 0xcf, 0xc9,
+ 0x20, 0x04, 0xa1, 0xc5, 0xa4, 0x0e, 0x36, 0x6b, 0xc4, 0x4d, 0x00, 0x17,
+ 0x6a, 0xf7, 0x1c, 0x15, 0xe4, 0x8c, 0x86, 0xd3, 0x7e, 0x01, 0x37, 0x23,
+ 0xca, 0xac, 0x72, 0x23, 0xab, 0x3b, 0xf4, 0xd5, 0x4f, 0x18, 0x28, 0x71,
+ 0x3b, 0x2b, 0x4a, 0x6f, 0xe4, 0x0f, 0xab, 0x74, 0x40, 0x5c, 0xb7, 0x38,
+ 0xb0, 0x64, 0xc0, 0x6e, 0xcc, 0x76, 0xe9, 0xef, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+};
+
+/* q=(p-1)/2 for prime prime_tls_8192 */
+static const unsigned char subprime_tls_8192_data[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xfc, 0x2a, 0x2c,
+ 0x51, 0x5d, 0xa5, 0x4d, 0x57, 0xee, 0x2b, 0x10, 0x13, 0x9e, 0x9e, 0x78,
+ 0xec, 0x5c, 0xe2, 0xc1, 0xe7, 0x16, 0x9b, 0x4a, 0xd4, 0xf0, 0x9b, 0x20,
+ 0x8a, 0x32, 0x19, 0xfd, 0xe6, 0x49, 0xce, 0xe7, 0x12, 0x4d, 0x9f, 0x7c,
+ 0xbe, 0x97, 0xf1, 0xb1, 0xb1, 0x86, 0x3a, 0xec, 0x7b, 0x40, 0xd9, 0x01,
+ 0x57, 0x62, 0x30, 0xbd, 0x69, 0xef, 0x8f, 0x6a, 0xea, 0xfe, 0xb2, 0xb0,
+ 0x92, 0x19, 0xfa, 0x8f, 0xaf, 0x83, 0x37, 0x68, 0x42, 0xb1, 0xb2, 0xaa,
+ 0x9e, 0xf6, 0x8d, 0x79, 0xda, 0xab, 0x89, 0xaf, 0x3f, 0xab, 0xe4, 0x9a,
+ 0xcc, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xbb, 0xf1, 0x53, 0x44, 0xed,
+ 0x79, 0xf7, 0xf4, 0x39, 0x0e, 0xf8, 0xac, 0x50, 0x9b, 0x56, 0xf3, 0x9a,
+ 0x98, 0x56, 0x65, 0x27, 0xa4, 0x1d, 0x3c, 0xbd, 0x5e, 0x05, 0x58, 0xc1,
+ 0x59, 0x92, 0x7d, 0xb0, 0xe8, 0x84, 0x54, 0xa5, 0xd9, 0x64, 0x71, 0xfd,
+ 0xdc, 0xb5, 0x6d, 0x5b, 0xb0, 0x6b, 0xfa, 0x34, 0x0e, 0xa7, 0xa1, 0x51,
+ 0xef, 0x1c, 0xa6, 0xfa, 0x57, 0x2b, 0x76, 0xf3, 0xb1, 0xb9, 0x5d, 0x8c,
+ 0x85, 0x83, 0xd3, 0xe4, 0x77, 0x05, 0x36, 0xb8, 0x4f, 0x01, 0x7e, 0x70,
+ 0xe6, 0xfb, 0xf1, 0x76, 0x60, 0x1a, 0x02, 0x66, 0x94, 0x1a, 0x17, 0xb0,
+ 0xc8, 0xb9, 0x7f, 0x4e, 0x74, 0xc2, 0xc1, 0xff, 0xc7, 0x27, 0x89, 0x19,
+ 0x77, 0x79, 0x40, 0xc1, 0xe1, 0xff, 0x1d, 0x8d, 0xa6, 0x37, 0xd6, 0xb9,
+ 0x9d, 0xda, 0xfe, 0x5e, 0x17, 0x61, 0x10, 0x02, 0xe2, 0xc7, 0x78, 0xc1,
+ 0xbe, 0x8b, 0x41, 0xd9, 0x63, 0x79, 0xa5, 0x13, 0x60, 0xd9, 0x77, 0xfd,
+ 0x44, 0x35, 0xa1, 0x1c, 0x30, 0x8f, 0xe7, 0xee, 0x6f, 0x1a, 0xad, 0x9d,
+ 0xb2, 0x8c, 0x81, 0xad, 0xde, 0x1a, 0x7a, 0x6f, 0x7c, 0xce, 0x01, 0x1c,
+ 0x30, 0xda, 0x37, 0xe4, 0xeb, 0x73, 0x64, 0x83, 0xbd, 0x6c, 0x8e, 0x93,
+ 0x48, 0xfb, 0xfb, 0xf7, 0x2c, 0xc6, 0x58, 0x7d, 0x60, 0xc3, 0x6c, 0x8e,
+ 0x57, 0x7f, 0x09, 0x84, 0xc2, 0x89, 0xc9, 0x38, 0x5a, 0x09, 0x86, 0x49,
+ 0xde, 0x21, 0xbc, 0xa2, 0x7a, 0x7e, 0xa2, 0x29, 0x71, 0x6b, 0xa6, 0xe9,
+ 0xb2, 0x79, 0x71, 0x0f, 0x38, 0xfa, 0xa5, 0xff, 0xae, 0x57, 0x41, 0x55,
+ 0xce, 0x4e, 0xfb, 0x4f, 0x74, 0x36, 0x95, 0xe2, 0x91, 0x1b, 0x1d, 0x06,
+ 0xd5, 0xe2, 0x90, 0xcb, 0xcd, 0x86, 0xf5, 0x6d, 0x0e, 0xdf, 0xcd, 0x21,
+ 0x6a, 0xe2, 0x24, 0x27, 0x05, 0x5e, 0x68, 0x35, 0xfd, 0x29, 0xee, 0xf7,
+ 0x9e, 0x0d, 0x90, 0x77, 0x1f, 0xea, 0xce, 0xbe, 0x12, 0xf2, 0x0e, 0x95,
+ 0xb3, 0x4f, 0x0f, 0x78, 0xb7, 0x37, 0xa9, 0x61, 0x8b, 0x26, 0xfa, 0x7d,
+ 0xbc, 0x98, 0x74, 0xf2, 0x72, 0xc4, 0x2b, 0xdb, 0x56, 0x3e, 0xaf, 0xa1,
+ 0x6b, 0x4f, 0xb6, 0x8c, 0x3b, 0xb1, 0xe7, 0x8e, 0xaa, 0x81, 0xa0, 0x02,
+ 0x43, 0xfa, 0xad, 0xd2, 0xbf, 0x18, 0xe6, 0x3d, 0x38, 0x9a, 0xe4, 0x43,
+ 0x77, 0xda, 0x18, 0xc5, 0x76, 0xb5, 0x0f, 0x00, 0x96, 0xcf, 0x34, 0x19,
+ 0x54, 0x83, 0xb0, 0x05, 0x48, 0xc0, 0x98, 0x62, 0x36, 0xe3, 0xbc, 0x7c,
+ 0xb8, 0xd6, 0x80, 0x1c, 0x04, 0x94, 0xcc, 0xd1, 0x99, 0xe5, 0xc5, 0xbd,
+ 0x0d, 0x0e, 0xdc, 0x9e, 0xb8, 0xa0, 0x00, 0x1e, 0x15, 0x27, 0x67, 0x54,
+ 0xfc, 0xc6, 0x85, 0x66, 0x05, 0x41, 0x48, 0xe6, 0xe7, 0x64, 0xbe, 0xe7,
+ 0xc7, 0x64, 0xda, 0xad, 0x3f, 0xc4, 0x52, 0x35, 0xa6, 0xda, 0xd4, 0x28,
+ 0xfa, 0x20, 0xc1, 0x70, 0xe3, 0x45, 0x00, 0x3f, 0x2f, 0x06, 0xec, 0x81,
+ 0x05, 0xfe, 0xb2, 0x5b, 0x22, 0x81, 0xb6, 0x3d, 0x27, 0x33, 0xbe, 0x96,
+ 0x1c, 0x29, 0x95, 0x1d, 0x11, 0xdd, 0x22, 0x21, 0x65, 0x7a, 0x9f, 0x53,
+ 0x1d, 0xda, 0x2a, 0x19, 0x4d, 0xbb, 0x12, 0x64, 0x48, 0xbd, 0xee, 0xb2,
+ 0x58, 0xe0, 0x7e, 0xa6, 0x59, 0xc7, 0x46, 0x19, 0xa6, 0x38, 0x0e, 0x1d,
+ 0x66, 0xd6, 0x83, 0x2b, 0xfe, 0x67, 0xf6, 0x38, 0xcd, 0x8f, 0xae, 0x1f,
+ 0x27, 0x23, 0x02, 0x0f, 0x9c, 0x40, 0xa3, 0xfd, 0xa6, 0x7e, 0xda, 0x3b,
+ 0xd2, 0x92, 0x38, 0xfb, 0xd4, 0xd4, 0xb4, 0x88, 0x5c, 0x2a, 0x99, 0x17,
+ 0x6d, 0xb1, 0xa0, 0x6c, 0x50, 0x07, 0x78, 0x49, 0x1a, 0x82, 0x88, 0xf1,
+ 0x85, 0x5f, 0x60, 0xff, 0xfc, 0xf1, 0xd1, 0x37, 0x3f, 0xd9, 0x4f, 0xc6,
+ 0x0c, 0x18, 0x11, 0xe1, 0xac, 0x3f, 0x1c, 0x6d, 0x00, 0x3b, 0xec, 0xda,
+ 0x3b, 0x1f, 0x27, 0x25, 0xca, 0x59, 0x5d, 0xe0, 0xca, 0x63, 0x32, 0x8f,
+ 0x3b, 0xe5, 0x7c, 0xc9, 0x77, 0x55, 0x60, 0x11, 0x95, 0x14, 0x0d, 0xfb,
+ 0x59, 0xd3, 0x9c, 0xe0, 0x91, 0x30, 0x8b, 0x41, 0x05, 0x74, 0x6d, 0xac,
+ 0x23, 0xd3, 0x3e, 0x5f, 0x7c, 0xe4, 0x84, 0x8d, 0xa3, 0x16, 0xa9, 0xc6,
+ 0x6b, 0x95, 0x81, 0xba, 0x35, 0x73, 0xbf, 0xaf, 0x31, 0x14, 0x96, 0x18,
+ 0x8a, 0xb1, 0x54, 0x23, 0x28, 0x2e, 0xe4, 0x16, 0xdc, 0x2a, 0x19, 0xc5,
+ 0x72, 0x4f, 0xa9, 0x1a, 0xe4, 0xad, 0xc8, 0x8b, 0xc6, 0x67, 0x96, 0xea,
+ 0xe5, 0x67, 0x7a, 0x01, 0xf6, 0x4e, 0x8c, 0x08, 0x63, 0x13, 0x95, 0x82,
+ 0x2d, 0x9d, 0xb8, 0xfc, 0xee, 0x35, 0xc0, 0x6b, 0x1f, 0xee, 0xa5, 0x47,
+ 0x4d, 0x6d, 0x8f, 0x34, 0xb1, 0x53, 0x4a, 0x93, 0x6a, 0x18, 0xb0, 0xe0,
+ 0xd2, 0x0e, 0xab, 0x86, 0xbc, 0x9c, 0x6d, 0x6a, 0x52, 0x07, 0x19, 0x4e,
+ 0x67, 0xfa, 0x35, 0x55, 0x1b, 0x56, 0x80, 0x26, 0x7b, 0x00, 0x64, 0x1c,
+ 0x0f, 0x21, 0x2d, 0x18, 0xec, 0xa8, 0xd7, 0x32, 0x7e, 0xd9, 0x1f, 0xe7,
+ 0x64, 0xa8, 0x4e, 0xa1, 0xb4, 0x3f, 0xf5, 0xb4, 0xf6, 0xe8, 0xe6, 0x2f,
+ 0x05, 0xc6, 0x61, 0xde, 0xfb, 0x25, 0x88, 0x77, 0xc3, 0x5b, 0x18, 0xa1,
+ 0x51, 0xd5, 0xc4, 0x14, 0xaa, 0xad, 0x97, 0xba, 0x3e, 0x49, 0x93, 0x32,
+ 0xe5, 0x96, 0x07, 0x8e, 0x60, 0x0d, 0xeb, 0x81, 0x14, 0x9c, 0x44, 0x1c,
+ 0xe9, 0x57, 0x82, 0xf2, 0x2a, 0x28, 0x25, 0x63, 0xc5, 0xba, 0xc1, 0x41,
+ 0x14, 0x23, 0x60, 0x5d, 0x1a, 0xe1, 0xaf, 0xae, 0x2c, 0x8b, 0x06, 0x60,
+ 0x23, 0x7e, 0xc1, 0x28, 0xaa, 0x0f, 0xe3, 0x46, 0x4e, 0x43, 0x58, 0x11,
+ 0x5d, 0xb8, 0x4c, 0xc3, 0xb5, 0x23, 0x07, 0x3a, 0x28, 0xd4, 0x54, 0x98,
+ 0x84, 0xb8, 0x1f, 0xf7, 0x0e, 0x10, 0xbf, 0x36, 0x1c, 0x13, 0x72, 0x96,
+ 0x28, 0xd5, 0x34, 0x8f, 0x07, 0x21, 0x1e, 0x7e, 0x4c, 0xf4, 0xf1, 0x8b,
+ 0x28, 0x60, 0x90, 0xbd, 0xb1, 0x24, 0x0b, 0x66, 0xd6, 0xcd, 0x4a, 0xfc,
+ 0xea, 0xdc, 0x00, 0xca, 0x44, 0x6c, 0xe0, 0x50, 0x50, 0xff, 0x18, 0x3a,
+ 0xd2, 0xbb, 0xf1, 0x18, 0xc1, 0xfc, 0x0e, 0xa5, 0x1f, 0x97, 0xd2, 0x2b,
+ 0x8f, 0x7e, 0x46, 0x70, 0x5d, 0x45, 0x27, 0xf4, 0x5b, 0x42, 0xae, 0xff,
+ 0x39, 0x58, 0x53, 0x37, 0x6f, 0x69, 0x7d, 0xd5, 0xfd, 0xf2, 0xc5, 0x18,
+ 0x7d, 0x7d, 0x5f, 0x0e, 0x2e, 0xb8, 0xd4, 0x3f, 0x17, 0xba, 0x0f, 0x7c,
+ 0x60, 0xff, 0x43, 0x7f, 0x53, 0x5d, 0xfe, 0xf2, 0x98, 0x33, 0xbf, 0x86,
+ 0xcb, 0xe8, 0x8e, 0xa4, 0xfb, 0xd4, 0x22, 0x1e, 0x84, 0x11, 0x72, 0x83,
+ 0x54, 0xfa, 0x30, 0xa7, 0x00, 0x8f, 0x15, 0x4a, 0x41, 0xc7, 0xfc, 0x46,
+ 0x6b, 0x46, 0x45, 0xdb, 0xe2, 0xe3, 0x21, 0x26, 0x7f, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+};
+
+static const SECItem subprime_ike_1536 =
+ { siBuffer,
+ (unsigned char *)subprime_ike_1536_data,
+ sizeof(subprime_ike_1536_data) };
+static const SECItem subprime_ike_2048 =
+ { siBuffer,
+ (unsigned char *)subprime_ike_2048_data,
+ sizeof(subprime_ike_2048_data) };
+static const SECItem subprime_ike_3072 =
+ { siBuffer,
+ (unsigned char *)subprime_ike_3072_data,
+ sizeof(subprime_ike_3072_data) };
+static const SECItem subprime_ike_4096 =
+ { siBuffer,
+ (unsigned char *)subprime_ike_4096_data,
+ sizeof(subprime_ike_4096_data) };
+static const SECItem subprime_ike_6144 =
+ { siBuffer,
+ (unsigned char *)subprime_ike_6144_data,
+ sizeof(subprime_ike_6144_data) };
+static const SECItem subprime_ike_8192 =
+ { siBuffer,
+ (unsigned char *)subprime_ike_8192_data,
+ sizeof(subprime_ike_8192_data) };
+static const SECItem subprime_tls_2048 =
+ { siBuffer,
+ (unsigned char *)subprime_tls_2048_data,
+ sizeof(subprime_tls_2048_data) };
+static const SECItem subprime_tls_3072 =
+ { siBuffer,
+ (unsigned char *)subprime_tls_3072_data,
+ sizeof(subprime_tls_3072_data) };
+static const SECItem subprime_tls_4096 =
+ { siBuffer,
+ (unsigned char *)subprime_tls_4096_data,
+ sizeof(subprime_tls_4096_data) };
+static const SECItem subprime_tls_6144 =
+ { siBuffer,
+ (unsigned char *)subprime_tls_6144_data,
+ sizeof(subprime_tls_6144_data) };
+static const SECItem subprime_tls_8192 =
+ { siBuffer,
+ (unsigned char *)subprime_tls_8192_data,
+ sizeof(subprime_tls_8192_data) };
+
+/*
+ * verify that dhPrime matches one of our known primes
+ */
+const SECItem *
+sftk_VerifyDH_Prime(SECItem *dhPrime)
+{
+ /* use the length to decide which primes to check */
+ switch (dhPrime->len) {
+ case 1536 / PR_BITS_PER_BYTE:
+ if (PORT_Memcmp(dhPrime->data, prime_ike_1536,
+ sizeof(prime_ike_1536)) == 0) {
+ return &subprime_ike_1536;
+ }
+ break;
+ case 2048 / PR_BITS_PER_BYTE:
+ if (PORT_Memcmp(dhPrime->data, prime_tls_2048,
+ sizeof(prime_tls_2048)) == 0) {
+ return &subprime_tls_2048;
+ }
+ if (PORT_Memcmp(dhPrime->data, prime_ike_2048,
+ sizeof(prime_ike_2048)) == 0) {
+ return &subprime_ike_2048;
+ }
+ break;
+ case 3072 / PR_BITS_PER_BYTE:
+ if (PORT_Memcmp(dhPrime->data, prime_tls_3072,
+ sizeof(prime_tls_3072)) == 0) {
+ return &subprime_tls_3072;
+ }
+ if (PORT_Memcmp(dhPrime->data, prime_ike_3072,
+ sizeof(prime_ike_3072)) == 0) {
+ return &subprime_ike_3072;
+ }
+ break;
+ case 4096 / PR_BITS_PER_BYTE:
+ if (PORT_Memcmp(dhPrime->data, prime_tls_4096,
+ sizeof(prime_tls_4096)) == 0) {
+ return &subprime_tls_4096;
+ }
+ if (PORT_Memcmp(dhPrime->data, prime_ike_4096,
+ sizeof(prime_ike_4096)) == 0) {
+ return &subprime_ike_4096;
+ }
+ break;
+ case 6144 / PR_BITS_PER_BYTE:
+ if (PORT_Memcmp(dhPrime->data, prime_tls_6144,
+ sizeof(prime_tls_6144)) == 0) {
+ return &subprime_tls_6144;
+ }
+ if (PORT_Memcmp(dhPrime->data, prime_ike_6144,
+ sizeof(prime_ike_6144)) == 0) {
+ return &subprime_ike_6144;
+ }
+ break;
+ case 8192 / PR_BITS_PER_BYTE:
+ if (PORT_Memcmp(dhPrime->data, prime_tls_8192,
+ sizeof(prime_tls_8192)) == 0) {
+ return &subprime_tls_8192;
+ }
+ if (PORT_Memcmp(dhPrime->data, prime_ike_8192,
+ sizeof(prime_ike_8192)) == 0) {
+ return &subprime_ike_8192;
+ }
+ break;
+ }
+ /* no match found, return an error */
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+}
+
+/* Use the provided subPrime to see if dhPrime is a safe prime. We'll check
+ * primality of those values later. */
+SECStatus
+sftk_IsSafePrime(const SECItem *dhPrime, const SECItem *dhSubPrime, PRBool *isSafe)
+{
+ int i;
+ unsigned char carry = 0;
+ int offset = 0, subPrimeLen = dhPrime->len;
+ *isSafe = PR_FALSE;
+
+ /* Both dhPrime and dhSubPrime should be odd */
+ if (((dhPrime->data[dhPrime->len - 1] & 0x1) != 1) && ((dhSubPrime->data[dhSubPrime->len - 1] & 0x1) != 1)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ /* subPrime is p-1/2, which means subPrime is 1 bit shorter than p.
+ * It's length in bytes is the same unless the high byte of p == 1 or 0.
+ */
+ if (dhPrime->data[0] <= 1) {
+ subPrimeLen--;
+ offset++;
+ carry = (dhPrime->data[0]) << 7;
+ }
+
+ /* if subprime len is not long enough it is not a strong prime */
+ if (dhSubPrime->len != subPrimeLen) {
+ return SECSuccess;
+ }
+
+ /* does the subprime match q == (p-1)/2 */
+ for (i = 0; i < subPrimeLen; i++) {
+ if (dhSubPrime->data[i] !=
+ (carry | ((dhPrime->data[i + offset] >> 1) & 0x7f))) {
+ return SECSuccess;
+ }
+ carry = ((dhPrime->data[i + offset] & 1) << 7) & 0x80;
+ }
+ /* subPrime for p claims to be q=(p-1)/2. So the caller thinks p
+ * is a strong prime, just need to check primality of p and q to verify */
+ *isSafe = PR_TRUE;
+ return SECSuccess;
+}
diff --git a/security/nss/lib/softoken/sftkhmac.c b/security/nss/lib/softoken/sftkhmac.c
index 617e6fd4e..b9ee7d054 100644
--- a/security/nss/lib/softoken/sftkhmac.c
+++ b/security/nss/lib/softoken/sftkhmac.c
@@ -9,10 +9,10 @@
#include "softoken.h"
#include "hmacct.h"
-/* HMACMechanismToHash converts a PKCS#11 MAC mechanism into a freebl hash
+/* sftk_HMACMechanismToHash converts a PKCS#11 MAC mechanism into a freebl hash
* type. */
-static HASH_HashType
-HMACMechanismToHash(CK_MECHANISM_TYPE mech)
+HASH_HashType
+sftk_HMACMechanismToHash(CK_MECHANISM_TYPE mech)
{
switch (mech) {
case CKM_MD2_HMAC:
@@ -50,7 +50,7 @@ SetupMAC(CK_MECHANISM_PTR mech, SFTKObject *key)
return NULL;
}
- alg = HMACMechanismToHash(params->macAlg);
+ alg = sftk_HMACMechanismToHash(params->macAlg);
if (alg == HASH_AlgNULL) {
return NULL;
}
@@ -261,7 +261,7 @@ sftk_MAC_InitRaw(sftk_MACCtx *ctx, CK_MECHANISM_TYPE mech, const unsigned char *
case CKM_SHA256_HMAC:
case CKM_SHA384_HMAC:
case CKM_SHA512_HMAC:
- hashObj = HASH_GetRawHashObject(HMACMechanismToHash(mech));
+ hashObj = HASH_GetRawHashObject(sftk_HMACMechanismToHash(mech));
/* Because we condition above only on hashes we know to be valid,
* hashObj should never be NULL. This assert is only useful when
@@ -355,7 +355,7 @@ sftk_MAC_Reset(sftk_MACCtx *ctx)
}
CK_RV
-sftk_MAC_Update(sftk_MACCtx *ctx, CK_BYTE_PTR data, unsigned int data_len)
+sftk_MAC_Update(sftk_MACCtx *ctx, const CK_BYTE *data, unsigned int data_len)
{
switch (ctx->mech) {
case CKM_MD2_HMAC:
diff --git a/security/nss/lib/softoken/sftkike.c b/security/nss/lib/softoken/sftkike.c
index 7d5370bd4..27eacc087 100644
--- a/security/nss/lib/softoken/sftkike.c
+++ b/security/nss/lib/softoken/sftkike.c
@@ -189,10 +189,11 @@ fail:
/* encode the final pad block of aes xcbc, padBuf is modified */
CK_RV
-sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen, int blockSize,
- const unsigned char *k2, const unsigned char *k3)
+sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen,
+ unsigned int blockSize, const unsigned char *k2,
+ const unsigned char *k3)
{
- int i;
+ unsigned int i;
if (bufLen == blockSize) {
for (i = 0; i < blockSize; i++) {
padBuf[i] ^= k2[i];
@@ -697,18 +698,22 @@ fail:
* This function returns (from rfc2409 appendix b):
* Ka = K1 | K2 | K3 | K4 |... Kn
* where:
- * K1 = prf(K, 0x00)
- * K2 = prf(K, K1)
- * K3 = prf(K, K2)
- * K4 = prf(K, K3)
+ * K1 = prf(K, [gxyKey]|[extraData]) or prf(K, 0) if gxyKey and extraData
+ * ar not present.
+ * K2 = prf(K, K1|[gxyKey]|[extraData])
+ * K3 = prf(K, K2|[gxyKey]|[extraData])
+ * K4 = prf(K, K3|[gxyKey]|[extraData])
* .
- * Kn = prf(K, K(n-1))
+ * Kn = prf(K, K(n-1)|[gxyKey]|[extraData])
* K = inKey
*/
CK_RV
sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
- const CK_MECHANISM_TYPE *mech, SFTKObject *outKey, unsigned int keySize)
+ const CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *params,
+ SFTKObject *outKey, unsigned int keySize)
{
+ SFTKAttribute *gxyKeyValue = NULL;
+ SFTKObject *gxyKeyObj = NULL;
unsigned char *outKeyData = NULL;
unsigned char *thisKey = NULL;
unsigned char *lastKey = NULL;
@@ -718,11 +723,33 @@ sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
CK_RV crv;
prfContext context;
- crv = prf_setup(&context, *mech);
+ if ((params->ulExtraDataLen != 0) && (params->pExtraData == NULL)) {
+ return CKR_ARGUMENTS_BAD;
+ }
+ crv = prf_setup(&context, params->prfMechanism);
if (crv != CKR_OK) {
return crv;
}
+ if (params->bHasKeygxy) {
+ SFTKSession *session;
+ session = sftk_SessionFromHandle(hSession);
+ if (session == NULL) {
+ return CKR_SESSION_HANDLE_INVALID;
+ }
+ gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session);
+ sftk_FreeSession(session);
+ if (gxyKeyObj == NULL) {
+ crv = CKR_KEY_HANDLE_INVALID;
+ goto fail;
+ }
+ gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE);
+ if (gxyKeyValue == NULL) {
+ crv = CKR_KEY_HANDLE_INVALID;
+ goto fail;
+ }
+ }
+
macSize = prf_length(&context);
if (keySize == 0) {
@@ -741,25 +768,47 @@ sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
}
/*
- * this loop generates on block of the prf, basically
- * kn = prf(key, Kn-1)
- * Kn is thisKey, Kn-1 is lastKey
- * key is inKey
- */
+ * this loop generates on block of the prf, basically
+ * kn = prf(key, Kn-1 | [Keygxy] | [ExtraData])
+ * Kn is thisKey, Kn-1 is lastKey
+ * key is inKey
+ */
thisKey = outKeyData;
for (genKeySize = 0; genKeySize <= keySize; genKeySize += macSize) {
+ PRBool hashedData = PR_FALSE;
crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen);
if (crv != CKR_OK) {
goto fail;
}
- if (lastKey == NULL) {
- const unsigned char zero = 0;
- crv = prf_update(&context, &zero, 1);
- } else {
+ if (lastKey != NULL) {
crv = prf_update(&context, lastKey, macSize);
+ if (crv != CKR_OK) {
+ goto fail;
+ }
+ hashedData = PR_TRUE;
}
- if (crv != CKR_OK) {
- goto fail;
+ if (gxyKeyValue != NULL) {
+ crv = prf_update(&context, gxyKeyValue->attrib.pValue,
+ gxyKeyValue->attrib.ulValueLen);
+ if (crv != CKR_OK) {
+ goto fail;
+ }
+ hashedData = PR_TRUE;
+ }
+ if (params->ulExtraDataLen != 0) {
+ crv = prf_update(&context, params->pExtraData, params->ulExtraDataLen);
+ if (crv != CKR_OK) {
+ goto fail;
+ }
+ hashedData = PR_TRUE;
+ }
+ /* if we haven't hashed anything yet, hash a zero */
+ if (hashedData == PR_FALSE) {
+ const unsigned char zero = 0;
+ crv = prf_update(&context, &zero, 1);
+ if (crv != CKR_OK) {
+ goto fail;
+ }
}
crv = prf_final(&context, thisKey, macSize);
if (crv != CKR_OK) {
@@ -770,6 +819,12 @@ sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
}
crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
fail:
+ if (gxyKeyValue) {
+ sftk_FreeAttribute(gxyKeyValue);
+ }
+ if (gxyKeyObj) {
+ sftk_FreeObject(gxyKeyObj);
+ }
if (outKeyData) {
PORT_ZFree(outKeyData, outKeySize);
}
@@ -800,10 +855,12 @@ fail:
* K = inKey, S = seedKey | seedData
*/
-CK_RV
-sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
- const CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *params, SFTKObject *outKey,
- unsigned int keySize)
+static CK_RV
+sftk_ike_prf_plus_raw(CK_SESSION_HANDLE hSession,
+ const unsigned char *inKeyData, CK_ULONG inKeyLen,
+ const CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *params,
+ unsigned char **outKeyDataPtr, unsigned int *outKeySizePtr,
+ unsigned int keySize)
{
SFTKAttribute *seedValue = NULL;
SFTKObject *seedKeyObj = NULL;
@@ -869,8 +926,7 @@ sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
crv = CKR_KEY_SIZE_RANGE;
goto fail;
}
- crv = prf_init(&context, inKey->attrib.pValue,
- inKey->attrib.ulValueLen);
+ crv = prf_init(&context, inKeyData, inKeyLen);
if (crv != CKR_OK) {
goto fail;
}
@@ -909,7 +965,9 @@ sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
lastKey = thisKey;
thisKey += macSize;
}
- crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
+ *outKeyDataPtr = outKeyData;
+ *outKeySizePtr = outKeySize;
+ outKeyData = NULL; /* don't free it here, our caller will free it */
fail:
if (outKeyData) {
PORT_ZFree(outKeyData, outKeySize);
@@ -924,6 +982,30 @@ fail:
return crv;
}
+/*
+ * ike prf + with code to deliever results tosoftoken objects.
+ */
+CK_RV
+sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
+ const CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *params, SFTKObject *outKey,
+ unsigned int keySize)
+{
+ unsigned char *outKeyData = NULL;
+ unsigned int outKeySize;
+ CK_RV crv;
+
+ crv = sftk_ike_prf_plus_raw(hSession, inKey->attrib.pValue,
+ inKey->attrib.ulValueLen, params,
+ &outKeyData, &outKeySize, keySize);
+ if (crv != CKR_OK) {
+ return crv;
+ }
+
+ crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);
+ PORT_ZFree(outKeyData, outKeySize);
+ return crv;
+}
+
/* sftk_aes_xcbc_new_keys:
*
* aes xcbc creates 3 new keys from the input key. The first key will be the
@@ -1239,7 +1321,21 @@ sftk_fips_IKE_PowerUpSelfTests(void)
0x7f, 0x6f, 0x77, 0x2e, 0x5d, 0x65, 0xb5, 0x8e,
0xb1, 0x13, 0x40, 0x96, 0xe8, 0x47, 0x8d, 0x2b
};
+ static const PRUint8 ike_known_sha256_prf_plus[] = {
+ 0xe6, 0xf1, 0x9b, 0x4a, 0x02, 0xe9, 0x73, 0x72,
+ 0x93, 0x9f, 0xdb, 0x46, 0x1d, 0xb1, 0x49, 0xcb,
+ 0x53, 0x08, 0x98, 0x3d, 0x41, 0x36, 0xfa, 0x8b,
+ 0x47, 0x04, 0x49, 0x11, 0x0d, 0x6e, 0x96, 0x1d,
+ 0xab, 0xbe, 0x94, 0x28, 0xa0, 0xb7, 0x9c, 0xa3,
+ 0x29, 0xe1, 0x40, 0xf8, 0xf8, 0x88, 0xb9, 0xb5,
+ 0x40, 0xd4, 0x54, 0x4d, 0x25, 0xab, 0x94, 0xd4,
+ 0x98, 0xd8, 0x00, 0xbf, 0x6f, 0xef, 0xe8, 0x39
+ };
SECStatus rv;
+ CK_RV crv;
+ unsigned char *outKeyData = NULL;
+ unsigned int outKeySize;
+ CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS ike_params;
rv = prf_test(CKM_AES_XCBC_MAC,
ike_xcbc_known_key, sizeof(ike_xcbc_known_key),
@@ -1290,5 +1386,23 @@ sftk_fips_IKE_PowerUpSelfTests(void)
ike_sha512_known_plain_text,
sizeof(ike_sha512_known_plain_text),
ike_sha512_known_mac, sizeof(ike_sha512_known_mac));
+
+ ike_params.prfMechanism = CKM_SHA256_HMAC;
+ ike_params.bHasSeedKey = PR_FALSE;
+ ike_params.hSeedKey = CK_INVALID_HANDLE;
+ ike_params.pSeedData = (CK_BYTE_PTR)ike_sha256_known_plain_text;
+ ike_params.ulSeedDataLen = sizeof(ike_sha256_known_plain_text);
+ crv = sftk_ike_prf_plus_raw(CK_INVALID_HANDLE, ike_sha256_known_key,
+ sizeof(ike_sha256_known_key), &ike_params,
+ &outKeyData, &outKeySize, 64);
+ if ((crv != CKR_OK) ||
+ (outKeySize != sizeof(ike_known_sha256_prf_plus)) ||
+ (PORT_Memcmp(outKeyData, ike_known_sha256_prf_plus,
+ sizeof(ike_known_sha256_prf_plus)) != 0)) {
+ PORT_ZFree(outKeyData, outKeySize);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ PORT_ZFree(outKeyData, outKeySize);
return rv;
}
diff --git a/security/nss/lib/softoken/sftkmessage.c b/security/nss/lib/softoken/sftkmessage.c
new file mode 100644
index 000000000..76bc9b479
--- /dev/null
+++ b/security/nss/lib/softoken/sftkmessage.c
@@ -0,0 +1,377 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * This file implements PKCS 11 on top of our existing security modules
+ *
+ * Implement the PKCS #11 v3.0 Message interfaces
+ */
+#include "seccomon.h"
+#include "pkcs11.h"
+#include "pkcs11i.h"
+#include "blapi.h"
+#include "prenv.h"
+#include "softoken.h"
+
+static SECStatus
+sftk_ChaCha20_Poly1305_Message_Encrypt(ChaCha20Poly1305Context *ctx,
+ unsigned char *cipherText, unsigned int *cipherTextLen,
+ unsigned int maxOutLen, const unsigned char *plainText,
+ unsigned int plainTextLen,
+ CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *params,
+ unsigned int paramsLen, const unsigned char *aad,
+ unsigned int aadLen)
+{
+ return ChaCha20Poly1305_Encrypt(ctx, cipherText, cipherTextLen, maxOutLen,
+ plainText, plainTextLen, params->pNonce, params->ulNonceLen,
+ aad, aadLen, params->pTag);
+}
+static SECStatus
+sftk_ChaCha20_Poly1305_Message_Decrypt(ChaCha20Poly1305Context *ctx,
+ unsigned char *plainText, unsigned int *plainTextLen,
+ unsigned int maxOutLen, const unsigned char *cipherText,
+ unsigned int cipherTextLen,
+ CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *params,
+ unsigned int paramsLen, const unsigned char *aad,
+ unsigned int aadLen)
+{
+ return ChaCha20Poly1305_Decrypt(ctx, plainText, plainTextLen, maxOutLen,
+ cipherText, cipherTextLen, params->pNonce, params->ulNonceLen,
+ aad, aadLen, params->pTag);
+}
+
+/*
+ * Handle AEAD Encryption operation
+ *
+ * The setup is similiar to sftk_CryptInit except we set the aeadUpdate
+ * function instead of the normal update function. This function handles
+ * both the Encrypt case and the Decrypt case.
+ */
+static CK_RV
+sftk_MessageCryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey, SFTKContextType contextType,
+ CK_ATTRIBUTE_TYPE operation, PRBool encrypt)
+{
+ SFTKSession *session;
+ SFTKObject *key;
+ SFTKSessionContext *context;
+ SFTKAttribute *att;
+ CK_KEY_TYPE key_type;
+ CK_RV crv = CKR_OK;
+
+ if (!pMechanism) {
+ return CKR_MECHANISM_PARAM_INVALID;
+ }
+
+ crv = sftk_MechAllowsOperation(pMechanism->mechanism,
+ CKA_NSS_MESSAGE | operation);
+ if (crv != CKR_OK)
+ return crv;
+
+ session = sftk_SessionFromHandle(hSession);
+ if (session == NULL)
+ return CKR_SESSION_HANDLE_INVALID;
+
+ crv = sftk_InitGeneric(session, &context, contextType, &key, hKey,
+ &key_type, CKO_SECRET_KEY, operation);
+ if (crv != CKR_OK) {
+ sftk_FreeSession(session);
+ return crv;
+ }
+
+ att = sftk_FindAttribute(key, CKA_VALUE);
+ if (att == NULL) {
+ sftk_FreeSession(session);
+ sftk_FreeContext(context);
+ return CKR_KEY_HANDLE_INVALID;
+ }
+
+ context->doPad = PR_FALSE;
+ context->multi = PR_TRUE; /* All message are 'multi' operations */
+
+ switch (pMechanism->mechanism) {
+ case CKM_AES_GCM:
+ context->cipherInfo = AES_CreateContext(
+ (unsigned char *)att->attrib.pValue,
+ NULL, NSS_AES_GCM, encrypt, att->attrib.ulValueLen,
+ AES_BLOCK_SIZE);
+ context->aeadUpdate = (SFTKAEADCipher)AES_AEAD;
+ context->destroy = (SFTKDestroy)AES_DestroyContext;
+ break;
+ case CKM_CHACHA20_POLY1305:
+ context->cipherInfo = ChaCha20Poly1305_CreateContext(
+ (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen,
+ 16);
+ context->aeadUpdate = (SFTKAEADCipher)(encrypt ? sftk_ChaCha20_Poly1305_Message_Encrypt : sftk_ChaCha20_Poly1305_Message_Decrypt);
+ context->destroy = (SFTKDestroy)ChaCha20Poly1305_DestroyContext;
+ break;
+ default:
+ crv = CKR_MECHANISM_INVALID;
+ break;
+ }
+ if (context->cipherInfo == NULL) {
+ crv = sftk_MapCryptError(PORT_GetError());
+ if (crv == CKR_OK) {
+ crv = CKR_GENERAL_ERROR;
+ }
+ }
+ if (crv != CKR_OK) {
+ sftk_FreeContext(context);
+ sftk_FreeSession(session);
+ return crv;
+ }
+ sftk_SetContextByType(session, contextType, context);
+ sftk_FreeSession(session);
+ return CKR_OK;
+}
+
+/*
+ * Generic handler for the actual encryption/decryption. Each call handles
+ * The authentication data for the entire block. Multiple calls using
+ * BeginMessage and NextMessage are not supported and CKF_MESSSAGE_MULTI is
+ * not set on the supported algorithms
+ */
+static CK_RV
+sftk_CryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pIntext,
+ CK_ULONG ulIntextLen, CK_BYTE_PTR pOuttext,
+ CK_ULONG_PTR pulOuttextLen, SFTKContextType contextType)
+{
+ SFTKSessionContext *context;
+ unsigned int outlen;
+ unsigned int maxout = *pulOuttextLen;
+ CK_RV crv;
+ SECStatus rv;
+
+ CHECK_FORK();
+
+ /* make sure we're legal */
+ crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
+ if (crv != CKR_OK)
+ return crv;
+
+ if (!pOuttext) {
+ *pulOuttextLen = ulIntextLen;
+ return CKR_OK;
+ }
+ rv = (*context->aeadUpdate)(context->cipherInfo, pOuttext, &outlen,
+ maxout, pIntext, ulIntextLen,
+ pParameter, ulParameterLen,
+ pAssociatedData, ulAssociatedDataLen);
+
+ if (rv != SECSuccess) {
+ if (contextType == SFTK_MESSAGE_ENCRYPT) {
+ return sftk_MapCryptError(PORT_GetError());
+ } else {
+ return sftk_MapDecryptError(PORT_GetError());
+ }
+ }
+ *pulOuttextLen = (CK_ULONG)(outlen);
+ return CKR_OK;
+}
+
+/*
+ * Common message cleanup rountine
+ */
+static CK_RV
+sftk_MessageCryptFinal(CK_SESSION_HANDLE hSession,
+ SFTKContextType contextType)
+{
+ SFTKSession *session;
+ SFTKSessionContext *context;
+ CK_RV crv;
+
+ CHECK_FORK();
+
+ /* make sure we're legal */
+ crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, &session);
+ if (crv != CKR_OK)
+ return crv;
+ sftk_TerminateOp(session, contextType, context);
+ sftk_FreeSession(session);
+ return CKR_OK;
+}
+
+/* MessageEncrypt and EncryptMessage functions just use the helper functions
+ * above */
+CK_RV
+NSC_MessageEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ return sftk_MessageCryptInit(hSession, pMechanism, hKey,
+ SFTK_MESSAGE_ENCRYPT, CKA_ENCRYPT, PR_TRUE);
+}
+
+CK_RV
+NSC_EncryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pPlaintext,
+ CK_ULONG ulPlaintextLen, CK_BYTE_PTR pCiphertext,
+ CK_ULONG_PTR pulCiphertextLen)
+{
+ return sftk_CryptMessage(hSession, pParameter, ulParameterLen,
+ pAssociatedData, ulAssociatedDataLen, pPlaintext,
+ ulPlaintextLen, pCiphertext, pulCiphertextLen,
+ SFTK_MESSAGE_ENCRYPT);
+}
+
+/*
+ * We only support the single shot function. The Begin/Next version can be
+ * dealt with if we need to support S/MIME or something. It would probably
+ * just buffer rather then returning intermediate results.
+ */
+CK_RV
+NSC_EncryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_EncryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pPlaintextPart,
+ CK_ULONG ulPlaintextPartLen, CK_BYTE_PTR pCiphertextPart,
+ CK_ULONG_PTR pulCiphertextPartLen, CK_FLAGS flags)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_MessageEncryptFinal(CK_SESSION_HANDLE hSession)
+{
+ return sftk_MessageCryptFinal(hSession, SFTK_MESSAGE_ENCRYPT);
+}
+
+/* MessageDecrypt and DecryptMessage functions just use the helper functions
+ * above */
+CK_RV
+NSC_MessageDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ return sftk_MessageCryptInit(hSession, pMechanism, hKey,
+ SFTK_MESSAGE_DECRYPT, CKA_DECRYPT, PR_FALSE);
+}
+
+CK_RV
+NSC_DecryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pCiphertext,
+ CK_ULONG ulCiphertextLen, CK_BYTE_PTR pPlaintext,
+ CK_ULONG_PTR pulPlaintextLen)
+{
+ return sftk_CryptMessage(hSession, pParameter, ulParameterLen,
+ pAssociatedData, ulAssociatedDataLen, pCiphertext,
+ ulCiphertextLen, pPlaintext, pulPlaintextLen,
+ SFTK_MESSAGE_DECRYPT);
+}
+
+/*
+ * We only support the single shot function. The Begin/Next version can be
+ * dealt with if we need to support S/MIME or something. It would probably
+ * just buffer rather then returning intermediate results. This is expecially
+ * true for decrypt, which isn't supposed to return any data unless it's been
+ * authenticated (which can't happen until the last block is processed).
+ */
+CK_RV
+NSC_DecryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData,
+ CK_ULONG ulAssociatedDataLen)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_DecryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pCiphertextPart,
+ CK_ULONG ulCiphertextPartLen, CK_BYTE_PTR pPlaintextPart,
+ CK_ULONG_PTR pulPlaintextPartLen, CK_FLAGS flags)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_MessageDecryptFinal(CK_SESSION_HANDLE hSession)
+{
+ return sftk_MessageCryptFinal(hSession, SFTK_MESSAGE_DECRYPT);
+}
+
+/*
+ * There are no mechanisms defined to use the MessageSign and MessageVerify
+ * interfaces yet, so we don't need to implement anything.
+ */
+CK_RV
+NSC_MessageSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_SignMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_SignMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_SignMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_MessageSignFinal(CK_SESSION_HANDLE hSession)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_MessageVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_VerifyMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_VerifyMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_VerifyMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter,
+ CK_ULONG ulParameterLen, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
+
+CK_RV
+NSC_MessageVerifyFinal(CK_SESSION_HANDLE hSession)
+{
+ return CKR_FUNCTION_NOT_SUPPORTED;
+}
diff --git a/security/nss/lib/softoken/sftkpwd.c b/security/nss/lib/softoken/sftkpwd.c
index f2acf7664..b41cf9dab 100644
--- a/security/nss/lib/softoken/sftkpwd.c
+++ b/security/nss/lib/softoken/sftkpwd.c
@@ -92,6 +92,11 @@ sftkdb_passwordToKey(SFTKDBHandle *keydb, SECItem *salt,
SHA1Context *cx = NULL;
SECStatus rv = SECFailure;
+ if (!pw) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
key->data = PORT_Alloc(SHA1_LENGTH);
if (key->data == NULL) {
goto loser;
@@ -260,18 +265,19 @@ loser:
* with SECITEM_FreeItem by the caller.
*/
SECStatus
-sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText,
- SECItem **plain)
+sftkdb_DecryptAttribute(SFTKDBHandle *handle, SECItem *passKey,
+ CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type,
+ SECItem *cipherText, SECItem **plain)
{
SECStatus rv;
sftkCipherValue cipherValue;
/* First get the cipher type */
+ *plain = NULL;
rv = sftkdb_decodeCipherText(cipherText, &cipherValue);
if (rv != SECSuccess) {
goto loser;
}
- /* fprintf(stderr, "sftkdb_DecryptAttribute iteration: %d\n", cipherValue.param->iter); */
*plain = nsspkcs5_CipherData(cipherValue.param, passKey, &cipherValue.value,
PR_FALSE, NULL);
@@ -280,6 +286,33 @@ sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText,
goto loser;
}
+ /* If we are using aes 256, we need to check authentication as well.*/
+ if ((type != CKT_INVALID_TYPE) && (cipherValue.alg == SEC_OID_AES_256_CBC)) {
+ SECItem signature;
+ unsigned char signData[SDB_MAX_META_DATA_LEN];
+
+ /* if we get here from the old legacy db, there is clearly an
+ * error, don't return the plaintext */
+ if (handle == NULL) {
+ rv = SECFailure;
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ goto loser;
+ }
+
+ signature.data = signData;
+ signature.len = sizeof(signData);
+ rv = sftkdb_GetAttributeSignature(handle, handle, id, type,
+ &signature);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ rv = sftkdb_VerifyAttribute(handle, passKey, CK_INVALID_HANDLE, type,
+ *plain, &signature);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+
loser:
if (cipherValue.param) {
nsspkcs5_DestroyPBEParameter(cipherValue.param);
@@ -287,9 +320,36 @@ loser:
if (cipherValue.arena) {
PORT_FreeArena(cipherValue.arena, PR_FALSE);
}
+ /* Item decrypted, but failed integrity, clear it out */
+ if (*plain && rv != SECSuccess) {
+ SECITEM_ZfreeItem(*plain, PR_TRUE);
+ *plain = NULL;
+ }
return rv;
}
+/* If the database can't store the integrity check, it's a non-FIPS database
+ * and we use the old encryption scheme for it */
+static PRBool
+sftkdb_useLegacyEncryption(SFTKDBHandle *handle, SDB *db)
+{
+ if ((handle == NULL) || (db == NULL)) {
+ /* this is the case where the legacy db is calling back to us to
+ * encrypt or decrypt attributes inside the lower level db code.
+ * This is because the legacy db stored keys as pkcs #8 encrypted
+ * blobs rather than individual encrypted attributes */
+ return PR_TRUE;
+ }
+ /* currently, only the legacy db can't store meta data, but if we
+ * add a new db that also can't store meta data, then it to wouldn't
+ * be able to do the integrity checks. In both cases use the old encryption
+ * algorithms. */
+ if ((db->sdb_flags & SDB_HAS_META) == 0) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
/*
* encrypt a block. This function returned the encrypted ciphertext which
* the caller must free. If the caller provides an arena, cipherText will
@@ -297,22 +357,32 @@ loser:
* salt automatically.
*/
SECStatus
-sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey,
- int iterationCount, SECItem *plainText,
- SECItem **cipherText)
+sftkdb_EncryptAttribute(PLArenaPool *arena, SFTKDBHandle *handle, SDB *db,
+ SECItem *passKey, int iterationCount,
+ CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type,
+ SECItem *plainText, SECItem **cipherText)
{
SECStatus rv;
sftkCipherValue cipherValue;
SECItem *cipher = NULL;
NSSPKCS5PBEParameter *param = NULL;
unsigned char saltData[HASH_LENGTH_MAX];
+ SECItem *signature = NULL;
+ HASH_HashType hashType = HASH_AlgNULL;
- cipherValue.alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;
- cipherValue.salt.len = SHA1_LENGTH;
+ if (sftkdb_useLegacyEncryption(handle, db)) {
+ cipherValue.alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;
+ cipherValue.salt.len = SHA1_LENGTH;
+ hashType = HASH_AlgSHA1;
+ } else {
+ cipherValue.alg = SEC_OID_AES_256_CBC;
+ cipherValue.salt.len = SHA256_LENGTH;
+ hashType = HASH_AlgSHA256;
+ }
cipherValue.salt.data = saltData;
RNG_GenerateGlobalRandomBytes(saltData, cipherValue.salt.len);
- param = nsspkcs5_NewParam(cipherValue.alg, HASH_AlgSHA1, &cipherValue.salt,
+ param = nsspkcs5_NewParam(cipherValue.alg, hashType, &cipherValue.salt,
iterationCount);
if (param == NULL) {
rv = SECFailure;
@@ -331,7 +401,26 @@ sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey,
goto loser;
}
+ /* If we are using aes 256, we need to add authentication as well */
+ if ((type != CKT_INVALID_TYPE) &&
+ (cipherValue.param->encAlg == SEC_OID_AES_256_CBC)) {
+ rv = sftkdb_SignAttribute(arena, handle, db, passKey, iterationCount,
+ CK_INVALID_HANDLE, type, plainText,
+ &signature);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ rv = sftkdb_PutAttributeSignature(handle, db, id, type,
+ signature);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+
loser:
+ if ((arena == NULL) && signature) {
+ SECITEM_FreeItem(cipher, PR_TRUE);
+ }
if (cipher) {
SECITEM_FreeItem(cipher, PR_TRUE);
}
@@ -408,7 +497,8 @@ loser:
* plainText is the plainText of the attribute.
*/
SECStatus
-sftkdb_VerifyAttribute(SECItem *passKey, CK_OBJECT_HANDLE objectID,
+sftkdb_VerifyAttribute(SFTKDBHandle *handle,
+ SECItem *passKey, CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE attrType,
SECItem *plainText, SECItem *signText)
{
@@ -450,8 +540,9 @@ loser:
* attribute. The signText is a PKCS 5 v2 pbe.
*/
SECStatus
-sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey,
- int iterationCount, CK_OBJECT_HANDLE objectID,
+sftkdb_SignAttribute(PLArenaPool *arena, SFTKDBHandle *keyDB, SDB *db,
+ SECItem *passKey, int iterationCount,
+ CK_OBJECT_HANDLE objectID,
CK_ATTRIBUTE_TYPE attrType,
SECItem *plainText, SECItem **signature)
{
@@ -860,7 +951,8 @@ sftkdb_finishPasswordCheck(SFTKDBHandle *keydb, SECItem *key, const char *pw,
}
/* decrypt the entry value */
- rv = sftkdb_DecryptAttribute(key, value, &result);
+ rv = sftkdb_DecryptAttribute(keydb, key, CK_INVALID_HANDLE,
+ CKT_INVALID_TYPE, value, &result);
if (rv != SECSuccess) {
goto done;
}
@@ -1070,9 +1162,9 @@ sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle,
SECItem plainText;
plainText.data = authAttr.pValue;
plainText.len = authAttr.ulValueLen;
- if (sftkdb_SignAttribute(arena, newKey, iterationCount, id,
- authAttr.type, &plainText,
- &signText) != SECSuccess) {
+ if (sftkdb_SignAttribute(arena, handle, keyTarget, newKey,
+ iterationCount, id, authAttr.type,
+ &plainText, &signText) != SECSuccess) {
return CKR_GENERAL_ERROR;
}
if (sftkdb_PutAttributeSignature(handle, keyTarget, id, authAttr.type,
@@ -1127,7 +1219,8 @@ sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
SECItem *result;
plainText.data = privAttr.pValue;
plainText.len = privAttr.ulValueLen;
- if (sftkdb_EncryptAttribute(arena, newKey, iterationCount,
+ if (sftkdb_EncryptAttribute(arena, keydb, keydb->db, newKey,
+ iterationCount, id, privAttr.type,
&plainText, &result) != SECSuccess) {
return CKR_GENERAL_ERROR;
}
@@ -1296,7 +1389,7 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb,
certdb = keydb->peerDB;
if (certdb) {
CK_ATTRIBUTE objectType = { CKA_CLASS, 0, sizeof(CK_OBJECT_CLASS) };
- CK_OBJECT_CLASS myClass = CKO_NETSCAPE_TRUST;
+ CK_OBJECT_CLASS myClass = CKO_NSS_TRUST;
objectType.pValue = &myClass;
crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey,
@@ -1317,8 +1410,9 @@ sftkdb_ChangePassword(SFTKDBHandle *keydb,
plainText.data = (unsigned char *)SFTK_PW_CHECK_STRING;
plainText.len = SFTK_PW_CHECK_LEN;
- rv = sftkdb_EncryptAttribute(NULL, &newKey, iterationCount,
- &plainText, &result);
+ rv = sftkdb_EncryptAttribute(NULL, keydb, keydb->db, &newKey,
+ iterationCount, CK_INVALID_HANDLE,
+ CKT_INVALID_TYPE, &plainText, &result);
if (rv != SECSuccess) {
goto loser;
}
diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h
index 806f3f1e9..9e02433e2 100644
--- a/security/nss/lib/softoken/softkver.h
+++ b/security/nss/lib/softoken/softkver.h
@@ -17,11 +17,11 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
*/
-#define SOFTOKEN_VERSION "3.48.5" SOFTOKEN_ECC_STRING
+#define SOFTOKEN_VERSION "3.59.1.1" SOFTOKEN_ECC_STRING
#define SOFTOKEN_VMAJOR 3
-#define SOFTOKEN_VMINOR 48
-#define SOFTOKEN_VPATCH 5
-#define SOFTOKEN_VBUILD 0
+#define SOFTOKEN_VMINOR 59
+#define SOFTOKEN_VPATCH 1
+#define SOFTOKEN_VBUILD 1
#define SOFTOKEN_BETA PR_FALSE
#endif /* _SOFTKVER_H_ */
diff --git a/security/nss/lib/softoken/softoken.gyp b/security/nss/lib/softoken/softoken.gyp
index 8b6751182..1ff5286d7 100644
--- a/security/nss/lib/softoken/softoken.gyp
+++ b/security/nss/lib/softoken/softoken.gyp
@@ -48,7 +48,7 @@
'fipstest.c',
'fipstokn.c',
'jpakesftk.c',
- 'lgglue.c',
+ 'kbkdf.c',
'lowkey.c',
'lowpbe.c',
'padbuf.c',
@@ -56,14 +56,23 @@
'pkcs11c.c',
'pkcs11u.c',
'sdb.c',
+ 'sftkdhverify.c',
'sftkdb.c',
'sftkhmac.c',
'sftkike.c',
+ 'sftkmessage.c',
'sftkpars.c',
'sftkpwd.c',
'softkver.c',
'tlsprf.c'
],
+ 'conditions': [
+ [ 'disable_dbm==0', {
+ 'sources': [
+ 'lgglue.c',
+ ]
+ }]
+ ]
},
},
{
diff --git a/security/nss/lib/softoken/softoken.h b/security/nss/lib/softoken/softoken.h
index 4626e7849..30586fcf4 100644
--- a/security/nss/lib/softoken/softoken.h
+++ b/security/nss/lib/softoken/softoken.h
@@ -145,7 +145,9 @@ extern PRBool sftk_fatalError;
/*
** macros to check for forked child process after C_Initialize
*/
-#if defined(XP_UNIX) && !defined(NO_FORK_CHECK)
+/* for PKCS #11 3.0, default is NO_FORK_CHECK, if you want it, now you
+ * need to define DO_FORK_CHECK */
+#if defined(XP_UNIX) && defined(DO_FORK_CHECK)
#ifdef DEBUG
@@ -260,6 +262,19 @@ extern PRBool sftkForkCheckDisabled;
#endif
+/*
+ * If we were trying to be complete, we would have both FORK_SAFE
+ * and non-Fork safe interfaces here. That would require doubling
+ * the functions in our function list for both this and the FIPS
+ * interface. Since NSS now always asks for a FORK_SAFE interface,
+ * and can fall back to a non-FORK_SAFE interface, we set only
+ * export one set of interfaces here */
+#ifdef NO_FORK_CHECK
+#define NSS_INTERFACE_FLAGS CKF_INTERFACE_FORK_SAFE
+#else
+#define NSS_INTERFACE_FLAGS 0
+#endif
+
SEC_END_PROTOS
#endif /* _SOFTOKEN_H_ */
diff --git a/security/nss/lib/softoken/softokn.def b/security/nss/lib/softoken/softokn.def
index 0c71a1b4c..135755be6 100644
--- a/security/nss/lib/softoken/softokn.def
+++ b/security/nss/lib/softoken/softokn.def
@@ -26,3 +26,14 @@ NSC_ModuleDBFunc;
;+ local:
;+ *;
;+};
+;+NSS_3.52 { # NSS 3.52 release adds pkcs #11 v3.0
+;+ global:
+C_GetInterfaceList;
+FC_GetInterfaceList;
+NSC_GetInterfaceList;
+C_GetInterface;
+FC_GetInterface;
+NSC_GetInterface;
+;+ local:
+;+ *;
+;+};