[3/4] rsaenh: Change the way AES 128 is derived to match Windows behavior

Bruno Jesus 00cpxxx at gmail.com
Tue Jul 22 22:48:09 CDT 2014


AES 192 and 256 are working fine, but AES 128 is not. After hours of
testing I think this is a plausible solution. What I don't understand
is how this ever worked, is there anything else that would affect the
keys?
-------------- next part --------------

---
 dlls/rsaenh/rsaenh.c       | 26 +++++++++++++++++++++++---
 dlls/rsaenh/tests/rsaenh.c |  5 -----
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c
index dd49618..aec203c 100644
--- a/dlls/rsaenh/rsaenh.c
+++ b/dlls/rsaenh/rsaenh.c
@@ -3926,6 +3926,8 @@ BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseD
     switch (GET_ALG_CLASS(Algid))
     {
         case ALG_CLASS_DATA_ENCRYPT:
+        {
+            int need_padding;
             *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
             if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
 
@@ -3936,8 +3938,26 @@ BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseD
              */
             dwLen = RSAENH_MAX_HASH_SIZE;
             RSAENH_CPGetHashParam(pCryptHash->hProv, hBaseData, HP_HASHVAL, abHashValue, &dwLen, 0);
-    
-            if (dwLen < pCryptKey->dwKeyLen) {
+
+            /* 
+             * The usage of padding seems to vary from algorithm to algorithm.
+             * For now the only different case found was for AES with 128 bit key.
+             */
+            switch(Algid)
+            {
+                case CALG_AES_128:
+                    /* To reduce the chance of regressions we will only deviate
+                     * from the old behavior for the tested hash lengths */
+                    if (dwLen == 16 || dwLen == 20)
+                    {
+                        need_padding = 1;
+                        break;
+                    }
+                default:
+                    need_padding = dwLen < 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;
@@ -3966,7 +3986,7 @@ BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseD
             memcpy(pCryptKey->abKeyValue, abHashValue, 
                    RSAENH_MIN(pCryptKey->dwKeyLen, sizeof(pCryptKey->abKeyValue)));
             break;
-
+        }
         case ALG_CLASS_MSG_ENCRYPT:
             if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY,
                                (OBJECTHDR**)&pMasterKey)) 
diff --git a/dlls/rsaenh/tests/rsaenh.c b/dlls/rsaenh/tests/rsaenh.c
index dad6a27..c49bd92 100644
--- a/dlls/rsaenh/tests/rsaenh.c
+++ b/dlls/rsaenh/tests/rsaenh.c
@@ -1140,9 +1140,6 @@ static void test_aes(int keylen)
     result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, sizeof(pbData));
     ok(result, "Expected OK, got last error %d\n", GetLastError());
     ok(dwLen == 48, "Expected dwLen 48, got %d\n", dwLen);
-    if(i == 0) todo_wine
-    ok(!memcmp(aes_cbc_enc[i], pbData, dwLen), "Expected equal data sequences\n");
-    else
     ok(!memcmp(aes_cbc_enc[i], pbData, dwLen), "Expected equal data sequences\n");
 
     result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
@@ -3530,9 +3527,7 @@ static void test_key_derivation(const char *prov)
 
     memset(wine_broken, 0, sizeof(wine_broken));
     wine_broken[8].mode = wine_broken[8].blen = 1;
-    wine_broken[9].exp_data = 1;
     wine_broken[20] = wine_broken[32] = wine_broken[44] = wine_broken[8];
-    wine_broken[21] = wine_broken[33] = wine_broken[45] = wine_broken[9];
 
     for (i=0; i<sizeof(tests)/sizeof(tests[0]); i++)
     {
-- 
1.8.3.2



More information about the wine-patches mailing list