rsaenh: Use the remaining hash data as salt if requested.
This commit is contained in:
parent
fb58e7eca6
commit
d7aae7d728
|
@ -3947,7 +3947,7 @@ BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseD
|
||||||
{
|
{
|
||||||
case ALG_CLASS_DATA_ENCRYPT:
|
case ALG_CLASS_DATA_ENCRYPT:
|
||||||
{
|
{
|
||||||
int need_padding;
|
int need_padding, copy_len;
|
||||||
*phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
|
*phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
|
||||||
if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
|
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;
|
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 pad1[RSAENH_HMAC_DEF_PAD_LEN], pad2[RSAENH_HMAC_DEF_PAD_LEN];
|
||||||
BYTE old_hashval[RSAENH_MAX_HASH_SIZE];
|
BYTE old_hashval[RSAENH_MAX_HASH_SIZE];
|
||||||
DWORD i;
|
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);
|
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,
|
memcpy(pCryptKey->abKeyValue, abHashValue,
|
||||||
RSAENH_MIN(pCryptKey->dwKeyLen, sizeof(pCryptKey->abKeyValue)));
|
RSAENH_MIN(copy_len, sizeof(pCryptKey->abKeyValue)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ALG_CLASS_MSG_ENCRYPT:
|
case ALG_CLASS_MSG_ENCRYPT:
|
||||||
|
|
|
@ -1355,10 +1355,22 @@ static void test_rc2(void)
|
||||||
static const BYTE rc2_40def_encrypted[] = {
|
static const BYTE rc2_40def_encrypted[] = {
|
||||||
0x23,0xc8,0x70,0x13,0x42,0x2e,0xa8,0x98,
|
0x23,0xc8,0x70,0x13,0x42,0x2e,0xa8,0x98,
|
||||||
0x5c,0xdf,0x7a,0x9b,0xea,0xdb,0x96,0x1b };
|
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;
|
HCRYPTHASH hHash;
|
||||||
HCRYPTKEY hKey;
|
HCRYPTKEY hKey;
|
||||||
BOOL result;
|
BOOL result;
|
||||||
DWORD dwLen, dwKeyLen, dwDataLen, dwMode, dwModeBits;
|
DWORD dwLen, dwKeyLen, dwDataLen, dwMode, dwModeBits, error;
|
||||||
unsigned char pbData[2000], pbHashValue[16], pszBuffer[256];
|
unsigned char pbData[2000], pbHashValue[16], pszBuffer[256];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -1575,6 +1587,67 @@ static void test_rc2(void)
|
||||||
|
|
||||||
result = CryptDestroyKey(hKey);
|
result = CryptDestroyKey(hKey);
|
||||||
ok(result, "%08x\n", GetLastError());
|
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] = {
|
static const BYTE rc4[16] = {
|
||||||
0x17, 0x0c, 0x44, 0x8e, 0xae, 0x90, 0xcd, 0xb0,
|
0x17, 0x0c, 0x44, 0x8e, 0xae, 0x90, 0xcd, 0xb0,
|
||||||
0x7f, 0x87, 0xf5, 0x7a, 0xec, 0xb2, 0x2e, 0x35 };
|
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;
|
BOOL result;
|
||||||
HCRYPTHASH hHash;
|
HCRYPTHASH hHash;
|
||||||
HCRYPTKEY hKey;
|
HCRYPTKEY hKey;
|
||||||
|
@ -1684,6 +1763,57 @@ static void test_rc4(void)
|
||||||
|
|
||||||
result = CryptDestroyKey(hKey);
|
result = CryptDestroyKey(hKey);
|
||||||
ok(result, "%08x\n", GetLastError());
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue