diff options
Diffstat (limited to 'security/nss/lib/softoken/sftkike.c')
-rw-r--r-- | security/nss/lib/softoken/sftkike.c | 170 |
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; } |