summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/softoken/sftkike.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/softoken/sftkike.c')
-rw-r--r--security/nss/lib/softoken/sftkike.c170
1 files changed, 142 insertions, 28 deletions
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;
}