mirror of https://github.com/FreeRDP/FreeRDP
[core,security] refactor functions to check lengths
This commit is contained in:
parent
7c1007b1b6
commit
00f2679eda
|
@ -1003,7 +1003,10 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, size_t
|
|||
Stream_Write_UINT8(s, 0x1); /* TSFIPS_VERSION 1*/
|
||||
Stream_Write_UINT8(s, pad); /* padding */
|
||||
|
||||
if (!security_hmac_signature(fpInputEvents, fpInputEvents_length, Stream_Pointer(s),
|
||||
if (!Stream_CheckAndLogRequiredCapacity(TAG, s, 8))
|
||||
goto unlock;
|
||||
|
||||
if (!security_hmac_signature(fpInputEvents, fpInputEvents_length, Stream_Pointer(s), 8,
|
||||
rdp))
|
||||
goto unlock;
|
||||
|
||||
|
@ -1018,12 +1021,14 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, size_t
|
|||
else
|
||||
{
|
||||
BOOL res;
|
||||
if (!Stream_CheckAndLogRequiredCapacity(TAG, s, 8))
|
||||
goto unlock;
|
||||
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
|
||||
res = security_salted_mac_signature(rdp, fpInputEvents, fpInputEvents_length, TRUE,
|
||||
Stream_Pointer(s));
|
||||
Stream_Pointer(s), 8);
|
||||
else
|
||||
res = security_mac_signature(rdp, fpInputEvents, fpInputEvents_length,
|
||||
Stream_Pointer(s));
|
||||
Stream_Pointer(s), 8);
|
||||
|
||||
if (!res || !security_encrypt(fpInputEvents, fpInputEvents_length, rdp))
|
||||
goto unlock;
|
||||
|
@ -1238,7 +1243,8 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
|
|||
|
||||
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
|
||||
{
|
||||
if (!security_hmac_signature(data, dataSize - pad, pSignature, rdp))
|
||||
// TODO: Ensure stream capacity
|
||||
if (!security_hmac_signature(data, dataSize - pad, pSignature, 8, rdp))
|
||||
goto unlock;
|
||||
|
||||
if (!security_fips_encrypt(data, dataSize, rdp))
|
||||
|
@ -1246,10 +1252,12 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
|
|||
}
|
||||
else
|
||||
{
|
||||
// TODO: Ensure stream capacity
|
||||
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
|
||||
status = security_salted_mac_signature(rdp, data, dataSize, TRUE, pSignature);
|
||||
status =
|
||||
security_salted_mac_signature(rdp, data, dataSize, TRUE, pSignature, 8);
|
||||
else
|
||||
status = security_mac_signature(rdp, data, dataSize, pSignature);
|
||||
status = security_mac_signature(rdp, data, dataSize, pSignature, 8);
|
||||
|
||||
if (!status || !security_encrypt(data, dataSize, rdp))
|
||||
goto unlock;
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include "license.h"
|
||||
|
||||
#include "../crypto/crypto.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.license")
|
||||
|
||||
#if 0
|
||||
|
@ -1003,7 +1005,7 @@ void license_generate_randoms(rdpLicense* license)
|
|||
#ifdef LICENSE_NULL_CLIENT_RANDOM
|
||||
ZeroMemory(license->ClientRandom, sizeof(license->ClientRandom)); /* ClientRandom */
|
||||
#else
|
||||
winpr_RAND(license->ClientRandom, sizeof(license->ClientRandom)); /* ClientRandom */
|
||||
winpr_RAND(license->ClientRandom, sizeof(license->ClientRandom)); /* ClientRandom */
|
||||
#endif
|
||||
|
||||
winpr_RAND(license->ServerRandom, sizeof(license->ServerRandom)); /* ServerRandom */
|
||||
|
@ -1028,19 +1030,27 @@ static BOOL license_generate_keys(rdpLicense* license)
|
|||
|
||||
if (
|
||||
/* MasterSecret */
|
||||
!security_master_secret(license->PremasterSecret, license->ClientRandom,
|
||||
license->ServerRandom, license->MasterSecret) ||
|
||||
!security_master_secret(license->PremasterSecret, sizeof(license->PremasterSecret),
|
||||
license->ClientRandom, sizeof(license->ClientRandom),
|
||||
license->ServerRandom, sizeof(license->ServerRandom),
|
||||
license->MasterSecret, sizeof(license->MasterSecret)) ||
|
||||
/* SessionKeyBlob */
|
||||
!security_session_key_blob(license->MasterSecret, license->ClientRandom,
|
||||
license->ServerRandom, license->SessionKeyBlob))
|
||||
!security_session_key_blob(license->MasterSecret, sizeof(license->MasterSecret),
|
||||
license->ClientRandom, sizeof(license->ClientRandom),
|
||||
license->ServerRandom, sizeof(license->ServerRandom),
|
||||
license->SessionKeyBlob, sizeof(license->SessionKeyBlob)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
security_mac_salt_key(license->SessionKeyBlob, license->ClientRandom, license->ServerRandom,
|
||||
license->MacSaltKey); /* MacSaltKey */
|
||||
security_mac_salt_key(license->SessionKeyBlob, sizeof(license->SessionKeyBlob),
|
||||
license->ClientRandom, sizeof(license->ClientRandom),
|
||||
license->ServerRandom, sizeof(license->ServerRandom), license->MacSaltKey,
|
||||
sizeof(license->MacSaltKey)); /* MacSaltKey */
|
||||
ret = security_licensing_encryption_key(
|
||||
license->SessionKeyBlob, license->ClientRandom, license->ServerRandom,
|
||||
license->LicensingEncryptionKey); /* LicensingEncryptionKey */
|
||||
license->SessionKeyBlob, sizeof(license->SessionKeyBlob), license->ClientRandom,
|
||||
sizeof(license->ClientRandom), license->ServerRandom, sizeof(license->ServerRandom),
|
||||
license->LicensingEncryptionKey,
|
||||
sizeof(license->LicensingEncryptionKey)); /* LicensingEncryptionKey */
|
||||
#ifdef WITH_DEBUG_LICENSE
|
||||
WLog_DBG(TAG, "ClientRandom:");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, sizeof(license->ClientRandom));
|
||||
|
|
|
@ -656,7 +656,9 @@ static BOOL rdp_security_stream_out(rdpRdp* rdp, wStream* s, int length, UINT32
|
|||
|
||||
Stream_Write_UINT8(s, *pad);
|
||||
|
||||
if (!security_hmac_signature(data, length, Stream_Pointer(s), rdp))
|
||||
if (!Stream_CheckAndLogRequiredCapacity(TAG, s, 8))
|
||||
goto unlock;
|
||||
if (!security_hmac_signature(data, length, Stream_Pointer(s), 8, rdp))
|
||||
goto unlock;
|
||||
|
||||
Stream_Seek(s, 8);
|
||||
|
@ -668,11 +670,13 @@ static BOOL rdp_security_stream_out(rdpRdp* rdp, wStream* s, int length, UINT32
|
|||
data = Stream_Pointer(s) + 8;
|
||||
length = length - (data - Stream_Buffer(s));
|
||||
|
||||
if (!Stream_CheckAndLogRequiredCapacity(TAG, s, 8))
|
||||
goto unlock;
|
||||
if (sec_flags & SEC_SECURE_CHECKSUM)
|
||||
status =
|
||||
security_salted_mac_signature(rdp, data, length, TRUE, Stream_Pointer(s));
|
||||
status = security_salted_mac_signature(rdp, data, length, TRUE,
|
||||
Stream_Pointer(s), 8);
|
||||
else
|
||||
status = security_mac_signature(rdp, data, length, Stream_Pointer(s));
|
||||
status = security_mac_signature(rdp, data, length, Stream_Pointer(s), 8);
|
||||
|
||||
if (!status)
|
||||
goto unlock;
|
||||
|
@ -1342,7 +1346,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags)
|
|||
{
|
||||
UINT16 len;
|
||||
BYTE version, pad;
|
||||
BYTE* sig;
|
||||
const BYTE* sig;
|
||||
INT64 padLength;
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
|
||||
|
@ -1365,7 +1369,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags)
|
|||
if (!security_fips_decrypt(Stream_Pointer(s), length, rdp))
|
||||
goto unlock;
|
||||
|
||||
if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, rdp))
|
||||
if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, 8, rdp))
|
||||
goto unlock;
|
||||
|
||||
Stream_SetLength(s, Stream_Length(s) - pad);
|
||||
|
@ -1389,9 +1393,10 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags)
|
|||
goto unlock;
|
||||
|
||||
if (securityFlags & SEC_SECURE_CHECKSUM)
|
||||
status = security_salted_mac_signature(rdp, Stream_Pointer(s), length, FALSE, cmac);
|
||||
status = security_salted_mac_signature(rdp, Stream_Pointer(s), length, FALSE, cmac,
|
||||
sizeof(cmac));
|
||||
else
|
||||
status = security_mac_signature(rdp, Stream_Pointer(s), length, cmac);
|
||||
status = security_mac_signature(rdp, Stream_Pointer(s), length, cmac, sizeof(cmac));
|
||||
|
||||
if (!status)
|
||||
goto unlock;
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
#define TAG FREERDP_TAG("core")
|
||||
|
||||
static const BYTE A[] = { 'A' };
|
||||
static const BYTE BB[] = { 'B', 'B' };
|
||||
static const BYTE CCC[] = { 'C', 'C', 'C' };
|
||||
|
||||
/* 0x36 repeated 40 times */
|
||||
static const BYTE pad1[40] = { "\x36\x36\x36\x36\x36\x36\x36\x36"
|
||||
"\x36\x36\x36\x36\x36\x36\x36\x36"
|
||||
|
@ -80,15 +84,17 @@ static const BYTE fips_oddparity_table[256] = {
|
|||
0xf1, 0xf1, 0xf2, 0xf2, 0xf4, 0xf4, 0xf7, 0xf7, 0xf8, 0xf8, 0xfb, 0xfb, 0xfd, 0xfd, 0xfe, 0xfe
|
||||
};
|
||||
|
||||
static BOOL security_salted_hash(const BYTE* salt, const BYTE* input, size_t length,
|
||||
const BYTE* salt1, const BYTE* salt2, BYTE* output)
|
||||
static BOOL security_salted_hash(const BYTE* salt, size_t salt_len, const BYTE* input,
|
||||
size_t length, const BYTE* salt1, size_t salt1_len,
|
||||
const BYTE* salt2, size_t salt2_len, BYTE* output, size_t out_len)
|
||||
{
|
||||
WINPR_DIGEST_CTX* sha1 = NULL;
|
||||
WINPR_DIGEST_CTX* md5 = NULL;
|
||||
BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH];
|
||||
BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH] = { 0 };
|
||||
BOOL result = FALSE;
|
||||
|
||||
/* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1(Input + Salt + Salt1 + Salt2)) */
|
||||
WINPR_ASSERT(out_len >= WINPR_MD5_DIGEST_LENGTH);
|
||||
|
||||
/* SHA1_Digest = SHA1(Input + Salt + Salt1 + Salt2) */
|
||||
if (!(sha1 = winpr_Digest_New()))
|
||||
|
@ -130,7 +136,7 @@ static BOOL security_salted_hash(const BYTE* salt, const BYTE* input, size_t len
|
|||
if (!winpr_Digest_Update(md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */
|
||||
goto out;
|
||||
|
||||
if (!winpr_Digest_Final(md5, output, WINPR_MD5_DIGEST_LENGTH))
|
||||
if (!winpr_Digest_Final(md5, output, out_len))
|
||||
goto out;
|
||||
|
||||
result = TRUE;
|
||||
|
@ -140,57 +146,74 @@ out:
|
|||
return result;
|
||||
}
|
||||
|
||||
static BOOL security_premaster_hash(const char* input, int length, const BYTE* premaster_secret,
|
||||
const BYTE* client_random, const BYTE* server_random,
|
||||
BYTE* output)
|
||||
static BOOL security_premaster_hash(const BYTE* input, size_t length, const BYTE* premaster_secret,
|
||||
size_t pre_len, const BYTE* client_random, size_t client_len,
|
||||
const BYTE* server_random, size_t server_len, BYTE* output,
|
||||
size_t out_len)
|
||||
{
|
||||
/* PremasterHash(Input) = SaltedHash(PremasterSecret, Input, ClientRandom, ServerRandom) */
|
||||
return security_salted_hash(premaster_secret, (const BYTE*)input, length, client_random,
|
||||
server_random, output);
|
||||
return security_salted_hash(premaster_secret, pre_len, input, length, client_random, client_len,
|
||||
server_random, server_len, output, out_len);
|
||||
}
|
||||
|
||||
BOOL security_master_secret(const BYTE* premaster_secret, const BYTE* client_random,
|
||||
const BYTE* server_random, BYTE* output)
|
||||
BOOL security_master_secret(const BYTE* premaster_secret, size_t pre_len, const BYTE* client_random,
|
||||
size_t client_len, const BYTE* server_random, size_t server_len,
|
||||
BYTE* output, size_t out_len)
|
||||
{
|
||||
/* MasterSecret = PremasterHash('A') + PremasterHash('BB') + PremasterHash('CCC') */
|
||||
return security_premaster_hash("A", 1, premaster_secret, client_random, server_random,
|
||||
&output[0]) &&
|
||||
security_premaster_hash("BB", 2, premaster_secret, client_random, server_random,
|
||||
&output[16]) &&
|
||||
security_premaster_hash("CCC", 3, premaster_secret, client_random, server_random,
|
||||
&output[32]);
|
||||
WINPR_ASSERT(out_len >= 32);
|
||||
return security_premaster_hash(A, sizeof(A), premaster_secret, pre_len, client_random,
|
||||
client_len, server_random, server_len, &output[0], out_len) &&
|
||||
security_premaster_hash(BB, sizeof(BB), premaster_secret, pre_len, client_random,
|
||||
client_len, server_random, server_len, &output[16],
|
||||
out_len - 16) &&
|
||||
security_premaster_hash(CCC, sizeof(CCC), premaster_secret, pre_len, client_random,
|
||||
client_len, server_random, server_len, &output[32],
|
||||
out_len - 32);
|
||||
}
|
||||
|
||||
static BOOL security_master_hash(const char* input, int length, const BYTE* master_secret,
|
||||
const BYTE* client_random, const BYTE* server_random, BYTE* output)
|
||||
static BOOL security_master_hash(const BYTE* input, size_t length, const BYTE* master_secret,
|
||||
size_t master_len, const BYTE* client_random, size_t client_len,
|
||||
const BYTE* server_random, size_t server_len, BYTE* output,
|
||||
size_t out_len)
|
||||
{
|
||||
/* MasterHash(Input) = SaltedHash(MasterSecret, Input, ServerRandom, ClientRandom) */
|
||||
return security_salted_hash(master_secret, (const BYTE*)input, length, server_random,
|
||||
client_random, output);
|
||||
return security_salted_hash(master_secret, master_len, input, length, server_random, server_len,
|
||||
client_random, client_len, output, out_len);
|
||||
}
|
||||
|
||||
BOOL security_session_key_blob(const BYTE* master_secret, const BYTE* client_random,
|
||||
const BYTE* server_random, BYTE* output)
|
||||
BOOL security_session_key_blob(const BYTE* master_secret, size_t master_len,
|
||||
const BYTE* client_random, size_t client_len,
|
||||
const BYTE* server_random, size_t server_len, BYTE* output,
|
||||
size_t out_len)
|
||||
{
|
||||
/* MasterHash = MasterHash('A') + MasterHash('BB') + MasterHash('CCC') */
|
||||
return security_master_hash("A", 1, master_secret, client_random, server_random, &output[0]) &&
|
||||
security_master_hash("BB", 2, master_secret, client_random, server_random,
|
||||
&output[16]) &&
|
||||
security_master_hash("CCC", 3, master_secret, client_random, server_random, &output[32]);
|
||||
WINPR_ASSERT(out_len >= 32);
|
||||
return security_master_hash(A, sizeof(A), master_secret, master_len, client_random, client_len,
|
||||
server_random, server_len, &output[0], 16) &&
|
||||
security_master_hash(BB, sizeof(BB), master_secret, master_len, client_random,
|
||||
client_len, server_random, server_len, &output[16], 16) &&
|
||||
security_master_hash(CCC, sizeof(CCC), master_secret, master_len, client_random,
|
||||
client_len, server_random, server_len, &output[32], out_len - 32);
|
||||
}
|
||||
|
||||
void security_mac_salt_key(const BYTE* session_key_blob, const BYTE* client_random,
|
||||
const BYTE* server_random, BYTE* output)
|
||||
void security_mac_salt_key(const BYTE* session_key_blob, size_t session_len,
|
||||
const BYTE* client_random, size_t client_len, const BYTE* server_random,
|
||||
size_t server_len, BYTE* output, size_t out_len)
|
||||
{
|
||||
/* MacSaltKey = First128Bits(SessionKeyBlob) */
|
||||
WINPR_ASSERT(out_len >= 16);
|
||||
memcpy(output, session_key_blob, 16);
|
||||
}
|
||||
|
||||
static BOOL security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE* in2, BYTE* output)
|
||||
static BOOL security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE* in2, BYTE* output,
|
||||
size_t out_len)
|
||||
{
|
||||
WINPR_DIGEST_CTX* md5 = NULL;
|
||||
BOOL result = FALSE;
|
||||
|
||||
WINPR_ASSERT(WINPR_MD5_DIGEST_LENGTH <= out_len);
|
||||
|
||||
if (!(md5 = winpr_Digest_New()))
|
||||
return FALSE;
|
||||
|
||||
|
@ -206,7 +229,7 @@ static BOOL security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE*
|
|||
if (!winpr_Digest_Update(md5, in2, 32))
|
||||
goto out;
|
||||
|
||||
if (!winpr_Digest_Final(md5, output, WINPR_MD5_DIGEST_LENGTH))
|
||||
if (!winpr_Digest_Final(md5, output, out_len))
|
||||
goto out;
|
||||
|
||||
result = TRUE;
|
||||
|
@ -216,11 +239,13 @@ out:
|
|||
}
|
||||
|
||||
static BOOL security_md5_16_32_32_Allow_FIPS(const BYTE* in0, const BYTE* in1, const BYTE* in2,
|
||||
BYTE* output)
|
||||
BYTE* output, size_t out_len)
|
||||
{
|
||||
WINPR_DIGEST_CTX* md5 = NULL;
|
||||
BOOL result = FALSE;
|
||||
|
||||
WINPR_ASSERT(out_len >= WINPR_MD5_DIGEST_LENGTH);
|
||||
|
||||
if (!(md5 = winpr_Digest_New()))
|
||||
return FALSE;
|
||||
if (!winpr_Digest_Init_Allow_FIPS(md5, WINPR_MD_MD5))
|
||||
|
@ -231,7 +256,7 @@ static BOOL security_md5_16_32_32_Allow_FIPS(const BYTE* in0, const BYTE* in1, c
|
|||
goto out;
|
||||
if (!winpr_Digest_Update(md5, in2, 32))
|
||||
goto out;
|
||||
if (!winpr_Digest_Final(md5, output, WINPR_MD5_DIGEST_LENGTH))
|
||||
if (!winpr_Digest_Final(md5, output, out_len))
|
||||
goto out;
|
||||
|
||||
result = TRUE;
|
||||
|
@ -240,19 +265,23 @@ out:
|
|||
return result;
|
||||
}
|
||||
|
||||
BOOL security_licensing_encryption_key(const BYTE* session_key_blob, const BYTE* client_random,
|
||||
const BYTE* server_random, BYTE* output)
|
||||
BOOL security_licensing_encryption_key(const BYTE* session_key_blob, size_t session_len,
|
||||
const BYTE* client_random, size_t client_len,
|
||||
const BYTE* server_random, size_t server_len, BYTE* output,
|
||||
size_t out_len)
|
||||
{
|
||||
/* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom))
|
||||
* Allow FIPS use of MD5 here, this is just used for creating the licensing encryption key as
|
||||
* described in MS-RDPELE. This is for RDP licensing packets which will already be encrypted
|
||||
* under FIPS, so the use of MD5 here is not for sensitive data protection. */
|
||||
return security_md5_16_32_32_Allow_FIPS(&session_key_blob[16], client_random, server_random,
|
||||
output);
|
||||
output, out_len);
|
||||
}
|
||||
|
||||
static void security_UINT32_le(BYTE* output, UINT32 value)
|
||||
static void security_UINT32_le(BYTE* output, size_t out_len, UINT32 value)
|
||||
{
|
||||
WINPR_ASSERT(output);
|
||||
WINPR_ASSERT(out_len >= 4);
|
||||
output[0] = (value)&0xFF;
|
||||
output[1] = (value >> 8) & 0xFF;
|
||||
output[2] = (value >> 16) & 0xFF;
|
||||
|
@ -272,7 +301,7 @@ BOOL security_mac_data(const BYTE* mac_salt_key, size_t mac_salt_key_length, con
|
|||
WINPR_ASSERT(output_length == WINPR_MD5_DIGEST_LENGTH);
|
||||
|
||||
/* MacData = MD5(MacSaltKey + pad2 + SHA1(MacSaltKey + pad1 + length + data)) */
|
||||
security_UINT32_le(length_le, length); /* length must be little-endian */
|
||||
security_UINT32_le(length_le, sizeof(length_le), length); /* length must be little-endian */
|
||||
|
||||
/* SHA1_Digest = SHA1(MacSaltKey + pad1 + length + data) */
|
||||
if (!(sha1 = winpr_Digest_New()))
|
||||
|
@ -328,7 +357,8 @@ out:
|
|||
return result;
|
||||
}
|
||||
|
||||
BOOL security_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length, BYTE* output)
|
||||
BOOL security_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length, BYTE* output,
|
||||
size_t out_len)
|
||||
{
|
||||
WINPR_DIGEST_CTX* sha1 = NULL;
|
||||
WINPR_DIGEST_CTX* md5 = NULL;
|
||||
|
@ -340,8 +370,9 @@ BOOL security_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length, BYTE*
|
|||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(data || (length == 0));
|
||||
WINPR_ASSERT(output);
|
||||
WINPR_ASSERT(out_len >= 8);
|
||||
|
||||
security_UINT32_le(length_le, length); /* length must be little-endian */
|
||||
security_UINT32_le(length_le, sizeof(length_le), length); /* length must be little-endian */
|
||||
|
||||
/* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */
|
||||
if (!(sha1 = winpr_Digest_New()))
|
||||
|
@ -395,7 +426,7 @@ out:
|
|||
}
|
||||
|
||||
BOOL security_salted_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length, BOOL encryption,
|
||||
BYTE* output)
|
||||
BYTE* output, size_t out_len)
|
||||
{
|
||||
WINPR_DIGEST_CTX* sha1 = NULL;
|
||||
WINPR_DIGEST_CTX* md5 = NULL;
|
||||
|
@ -408,12 +439,13 @@ BOOL security_salted_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length,
|
|||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(data || (length == 0));
|
||||
WINPR_ASSERT(output);
|
||||
WINPR_ASSERT(out_len >= 8);
|
||||
|
||||
security_UINT32_le(length_le, length); /* length must be little-endian */
|
||||
security_UINT32_le(length_le, sizeof(length_le), length); /* length must be little-endian */
|
||||
|
||||
if (encryption)
|
||||
{
|
||||
security_UINT32_le(use_count_le, rdp->encrypt_checksum_use_count);
|
||||
security_UINT32_le(use_count_le, sizeof(use_count_le), rdp->encrypt_checksum_use_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -421,7 +453,7 @@ BOOL security_salted_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length,
|
|||
* We calculate checksum on plain text, so we must have already
|
||||
* decrypt it, which means decrypt_checksum_use_count is off by one.
|
||||
*/
|
||||
security_UINT32_le(use_count_le, rdp->decrypt_checksum_use_count - 1);
|
||||
security_UINT32_le(use_count_le, sizeof(use_count_le), rdp->decrypt_checksum_use_count - 1);
|
||||
}
|
||||
|
||||
/* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */
|
||||
|
@ -479,43 +511,62 @@ out:
|
|||
return result;
|
||||
}
|
||||
|
||||
static BOOL security_A(BYTE* master_secret, const BYTE* client_random, BYTE* server_random,
|
||||
BYTE* output)
|
||||
static BOOL security_A(const BYTE* master_secret, size_t master_len, const BYTE* client_random,
|
||||
size_t client_len, const BYTE* server_random, size_t server_len,
|
||||
BYTE* output, size_t out_len)
|
||||
{
|
||||
return security_premaster_hash("A", 1, master_secret, client_random, server_random,
|
||||
&output[0]) &&
|
||||
security_premaster_hash("BB", 2, master_secret, client_random, server_random,
|
||||
&output[16]) &&
|
||||
security_premaster_hash("CCC", 3, master_secret, client_random, server_random,
|
||||
&output[32]);
|
||||
WINPR_ASSERT(out_len >= 32);
|
||||
|
||||
return security_premaster_hash(A, sizeof(A), master_secret, master_len, client_random,
|
||||
client_len, server_random, server_len, &output[0], 16) &&
|
||||
security_premaster_hash(BB, sizeof(BB), master_secret, master_len, client_random,
|
||||
client_len, server_random, server_len, &output[16], 16) &&
|
||||
security_premaster_hash(CCC, sizeof(CCC), master_secret, master_len, client_random,
|
||||
client_len, server_random, server_len, &output[32],
|
||||
out_len - 32);
|
||||
}
|
||||
|
||||
static BOOL security_X(BYTE* master_secret, const BYTE* client_random, BYTE* server_random,
|
||||
BYTE* output)
|
||||
static BOOL security_X(const BYTE* master_secret, size_t master_len, const BYTE* client_random,
|
||||
size_t client_len, const BYTE* server_random, size_t server_len,
|
||||
BYTE* output, size_t out_len)
|
||||
{
|
||||
return security_premaster_hash("X", 1, master_secret, client_random, server_random,
|
||||
&output[0]) &&
|
||||
security_premaster_hash("YY", 2, master_secret, client_random, server_random,
|
||||
&output[16]) &&
|
||||
security_premaster_hash("ZZZ", 3, master_secret, client_random, server_random,
|
||||
&output[32]);
|
||||
const BYTE X[] = { 'X' };
|
||||
const BYTE YY[] = { 'Y', 'Y' };
|
||||
const BYTE ZZZ[] = { 'Z', 'Z', 'Z' };
|
||||
|
||||
WINPR_ASSERT(out_len >= 32);
|
||||
|
||||
return security_premaster_hash(X, sizeof(X), master_secret, master_len, client_random,
|
||||
client_len, server_random, server_len, &output[0], 16) &&
|
||||
security_premaster_hash(YY, sizeof(YY), master_secret, master_len, client_random,
|
||||
client_len, server_random, server_len, &output[16], 16) &&
|
||||
security_premaster_hash(ZZZ, sizeof(ZZZ), master_secret, master_len, client_random,
|
||||
client_len, server_random, server_len, &output[32],
|
||||
out_len - 32);
|
||||
}
|
||||
|
||||
static void fips_expand_key_bits(BYTE* in, BYTE* out)
|
||||
static void fips_expand_key_bits(const BYTE* in, size_t in_len, BYTE* out, size_t out_len)
|
||||
{
|
||||
BYTE buf[21], c;
|
||||
int i, b, p, r;
|
||||
BYTE buf[21] = { 0 };
|
||||
|
||||
WINPR_ASSERT(in);
|
||||
WINPR_ASSERT(in_len >= sizeof(buf));
|
||||
|
||||
WINPR_ASSERT(out);
|
||||
WINPR_ASSERT(out_len > 24);
|
||||
|
||||
/* reverse every byte in the key */
|
||||
for (i = 0; i < 21; i++)
|
||||
for (size_t i = 0; i < sizeof(buf); i++)
|
||||
buf[i] = fips_reverse_table[in[i]];
|
||||
|
||||
/* insert a zero-bit after every 7th bit */
|
||||
for (i = 0, b = 0; i < 24; i++, b += 7)
|
||||
size_t b = 0;
|
||||
for (size_t i = 0; i < 24; i++, b += 7)
|
||||
{
|
||||
p = b / 8;
|
||||
r = b % 8;
|
||||
const size_t p = b / 8;
|
||||
const size_t r = b % 8;
|
||||
|
||||
WINPR_ASSERT(p < sizeof(buf));
|
||||
if (r <= 1)
|
||||
{
|
||||
out[i] = (buf[p] << r) & 0xfe;
|
||||
|
@ -523,7 +574,7 @@ static void fips_expand_key_bits(BYTE* in, BYTE* out)
|
|||
else
|
||||
{
|
||||
/* c is accumulator */
|
||||
c = buf[p] << r;
|
||||
BYTE c = buf[p] << r;
|
||||
c |= buf[p + 1] >> (8 - r);
|
||||
out[i] = c & 0xfe;
|
||||
}
|
||||
|
@ -531,7 +582,7 @@ static void fips_expand_key_bits(BYTE* in, BYTE* out)
|
|||
|
||||
/* reverse every byte */
|
||||
/* alter lsb so the byte has odd parity */
|
||||
for (i = 0; i < 24; i++)
|
||||
for (size_t i = 0; i < 24; i++)
|
||||
out[i] = fips_oddparity_table[fips_reverse_table[out[i]]];
|
||||
}
|
||||
|
||||
|
@ -597,21 +648,29 @@ BOOL security_establish_keys(rdpRdp* rdp)
|
|||
|
||||
if (settings->ServerMode)
|
||||
{
|
||||
fips_expand_key_bits(client_encrypt_key_t, rdp->fips_decrypt_key);
|
||||
fips_expand_key_bits(client_decrypt_key_t, rdp->fips_encrypt_key);
|
||||
fips_expand_key_bits(client_encrypt_key_t, sizeof(client_encrypt_key_t),
|
||||
rdp->fips_decrypt_key, sizeof(rdp->fips_decrypt_key));
|
||||
fips_expand_key_bits(client_decrypt_key_t, sizeof(client_decrypt_key_t),
|
||||
rdp->fips_encrypt_key, sizeof(rdp->fips_encrypt_key));
|
||||
}
|
||||
else
|
||||
{
|
||||
fips_expand_key_bits(client_encrypt_key_t, rdp->fips_encrypt_key);
|
||||
fips_expand_key_bits(client_decrypt_key_t, rdp->fips_decrypt_key);
|
||||
fips_expand_key_bits(client_encrypt_key_t, sizeof(client_encrypt_key_t),
|
||||
rdp->fips_encrypt_key, sizeof(rdp->fips_encrypt_key));
|
||||
fips_expand_key_bits(client_decrypt_key_t, sizeof(client_decrypt_key_t),
|
||||
rdp->fips_decrypt_key, sizeof(rdp->fips_decrypt_key));
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(pre_master_secret, client_random, 24);
|
||||
memcpy(pre_master_secret + 24, server_random, 24);
|
||||
|
||||
if (!security_A(pre_master_secret, client_random, server_random, master_secret) ||
|
||||
!security_X(master_secret, client_random, server_random, session_key_blob))
|
||||
if (!security_A(pre_master_secret, sizeof(pre_master_secret), client_random,
|
||||
sizeof(client_random), server_random, sizeof(server_random), master_secret,
|
||||
sizeof(master_secret)) ||
|
||||
!security_X(master_secret, sizeof(master_secret), client_random, sizeof(client_random),
|
||||
server_random, sizeof(server_random), session_key_blob,
|
||||
sizeof(session_key_blob)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -621,9 +680,9 @@ BOOL security_establish_keys(rdpRdp* rdp)
|
|||
if (settings->ServerMode)
|
||||
{
|
||||
status = security_md5_16_32_32(&session_key_blob[16], client_random, server_random,
|
||||
rdp->encrypt_key);
|
||||
rdp->encrypt_key, sizeof(rdp->encrypt_key));
|
||||
status &= security_md5_16_32_32(&session_key_blob[32], client_random, server_random,
|
||||
rdp->decrypt_key);
|
||||
rdp->decrypt_key, sizeof(rdp->decrypt_key));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -632,10 +691,12 @@ BOOL security_establish_keys(rdpRdp* rdp)
|
|||
/* This is for RDP licensing packets which will already be encrypted under FIPS, so the use
|
||||
* of MD5 here is not */
|
||||
/* for sensitive data protection. */
|
||||
status = security_md5_16_32_32_Allow_FIPS(&session_key_blob[16], client_random,
|
||||
server_random, rdp->decrypt_key);
|
||||
status &= security_md5_16_32_32_Allow_FIPS(&session_key_blob[32], client_random,
|
||||
server_random, rdp->encrypt_key);
|
||||
status =
|
||||
security_md5_16_32_32_Allow_FIPS(&session_key_blob[16], client_random, server_random,
|
||||
rdp->decrypt_key, sizeof(rdp->decrypt_key));
|
||||
status &=
|
||||
security_md5_16_32_32_Allow_FIPS(&session_key_blob[32], client_random, server_random,
|
||||
rdp->encrypt_key, sizeof(rdp->encrypt_key));
|
||||
}
|
||||
|
||||
if (!status)
|
||||
|
@ -674,7 +735,7 @@ BOOL security_establish_keys(rdpRdp* rdp)
|
|||
|
||||
static BOOL security_key_update(BYTE* key, BYTE* update_key, size_t key_len, rdpRdp* rdp)
|
||||
{
|
||||
BYTE sha1h[WINPR_SHA1_DIGEST_LENGTH];
|
||||
BYTE sha1h[WINPR_SHA1_DIGEST_LENGTH] = { 0 };
|
||||
WINPR_DIGEST_CTX* sha1 = NULL;
|
||||
WINPR_DIGEST_CTX* md5 = NULL;
|
||||
WINPR_RC4_CTX* rc4 = NULL;
|
||||
|
@ -801,16 +862,19 @@ fail:
|
|||
return rc;
|
||||
}
|
||||
|
||||
BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output, rdpRdp* rdp)
|
||||
BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output, size_t out_len,
|
||||
rdpRdp* rdp)
|
||||
{
|
||||
BYTE buf[WINPR_SHA1_DIGEST_LENGTH];
|
||||
BYTE use_count_le[4];
|
||||
WINPR_HMAC_CTX* hmac;
|
||||
BYTE buf[WINPR_SHA1_DIGEST_LENGTH] = { 0 };
|
||||
BYTE use_count_le[4] = { 0 };
|
||||
WINPR_HMAC_CTX* hmac = NULL;
|
||||
BOOL result = FALSE;
|
||||
|
||||
WINPR_ASSERT(rdp);
|
||||
WINPR_ASSERT(output);
|
||||
WINPR_ASSERT(out_len >= 8);
|
||||
|
||||
security_UINT32_le(use_count_le, rdp->encrypt_use_count);
|
||||
security_UINT32_le(use_count_le, sizeof(use_count_le), rdp->encrypt_use_count);
|
||||
|
||||
if (!(hmac = winpr_HMAC_New()))
|
||||
return FALSE;
|
||||
|
@ -837,7 +901,7 @@ out:
|
|||
BOOL security_fips_encrypt(BYTE* data, size_t length, rdpRdp* rdp)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
size_t olen;
|
||||
size_t olen = 0;
|
||||
|
||||
if (!winpr_Cipher_Update(rdp->fips_encrypt, data, length, data, &olen))
|
||||
goto fail;
|
||||
|
@ -850,7 +914,7 @@ fail:
|
|||
|
||||
BOOL security_fips_decrypt(BYTE* data, size_t length, rdpRdp* rdp)
|
||||
{
|
||||
size_t olen;
|
||||
size_t olen = 0;
|
||||
|
||||
if (!rdp || !rdp->fips_decrypt)
|
||||
{
|
||||
|
@ -864,14 +928,15 @@ BOOL security_fips_decrypt(BYTE* data, size_t length, rdpRdp* rdp)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE* sig, rdpRdp* rdp)
|
||||
BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE* sig, size_t sig_len,
|
||||
rdpRdp* rdp)
|
||||
{
|
||||
BYTE buf[WINPR_SHA1_DIGEST_LENGTH] = { 0 };
|
||||
BYTE use_count_le[4] = { 0 };
|
||||
WINPR_HMAC_CTX* hmac = NULL;
|
||||
BOOL result = FALSE;
|
||||
|
||||
security_UINT32_le(use_count_le, rdp->decrypt_use_count++);
|
||||
security_UINT32_le(use_count_le, sizeof(use_count_le), rdp->decrypt_use_count++);
|
||||
|
||||
if (!(hmac = winpr_HMAC_New()))
|
||||
return FALSE;
|
||||
|
|
|
@ -28,22 +28,30 @@
|
|||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
FREERDP_LOCAL BOOL security_master_secret(const BYTE* premaster_secret, const BYTE* client_random,
|
||||
const BYTE* server_random, BYTE* output);
|
||||
FREERDP_LOCAL BOOL security_session_key_blob(const BYTE* master_secret, const BYTE* client_random,
|
||||
const BYTE* server_random, BYTE* output);
|
||||
FREERDP_LOCAL void security_mac_salt_key(const BYTE* session_key_blob, const BYTE* client_random,
|
||||
const BYTE* server_random, BYTE* output);
|
||||
FREERDP_LOCAL BOOL security_master_secret(const BYTE* premaster_secret, size_t pre_len,
|
||||
const BYTE* client_random, size_t client_len,
|
||||
const BYTE* server_random, size_t server_len,
|
||||
BYTE* output, size_t out_len);
|
||||
FREERDP_LOCAL BOOL security_session_key_blob(const BYTE* master_secret, size_t master_len,
|
||||
const BYTE* client_random, size_t client_len,
|
||||
const BYTE* server_random, size_t server_len,
|
||||
BYTE* output, size_t out_len);
|
||||
FREERDP_LOCAL void security_mac_salt_key(const BYTE* session_key_blob, size_t session_len,
|
||||
const BYTE* client_random, size_t client_len,
|
||||
const BYTE* server_random, size_t server_len, BYTE* output,
|
||||
size_t out_len);
|
||||
FREERDP_LOCAL BOOL security_licensing_encryption_key(const BYTE* session_key_blob,
|
||||
const BYTE* client_random,
|
||||
const BYTE* server_random, BYTE* output);
|
||||
size_t session_len, const BYTE* client_random,
|
||||
size_t client_len, const BYTE* server_random,
|
||||
size_t server_len, BYTE* output,
|
||||
size_t out_len);
|
||||
FREERDP_LOCAL BOOL security_mac_data(const BYTE* mac_salt_key, size_t mac_salt_key_length,
|
||||
const BYTE* data, UINT32 length, BYTE* output,
|
||||
size_t output_length);
|
||||
FREERDP_LOCAL BOOL security_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length,
|
||||
BYTE* output);
|
||||
BYTE* output, size_t out_len);
|
||||
FREERDP_LOCAL BOOL security_salted_mac_signature(rdpRdp* rdp, const BYTE* data, UINT32 length,
|
||||
BOOL encryption, BYTE* output);
|
||||
BOOL encryption, BYTE* output, size_t out_len);
|
||||
FREERDP_LOCAL BOOL security_establish_keys(rdpRdp* rdp);
|
||||
|
||||
FREERDP_LOCAL BOOL security_lock(rdpRdp* rdp);
|
||||
|
@ -52,10 +60,10 @@ FREERDP_LOCAL BOOL security_unlock(rdpRdp* rdp);
|
|||
FREERDP_LOCAL BOOL security_encrypt(BYTE* data, size_t length, rdpRdp* rdp);
|
||||
FREERDP_LOCAL BOOL security_decrypt(BYTE* data, size_t length, rdpRdp* rdp);
|
||||
FREERDP_LOCAL BOOL security_hmac_signature(const BYTE* data, size_t length, BYTE* output,
|
||||
rdpRdp* rdp);
|
||||
size_t out_len, rdpRdp* rdp);
|
||||
FREERDP_LOCAL BOOL security_fips_encrypt(BYTE* data, size_t length, rdpRdp* rdp);
|
||||
FREERDP_LOCAL BOOL security_fips_decrypt(BYTE* data, size_t length, rdpRdp* rdp);
|
||||
FREERDP_LOCAL BOOL security_fips_check_signature(const BYTE* data, size_t length, const BYTE* sig,
|
||||
rdpRdp* rdp);
|
||||
size_t sig_len, rdpRdp* rdp);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_SECURITY_H */
|
||||
|
|
|
@ -34,17 +34,17 @@ extern "C"
|
|||
#endif
|
||||
|
||||
FREERDP_LOCAL SSIZE_T crypto_rsa_public_encrypt(const BYTE* input, size_t length,
|
||||
const rdpCertInfo* cert, BYTE* output,
|
||||
size_t output_length);
|
||||
const rdpCertInfo* cert, BYTE* output,
|
||||
size_t output_length);
|
||||
FREERDP_LOCAL SSIZE_T crypto_rsa_public_decrypt(const BYTE* input, size_t length,
|
||||
const rdpCertInfo* cert, BYTE* output,
|
||||
size_t output_length);
|
||||
const rdpCertInfo* cert, BYTE* output,
|
||||
size_t output_length);
|
||||
FREERDP_LOCAL SSIZE_T crypto_rsa_private_encrypt(const BYTE* input, size_t length,
|
||||
const rdpRsaKey* key, BYTE* output,
|
||||
size_t output_length);
|
||||
const rdpRsaKey* key, BYTE* output,
|
||||
size_t output_length);
|
||||
FREERDP_LOCAL SSIZE_T crypto_rsa_private_decrypt(const BYTE* input, size_t length,
|
||||
const rdpRsaKey* key, BYTE* output,
|
||||
size_t output_length);
|
||||
const rdpRsaKey* key, BYTE* output,
|
||||
size_t output_length);
|
||||
FREERDP_LOCAL void crypto_reverse(BYTE* data, size_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
Loading…
Reference in New Issue