diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 9faf6afe1..c7ec504cf 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -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; diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index cc562922f..08c815107 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -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)); diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 0fe06ccc3..7dc929f0a 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -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; diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index 39e5afd16..b5b0d041e 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -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; diff --git a/libfreerdp/core/security.h b/libfreerdp/core/security.h index 037b3c60d..326ff8496 100644 --- a/libfreerdp/core/security.h +++ b/libfreerdp/core/security.h @@ -28,22 +28,30 @@ #include -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 */ diff --git a/libfreerdp/crypto/crypto.h b/libfreerdp/crypto/crypto.h index 668f08f3b..afc0840d4 100644 --- a/libfreerdp/crypto/crypto.h +++ b/libfreerdp/crypto/crypto.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