core: FIPS for fastpath and RDP security fixes

- fixed invalid stream position if extEncryptionMethods is not used
- enabled 56bit rdp security method
- fixed entropy reduction of the keys for 40 bit and 56 bit
- added rdp security incl. FIPS for fastpath output
- added FIPS encryption to fast path input
- fixed FIPS key generation in server mode
- fixed stream length correction in FIPS mode
- added rdp encryption for licensing packets (apparently some clients,
  specifically cetsc, require the license packets received from the
  server to be encrypted under certain RDP encryption levels)
- replace errnous virtual extended mouse event in focus in event
This commit is contained in:
Norbert Federa 2014-04-02 14:17:39 +02:00
parent 8bf5559f51
commit 18cb418c81
11 changed files with 198 additions and 87 deletions

View File

@ -1601,7 +1601,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
settings->NlaSecurity = FALSE;
settings->ExtSecurity = FALSE;
settings->DisableEncryption = TRUE;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT| ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
}
else if (strcmp("tls", arg->Value) == 0) /* TLS */

View File

@ -693,7 +693,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
settings->TlsSecurity = FALSE;
settings->NlaSecurity = FALSE;
settings->DisableEncryption = FALSE;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
}
else if (strncmp("tls", arg->Value, 1) == 0) /* TLS */

View File

@ -427,7 +427,7 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
s = Stream_New(NULL, length);
rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
rdp_write_security_header(s, SEC_EXCHANGE_PKT);
rdp_write_security_header(s, SEC_EXCHANGE_PKT | SEC_LICENSE_ENCRYPT_SC);
length = key_len + 8;
Stream_Write_UINT32(s, length);

View File

@ -3,6 +3,7 @@
* Fast Path
*
* Copyright 2011 Vic Lee
* Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -137,7 +138,7 @@ UINT32 fastpath_get_update_header_size(FASTPATH_UPDATE_HEADER* fpUpdateHeader)
return (fpUpdateHeader->compression) ? 4 : 3;
}
void fastpath_write_update_pdu_header(wStream* s, FASTPATH_UPDATE_PDU_HEADER* fpUpdatePduHeader)
void fastpath_write_update_pdu_header(wStream* s, FASTPATH_UPDATE_PDU_HEADER* fpUpdatePduHeader, rdpRdp* rdp)
{
fpUpdatePduHeader->fpOutputHeader = 0;
fpUpdatePduHeader->fpOutputHeader |= (fpUpdatePduHeader->action & 0x03);
@ -147,18 +148,25 @@ void fastpath_write_update_pdu_header(wStream* s, FASTPATH_UPDATE_PDU_HEADER* fp
Stream_Write_UINT8(s, 0x80 | (fpUpdatePduHeader->length >> 8)); /* length1 */
Stream_Write_UINT8(s, fpUpdatePduHeader->length & 0xFF); /* length2 */
}
UINT32 fastpath_get_update_pdu_header_size(FASTPATH_UPDATE_PDU_HEADER* fpUpdatePduHeader)
{
UINT32 size = 1;
size += 2;
if (fpUpdatePduHeader->secFlags)
{
size += 4;
size += 8;
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
Stream_Write(s, fpUpdatePduHeader->fipsInformation, 4);
Stream_Write(s, fpUpdatePduHeader->dataSignature, 8);
}
}
UINT32 fastpath_get_update_pdu_header_size(FASTPATH_UPDATE_PDU_HEADER* fpUpdatePduHeader, rdpRdp* rdp)
{
UINT32 size = 3; /* fpUpdatePduHeader + length1 + length2 */
if (fpUpdatePduHeader->secFlags)
{
size += 8; /* dataSignature */
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
size += 4; /* fipsInformation */
}
return size;
@ -746,7 +754,6 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNu
rdpRdp* rdp;
UINT16 length;
BYTE eventHeader;
int sec_bytes;
/*
* A maximum of 15 events are allowed per request
@ -776,7 +783,48 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNu
Stream_SetPosition(s, 0);
Stream_Write_UINT8(s, eventHeader);
sec_bytes = fastpath_get_sec_bytes(fastpath->rdp);
/* Write length later, RDP encryption might add a padding */
Stream_Seek(s, 2);
if (rdp->sec_flags & SEC_ENCRYPT)
{
int sec_bytes = fastpath_get_sec_bytes(fastpath->rdp);
BYTE* fpInputEvents = Stream_Pointer(s) + sec_bytes;
UINT16 fpInputEvents_length = length - 3 - sec_bytes;
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
{
BYTE pad;
if ((pad = 8 - (fpInputEvents_length % 8)) == 8)
pad = 0;
Stream_Write_UINT16(s, 0x10); /* length */
Stream_Write_UINT8(s, 0x1); /* TSFIPS_VERSION 1*/
Stream_Write_UINT8(s, pad); /* padding */
security_hmac_signature(fpInputEvents, fpInputEvents_length, Stream_Pointer(s), rdp);
if (pad)
memset(fpInputEvents + fpInputEvents_length, 0, pad);
security_fips_encrypt(fpInputEvents, fpInputEvents_length + pad, rdp);
length += pad;
}
else
{
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
security_salted_mac_signature(rdp, fpInputEvents, fpInputEvents_length, TRUE, Stream_Pointer(s));
else
security_mac_signature(rdp, fpInputEvents, fpInputEvents_length, Stream_Pointer(s));
security_encrypt(fpInputEvents, fpInputEvents_length, rdp);
}
}
rdp->sec_flags = 0;
/*
* We always encode length in two bytes, even though we could use
@ -784,26 +832,9 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNu
* because we can leave room for fixed-length header, store all
* the data first and then store the header.
*/
Stream_SetPosition(s, 1);
Stream_Write_UINT16_BE(s, 0x8000 | length);
if (sec_bytes > 0)
{
BYTE* fpInputEvents;
UINT16 fpInputEvents_length;
fpInputEvents = Stream_Pointer(s) + sec_bytes;
fpInputEvents_length = length - 3 - sec_bytes;
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
security_salted_mac_signature(rdp, fpInputEvents, fpInputEvents_length, TRUE, Stream_Pointer(s));
else
security_mac_signature(rdp, fpInputEvents, fpInputEvents_length, Stream_Pointer(s));
security_encrypt(fpInputEvents, fpInputEvents_length, rdp);
}
rdp->sec_flags = 0;
Stream_SetPosition(s, length);
Stream_SealLength(s);
@ -860,6 +891,14 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
maxLength -= 20;
}
if (rdp->do_crypt)
{
rdp->sec_flags |= SEC_ENCRYPT;
if (rdp->do_secure_checksum)
rdp->sec_flags |= SEC_SECURE_CHECKSUM;
}
totalLength = Stream_GetPosition(s);
Stream_SetPosition(s, 0);
@ -870,6 +909,8 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
UINT32 DstSize = 0;
BYTE* pDstData = NULL;
UINT32 compressionFlags = 0;
BYTE pad = 0;
BYTE* pSignature;
fpUpdatePduHeader.action = 0;
fpUpdatePduHeader.secFlags = 0;
@ -882,6 +923,11 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
pSrcData = pDstData = Stream_Pointer(s);
SrcSize = DstSize = fpUpdateHeader.size;
if (rdp->sec_flags & SEC_ENCRYPT)
fpUpdatePduHeader.secFlags |= FASTPATH_OUTPUT_ENCRYPTED;
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
fpUpdatePduHeader.secFlags |= FASTPATH_OUTPUT_SECURE_CHECKSUM;
if (settings->CompressionEnabled)
{
if (bulk_compress(rdp->bulk, pSrcData, SrcSize, &pDstData, &DstSize, &compressionFlags) >= 0)
@ -909,16 +955,58 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
fpUpdateHeader.fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT;
fpUpdateHeaderSize = fastpath_get_update_header_size(&fpUpdateHeader);
fpUpdatePduHeaderSize = fastpath_get_update_pdu_header_size(&fpUpdatePduHeader);
fpUpdatePduHeaderSize = fastpath_get_update_pdu_header_size(&fpUpdatePduHeader, rdp);
fpHeaderSize = fpUpdateHeaderSize + fpUpdatePduHeaderSize;
fpUpdatePduHeader.length = fpUpdateHeader.size + fpHeaderSize;
if (rdp->sec_flags & SEC_ENCRYPT)
{
pSignature = Stream_Buffer(fs) + 3;
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
{
pSignature += 4;
if ((pad = 8 - ((DstSize + fpUpdateHeaderSize) % 8)) == 8)
pad = 0;
fpUpdatePduHeader.fipsInformation[0] = 0x10;
fpUpdatePduHeader.fipsInformation[1] = 0x00;
fpUpdatePduHeader.fipsInformation[2] = 0x01;
fpUpdatePduHeader.fipsInformation[3] = pad;
}
}
fpUpdatePduHeader.length = fpUpdateHeader.size + fpHeaderSize + pad;
Stream_SetPosition(fs, 0);
fastpath_write_update_pdu_header(fs, &fpUpdatePduHeader);
fastpath_write_update_pdu_header(fs, &fpUpdatePduHeader, rdp);
fastpath_write_update_header(fs, &fpUpdateHeader);
Stream_Write(fs, pDstData, DstSize);
if (pad)
Stream_Zero(fs, pad);
if (rdp->sec_flags & SEC_ENCRYPT)
{
UINT32 dataSize = fpUpdateHeaderSize + DstSize + pad;
BYTE *data = Stream_Pointer(fs) - dataSize;
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
{
security_hmac_signature(data, dataSize - pad, pSignature, rdp);
security_fips_encrypt(data, dataSize, rdp);
}
else
{
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
security_salted_mac_signature(rdp, data, dataSize, TRUE, pSignature);
else
security_mac_signature(rdp, data, dataSize, pSignature);
security_encrypt(data, dataSize, rdp);
}
}
Stream_SealLength(fs);
if (transport_write(rdp->transport, fs) < 0)
@ -930,6 +1018,8 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
Stream_Seek(s, SrcSize);
}
rdp->sec_flags = 0;
return status;
}

View File

@ -916,6 +916,8 @@ BOOL gcc_read_client_security_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
Stream_Read_UINT32(s, settings->EncryptionMethods); /* encryptionMethods */
if (settings->EncryptionMethods == 0)
Stream_Read_UINT32(s, settings->EncryptionMethods); /* extEncryptionMethods */
else
Stream_Seek(s, 4);
}
else
{
@ -1082,6 +1084,10 @@ void gcc_write_server_security_data(wStream* s, rdpMcs* mcs)
{
settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT;
}
else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_56BIT) != 0)
{
settings->EncryptionMethods = ENCRYPTION_METHOD_56BIT;
}
else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_40BIT) != 0)
{
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT;

View File

@ -163,7 +163,7 @@ void input_send_focus_in_event(rdpInput* input, UINT16 toggleStates, UINT16 x, U
input_send_keyboard_event(input, KBD_FLAGS_RELEASE, 0x0f);
/* finish with a mouse pointer position like mstsc.exe */
input_send_extended_mouse_event(input, PTR_FLAGS_MOVE, x, y);
input_send_mouse_event(input, PTR_FLAGS_MOVE, x, y);
}
void input_send_fastpath_synchronize_event(rdpInput* input, UINT32 flags)

View File

@ -3,6 +3,7 @@
* RDP Licensing
*
* Copyright 2011-2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -163,8 +164,15 @@ wStream* license_send_stream_init(rdpLicense* license)
{
wStream* s;
s = Stream_New(NULL, 4096);
Stream_Seek(s, LICENSE_PACKET_HEADER_MAX_LENGTH);
license->rdp->sec_flags = SEC_LICENSE_PKT;
if (license->rdp->do_crypt)
license->rdp->sec_flags |= SEC_LICENSE_ENCRYPT_CS;
s = transport_send_stream_init(license->rdp->transport, 4096);
rdp_init_stream(license->rdp, s);
license->PacketHeaderLength = Stream_GetPosition(s);
Stream_Seek(s, LICENSE_PREAMBLE_LENGTH);
return s;
}
@ -181,15 +189,13 @@ BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
int length;
BYTE flags;
UINT16 wMsgSize;
UINT16 sec_flags;
rdpRdp* rdp = license->rdp;
DEBUG_LICENSE("Sending %s Packet", LICENSE_MESSAGE_STRINGS[type & 0x1F]);
length = Stream_GetPosition(s);
Stream_SetPosition(s, 0);
sec_flags = SEC_LICENSE_PKT;
wMsgSize = length - LICENSE_PACKET_HEADER_MAX_LENGTH + 4;
wMsgSize = length - license->PacketHeaderLength;
Stream_SetPosition(s, license->PacketHeaderLength);
flags = PREAMBLE_VERSION_3_0;
@ -198,25 +204,20 @@ BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
* running in server mode! This flag seems to be incorrectly documented.
*/
if (!license->rdp->settings->ServerMode)
if (!rdp->settings->ServerMode)
flags |= EXTENDED_ERROR_MSG_SUPPORTED;
rdp_write_header(license->rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
rdp_write_security_header(s, sec_flags);
license_write_preamble(s, type, flags, wMsgSize);
#ifdef WITH_DEBUG_LICENSE
fprintf(stderr, "Sending %s Packet, length %d\n", LICENSE_MESSAGE_STRINGS[type & 0x1F], wMsgSize);
winpr_HexDump(Stream_Pointer(s) - 4, wMsgSize);
winpr_HexDump(Stream_Pointer(s) - LICENSE_PREAMBLE_LENGTH, wMsgSize);
#endif
Stream_SetPosition(s, length);
Stream_SealLength(s);
rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
if (transport_write(license->rdp->transport, s) < 0)
return FALSE;
Stream_Free(s, TRUE);
rdp->sec_flags = 0;
return TRUE;
}

View File

@ -48,7 +48,6 @@ typedef struct rdp_license rdpLicense;
#define LICENSE_PKT_MASK (LICENSE_PKT_CS_MASK | LICENSE_PKT_SC_MASK)
#define LICENSE_PREAMBLE_LENGTH 4
#define LICENSE_PACKET_HEADER_MAX_LENGTH (RDP_PACKET_HEADER_MAX_LENGTH + RDP_SECURITY_HEADER_LENGTH + LICENSE_PREAMBLE_LENGTH)
/* Cryptographic Lengths */
@ -198,6 +197,7 @@ struct rdp_license
LICENSE_BLOB* EncryptedPlatformChallenge;
LICENSE_BLOB* EncryptedHardwareId;
SCOPE_LIST* ScopeList;
UINT32 PacketHeaderLength;
};
int license_recv(rdpLicense* license, wStream* s);

View File

@ -156,7 +156,7 @@ BOOL nego_connect(rdpNego* nego)
if (nego->selected_protocol == PROTOCOL_RDP)
{
nego->transport->settings->DisableEncryption = TRUE;
nego->transport->settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
nego->transport->settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
nego->transport->settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
}
@ -939,7 +939,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
if (!settings->LocalConnection)
{
settings->DisableEncryption = TRUE;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
}

View File

@ -291,11 +291,19 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
{
int reason = 0;
TerminateEventArgs e;
rdpContext* context = rdp->instance->context;
rdpContext* context;
if (!mcs_recv_disconnect_provider_ultimatum(rdp->mcs, s, &reason))
return FALSE;
if (rdp->instance == NULL)
{
rdp->disconnect = TRUE;
return FALSE;
}
context = rdp->instance->context;
if (rdp->errorInfo == ERRINFO_SUCCESS)
{
/**
@ -467,20 +475,13 @@ static UINT32 rdp_get_sec_bytes(rdpRdp* rdp)
BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channel_id)
{
int secm;
UINT16 length;
UINT32 sec_bytes;
length = Stream_GetPosition(s);
Stream_SetPosition(s, 0);
rdp_write_header(rdp, s, length, channel_id);
sec_bytes = rdp_get_sec_bytes(rdp);
secm = Stream_GetPosition(s);
Stream_Seek(s, sec_bytes);
Stream_SetPosition(s, secm);
length += rdp_security_stream_out(rdp, s, length, 0);
Stream_SetPosition(s, length);
@ -932,8 +933,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags)
return FALSE; /* TODO */
}
/* is this what needs adjusting? */
Stream_Capacity(s) -= pad;
Stream_Length(s) -= pad;
return TRUE;
}

View File

@ -3,6 +3,7 @@
* RDP Security
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -406,7 +407,7 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
BYTE master_secret[48];
BYTE session_key_blob[48];
BYTE* server_random;
BYTE salt40[] = { 0xD1, 0x26, 0x9E };
BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */
rdpSettings* settings;
settings = rdp->settings;
@ -420,9 +421,6 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
fprintf(stderr, "FIPS Compliant encryption level.\n");
/* disable fastpath input; it doesnt handle FIPS encryption yet */
rdp->settings->FastPathInput = FALSE;
sha1 = crypto_sha1_init();
if (!sha1)
{
@ -432,9 +430,7 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
crypto_sha1_update(sha1, client_random + 16, 16);
crypto_sha1_update(sha1, server_random + 16, 16);
crypto_sha1_final(sha1, client_encrypt_key_t);
client_encrypt_key_t[20] = client_encrypt_key_t[0];
fips_expand_key_bits(client_encrypt_key_t, rdp->fips_encrypt_key);
sha1 = crypto_sha1_init();
if (!sha1)
@ -445,9 +441,7 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
crypto_sha1_update(sha1, client_random, 16);
crypto_sha1_update(sha1, server_random, 16);
crypto_sha1_final(sha1, client_decrypt_key_t);
client_decrypt_key_t[20] = client_decrypt_key_t[0];
fips_expand_key_bits(client_decrypt_key_t, rdp->fips_decrypt_key);
sha1 = crypto_sha1_init();
if (!sha1)
@ -458,6 +452,17 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
crypto_sha1_update(sha1, client_decrypt_key_t, 20);
crypto_sha1_update(sha1, client_encrypt_key_t, 20);
crypto_sha1_final(sha1, rdp->fips_sign_key);
if (rdp->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);
}
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);
}
}
memcpy(pre_master_secret, client_random, 24);
@ -483,14 +488,21 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
server_random, rdp->encrypt_key);
}
if (settings->EncryptionMethods == 1) /* 40 and 56 bit */
if (settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT)
{
memcpy(rdp->sign_key, salt40, 3); /* TODO 56 bit */
memcpy(rdp->decrypt_key, salt40, 3); /* TODO 56 bit */
memcpy(rdp->encrypt_key, salt40, 3); /* TODO 56 bit */
memcpy(rdp->sign_key, salt, 3);
memcpy(rdp->decrypt_key, salt, 3);
memcpy(rdp->encrypt_key, salt, 3);
rdp->rc4_key_len = 8;
}
else if (settings->EncryptionMethods == 2) /* 128 bit */
else if (settings->EncryptionMethods == ENCRYPTION_METHOD_56BIT)
{
memcpy(rdp->sign_key, salt, 1);
memcpy(rdp->decrypt_key, salt, 1);
memcpy(rdp->encrypt_key, salt, 1);
rdp->rc4_key_len = 8;
}
else if (settings->EncryptionMethods == ENCRYPTION_METHOD_128BIT)
{
rdp->rc4_key_len = 16;
}
@ -505,13 +517,13 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
return TRUE;
}
BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len)
BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp)
{
BYTE sha1h[CRYPTO_SHA1_DIGEST_LENGTH];
CryptoMd5 md5;
CryptoSha1 sha1;
CryptoRc4 rc4;
BYTE salt40[] = { 0xD1, 0x26, 0x9E };
BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */
sha1 = crypto_sha1_init();
if (!sha1)
@ -544,8 +556,10 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len)
crypto_rc4(rc4, key_len, key, key);
crypto_rc4_free(rc4);
if (key_len == 8)
memcpy(key, salt40, 3); /* TODO 56 bit */
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT)
memcpy(key, salt, 3);
else if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_56BIT)
memcpy(key, salt, 1);
return TRUE;
}
@ -554,7 +568,7 @@ BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp)
{
if (rdp->encrypt_use_count >= 4096)
{
security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len);
security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len, rdp);
crypto_rc4_free(rdp->rc4_encrypt_key);
rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len);
if (!rdp->rc4_encrypt_key)
@ -576,7 +590,7 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp)
return FALSE;
if (rdp->decrypt_use_count >= 4096)
{
security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len);
security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len, rdp);
crypto_rc4_free(rdp->rc4_decrypt_key);
rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len);
if (!rdp->rc4_decrypt_key)