rsaenh: Store key state in hash data for _MAC hash algorithm.
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
dc9ab100fd
commit
4474004b88
|
@ -39,6 +39,13 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
||||||
|
|
||||||
|
#define RSAENH_MAGIC_KEY 0x73620457u
|
||||||
|
#define RSAENH_MAX_KEY_SIZE 64
|
||||||
|
#define RSAENH_MAX_BLOCK_SIZE 24
|
||||||
|
#define RSAENH_KEYSTATE_IDLE 0
|
||||||
|
#define RSAENH_KEYSTATE_ENCRYPTING 1
|
||||||
|
#define RSAENH_KEYSTATE_MASTERKEY 2
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* CRYPTHASH - hash objects
|
* CRYPTHASH - hash objects
|
||||||
*/
|
*/
|
||||||
|
@ -64,17 +71,14 @@ typedef struct tagCRYPTHASH
|
||||||
PHMAC_INFO pHMACInfo;
|
PHMAC_INFO pHMACInfo;
|
||||||
RSAENH_TLS1PRF_PARAMS tpPRFParams;
|
RSAENH_TLS1PRF_PARAMS tpPRFParams;
|
||||||
DWORD buffered_hash_bytes;
|
DWORD buffered_hash_bytes;
|
||||||
|
ALG_ID key_alg_id;
|
||||||
|
KEY_CONTEXT key_context;
|
||||||
|
BYTE abChainVector[RSAENH_MAX_BLOCK_SIZE];
|
||||||
} CRYPTHASH;
|
} CRYPTHASH;
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* CRYPTKEY - key objects
|
* CRYPTKEY - key objects
|
||||||
*/
|
*/
|
||||||
#define RSAENH_MAGIC_KEY 0x73620457u
|
|
||||||
#define RSAENH_MAX_KEY_SIZE 64
|
|
||||||
#define RSAENH_MAX_BLOCK_SIZE 24
|
|
||||||
#define RSAENH_KEYSTATE_IDLE 0
|
|
||||||
#define RSAENH_KEYSTATE_ENCRYPTING 1
|
|
||||||
#define RSAENH_KEYSTATE_MASTERKEY 2
|
|
||||||
typedef struct _RSAENH_SCHANNEL_INFO
|
typedef struct _RSAENH_SCHANNEL_INFO
|
||||||
{
|
{
|
||||||
SCHANNEL_ALG saEncAlg;
|
SCHANNEL_ALG saEncAlg;
|
||||||
|
@ -271,18 +275,6 @@ RSAENH_CPGetKeyParam(
|
||||||
DWORD dwFlags
|
DWORD dwFlags
|
||||||
);
|
);
|
||||||
|
|
||||||
BOOL WINAPI
|
|
||||||
RSAENH_CPEncrypt(
|
|
||||||
HCRYPTPROV hProv,
|
|
||||||
HCRYPTKEY hKey,
|
|
||||||
HCRYPTHASH hHash,
|
|
||||||
BOOL Final,
|
|
||||||
DWORD dwFlags,
|
|
||||||
BYTE *pbData,
|
|
||||||
DWORD *pdwDataLen,
|
|
||||||
DWORD dwBufLen
|
|
||||||
);
|
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
RSAENH_CPCreateHash(
|
RSAENH_CPCreateHash(
|
||||||
HCRYPTPROV hProv,
|
HCRYPTPROV hProv,
|
||||||
|
@ -674,6 +666,8 @@ static void destroy_hash(OBJECTHDR *pObject)
|
||||||
free_hmac_info(pCryptHash->pHMACInfo);
|
free_hmac_info(pCryptHash->pHMACInfo);
|
||||||
free_data_blob(&pCryptHash->tpPRFParams.blobLabel);
|
free_data_blob(&pCryptHash->tpPRFParams.blobLabel);
|
||||||
free_data_blob(&pCryptHash->tpPRFParams.blobSeed);
|
free_data_blob(&pCryptHash->tpPRFParams.blobSeed);
|
||||||
|
if (pCryptHash->aiAlgid == CALG_MAC)
|
||||||
|
free_key_impl(pCryptHash->key_alg_id, &pCryptHash->key_context);
|
||||||
free(pCryptHash);
|
free(pCryptHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,6 +722,7 @@ static inline BOOL init_hash(CRYPTHASH *pCryptHash) {
|
||||||
*/
|
*/
|
||||||
static inline void update_hash(CRYPTHASH *pCryptHash, const BYTE *pbData, DWORD dwDataLen)
|
static inline void update_hash(CRYPTHASH *pCryptHash, const BYTE *pbData, DWORD dwDataLen)
|
||||||
{
|
{
|
||||||
|
CRYPTKEY *key;
|
||||||
BYTE *pbTemp;
|
BYTE *pbTemp;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
|
|
||||||
|
@ -739,6 +734,11 @@ static inline void update_hash(CRYPTHASH *pCryptHash, const BYTE *pbData, DWORD
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CALG_MAC:
|
case CALG_MAC:
|
||||||
|
if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&key))
|
||||||
|
{
|
||||||
|
FIXME("Key lookup failed.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (pCryptHash->buffered_hash_bytes)
|
if (pCryptHash->buffered_hash_bytes)
|
||||||
{
|
{
|
||||||
len = min(pCryptHash->dwHashSize - pCryptHash->buffered_hash_bytes, dwDataLen);
|
len = min(pCryptHash->dwHashSize - pCryptHash->buffered_hash_bytes, dwDataLen);
|
||||||
|
@ -750,10 +750,10 @@ static inline void update_hash(CRYPTHASH *pCryptHash, const BYTE *pbData, DWORD
|
||||||
return;
|
return;
|
||||||
pCryptHash->buffered_hash_bytes = 0;
|
pCryptHash->buffered_hash_bytes = 0;
|
||||||
len = pCryptHash->dwHashSize;
|
len = pCryptHash->dwHashSize;
|
||||||
if (!RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, FALSE, 0,
|
if (!block_encrypt(key, pCryptHash->abHashValue, &len, len, FALSE,
|
||||||
pCryptHash->abHashValue, &len, len))
|
&pCryptHash->key_context, pCryptHash->abChainVector))
|
||||||
{
|
{
|
||||||
FIXME("RSAENH_CPEncrypt failed.\n");
|
FIXME("block_encrypt failed.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -769,10 +769,10 @@ static inline void update_hash(CRYPTHASH *pCryptHash, const BYTE *pbData, DWORD
|
||||||
memcpy(pbTemp, pbData, len);
|
memcpy(pbTemp, pbData, len);
|
||||||
pbData += len;
|
pbData += len;
|
||||||
dwDataLen -= len;
|
dwDataLen -= len;
|
||||||
if (!RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, FALSE, 0,
|
if (!block_encrypt(key, pbTemp, &len, len, FALSE,
|
||||||
pbTemp, &len, len))
|
&pCryptHash->key_context, pCryptHash->abChainVector))
|
||||||
{
|
{
|
||||||
FIXME("RSAENH_CPEncrypt failed.\n");
|
FIXME("block_encrypt failed.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
free(pbTemp);
|
free(pbTemp);
|
||||||
|
@ -798,8 +798,10 @@ static inline void update_hash(CRYPTHASH *pCryptHash, const BYTE *pbData, DWORD
|
||||||
* PARAMS
|
* PARAMS
|
||||||
* pCryptHash [I] Hash object to be finalized.
|
* pCryptHash [I] Hash object to be finalized.
|
||||||
*/
|
*/
|
||||||
static inline void finalize_hash(CRYPTHASH *pCryptHash) {
|
static inline void finalize_hash(CRYPTHASH *pCryptHash)
|
||||||
|
{
|
||||||
DWORD dwDataLen;
|
DWORD dwDataLen;
|
||||||
|
CRYPTKEY *key;
|
||||||
|
|
||||||
switch (pCryptHash->aiAlgid)
|
switch (pCryptHash->aiAlgid)
|
||||||
{
|
{
|
||||||
|
@ -821,10 +823,15 @@ static inline void finalize_hash(CRYPTHASH *pCryptHash) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CALG_MAC:
|
case CALG_MAC:
|
||||||
|
if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&key))
|
||||||
|
{
|
||||||
|
FIXME("Key lookup failed.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
dwDataLen = pCryptHash->buffered_hash_bytes;
|
dwDataLen = pCryptHash->buffered_hash_bytes;
|
||||||
if (!RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, TRUE, 0,
|
if (!block_encrypt(key, pCryptHash->abHashValue, &dwDataLen, pCryptHash->dwHashSize, TRUE,
|
||||||
pCryptHash->abHashValue, &dwDataLen, pCryptHash->dwHashSize))
|
&pCryptHash->key_context, pCryptHash->abChainVector))
|
||||||
FIXME("RSAENH_CPEncrypt failed.\n");
|
FIXME("block_encrypt failed.\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -2264,7 +2271,7 @@ BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
|
||||||
BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags,
|
BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags,
|
||||||
HCRYPTHASH *phHash)
|
HCRYPTHASH *phHash)
|
||||||
{
|
{
|
||||||
CRYPTKEY *pCryptKey;
|
CRYPTKEY *pCryptKey = NULL;
|
||||||
CRYPTHASH *pCryptHash;
|
CRYPTHASH *pCryptHash;
|
||||||
const PROV_ENUMALGS_EX *peaAlgidInfo;
|
const PROV_ENUMALGS_EX *peaAlgidInfo;
|
||||||
|
|
||||||
|
@ -2319,6 +2326,13 @@ BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
|
||||||
|
|
||||||
pCryptHash->aiAlgid = Algid;
|
pCryptHash->aiAlgid = Algid;
|
||||||
pCryptHash->hKey = hKey;
|
pCryptHash->hKey = hKey;
|
||||||
|
if (Algid == CALG_MAC)
|
||||||
|
{
|
||||||
|
pCryptHash->key_alg_id = pCryptKey->aiAlgid;
|
||||||
|
setup_key(pCryptKey);
|
||||||
|
duplicate_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, &pCryptHash->key_context);
|
||||||
|
memcpy(pCryptHash->abChainVector, pCryptKey->abChainVector, sizeof(pCryptHash->abChainVector));
|
||||||
|
}
|
||||||
pCryptHash->hProv = hProv;
|
pCryptHash->hProv = hProv;
|
||||||
pCryptHash->dwState = RSAENH_HASHSTATE_HASHING;
|
pCryptHash->dwState = RSAENH_HASHSTATE_HASHING;
|
||||||
pCryptHash->pHMACInfo = NULL;
|
pCryptHash->pHMACInfo = NULL;
|
||||||
|
|
|
@ -1853,7 +1853,9 @@ static void test_mac(void) {
|
||||||
DWORD dwLen;
|
DWORD dwLen;
|
||||||
BYTE abData[256], abEnc[264];
|
BYTE abData[256], abEnc[264];
|
||||||
static const BYTE mac_40[8] = { 0xb7, 0xa2, 0x46, 0xe9, 0x11, 0x31, 0xe0, 0xad};
|
static const BYTE mac_40[8] = { 0xb7, 0xa2, 0x46, 0xe9, 0x11, 0x31, 0xe0, 0xad};
|
||||||
|
static const BYTE mac_40_old[8] = { 0x44, 0x78, 0x38, 0xad, 0x10, 0x13, 0x60, 0x8e};
|
||||||
static const BYTE mac_40_2[8] = { 0xef, 0x22, 0x0a, 0x3b, 0xd0, 0xab, 0x48, 0x49};
|
static const BYTE mac_40_2[8] = { 0xef, 0x22, 0x0a, 0x3b, 0xd0, 0xab, 0x48, 0x49};
|
||||||
|
static const BYTE mac_40_2_old[8] = { 0xa3, 0xf3, 0xfc, 0x70, 0xf4, 0xfa, 0xb0, 0x3e};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i < ARRAY_SIZE(abData); i++) abData[i] = (BYTE)i;
|
for (i=0; i < ARRAY_SIZE(abData); i++) abData[i] = (BYTE)i;
|
||||||
|
@ -1869,6 +1871,10 @@ static void test_mac(void) {
|
||||||
ok(result, "%08lx\n", GetLastError());
|
ok(result, "%08lx\n", GetLastError());
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
|
|
||||||
|
dwLen = 8;
|
||||||
|
result = CryptEncrypt(hKey, 0, FALSE, 0, abEnc, &dwLen, dwLen);
|
||||||
|
ok(result, "%08lx\n", GetLastError());
|
||||||
|
|
||||||
result = CryptHashData(hHash, abData, sizeof(abData), 0);
|
result = CryptHashData(hHash, abData, sizeof(abData), 0);
|
||||||
ok(result, "%08lx\n", GetLastError());
|
ok(result, "%08lx\n", GetLastError());
|
||||||
|
|
||||||
|
@ -1876,7 +1882,9 @@ static void test_mac(void) {
|
||||||
result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
|
result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
|
||||||
ok(result && dwLen == 8, "%08lx, dwLen: %ld\n", GetLastError(), dwLen);
|
ok(result && dwLen == 8, "%08lx, dwLen: %ld\n", GetLastError(), dwLen);
|
||||||
|
|
||||||
ok(!memcmp(abData, mac_40, sizeof(mac_40)), "MAC failed!\n");
|
/* Hash state is affected by key state before Win8. */
|
||||||
|
ok(!memcmp(abData, mac_40, sizeof(mac_40)) || broken(!memcmp(abData, mac_40_old, sizeof(mac_40_old))),
|
||||||
|
"Hash does not match.\n");
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(abData); ++i)
|
for (i = 0; i < ARRAY_SIZE(abData); ++i)
|
||||||
abData[i] = (BYTE)i;
|
abData[i] = (BYTE)i;
|
||||||
|
@ -1890,8 +1898,17 @@ static void test_mac(void) {
|
||||||
result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
|
result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
|
||||||
ok(result, "%08lx\n", GetLastError());
|
ok(result, "%08lx\n", GetLastError());
|
||||||
|
|
||||||
|
dwLen = 8;
|
||||||
|
result = CryptEncrypt(hKey, 0, FALSE, 0, abEnc, &dwLen, dwLen);
|
||||||
|
ok(result, "%08lx\n", GetLastError());
|
||||||
|
|
||||||
result = CryptHashData(hHash, abData, 1, 0);
|
result = CryptHashData(hHash, abData, 1, 0);
|
||||||
ok(result, "%08lx\n", GetLastError());
|
ok(result, "%08lx\n", GetLastError());
|
||||||
|
|
||||||
|
dwLen = 8;
|
||||||
|
result = CryptDecrypt(hKey, 0, FALSE, 0, abEnc, &dwLen);
|
||||||
|
ok(result, "%08lx\n", GetLastError());
|
||||||
|
|
||||||
result = CryptHashData(hHash, abData + 1, 1, 0);
|
result = CryptHashData(hHash, abData + 1, 1, 0);
|
||||||
ok(result, "%08lx\n", GetLastError());
|
ok(result, "%08lx\n", GetLastError());
|
||||||
result = CryptHashData(hHash, abData + 2, 6, 0);
|
result = CryptHashData(hHash, abData + 2, 6, 0);
|
||||||
|
@ -1899,11 +1916,17 @@ static void test_mac(void) {
|
||||||
result = CryptHashData(hHash, abData + 8, 9, 0);
|
result = CryptHashData(hHash, abData + 8, 9, 0);
|
||||||
ok(result, "%08lx\n", GetLastError());
|
ok(result, "%08lx\n", GetLastError());
|
||||||
|
|
||||||
|
dwLen = 8;
|
||||||
|
result = CryptDecrypt(hKey, 0, FALSE, 0, abEnc, &dwLen);
|
||||||
|
ok(result, "%08lx\n", GetLastError());
|
||||||
|
|
||||||
dwLen = ARRAY_SIZE(abData);
|
dwLen = ARRAY_SIZE(abData);
|
||||||
result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
|
result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
|
||||||
ok(result && dwLen == 8, "%08lx, dwLen %ld\n", GetLastError(), dwLen);
|
ok(result && dwLen == 8, "%08lx, dwLen %ld\n", GetLastError(), dwLen);
|
||||||
|
|
||||||
ok(!memcmp(abData, mac_40_2, sizeof(mac_40)), "Hash does not match.\n");
|
/* Hash state is affected by key state before Win8. */
|
||||||
|
ok(!memcmp(abData, mac_40_2, sizeof(mac_40_2))
|
||||||
|
|| broken(!memcmp(abData, mac_40_2_old, sizeof(mac_40_2_old))), "Hash does not match.\n");
|
||||||
|
|
||||||
result = CryptDestroyHash(hHash);
|
result = CryptDestroyHash(hHash);
|
||||||
ok(result, "%08lx\n", GetLastError());
|
ok(result, "%08lx\n", GetLastError());
|
||||||
|
|
Loading…
Reference in New Issue