[core,security] refactor functions to check lengths

This commit is contained in:
akallabeth 2023-01-30 12:14:03 +01:00 committed by akallabeth
parent 7c1007b1b6
commit 00f2679eda
6 changed files with 230 additions and 134 deletions

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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