From: Bruno Jesus <00cpxxx@gmail.com> Subject: [3/4] rsaenh: Change the way AES 128 is derived to match Windows behavior Message-Id: Date: Wed, 23 Jul 2014 00:48:09 -0300 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? --- 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