Bruno Jesus : rsaenh: Use the remaining hash data as salt if requested.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Aug 5 18:03:06 CDT 2014


Module: wine
Branch: master
Commit: d7aae7d728a03780c3a741e3d0c5bbc82b390e15
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d7aae7d728a03780c3a741e3d0c5bbc82b390e15

Author: Bruno Jesus <00cpxxx at gmail.com>
Date:   Tue Aug  5 00:15:47 2014 -0300

rsaenh: Use the remaining hash data as salt if requested.

---

 dlls/rsaenh/rsaenh.c       |  17 ++++--
 dlls/rsaenh/tests/rsaenh.c | 132 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 145 insertions(+), 4 deletions(-)

diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c
index 32646eb..aa415e7 100644
--- a/dlls/rsaenh/rsaenh.c
+++ b/dlls/rsaenh/rsaenh.c
@@ -3947,7 +3947,7 @@ BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseD
     {
         case ALG_CLASS_DATA_ENCRYPT:
         {
-            int need_padding;
+            int need_padding, copy_len;
             *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
             if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
 
@@ -3977,7 +3977,9 @@ BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseD
                     need_padding = dwLen < pCryptKey->dwKeyLen;
             }
 
-            if (need_padding) {
+            copy_len = pCryptKey->dwKeyLen;
+            if (need_padding)
+            {
                 BYTE pad1[RSAENH_HMAC_DEF_PAD_LEN], pad2[RSAENH_HMAC_DEF_PAD_LEN];
                 BYTE old_hashval[RSAENH_MAX_HASH_SIZE];
                 DWORD i;
@@ -4002,9 +4004,18 @@ BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseD
 
                 memcpy(pCryptHash->abHashValue, old_hashval, RSAENH_MAX_HASH_SIZE);
             }
+            /*
+             * Padding was not required, we have more hash than needed.
+             * Do we need to use the remaining hash as salt?
+             */
+            else if((dwFlags & CRYPT_CREATE_SALT) &&
+                    (Algid == CALG_RC2 || Algid == CALG_RC4))
+            {
+                copy_len += pCryptKey->dwSaltLen;
+            }
     
             memcpy(pCryptKey->abKeyValue, abHashValue, 
-                   RSAENH_MIN(pCryptKey->dwKeyLen, sizeof(pCryptKey->abKeyValue)));
+                   RSAENH_MIN(copy_len, sizeof(pCryptKey->abKeyValue)));
             break;
         }
         case ALG_CLASS_MSG_ENCRYPT:
diff --git a/dlls/rsaenh/tests/rsaenh.c b/dlls/rsaenh/tests/rsaenh.c
index fe1e293..bf105de 100644
--- a/dlls/rsaenh/tests/rsaenh.c
+++ b/dlls/rsaenh/tests/rsaenh.c
@@ -1355,10 +1355,22 @@ static void test_rc2(void)
     static const BYTE rc2_40def_encrypted[] = {
         0x23,0xc8,0x70,0x13,0x42,0x2e,0xa8,0x98,
         0x5c,0xdf,0x7a,0x9b,0xea,0xdb,0x96,0x1b };
+    static const BYTE rc2_40_salt_enh[24] = {
+        0xA3, 0xD7, 0x41, 0x87, 0x7A, 0xD0, 0x18, 0xDB,
+        0xD4, 0x6A, 0x4F, 0xEE, 0xF3, 0xCA, 0xCD, 0x34,
+        0xB3, 0x15, 0x9A, 0x2A, 0x88, 0x5F, 0x43, 0xA5 };
+    static const BYTE rc2_40_salt_base[24] = {
+        0x8C, 0x4E, 0xA6, 0x00, 0x9B, 0x15, 0xEF, 0x9E,
+        0x88, 0x81, 0xD0, 0x65, 0xD6, 0x53, 0x57, 0x08,
+        0x0A, 0x77, 0x80, 0xFA, 0x7E, 0x89, 0x14, 0x55 };
+    static const BYTE rc2_40_salt_strong[24] = {
+        0xB9, 0x33, 0xB6, 0x7A, 0x35, 0xC3, 0x06, 0x88,
+        0xBF, 0xD5, 0xCC, 0xAF, 0x14, 0xAE, 0xE2, 0x31,
+        0xC6, 0x9A, 0xAA, 0x3F, 0x05, 0x2F, 0x22, 0xDA };
     HCRYPTHASH hHash;
     HCRYPTKEY hKey;
     BOOL result;
-    DWORD dwLen, dwKeyLen, dwDataLen, dwMode, dwModeBits;
+    DWORD dwLen, dwKeyLen, dwDataLen, dwMode, dwModeBits, error;
     unsigned char pbData[2000], pbHashValue[16], pszBuffer[256];
     int i;
     
@@ -1575,6 +1587,67 @@ static void test_rc2(void)
 
         result = CryptDestroyKey(hKey);
         ok(result, "%08x\n", GetLastError());
+
+        /* Test a 40 bit key with salt */
+        result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
+        ok(result, "%08x\n", GetLastError());
+
+        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
+        ok(result, "%08x\n", GetLastError());
+
+        result = CryptDeriveKey(hProv, CALG_RC2, hHash, (40<<16)|CRYPT_CREATE_SALT, &hKey);
+        ok(result, "%08x\n", GetLastError());
+
+        dwDataLen = 16;
+        memset(pbData, 0xAF, dwDataLen);
+        SetLastError(0xdeadbeef);
+        result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
+        if(result)
+        {
+            /* Remove IF when fixed */
+            if(ENHANCED_PROV)
+            {
+            todo_wine
+            ok((ENHANCED_PROV && !memcmp(pbData, rc2_40_salt_enh, dwDataLen)) ||
+               (STRONG_PROV && !memcmp(pbData, rc2_40_salt_strong, dwDataLen)) ||
+               (BASE_PROV && !memcmp(pbData, rc2_40_salt_base, dwDataLen)),
+               "RC2 encryption failed!\n");
+            }
+            else
+            {
+            ok((ENHANCED_PROV && !memcmp(pbData, rc2_40_salt_enh, dwDataLen)) ||
+               (STRONG_PROV && !memcmp(pbData, rc2_40_salt_strong, dwDataLen)) ||
+               (BASE_PROV && !memcmp(pbData, rc2_40_salt_base, dwDataLen)),
+               "RC2 encryption failed!\n");
+            }
+        }
+        else /* <= XP */
+        {
+            error = GetLastError();
+            ok(error == NTE_BAD_DATA || broken(error == NTE_DOUBLE_ENCRYPT),
+               "Expected 0x80009005, got 0x%08X\n", error);
+        }
+        dwLen = sizeof(DWORD);
+        dwKeyLen = 12345;
+        result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
+        ok(result, "%08x\n", GetLastError());
+        ok(dwKeyLen == 40, "Expected 40, got %d\n", dwKeyLen);
+
+        dwLen = sizeof(pszBuffer);
+        memset(pszBuffer, 0xAF, dwLen);
+        result = CryptGetKeyParam(hKey, KP_SALT, pszBuffer, &dwLen, 0);
+        ok(result, "%08x\n", GetLastError());
+        if (!ENHANCED_PROV)
+            ok(dwLen == 11, "Expected 11, got %d\n", dwLen);
+        else
+            todo_wine
+            ok(dwLen == 0, "Expected 0, got %d\n", dwLen);
+
+        result = CryptDestroyKey(hKey);
+        ok(result, "%08x\n", GetLastError());
+
+        result = CryptDestroyHash(hHash);
+        ok(result, "%08x\n", GetLastError());
     }
 }
 
@@ -1583,6 +1656,12 @@ static void test_rc4(void)
     static const BYTE rc4[16] = { 
         0x17, 0x0c, 0x44, 0x8e, 0xae, 0x90, 0xcd, 0xb0, 
         0x7f, 0x87, 0xf5, 0x7a, 0xec, 0xb2, 0x2e, 0x35 };    
+    static const BYTE rc4_40_salt[16] = {
+        0x41, 0xE6, 0x33, 0xC9, 0x50, 0xA1, 0xBF, 0x88,
+        0x12, 0x4D, 0xD3, 0xE3, 0x47, 0x88, 0x6D, 0xA5 };
+    static const BYTE rc4_40_salt_base[16] = {
+        0x2F, 0xAC, 0xEA, 0xEA, 0xFF, 0x68, 0x7E, 0x77,
+        0xF4, 0xB9, 0x48, 0x7C, 0x4E, 0x79, 0xA6, 0xB5 };
     BOOL result;
     HCRYPTHASH hHash;
     HCRYPTKEY hKey;
@@ -1684,6 +1763,57 @@ static void test_rc4(void)
 
         result = CryptDestroyKey(hKey);
         ok(result, "%08x\n", GetLastError());
+
+        /* Test a 40 bit key with salt */
+        result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
+        ok(result, "%08x\n", GetLastError());
+
+        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
+        ok(result, "%08x\n", GetLastError());
+
+        result = CryptDeriveKey(hProv, CALG_RC4, hHash, (40<<16)|CRYPT_CREATE_SALT, &hKey);
+        ok(result, "%08x\n", GetLastError());
+        dwDataLen = 16;
+        memset(pbData, 0xAF, dwDataLen);
+        SetLastError(0xdeadbeef);
+        result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
+        ok(result, "%08x\n", GetLastError());
+        /* Remove IF when fixed */
+        if (ENHANCED_PROV)
+        {
+        todo_wine
+        ok((ENHANCED_PROV && !memcmp(pbData, rc4_40_salt, dwDataLen)) ||
+           (!ENHANCED_PROV && !memcmp(pbData, rc4_40_salt_base, dwDataLen)),
+           "RC4 encryption failed!\n");
+        }
+        else
+        {
+        ok((ENHANCED_PROV && !memcmp(pbData, rc4_40_salt, dwDataLen)) ||
+           (!ENHANCED_PROV && !memcmp(pbData, rc4_40_salt_base, dwDataLen)),
+           "RC4 encryption failed!\n");
+        }
+
+        dwLen = sizeof(DWORD);
+        dwKeyLen = 12345;
+        result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
+        ok(result, "%08x\n", GetLastError());
+        ok(dwKeyLen == 40, "Expected 40, got %d\n", dwKeyLen);
+
+        dwLen = sizeof(pszBuffer);
+        memset(pszBuffer, 0xAF, dwLen);
+        result = CryptGetKeyParam(hKey, KP_SALT, pszBuffer, &dwLen, 0);
+        ok(result, "%08x\n", GetLastError());
+        if (!ENHANCED_PROV)
+            ok(dwLen == 11, "Expected 11, got %d\n", dwLen);
+        else
+            todo_wine
+            ok(dwLen == 0, "Expected 0, got %d\n", dwLen);
+
+        result = CryptDestroyKey(hKey);
+        ok(result, "%08x\n", GetLastError());
+
+        result = CryptDestroyHash(hHash);
+        ok(result, "%08x\n", GetLastError());
     }
 }
 




More information about the wine-cvs mailing list