Paul Gofman : rsaenh: Handle uneven hash data updates sizes for CALG_MAC.

Alexandre Julliard julliard at winehq.org
Mon May 16 15:37:59 CDT 2022


Module: wine
Branch: master
Commit: 6bb21c771b41655f4e3b4c653c9c3a7ef1fc1346
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=6bb21c771b41655f4e3b4c653c9c3a7ef1fc1346

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Fri May 13 10:25:08 2022 -0500

rsaenh: Handle uneven hash data updates sizes for CALG_MAC.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/rsaenh/rsaenh.c       | 59 +++++++++++++++++++++++++++++++++++++++-------
 dlls/rsaenh/tests/rsaenh.c | 30 ++++++++++++++++++++++-
 2 files changed, 79 insertions(+), 10 deletions(-)

diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c
index f9513d0533e..140fdec40d5 100644
--- a/dlls/rsaenh/rsaenh.c
+++ b/dlls/rsaenh/rsaenh.c
@@ -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);
 
diff --git a/dlls/rsaenh/tests/rsaenh.c b/dlls/rsaenh/tests/rsaenh.c
index f822c29bbc0..c9dbb72f427 100644
--- a/dlls/rsaenh/tests/rsaenh.c
+++ b/dlls/rsaenh/tests/rsaenh.c
@@ -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());
     




More information about the wine-cvs mailing list