client/common: improve remote assistance blob encryption
This commit is contained in:
parent
fc315365f6
commit
90ea609576
@ -75,33 +75,76 @@
|
|||||||
* Use the first n bytes of the result of step 5 as the derived key.
|
* Use the first n bytes of the result of step 5 as the derived key.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int freerdp_client_assistance_crypt_derive_key(BYTE* hash, int hashLength, BYTE* key, int keyLength)
|
int freerdp_client_assistance_crypt_derive_key_md5(BYTE* hash, int hashLength, BYTE* key, int keyLength)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
BYTE* bufferHash;
|
BYTE* buffer;
|
||||||
BYTE buffer36[64];
|
BYTE pad1[64];
|
||||||
BYTE buffer5c[64];
|
BYTE pad2[64];
|
||||||
|
MD5_CTX hashCtx;
|
||||||
|
|
||||||
memset(buffer36, 0x36, sizeof(buffer36));
|
memset(pad1, 0x36, 64);
|
||||||
memset(buffer5c, 0x5C, sizeof(buffer5c));
|
memset(pad2, 0x5C, 64);
|
||||||
|
|
||||||
for (i = 0; i < hashLength; i++)
|
for (i = 0; i < hashLength; i++)
|
||||||
{
|
{
|
||||||
buffer36[i] ^= hash[i];
|
pad1[i] ^= hash[i];
|
||||||
buffer5c[i] ^= hash[i];
|
pad2[i] ^= hash[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferHash = (BYTE*) calloc(1, hashLength * 2);
|
buffer = (BYTE*) calloc(1, hashLength * 2);
|
||||||
|
|
||||||
if (!bufferHash)
|
if (!buffer)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
SHA1(buffer36, 64, bufferHash);
|
MD5_Init(&hashCtx);
|
||||||
SHA1(buffer5c, 64, &bufferHash[hashLength]);
|
MD5_Update(&hashCtx, pad1, 64);
|
||||||
|
MD5_Final((void*) buffer, &hashCtx);
|
||||||
|
|
||||||
CopyMemory(key, bufferHash, keyLength);
|
MD5_Init(&hashCtx);
|
||||||
|
MD5_Update(&hashCtx, pad2, 64);
|
||||||
|
MD5_Final((void*) &buffer[hashLength], &hashCtx);
|
||||||
|
|
||||||
free(bufferHash);
|
CopyMemory(key, buffer, keyLength);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freerdp_client_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* key, int keyLength)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
BYTE* buffer;
|
||||||
|
BYTE pad1[64];
|
||||||
|
BYTE pad2[64];
|
||||||
|
SHA_CTX hashCtx;
|
||||||
|
|
||||||
|
memset(pad1, 0x36, 64);
|
||||||
|
memset(pad2, 0x5C, 64);
|
||||||
|
|
||||||
|
for (i = 0; i < hashLength; i++)
|
||||||
|
{
|
||||||
|
pad1[i] ^= hash[i];
|
||||||
|
pad2[i] ^= hash[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = (BYTE*) calloc(1, hashLength * 2);
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
SHA_Init(&hashCtx);
|
||||||
|
SHA_Update(&hashCtx, pad1, 64);
|
||||||
|
SHA_Final((void*) buffer, &hashCtx);
|
||||||
|
|
||||||
|
SHA_Init(&hashCtx);
|
||||||
|
SHA_Update(&hashCtx, pad2, 64);
|
||||||
|
SHA_Final((void*) &buffer[hashLength], &hashCtx);
|
||||||
|
|
||||||
|
CopyMemory(key, buffer, keyLength);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -109,14 +152,16 @@ int freerdp_client_assistance_crypt_derive_key(BYTE* hash, int hashLength, BYTE*
|
|||||||
int freerdp_client_assistance_decrypt1(rdpAssistanceFile* file, const char* password)
|
int freerdp_client_assistance_decrypt1(rdpAssistanceFile* file, const char* password)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
RC4_KEY rc4;
|
int cbOutLen;
|
||||||
MD5_CTX md5Ctx;
|
MD5_CTX md5Ctx;
|
||||||
int cbPasswordW;
|
int cbPasswordW;
|
||||||
int cbPassStubW;
|
int cbPassStubW;
|
||||||
|
EVP_CIPHER_CTX rc4Ctx;
|
||||||
BYTE* PlainBlob = NULL;
|
BYTE* PlainBlob = NULL;
|
||||||
WCHAR* PasswordW = NULL;
|
WCHAR* PasswordW = NULL;
|
||||||
WCHAR* PassStubW = NULL;
|
WCHAR* PassStubW = NULL;
|
||||||
BYTE EncryptionKey[AES_BLOCK_SIZE];
|
BYTE DerivedKey[16];
|
||||||
|
BYTE InitializationVector[16];
|
||||||
BYTE PasswordHash[MD5_DIGEST_LENGTH];
|
BYTE PasswordHash[MD5_DIGEST_LENGTH];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,7 +180,7 @@ int freerdp_client_assistance_decrypt1(rdpAssistanceFile* file, const char* pass
|
|||||||
cbPasswordW = (status - 1) * 2;
|
cbPasswordW = (status - 1) * 2;
|
||||||
|
|
||||||
printf("PasswordW (%d)\n", cbPasswordW);
|
printf("PasswordW (%d)\n", cbPasswordW);
|
||||||
winpr_HexDump(PasswordW, cbPasswordW);
|
winpr_HexDump((BYTE*) PasswordW, cbPasswordW);
|
||||||
|
|
||||||
MD5_Init(&md5Ctx);
|
MD5_Init(&md5Ctx);
|
||||||
MD5_Update(&md5Ctx, PasswordW, cbPasswordW);
|
MD5_Update(&md5Ctx, PasswordW, cbPasswordW);
|
||||||
@ -144,14 +189,16 @@ int freerdp_client_assistance_decrypt1(rdpAssistanceFile* file, const char* pass
|
|||||||
printf("PasswordHash (%s):\n", password);
|
printf("PasswordHash (%s):\n", password);
|
||||||
winpr_HexDump(PasswordHash, sizeof(PasswordHash));
|
winpr_HexDump(PasswordHash, sizeof(PasswordHash));
|
||||||
|
|
||||||
status = freerdp_client_assistance_crypt_derive_key(PasswordHash, sizeof(PasswordHash),
|
status = freerdp_client_assistance_crypt_derive_key_md5(PasswordHash, sizeof(PasswordHash),
|
||||||
EncryptionKey, sizeof(EncryptionKey));
|
DerivedKey, sizeof(DerivedKey));
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
printf("DerivedKey (%d):\n", sizeof(EncryptionKey));
|
printf("DerivedKey (%d):\n", sizeof(DerivedKey));
|
||||||
winpr_HexDump(EncryptionKey, sizeof(EncryptionKey));
|
winpr_HexDump(DerivedKey, sizeof(DerivedKey));
|
||||||
|
|
||||||
|
ZeroMemory(InitializationVector, sizeof(InitializationVector));
|
||||||
|
|
||||||
status = ConvertToUnicode(CP_UTF8, 0, file->PassStub, -1, &PassStubW, 0);
|
status = ConvertToUnicode(CP_UTF8, 0, file->PassStub, -1, &PassStubW, 0);
|
||||||
|
|
||||||
@ -161,7 +208,7 @@ int freerdp_client_assistance_decrypt1(rdpAssistanceFile* file, const char* pass
|
|||||||
cbPassStubW = (status - 1) * 2;
|
cbPassStubW = (status - 1) * 2;
|
||||||
|
|
||||||
printf("PassStubW (%d)\n", cbPassStubW);
|
printf("PassStubW (%d)\n", cbPassStubW);
|
||||||
winpr_HexDump(PassStubW, cbPassStubW);
|
winpr_HexDump((BYTE*) PassStubW, cbPassStubW);
|
||||||
|
|
||||||
file->EncryptedPassStubLength = cbPassStubW + 4;
|
file->EncryptedPassStubLength = cbPassStubW + 4;
|
||||||
|
|
||||||
@ -180,14 +227,34 @@ int freerdp_client_assistance_decrypt1(rdpAssistanceFile* file, const char* pass
|
|||||||
printf("PlainBlob (%d)\n", file->EncryptedPassStubLength);
|
printf("PlainBlob (%d)\n", file->EncryptedPassStubLength);
|
||||||
winpr_HexDump(PlainBlob, file->EncryptedPassStubLength);
|
winpr_HexDump(PlainBlob, file->EncryptedPassStubLength);
|
||||||
|
|
||||||
#if 0
|
EVP_CIPHER_CTX_init(&rc4Ctx);
|
||||||
void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data);
|
|
||||||
void RC4(RC4_KEY *key, size_t len, const unsigned char *indata,
|
|
||||||
unsigned char *outdata);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RC4_set_key(&rc4, sizeof(EncryptionKey), EncryptionKey);
|
status = EVP_EncryptInit_ex(&rc4Ctx, EVP_rc4(), NULL, DerivedKey, InitializationVector);
|
||||||
RC4(&rc4, file->EncryptedPassStubLength, PlainBlob, file->EncryptedPassStub);
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EVP_CipherInit_ex failure\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbOutLen = file->EncryptedPassStubLength;
|
||||||
|
status = EVP_EncryptUpdate(&rc4Ctx, file->EncryptedPassStub, &cbOutLen, PlainBlob, file->EncryptedPassStubLength);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EVP_CipherUpdate failure\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = EVP_EncryptFinal_ex(&rc4Ctx, file->EncryptedPassStub, &cbOutLen);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EVP_CipherFinal_ex failure\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_cleanup(&rc4Ctx);
|
||||||
|
|
||||||
printf("EncryptedPassStub (%d):\n", file->EncryptedPassStubLength);
|
printf("EncryptedPassStub (%d):\n", file->EncryptedPassStubLength);
|
||||||
winpr_HexDump(file->EncryptedPassStub, file->EncryptedPassStubLength);
|
winpr_HexDump(file->EncryptedPassStub, file->EncryptedPassStubLength);
|
||||||
@ -199,10 +266,12 @@ int freerdp_client_assistance_decrypt2(rdpAssistanceFile* file, const char* pass
|
|||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
SHA_CTX shaCtx;
|
SHA_CTX shaCtx;
|
||||||
int cbOut, cbFinal;
|
int cbPasswordW;
|
||||||
EVP_CIPHER_CTX aesDec;
|
EVP_CIPHER_CTX aesDec;
|
||||||
WCHAR* PasswordW = NULL;
|
WCHAR* PasswordW = NULL;
|
||||||
BYTE EncryptionKey[AES_BLOCK_SIZE];
|
BYTE *pbIn, *pbOut;
|
||||||
|
int cbOut, cbIn, cbFinal;
|
||||||
|
BYTE DerivedKey[AES_BLOCK_SIZE];
|
||||||
BYTE PasswordHash[SHA_DIGEST_LENGTH];
|
BYTE PasswordHash[SHA_DIGEST_LENGTH];
|
||||||
|
|
||||||
status = ConvertToUnicode(CP_UTF8, 0, password, -1, &PasswordW, 0);
|
status = ConvertToUnicode(CP_UTF8, 0, password, -1, &PasswordW, 0);
|
||||||
@ -210,40 +279,54 @@ int freerdp_client_assistance_decrypt2(rdpAssistanceFile* file, const char* pass
|
|||||||
if (status <= 0)
|
if (status <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
cbPasswordW = (status - 1) * 2;
|
||||||
|
|
||||||
SHA_Init(&shaCtx);
|
SHA_Init(&shaCtx);
|
||||||
SHA_Update(&shaCtx, PasswordW, status * 2);
|
SHA_Update(&shaCtx, PasswordW, cbPasswordW);
|
||||||
SHA_Final((void*) PasswordHash, &shaCtx);
|
SHA_Final((void*) PasswordHash, &shaCtx);
|
||||||
|
|
||||||
status = freerdp_client_assistance_crypt_derive_key(PasswordHash, sizeof(PasswordHash),
|
status = freerdp_client_assistance_crypt_derive_key_sha1(PasswordHash, sizeof(PasswordHash),
|
||||||
EncryptionKey, sizeof(EncryptionKey));
|
DerivedKey, sizeof(DerivedKey));
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
EVP_CIPHER_CTX_init(&aesDec);
|
EVP_CIPHER_CTX_init(&aesDec);
|
||||||
|
|
||||||
status = EVP_DecryptInit(&aesDec, EVP_aes_128_cbc(), EncryptionKey, NULL);
|
EVP_CIPHER_CTX_set_padding(&aesDec, 0);
|
||||||
|
|
||||||
|
status = EVP_DecryptInit_ex(&aesDec, EVP_aes_128_cbc(), NULL, DerivedKey, NULL);
|
||||||
|
|
||||||
if (status != 1)
|
if (status != 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
cbOut = file->EncryptedLHTicketLength;
|
cbOut = cbFinal = 0;
|
||||||
file->ConnectionString2 = (char*) calloc(1, cbOut);
|
cbIn = file->EncryptedLHTicketLength;
|
||||||
|
|
||||||
|
file->ConnectionString2 = (char*) calloc(1, cbOut + AES_BLOCK_SIZE);
|
||||||
|
|
||||||
if (!file->ConnectionString2)
|
if (!file->ConnectionString2)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
status = EVP_DecryptUpdate(&aesDec, (BYTE*) file->ConnectionString2, &cbOut,
|
pbIn = (BYTE*) file->EncryptedLHTicket;
|
||||||
(BYTE*) file->EncryptedLHTicket, file->EncryptedLHTicketLength);
|
pbOut = (BYTE*) file->ConnectionString2;
|
||||||
|
|
||||||
|
status = EVP_DecryptUpdate(&aesDec, pbOut, &cbOut, pbIn, cbIn);
|
||||||
|
|
||||||
if (status != 1)
|
if (status != 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
status = EVP_DecryptFinal(&aesDec, (BYTE*) &file->ConnectionString2[cbOut], &cbFinal);
|
status = EVP_DecryptFinal_ex(&aesDec, pbOut + cbOut, &cbFinal);
|
||||||
|
|
||||||
/* FIXME: still fails */
|
/* FIXME: still fails */
|
||||||
|
|
||||||
if (status != 1)
|
if (status != 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "EVP_DecryptFinal_ex failure\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_CIPHER_CTX_cleanup(&aesDec);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -254,7 +337,10 @@ int freerdp_client_assistance_decrypt(rdpAssistanceFile* file, const char* passw
|
|||||||
|
|
||||||
status = freerdp_client_assistance_decrypt1(file, password);
|
status = freerdp_client_assistance_decrypt1(file, password);
|
||||||
|
|
||||||
freerdp_client_assistance_decrypt2(file, password);
|
if (file->Type > 1)
|
||||||
|
{
|
||||||
|
status = freerdp_client_assistance_decrypt2(file, password);
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,10 @@ static const char* TEST_MSRC_INCIDENT_FILE_TYPE1 =
|
|||||||
"L=\"0\" />"
|
"L=\"0\" />"
|
||||||
"</UPLOADINFO>";
|
"</UPLOADINFO>";
|
||||||
|
|
||||||
|
const BYTE TEST_MSRC_INCIDENT_EXPERT_BLOB_TYPE1[32] =
|
||||||
|
"\x3C\x9C\xAE\x0B\xCE\x7A\xB1\x5C\x8A\xAC\x01\xD6\x76\x04\x5E\xDF"
|
||||||
|
"\x3F\xFA\xF0\x92\xE2\xDE\x36\x8A\x20\x17\xE6\x8A\x0D\xED\x7C\x90";
|
||||||
|
|
||||||
const char* TEST_MSRC_INCIDENT_PASSWORD_TYPE2 = "48BJQ853X3B4";
|
const char* TEST_MSRC_INCIDENT_PASSWORD_TYPE2 = "48BJQ853X3B4";
|
||||||
|
|
||||||
static const char* TEST_MSRC_INCIDENT_FILE_TYPE2 =
|
static const char* TEST_MSRC_INCIDENT_FILE_TYPE2 =
|
||||||
|
Loading…
Reference in New Issue
Block a user