Juan Lang : rsaenh: Add support for CRYPT_IPSEC_HMAC_KEY.
Alexandre Julliard
julliard at winehq.org
Fri Jan 14 12:46:33 CST 2011
Module: wine
Branch: master
Commit: c91afb9733b2227935c0bafaab3f1ef0fcd75dd6
URL: http://source.winehq.org/git/wine.git/?a=commit;h=c91afb9733b2227935c0bafaab3f1ef0fcd75dd6
Author: Juan Lang <juan.lang at gmail.com>
Date: Thu Jan 13 15:08:48 2011 -0800
rsaenh: Add support for CRYPT_IPSEC_HMAC_KEY.
---
dlls/advapi32/tests/crypt.c | 4 --
dlls/rsaenh/rsaenh.c | 93 ++++++++++++++++++++++++++++++++++++-------
dlls/rsaenh/tests/rsaenh.c | 3 +-
3 files changed, 79 insertions(+), 21 deletions(-)
diff --git a/dlls/advapi32/tests/crypt.c b/dlls/advapi32/tests/crypt.c
index 99f113d..2ffc62e 100644
--- a/dlls/advapi32/tests/crypt.c
+++ b/dlls/advapi32/tests/crypt.c
@@ -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());
diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c
index 0f9959d..50954c5 100644
--- a/dlls/rsaenh/rsaenh.c
+++ b/dlls/rsaenh/rsaenh.c
@@ -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];
}
diff --git a/dlls/rsaenh/tests/rsaenh.c b/dlls/rsaenh/tests/rsaenh.c
index 844747c..dd69c1d 100644
--- a/dlls/rsaenh/tests/rsaenh.c
+++ b/dlls/rsaenh/tests/rsaenh.c
@@ -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);
}
More information about the wine-cvs
mailing list