rsaenh: Handle uneven hash data updates sizes for CALG_MAC.

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2022-05-13 10:25:08 -05:00 committed by Alexandre Julliard
parent cec9705008
commit 6bb21c771b
2 changed files with 79 additions and 10 deletions

View File

@ -63,6 +63,7 @@ typedef struct tagCRYPTHASH
BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
PHMAC_INFO pHMACInfo;
RSAENH_TLS1PRF_PARAMS tpPRFParams;
DWORD buffered_hash_bytes;
} CRYPTHASH;
/******************************************************************************
@ -661,6 +662,7 @@ static inline BOOL init_hash(CRYPTHASH *pCryptHash) {
static inline void update_hash(CRYPTHASH *pCryptHash, const BYTE *pbData, DWORD dwDataLen)
{
BYTE *pbTemp;
DWORD len;
switch (pCryptHash->aiAlgid)
{
@ -670,12 +672,49 @@ static inline void update_hash(CRYPTHASH *pCryptHash, const BYTE *pbData, DWORD
break;
case CALG_MAC:
pbTemp = malloc(dwDataLen);
if (!pbTemp) return;
memcpy(pbTemp, pbData, dwDataLen);
RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, FALSE, 0,
pbTemp, &dwDataLen, dwDataLen);
free(pbTemp);
if (pCryptHash->buffered_hash_bytes)
{
len = min(pCryptHash->dwHashSize - pCryptHash->buffered_hash_bytes, dwDataLen);
memcpy(pCryptHash->abHashValue + pCryptHash->buffered_hash_bytes, pbData, len);
pbData += len;
dwDataLen -= len;
pCryptHash->buffered_hash_bytes += len;
if (pCryptHash->buffered_hash_bytes < pCryptHash->dwHashSize)
return;
pCryptHash->buffered_hash_bytes = 0;
len = pCryptHash->dwHashSize;
if (!RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, FALSE, 0,
pCryptHash->abHashValue, &len, len))
{
FIXME("RSAENH_CPEncrypt failed.\n");
return;
}
}
len = dwDataLen - dwDataLen % pCryptHash->dwHashSize;
if (len)
{
pbTemp = malloc(len);
if (!pbTemp)
{
ERR("No memory.\n");
return;
}
memcpy(pbTemp, pbData, len);
pbData += len;
dwDataLen -= len;
if (!RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, FALSE, 0,
pbTemp, &len, len))
{
FIXME("RSAENH_CPEncrypt failed.\n");
return;
}
free(pbTemp);
}
if (dwDataLen)
{
memcpy(pCryptHash->abHashValue, pbData, dwDataLen);
pCryptHash->buffered_hash_bytes = dwDataLen;
}
break;
default:
@ -715,9 +754,10 @@ static inline void finalize_hash(CRYPTHASH *pCryptHash) {
break;
case CALG_MAC:
dwDataLen = 0;
RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, TRUE, 0,
pCryptHash->abHashValue, &dwDataLen, pCryptHash->dwHashSize);
dwDataLen = pCryptHash->buffered_hash_bytes;
if (!RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, TRUE, 0,
pCryptHash->abHashValue, &dwDataLen, pCryptHash->dwHashSize))
FIXME("RSAENH_CPEncrypt failed.\n");
break;
default:
@ -2217,6 +2257,7 @@ BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey,
pCryptHash->pHMACInfo = NULL;
pCryptHash->hash_handle = NULL;
pCryptHash->dwHashSize = peaAlgidInfo->dwDefaultLen >> 3;
pCryptHash->buffered_hash_bytes = 0;
init_data_blob(&pCryptHash->tpPRFParams.blobLabel);
init_data_blob(&pCryptHash->tpPRFParams.blobSeed);

View File

@ -1853,6 +1853,7 @@ static void test_mac(void) {
DWORD dwLen;
BYTE abData[256], abEnc[264];
static const BYTE mac_40[8] = { 0xb7, 0xa2, 0x46, 0xe9, 0x11, 0x31, 0xe0, 0xad};
static const BYTE mac_40_2[8] = { 0xef, 0x22, 0x0a, 0x3b, 0xd0, 0xab, 0x48, 0x49};
int i;
for (i=0; i < ARRAY_SIZE(abData); i++) abData[i] = (BYTE)i;
@ -1876,7 +1877,34 @@ static void test_mac(void) {
ok(result && dwLen == 8, "%08lx, dwLen: %ld\n", GetLastError(), dwLen);
ok(!memcmp(abData, mac_40, sizeof(mac_40)), "MAC failed!\n");
for (i = 0; i < ARRAY_SIZE(abData); ++i)
abData[i] = (BYTE)i;
result = CryptHashData(hHash, abData, 1, 0);
ok(!result && GetLastError() == NTE_BAD_HASH_STATE, "Unexpected result %d, error %#lx\n", result, GetLastError());
result = CryptDestroyHash(hHash);
ok(result, "%08lx\n", GetLastError());
result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
ok(result, "%08lx\n", GetLastError());
result = CryptHashData(hHash, abData, 1, 0);
ok(result, "%08lx\n", GetLastError());
result = CryptHashData(hHash, abData + 1, 1, 0);
ok(result, "%08lx\n", GetLastError());
result = CryptHashData(hHash, abData + 2, 6, 0);
ok(result, "%08lx\n", GetLastError());
result = CryptHashData(hHash, abData + 8, 9, 0);
ok(result, "%08lx\n", GetLastError());
dwLen = ARRAY_SIZE(abData);
result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
ok(result && dwLen == 8, "%08lx, dwLen %ld\n", GetLastError(), dwLen);
ok(!memcmp(abData, mac_40_2, sizeof(mac_40)), "Hash does not match.\n");
result = CryptDestroyHash(hHash);
ok(result, "%08lx\n", GetLastError());