Commit c91afb97 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

rsaenh: Add support for CRYPT_IPSEC_HMAC_KEY.

parent 5ccf2bd9
......@@ -993,7 +993,6 @@ static void test_rc2_keylen(void)
sizeof(BLOBHEADER)+sizeof(DWORD)+key_blob.key_size,
0, CRYPT_IPSEC_HMAC_KEY, &hkey);
/* CRYPT_IPSEC_HMAC_KEY is not supported on W2K and lower */
todo_wine
ok(ret ||
broken(!ret && GetLastError() == NTE_BAD_FLAGS),
"CryptImportKey error %08x\n", GetLastError());
......@@ -1041,7 +1040,6 @@ static void test_rc2_keylen(void)
sizeof(BLOBHEADER)+sizeof(DWORD)+key_blob.key_size,
0, CRYPT_IPSEC_HMAC_KEY, &hkey);
/* CRYPT_IPSEC_HMAC_KEY is not supported on W2K and lower */
todo_wine
ok(ret ||
broken(!ret && GetLastError() == NTE_BAD_FLAGS),
"CryptImportKey error %08x\n", GetLastError());
......@@ -1066,7 +1064,6 @@ static void test_rc2_keylen(void)
ret = pCryptImportKey(provider, (BYTE*)&key_blob,
sizeof(BLOBHEADER)+sizeof(DWORD)+key_blob.key_size,
0, CRYPT_IPSEC_HMAC_KEY, &hkey);
todo_wine
ok(ret ||
broken(!ret && GetLastError() == NTE_BAD_FLAGS),
"CryptImportKey error %08x\n", GetLastError());
......@@ -1081,7 +1078,6 @@ static void test_rc2_keylen(void)
ret = pCryptImportKey(provider, (BYTE*)&key_blob,
sizeof(BLOBHEADER)+sizeof(DWORD)+key_blob.key_size,
0, CRYPT_IPSEC_HMAC_KEY, &hkey);
todo_wine
ok(ret ||
broken(!ret && GetLastError() == NTE_BAD_FLAGS),
"CryptImportKey error %08x\n", GetLastError());
......
......@@ -74,7 +74,7 @@ typedef struct tagCRYPTHASH
* CRYPTKEY - key objects
*/
#define RSAENH_MAGIC_KEY 0x73620457u
#define RSAENH_MAX_KEY_SIZE 48
#define RSAENH_MAX_KEY_SIZE 64
#define RSAENH_MAX_BLOCK_SIZE 24
#define RSAENH_KEYSTATE_IDLE 0
#define RSAENH_KEYSTATE_ENCRYPTING 1
......@@ -105,6 +105,7 @@ typedef struct tagCRYPTKEY
BYTE abInitVector[RSAENH_MAX_BLOCK_SIZE];
BYTE abChainVector[RSAENH_MAX_BLOCK_SIZE];
RSAENH_SCHANNEL_INFO siSChannelInfo;
CRYPT_DATA_BLOB blobHmacKey;
} CRYPTKEY;
/******************************************************************************
......@@ -732,6 +733,7 @@ static void destroy_key(OBJECTHDR *pObject)
free_key_impl(pCryptKey->aiAlgid, &pCryptKey->context);
free_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
free_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
free_data_blob(&pCryptKey->blobHmacKey);
HeapFree(GetProcessHeap(), 0, pCryptKey);
}
......@@ -825,7 +827,13 @@ static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTK
return (HCRYPTKEY)INVALID_HANDLE_VALUE;
}
break;
case CALG_HMAC:
/* Avoid the key length check for HMAC keys, which have unlimited
* length.
*/
break;
default:
if (dwKeyLen % 8 ||
dwKeyLen > peaAlgidInfo->dwMaxLen ||
......@@ -859,6 +867,7 @@ static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTK
memset(pCryptKey->abInitVector, 0, sizeof(pCryptKey->abInitVector));
init_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
init_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
init_data_blob(&pCryptKey->blobHmacKey);
switch(aiAlgid)
{
......@@ -892,6 +901,11 @@ static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTK
pCryptKey->dwBlockLen = dwKeyLen >> 3;
pCryptKey->dwMode = 0;
break;
case CALG_HMAC:
pCryptKey->dwBlockLen = 0;
pCryptKey->dwMode = 0;
break;
}
*ppCryptKey = pCryptKey;
......@@ -2931,25 +2945,53 @@ static BOOL import_plaintext_key(HCRYPTPROV hProv, CONST BYTE *pbData,
CONST DWORD *pKeyLen = (CONST DWORD *)(pBlobHeader + 1);
CONST BYTE *pbKeyStream = (CONST BYTE*)(pKeyLen + 1);
if (dwFlags & CRYPT_IPSEC_HMAC_KEY)
{
FIXME("unimplemented for CRYPT_IPSEC_HMAC_KEY\n");
SetLastError(NTE_BAD_FLAGS);
return FALSE;
}
if (dwDataLen < sizeof(BLOBHEADER)+sizeof(DWORD)+*pKeyLen)
{
SetLastError(NTE_BAD_DATA); /* FIXME: error code */
return FALSE;
}
*phKey = new_key(hProv, pBlobHeader->aiKeyAlg, *pKeyLen<<19, &pCryptKey);
if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
return FALSE;
memcpy(pCryptKey->abKeyValue, pbKeyStream, *pKeyLen);
setup_key(pCryptKey);
if (dwFlags & CRYPT_EXPORTABLE)
pCryptKey->dwPermissions |= CRYPT_EXPORT;
if (dwFlags & CRYPT_IPSEC_HMAC_KEY)
{
*phKey = new_key(hProv, CALG_HMAC, 0, &pCryptKey);
if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
return FALSE;
if (*pKeyLen <= sizeof(pCryptKey->abKeyValue))
{
memcpy(pCryptKey->abKeyValue, pbKeyStream, *pKeyLen);
pCryptKey->dwKeyLen = *pKeyLen;
}
else
{
CRYPT_DATA_BLOB blobHmacKey = { *pKeyLen, (BYTE *)pbKeyStream };
/* In order to initialize an HMAC key, the key material is hashed,
* and the output of the hash function is used as the key material.
* Unfortunately, the way the Crypto API is designed, we don't know
* the hash algorithm yet, so we have to copy the entire key
* material.
*/
if (!copy_data_blob(&pCryptKey->blobHmacKey, &blobHmacKey))
{
release_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY);
*phKey = (HCRYPTKEY)INVALID_HANDLE_VALUE;
return FALSE;
}
}
setup_key(pCryptKey);
if (dwFlags & CRYPT_EXPORTABLE)
pCryptKey->dwPermissions |= CRYPT_EXPORT;
}
else
{
*phKey = new_key(hProv, pBlobHeader->aiKeyAlg, *pKeyLen<<19, &pCryptKey);
if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
return FALSE;
memcpy(pCryptKey->abKeyValue, pbKeyStream, *pKeyLen);
setup_key(pCryptKey);
if (dwFlags & CRYPT_EXPORTABLE)
pCryptKey->dwPermissions |= CRYPT_EXPORT;
}
return TRUE;
}
......@@ -4172,6 +4214,27 @@ BOOL WINAPI RSAENH_CPSetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwPa
return FALSE;
}
if (pCryptKey->aiAlgid == CALG_HMAC && !pCryptKey->dwKeyLen) {
HCRYPTHASH hKeyHash;
if (!RSAENH_CPCreateHash(hProv, ((PHMAC_INFO)pbData)->HashAlgid, 0, 0,
&hKeyHash))
return FALSE;
if (!RSAENH_CPHashData(hProv, hKeyHash, pCryptKey->blobHmacKey.pbData,
pCryptKey->blobHmacKey.cbData, 0))
{
RSAENH_CPDestroyHash(hProv, hKeyHash);
return FALSE;
}
pCryptKey->dwKeyLen = sizeof(pCryptKey->abKeyValue);
if (!RSAENH_CPGetHashParam(hProv, hKeyHash, HP_HASHVAL, pCryptKey->abKeyValue,
&pCryptKey->dwKeyLen, 0))
{
RSAENH_CPDestroyHash(hProv, hKeyHash);
return FALSE;
}
RSAENH_CPDestroyHash(hProv, hKeyHash);
}
for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbInnerString); i++) {
pCryptHash->pHMACInfo->pbInnerString[i] ^= pCryptKey->abKeyValue[i];
}
......
......@@ -2235,7 +2235,6 @@ static void test_import_hmac(void)
*key_len = test_case->key_len;
memcpy(key_bytes, test_case->key, *key_len);
result = CryptImportKey(hProv, blob, size, 0, CRYPT_IPSEC_HMAC_KEY, &key);
todo_wine
ok(result || broken(GetLastError() == NTE_BAD_FLAGS /* Win2k */), "CryptImportKey failed on test case %d: %08x\n", i, GetLastError());
if (result)
{
......@@ -2253,7 +2252,7 @@ static void test_import_hmac(void)
digest_size = sizeof(digest);
result = CryptGetHashParam(hash, HP_HASHVAL, digest, &digest_size, 0);
ok(result, "CryptGetHashParam failed on test case %d: %08x\n", i, GetLastError());
ok(!memcmp(digest, test_case->digest, sizeof(digest)), "Unexpected valued on test case %d\n", i);
ok(!memcmp(digest, test_case->digest, sizeof(digest)), "Unexpected value on test case %d\n", i);
CryptDestroyHash(hash);
CryptDestroyKey(key);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment