work on rdp encryption
This commit is contained in:
parent
afc9ac89ae
commit
2ac4a5fa96
@ -53,7 +53,8 @@ endif()
|
|||||||
|
|
||||||
# Compiler-specific flags
|
# Compiler-specific flags
|
||||||
if(CMAKE_COMPILER_IS_GNUCC)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-unused-but-set-variable")
|
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-unused-but-set-variable")
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -lncurses")
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
|
||||||
endif()
|
endif()
|
||||||
|
@ -198,6 +198,13 @@ struct rdp_settings
|
|||||||
rdpBlob server_certificate;
|
rdpBlob server_certificate;
|
||||||
struct rdp_certificate* server_cert;
|
struct rdp_certificate* server_cert;
|
||||||
|
|
||||||
|
uint8 sign_key[16];
|
||||||
|
uint8 decrypt_key[16];
|
||||||
|
uint8 encrypt_key[16];
|
||||||
|
uint8 decrypt_update_key[16];
|
||||||
|
uint8 encrypt_update_key[16];
|
||||||
|
int rc4_key_len;
|
||||||
|
|
||||||
boolean console_audio;
|
boolean console_audio;
|
||||||
boolean console_session;
|
boolean console_session;
|
||||||
uint32 redirected_session_id;
|
uint32 redirected_session_id;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "info.h"
|
#include "info.h"
|
||||||
|
#include "per.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection Sequence
|
* Connection Sequence
|
||||||
@ -107,10 +108,12 @@ boolean rdp_client_connect(rdpRdp* rdp)
|
|||||||
static boolean rdp_establish_keys(rdpRdp* rdp)
|
static boolean rdp_establish_keys(rdpRdp* rdp)
|
||||||
{
|
{
|
||||||
uint8 client_random[32];
|
uint8 client_random[32];
|
||||||
uint8 crypt_client_random[256];
|
uint8 crypt_client_random[256 + 8];
|
||||||
uint32 key_len;
|
uint32 key_len;
|
||||||
uint8* mod;
|
uint8* mod;
|
||||||
uint8* exp;
|
uint8* exp;
|
||||||
|
uint32 length;
|
||||||
|
STREAM* s;
|
||||||
|
|
||||||
printf("rdp_establish_keys:\n");
|
printf("rdp_establish_keys:\n");
|
||||||
if (rdp->settings->encryption == False)
|
if (rdp->settings->encryption == False)
|
||||||
@ -119,12 +122,51 @@ static boolean rdp_establish_keys(rdpRdp* rdp)
|
|||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(client_random, 0x5e, 32); /* TODO: get real random */
|
/* encrypt client random */
|
||||||
crypto_nonce(client_random, 32);
|
memset(crypt_client_random, 0, sizeof(crypt_client_random));
|
||||||
|
memset(client_random, 0x5e, 32);
|
||||||
|
//crypto_nonce(client_random, 32);
|
||||||
|
printf("client random\n");
|
||||||
|
freerdp_hexdump(client_random, 32);
|
||||||
key_len = rdp->settings->server_cert->cert_info.modulus.length;
|
key_len = rdp->settings->server_cert->cert_info.modulus.length;
|
||||||
|
printf("key_len %d %d %d\n", key_len, rdp->mcs->user_id, MCS_BASE_CHANNEL_ID);
|
||||||
mod = rdp->settings->server_cert->cert_info.modulus.data;
|
mod = rdp->settings->server_cert->cert_info.modulus.data;
|
||||||
exp = rdp->settings->server_cert->cert_info.exponent;
|
exp = rdp->settings->server_cert->cert_info.exponent;
|
||||||
crypto_rsa_encrypt(client_random, 32, key_len, mod, exp, crypt_client_random);
|
crypto_rsa_encrypt(client_random, 32, key_len, mod, exp, crypt_client_random);
|
||||||
|
printf("client crypt random\n");
|
||||||
|
freerdp_hexdump(crypt_client_random, key_len);
|
||||||
|
|
||||||
|
/* send crypt client random to server */
|
||||||
|
length = 7 + 8 + 4 + 4 + key_len + 8;
|
||||||
|
s = transport_send_stream_init(rdp->mcs->transport, length);
|
||||||
|
tpkt_write_header(s, length);
|
||||||
|
tpdu_write_header(s, 2, 0xf0);
|
||||||
|
per_write_choice(s, DomainMCSPDU_SendDataRequest << 2);
|
||||||
|
per_write_integer16(s, rdp->mcs->user_id, MCS_BASE_CHANNEL_ID);
|
||||||
|
per_write_integer16(s, MCS_GLOBAL_CHANNEL_ID, 0);
|
||||||
|
stream_write_uint8(s, 0x70);
|
||||||
|
length = (4 + 4 + key_len + 8) | 0x8000;
|
||||||
|
stream_write_uint16_be(s, length);
|
||||||
|
stream_write_uint32(s, 1); /* SEC_CLIENT_RANDOM */
|
||||||
|
length = key_len + 8;
|
||||||
|
stream_write_uint32(s, length);
|
||||||
|
memcpy(s->p, crypt_client_random, length);
|
||||||
|
stream_seek(s, length);
|
||||||
|
if (transport_write(rdp->mcs->transport, s) < 0)
|
||||||
|
{
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now calculate encrypt / decrypt and upate keys */
|
||||||
|
if (!security_establish_keys(client_random, rdp->settings))
|
||||||
|
{
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdp->rc4_decrypt_key = crypto_rc4_init(rdp->settings->decrypt_key, rdp->settings->rc4_key_len);
|
||||||
|
rdp->rc4_encrypt_key = crypto_rc4_init(rdp->settings->encrypt_key, rdp->settings->rc4_key_len);
|
||||||
|
|
||||||
|
rdp->do_crypt = True;
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s)
|
|||||||
if (fastpath != NULL)
|
if (fastpath != NULL)
|
||||||
{
|
{
|
||||||
fastpath->encryptionFlags = (header & 0xC0) >> 6;
|
fastpath->encryptionFlags = (header & 0xC0) >> 6;
|
||||||
|
printf("fastpath_read_header: fastpath->encryptionFlags %d\n", fastpath->encryptionFlags);
|
||||||
fastpath->numberEvents = (header & 0x3C) >> 2;
|
fastpath->numberEvents = (header & 0x3C) >> 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,11 +584,10 @@ boolean rdp_send_client_info(rdpRdp* rdp)
|
|||||||
{
|
{
|
||||||
STREAM* s;
|
STREAM* s;
|
||||||
|
|
||||||
|
//rdp->settings->crypt_flags |= SEC_INFO_PKT;
|
||||||
|
rdp->sec_flags |= SEC_INFO_PKT;
|
||||||
s = rdp_send_stream_init(rdp);
|
s = rdp_send_stream_init(rdp);
|
||||||
|
|
||||||
rdp_write_security_header(s, SEC_INFO_PKT);
|
|
||||||
rdp_write_info_packet(s, rdp->settings);
|
rdp_write_info_packet(s, rdp->settings);
|
||||||
|
|
||||||
return rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
|
return rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ boolean license_recv(rdpLicense* license, STREAM* s)
|
|||||||
rdp_read_security_header(s, &sec_flags);
|
rdp_read_security_header(s, &sec_flags);
|
||||||
if (!(sec_flags & SEC_LICENSE_PKT))
|
if (!(sec_flags & SEC_LICENSE_PKT))
|
||||||
{
|
{
|
||||||
printf("Unexpected license packet.\n");
|
printf("Unexpected license packet. got 0x%4.4x need bit 0x%4.4x set\n", sec_flags, SEC_LICENSE_PKT);
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +146,21 @@ void rdp_write_share_data_header(STREAM* s, uint16 length, uint8 type, uint32 sh
|
|||||||
stream_write_uint16(s, 0); /* compressedLength (2 bytes) */
|
stream_write_uint16(s, 0); /* compressedLength (2 bytes) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rdp_security_stream_init(rdpRdp* rdp, STREAM* s)
|
||||||
|
{
|
||||||
|
printf("rdp_security_stream_init:\n");
|
||||||
|
if (rdp->do_crypt)
|
||||||
|
{
|
||||||
|
stream_seek(s, 12);
|
||||||
|
rdp->sec_flags |= SEC_ENCRYPT;
|
||||||
|
}
|
||||||
|
else if (rdp->sec_flags != 0)
|
||||||
|
{
|
||||||
|
stream_seek(s, 4);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize an RDP packet stream.\n
|
* Initialize an RDP packet stream.\n
|
||||||
* @param rdp rdp module
|
* @param rdp rdp module
|
||||||
@ -155,8 +170,10 @@ void rdp_write_share_data_header(STREAM* s, uint16 length, uint8 type, uint32 sh
|
|||||||
STREAM* rdp_send_stream_init(rdpRdp* rdp)
|
STREAM* rdp_send_stream_init(rdpRdp* rdp)
|
||||||
{
|
{
|
||||||
STREAM* s;
|
STREAM* s;
|
||||||
|
|
||||||
s = transport_send_stream_init(rdp->transport, 2048);
|
s = transport_send_stream_init(rdp->transport, 2048);
|
||||||
stream_seek(s, RDP_PACKET_HEADER_LENGTH);
|
stream_seek(s, RDP_PACKET_HEADER_LENGTH);
|
||||||
|
rdp_security_stream_init(rdp, s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,6 +182,7 @@ STREAM* rdp_pdu_init(rdpRdp* rdp)
|
|||||||
STREAM* s;
|
STREAM* s;
|
||||||
s = transport_send_stream_init(rdp->transport, 2048);
|
s = transport_send_stream_init(rdp->transport, 2048);
|
||||||
stream_seek(s, RDP_PACKET_HEADER_LENGTH);
|
stream_seek(s, RDP_PACKET_HEADER_LENGTH);
|
||||||
|
rdp_security_stream_init(rdp, s);
|
||||||
stream_seek(s, RDP_SHARE_CONTROL_HEADER_LENGTH);
|
stream_seek(s, RDP_SHARE_CONTROL_HEADER_LENGTH);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -174,6 +192,7 @@ STREAM* rdp_data_pdu_init(rdpRdp* rdp)
|
|||||||
STREAM* s;
|
STREAM* s;
|
||||||
s = transport_send_stream_init(rdp->transport, 2048);
|
s = transport_send_stream_init(rdp->transport, 2048);
|
||||||
stream_seek(s, RDP_PACKET_HEADER_LENGTH);
|
stream_seek(s, RDP_PACKET_HEADER_LENGTH);
|
||||||
|
rdp_security_stream_init(rdp, s);
|
||||||
stream_seek(s, RDP_SHARE_CONTROL_HEADER_LENGTH);
|
stream_seek(s, RDP_SHARE_CONTROL_HEADER_LENGTH);
|
||||||
stream_seek(s, RDP_SHARE_DATA_HEADER_LENGTH);
|
stream_seek(s, RDP_SHARE_DATA_HEADER_LENGTH);
|
||||||
return s;
|
return s;
|
||||||
@ -229,6 +248,46 @@ void rdp_write_header(rdpRdp* rdp, STREAM* s, uint16 length, uint16 channel_id)
|
|||||||
stream_write_uint16_be(s, length); /* userData (OCTET_STRING) */
|
stream_write_uint16_be(s, length); /* userData (OCTET_STRING) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32 rdp_security_stream_out(rdpRdp* rdp, STREAM* s, int length)
|
||||||
|
{
|
||||||
|
uint32 sec_flags;
|
||||||
|
uint32 ml;
|
||||||
|
uint8* mk;
|
||||||
|
uint8* data;
|
||||||
|
|
||||||
|
printf("rdp_security_stream_out:\n");
|
||||||
|
sec_flags = rdp->sec_flags;
|
||||||
|
if (sec_flags != 0)
|
||||||
|
{
|
||||||
|
rdp_write_security_header(s, sec_flags);
|
||||||
|
if (sec_flags & SEC_ENCRYPT)
|
||||||
|
{
|
||||||
|
data = s->p + 8;
|
||||||
|
length = length - (data - s->data);
|
||||||
|
mk = rdp->settings->sign_key;
|
||||||
|
ml = rdp->settings->rc4_key_len;
|
||||||
|
security_mac_signature(mk, ml, data, length, s->p);
|
||||||
|
stream_seek(s, 8);
|
||||||
|
security_encrypt(s->p, length, rdp);
|
||||||
|
}
|
||||||
|
rdp->sec_flags = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32 rdp_get_sec_bytes(uint32 sec_flags)
|
||||||
|
{
|
||||||
|
uint32 sec_bytes;
|
||||||
|
|
||||||
|
if (sec_flags & SEC_ENCRYPT)
|
||||||
|
sec_bytes = 12;
|
||||||
|
else if (sec_flags != 0)
|
||||||
|
sec_bytes = 4;
|
||||||
|
else
|
||||||
|
sec_bytes = 0;
|
||||||
|
return sec_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send an RDP packet.\n
|
* Send an RDP packet.\n
|
||||||
* @param rdp RDP module
|
* @param rdp RDP module
|
||||||
@ -239,12 +298,22 @@ void rdp_write_header(rdpRdp* rdp, STREAM* s, uint16 length, uint16 channel_id)
|
|||||||
boolean rdp_send(rdpRdp* rdp, STREAM* s, uint16 channel_id)
|
boolean rdp_send(rdpRdp* rdp, STREAM* s, uint16 channel_id)
|
||||||
{
|
{
|
||||||
uint16 length;
|
uint16 length;
|
||||||
|
uint32 sec_bytes;
|
||||||
|
uint8* sec_hold;
|
||||||
|
|
||||||
|
printf("rdp_send:\n");
|
||||||
length = stream_get_length(s);
|
length = stream_get_length(s);
|
||||||
stream_set_pos(s, 0);
|
stream_set_pos(s, 0);
|
||||||
|
|
||||||
rdp_write_header(rdp, s, length, channel_id);
|
rdp_write_header(rdp, s, length, channel_id);
|
||||||
|
|
||||||
|
sec_bytes = rdp_get_sec_bytes(rdp->sec_flags);
|
||||||
|
sec_hold = s->p;
|
||||||
|
stream_seek(s, sec_bytes);
|
||||||
|
|
||||||
|
s->p = sec_hold;
|
||||||
|
rdp_security_stream_out(rdp, s, length);
|
||||||
|
|
||||||
stream_set_pos(s, length);
|
stream_set_pos(s, length);
|
||||||
if (transport_write(rdp->transport, s) < 0)
|
if (transport_write(rdp->transport, s) < 0)
|
||||||
return False;
|
return False;
|
||||||
@ -255,13 +324,24 @@ boolean rdp_send(rdpRdp* rdp, STREAM* s, uint16 channel_id)
|
|||||||
boolean rdp_send_pdu(rdpRdp* rdp, STREAM* s, uint16 type, uint16 channel_id)
|
boolean rdp_send_pdu(rdpRdp* rdp, STREAM* s, uint16 type, uint16 channel_id)
|
||||||
{
|
{
|
||||||
uint16 length;
|
uint16 length;
|
||||||
|
uint32 sec_bytes;
|
||||||
|
uint8* sec_hold;
|
||||||
|
|
||||||
|
printf("rdp_send_pdu:\n");
|
||||||
length = stream_get_length(s);
|
length = stream_get_length(s);
|
||||||
stream_set_pos(s, 0);
|
stream_set_pos(s, 0);
|
||||||
|
|
||||||
rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
|
rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
|
||||||
|
|
||||||
|
sec_bytes = rdp_get_sec_bytes(rdp->sec_flags);
|
||||||
|
sec_hold = s->p;
|
||||||
|
stream_seek(s, sec_bytes);
|
||||||
|
|
||||||
rdp_write_share_control_header(s, length, type, channel_id);
|
rdp_write_share_control_header(s, length, type, channel_id);
|
||||||
|
|
||||||
|
s->p = sec_hold;
|
||||||
|
rdp_security_stream_out(rdp, s, length);
|
||||||
|
|
||||||
stream_set_pos(s, length);
|
stream_set_pos(s, length);
|
||||||
if (transport_write(rdp->transport, s) < 0)
|
if (transport_write(rdp->transport, s) < 0)
|
||||||
return False;
|
return False;
|
||||||
@ -272,16 +352,27 @@ boolean rdp_send_pdu(rdpRdp* rdp, STREAM* s, uint16 type, uint16 channel_id)
|
|||||||
boolean rdp_send_data_pdu(rdpRdp* rdp, STREAM* s, uint8 type, uint16 channel_id)
|
boolean rdp_send_data_pdu(rdpRdp* rdp, STREAM* s, uint8 type, uint16 channel_id)
|
||||||
{
|
{
|
||||||
uint16 length;
|
uint16 length;
|
||||||
|
uint32 sec_bytes;
|
||||||
|
uint8* sec_hold;
|
||||||
|
|
||||||
|
printf("rdp_send_data_pdu:\n");
|
||||||
length = stream_get_length(s);
|
length = stream_get_length(s);
|
||||||
stream_set_pos(s, 0);
|
stream_set_pos(s, 0);
|
||||||
|
|
||||||
rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
|
rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
|
||||||
|
|
||||||
|
sec_bytes = rdp_get_sec_bytes(rdp->sec_flags);
|
||||||
|
sec_hold = s->p;
|
||||||
|
stream_seek(s, sec_bytes);
|
||||||
|
|
||||||
rdp_write_share_control_header(s, length, PDU_TYPE_DATA, channel_id);
|
rdp_write_share_control_header(s, length, PDU_TYPE_DATA, channel_id);
|
||||||
rdp_write_share_data_header(s, length, type, rdp->settings->share_id);
|
rdp_write_share_data_header(s, length, type, rdp->settings->share_id);
|
||||||
|
|
||||||
//printf("send %s Data PDU (0x%02X), length:%d\n", DATA_PDU_TYPE_STRINGS[type], type, length);
|
//printf("send %s Data PDU (0x%02X), length:%d\n", DATA_PDU_TYPE_STRINGS[type], type, length);
|
||||||
|
|
||||||
|
s->p = sec_hold;
|
||||||
|
rdp_security_stream_out(rdp, s, length);
|
||||||
|
|
||||||
stream_set_pos(s, length);
|
stream_set_pos(s, length);
|
||||||
if (transport_write(rdp->transport, s) < 0)
|
if (transport_write(rdp->transport, s) < 0)
|
||||||
return False;
|
return False;
|
||||||
|
@ -123,6 +123,12 @@ struct rdp_rdp
|
|||||||
struct rdp_settings* settings;
|
struct rdp_settings* settings;
|
||||||
struct rdp_transport* transport;
|
struct rdp_transport* transport;
|
||||||
struct rdp_vchan* vchan;
|
struct rdp_vchan* vchan;
|
||||||
|
struct crypto_rc4_struct* rc4_decrypt_key;
|
||||||
|
int decrypt_use_count;
|
||||||
|
struct crypto_rc4_struct* rc4_encrypt_key;
|
||||||
|
int encrypt_use_count;
|
||||||
|
uint32 sec_flags;
|
||||||
|
boolean do_crypt;
|
||||||
};
|
};
|
||||||
|
|
||||||
void rdp_read_security_header(STREAM* s, uint16* flags);
|
void rdp_read_security_header(STREAM* s, uint16* flags);
|
||||||
|
@ -85,10 +85,10 @@ static void security_master_hash(char* input, int length, uint8* master_secret,
|
|||||||
|
|
||||||
void security_session_key_blob(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
|
void security_session_key_blob(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
|
||||||
{
|
{
|
||||||
/* MasterHash = MasterHash('A') + MasterHash('BB') + MasterHash('CCC') */
|
/* MasterHash = MasterHash('X') + MasterHash('YY') + MasterHash('ZZZ') */
|
||||||
security_master_hash("A", 1, master_secret, client_random, server_random, &output[0]);
|
security_master_hash("X", 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("YY", 2, master_secret, client_random, server_random, &output[16]);
|
||||||
security_master_hash("CCC", 3, master_secret, client_random, server_random, &output[32]);
|
security_master_hash("ZZZ", 3, master_secret, client_random, server_random, &output[32]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void security_mac_salt_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output)
|
void security_mac_salt_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output)
|
||||||
@ -97,19 +97,23 @@ void security_mac_salt_key(uint8* session_key_blob, uint8* client_random, uint8*
|
|||||||
memcpy(output, session_key_blob, 16);
|
memcpy(output, session_key_blob, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output)
|
void security_md5_16_32_32(uint8* in0, uint8* in1, uint8* in2, uint8* output)
|
||||||
{
|
{
|
||||||
CryptoMd5 md5;
|
CryptoMd5 md5;
|
||||||
|
|
||||||
/* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom)) */
|
|
||||||
|
|
||||||
md5 = crypto_md5_init();
|
md5 = crypto_md5_init();
|
||||||
crypto_md5_update(md5, &session_key_blob[16], 16); /* Second128Bits(SessionKeyBlob) */
|
crypto_md5_update(md5, in0, 16);
|
||||||
crypto_md5_update(md5, client_random, 32); /* ClientRandom */
|
crypto_md5_update(md5, in1, 32);
|
||||||
crypto_md5_update(md5, server_random, 32); /* ServerRandom */
|
crypto_md5_update(md5, in2, 32);
|
||||||
crypto_md5_final(md5, output);
|
crypto_md5_final(md5, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output)
|
||||||
|
{
|
||||||
|
/* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom)) */
|
||||||
|
security_md5_16_32_32(&session_key_blob[16], client_random, server_random, output);
|
||||||
|
}
|
||||||
|
|
||||||
void security_uint32_le(uint8* output, uint32 value)
|
void security_uint32_le(uint8* output, uint32 value)
|
||||||
{
|
{
|
||||||
output[0] = (value) & 0xFF;
|
output[0] = (value) & 0xFF;
|
||||||
@ -172,3 +176,102 @@ void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uin
|
|||||||
|
|
||||||
memcpy(output, md5_digest, 8);
|
memcpy(output, md5_digest, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean security_establish_keys(uint8* client_random, rdpSettings* settings)
|
||||||
|
{
|
||||||
|
uint8 pre_master_secret[48];
|
||||||
|
uint8 master_secret[48];
|
||||||
|
uint8 session_key_blob[48];
|
||||||
|
uint8* server_random;
|
||||||
|
uint8 salt40[] = { 0xD1, 0x26, 0x9E };
|
||||||
|
|
||||||
|
printf("security_establish_keys:\n");
|
||||||
|
|
||||||
|
server_random = settings->server_random.data;
|
||||||
|
|
||||||
|
memcpy(pre_master_secret, client_random, 24);
|
||||||
|
memcpy(pre_master_secret + 24, server_random, 24);
|
||||||
|
|
||||||
|
security_master_secret(pre_master_secret, client_random, server_random, master_secret);
|
||||||
|
security_session_key_blob(master_secret, client_random, server_random, session_key_blob);
|
||||||
|
|
||||||
|
memcpy(settings->sign_key, session_key_blob, 16);
|
||||||
|
|
||||||
|
security_md5_16_32_32(&session_key_blob[16], client_random, server_random, settings->decrypt_key);
|
||||||
|
security_md5_16_32_32(&session_key_blob[32], client_random, server_random, settings->encrypt_key);
|
||||||
|
|
||||||
|
if (settings->encryption_method == 1) /* 40 and 56 bit */
|
||||||
|
{
|
||||||
|
memcpy(settings->sign_key, salt40, 3); /* TODO 56 bit */
|
||||||
|
memcpy(settings->decrypt_key, salt40, 3); /* TODO 56 bit */
|
||||||
|
memcpy(settings->encrypt_key, salt40, 3); /* TODO 56 bit */
|
||||||
|
settings->rc4_key_len = 8;
|
||||||
|
}
|
||||||
|
else /* 128 bit */
|
||||||
|
{
|
||||||
|
settings->rc4_key_len = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(settings->decrypt_update_key, settings->decrypt_key, 16);
|
||||||
|
memcpy(settings->encrypt_update_key, settings->encrypt_key, 16);
|
||||||
|
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean security_key_update(uint8* key, uint8* update_key, int key_len)
|
||||||
|
{
|
||||||
|
uint8 sha1h[20];
|
||||||
|
CryptoMd5 md5;
|
||||||
|
CryptoSha1 sha1;
|
||||||
|
CryptoRc4 rc4;
|
||||||
|
uint8 salt40[] = { 0xD1, 0x26, 0x9E };
|
||||||
|
|
||||||
|
sha1 = crypto_sha1_init();
|
||||||
|
crypto_sha1_update(sha1, update_key, key_len);
|
||||||
|
crypto_sha1_update(sha1, pad1, sizeof(pad1));
|
||||||
|
crypto_sha1_update(sha1, key, key_len);
|
||||||
|
crypto_sha1_final(sha1, sha1h);
|
||||||
|
|
||||||
|
md5 = crypto_md5_init();
|
||||||
|
crypto_md5_update(md5, update_key, key_len);
|
||||||
|
crypto_md5_update(md5, pad2, sizeof(pad2));
|
||||||
|
crypto_md5_update(md5, sha1h, 20);
|
||||||
|
crypto_md5_final(md5, key);
|
||||||
|
|
||||||
|
rc4 = crypto_rc4_init(key, key_len);
|
||||||
|
crypto_rc4(rc4, key_len, key, key);
|
||||||
|
crypto_rc4_free(rc4);
|
||||||
|
|
||||||
|
if (key_len == 8)
|
||||||
|
memcpy(key, salt40, 3); /* TODO 56 bit */
|
||||||
|
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean security_encrypt(uint8* data, int length, rdpRdp* rdp)
|
||||||
|
{
|
||||||
|
if (rdp->encrypt_use_count >= 4096)
|
||||||
|
{
|
||||||
|
security_key_update(rdp->settings->encrypt_key, rdp->settings->encrypt_update_key, rdp->settings->rc4_key_len);
|
||||||
|
crypto_rc4_free(rdp->rc4_encrypt_key);
|
||||||
|
rdp->rc4_encrypt_key = crypto_rc4_init(rdp->settings->encrypt_key, rdp->settings->rc4_key_len);
|
||||||
|
rdp->encrypt_use_count = 0;
|
||||||
|
}
|
||||||
|
crypto_rc4(rdp->rc4_encrypt_key, length, data, data);
|
||||||
|
rdp->encrypt_use_count += 1;
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean security_decrypt(uint8* data, int length, rdpRdp* rdp)
|
||||||
|
{
|
||||||
|
if (rdp->decrypt_use_count >= 4096)
|
||||||
|
{
|
||||||
|
security_key_update(rdp->settings->decrypt_key, rdp->settings->decrypt_update_key, rdp->settings->rc4_key_len);
|
||||||
|
crypto_rc4_free(rdp->rc4_decrypt_key);
|
||||||
|
rdp->rc4_decrypt_key = crypto_rc4_init(rdp->settings->decrypt_key, rdp->settings->rc4_key_len);
|
||||||
|
rdp->decrypt_use_count = 0;
|
||||||
|
}
|
||||||
|
crypto_rc4(rdp->rc4_decrypt_key, length, data, data);
|
||||||
|
rdp->decrypt_use_count += 1;
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
@ -33,5 +33,9 @@ void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_ra
|
|||||||
void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* output);
|
void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* output);
|
||||||
|
|
||||||
void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uint32 length, uint8* output);
|
void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uint32 length, uint8* output);
|
||||||
|
boolean security_establish_keys(uint8* client_random, rdpSettings* settings);
|
||||||
|
|
||||||
|
boolean security_encrypt(uint8* data, int length, rdpRdp* rdp);
|
||||||
|
boolean security_decrypt(uint8* data, int length, rdpRdp* rdp);
|
||||||
|
|
||||||
#endif /* __SECURITY_H */
|
#endif /* __SECURITY_H */
|
||||||
|
@ -226,6 +226,8 @@ int transport_write(rdpTransport* transport, STREAM* s)
|
|||||||
length = stream_get_length(s);
|
length = stream_get_length(s);
|
||||||
stream_set_pos(s, 0);
|
stream_set_pos(s, 0);
|
||||||
|
|
||||||
|
printf("transport_write:\n");
|
||||||
|
|
||||||
#ifdef WITH_DEBUG_TRANSPORT
|
#ifdef WITH_DEBUG_TRANSPORT
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user