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:
parent
8bf5559f51
commit
18cb418c81
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user