diff --git a/CMakeLists.txt b/CMakeLists.txt index a051c1424..6899c34af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,8 +163,16 @@ if(NOT WIN32) add_subdirectory(channels) endif() -add_subdirectory(client) -add_subdirectory(server) +option(WITH_CLIENT "Build client binaries" ON) +if(WITH_CLIENT) + add_subdirectory(client) +endif() + +option(WITH_SERVER "Build server binaries" OFF) +if(WITH_SERVER) + add_subdirectory(server) +endif() + add_subdirectory(keymaps) # Source package diff --git a/cmake/FindX11.cmake b/cmake/FindX11.cmake index 91f153339..594b2c022 100644 --- a/cmake/FindX11.cmake +++ b/cmake/FindX11.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(X11_INCLUDE_DIR NAMES Xlib.h +find_path(X11_INCLUDE_DIR NAMES X11/Xlib.h PATH_SUFFIXES X11 DOC "The X11 include directory" ) diff --git a/cmake/FindXKBFile.cmake b/cmake/FindXKBFile.cmake index db76ed6e4..4c0a33374 100644 --- a/cmake/FindXKBFile.cmake +++ b/cmake/FindXKBFile.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XKBFILE_INCLUDE_DIR NAMES XKBfile.h +find_path(XKBFILE_INCLUDE_DIR NAMES X11/extensions/XKBfile.h PATH_SUFFIXES X11/extensions DOC "The XKBFile include directory" ) diff --git a/cmake/FindXShm.cmake b/cmake/FindXShm.cmake index 4ac509168..8213f25e8 100644 --- a/cmake/FindXShm.cmake +++ b/cmake/FindXShm.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XSHM_INCLUDE_DIR NAMES XShm.h +find_path(XSHM_INCLUDE_DIR NAMES X11/extensions/XShm.h PATH_SUFFIXES X11/extensions DOC "The XShm include directory" ) diff --git a/cmake/FindXTest.cmake b/cmake/FindXTest.cmake index ea00dcff8..85fe7b8c8 100644 --- a/cmake/FindXTest.cmake +++ b/cmake/FindXTest.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XTEST_INCLUDE_DIR NAMES XTest.h +find_path(XTEST_INCLUDE_DIR NAMES X11/extensions/XTest.h PATH_SUFFIXES X11/extensions DOC "The XTest include directory" ) diff --git a/cmake/FindXcursor.cmake b/cmake/FindXcursor.cmake index 6217d597e..4eead70bb 100644 --- a/cmake/FindXcursor.cmake +++ b/cmake/FindXcursor.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XCURSOR_INCLUDE_DIR NAMES Xcursor.h +find_path(XCURSOR_INCLUDE_DIR NAMES X11/Xcursor/Xcursor.h PATH_SUFFIXES X11/Xcursor DOC "The Xcursor include directory" ) diff --git a/cmake/FindXdamage.cmake b/cmake/FindXdamage.cmake index 79ea6df9a..61d41587f 100644 --- a/cmake/FindXdamage.cmake +++ b/cmake/FindXdamage.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XDAMAGE_INCLUDE_DIR NAMES Xdamage.h +find_path(XDAMAGE_INCLUDE_DIR NAMES X11/extensions/Xdamage.h PATH_SUFFIXES X11/extensions DOC "The Xdamage include directory" ) diff --git a/cmake/FindXext.cmake b/cmake/FindXext.cmake index 8fd8372c6..8429ec645 100644 --- a/cmake/FindXext.cmake +++ b/cmake/FindXext.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XEXT_INCLUDE_DIR NAMES Xext.h +find_path(XEXT_INCLUDE_DIR NAMES X11/extensions/Xext.h PATH_SUFFIXES X11/extensions DOC "The Xext include directory" ) diff --git a/cmake/FindXfixes.cmake b/cmake/FindXfixes.cmake index f826cf056..c3875766e 100644 --- a/cmake/FindXfixes.cmake +++ b/cmake/FindXfixes.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XFIXES_INCLUDE_DIR NAMES Xfixes.h +find_path(XFIXES_INCLUDE_DIR NAMES X11/extensions/Xfixes.h PATH_SUFFIXES X11/extensions DOC "The Xfixes include directory" ) diff --git a/cmake/FindXinerama.cmake b/cmake/FindXinerama.cmake index c39fb96b4..3f786133b 100644 --- a/cmake/FindXinerama.cmake +++ b/cmake/FindXinerama.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XINERAMA_INCLUDE_DIR NAMES Xinerama.h +find_path(XINERAMA_INCLUDE_DIR NAMES X11/extensions/Xinerama.h PATH_SUFFIXES X11/extensions DOC "The Xinerama include directory" ) diff --git a/cmake/FindXv.cmake b/cmake/FindXv.cmake index 0a4c4e294..e8887d730 100644 --- a/cmake/FindXv.cmake +++ b/cmake/FindXv.cmake @@ -28,7 +28,7 @@ # limitations under the License. #============================================================================= -find_path(XV_INCLUDE_DIR NAMES Xv.h +find_path(XV_INCLUDE_DIR NAMES X11/extensions/Xv.h PATH_SUFFIXES X11/extensions DOC "The Xv include directory" ) diff --git a/libfreerdp-core/certificate.c b/libfreerdp-core/certificate.c index 850e7e06b..0d6b3abb0 100644 --- a/libfreerdp-core/certificate.c +++ b/libfreerdp-core/certificate.c @@ -256,9 +256,48 @@ static boolean certificate_process_server_public_key(rdpCertificate* certificate return true; } -static boolean certificate_process_server_public_signature(rdpCertificate* certificate, STREAM* s, uint32 length) +static boolean certificate_process_server_public_signature(rdpCertificate* certificate, uint8* sigdata, int sigdatalen, STREAM* s, uint32 siglen) { - stream_seek(s, length); + uint8 md5hash[CRYPTO_MD5_DIGEST_LENGTH]; + uint8 encsig[TSSK_KEY_LENGTH + 8]; + uint8 sig[TSSK_KEY_LENGTH]; + CryptoMd5 md5ctx; + int i, sum; + + md5ctx = crypto_md5_init(); + crypto_md5_update(md5ctx, sigdata, sigdatalen); + crypto_md5_final(md5ctx, md5hash); + + stream_read(s, encsig, siglen); + /* Last 8 bytes shall be all zero. */ + for (sum = 0, i = sizeof(encsig) - 8; i < sizeof(encsig); i++) + sum += encsig[i]; + if (sum != 0) { + printf("certificate_process_server_public_signature: invalid signature\n"); + //return false; + } + siglen -= 8; + + crypto_rsa_public_decrypt(encsig, siglen, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig); + + /* Verify signature. */ + if (memcmp(md5hash, sig, sizeof(md5hash)) != 0) { + printf("certificate_process_server_public_signature: invalid signature\n"); + //return false; + } + /* + * Verify rest of decrypted data: + * The 17th byte is 0x00. + * The 18th through 62nd bytes are each 0xFF. + * The 63rd byte is 0x01. + */ + for (sum = 0, i = 17; i < 62; i++) + sum += sig[i]; + if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01) { + printf("certificate_process_server_public_signature: invalid signature\n"); + //return false; + } + return true; } @@ -276,10 +315,14 @@ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certific uint32 wPublicKeyBlobLen; uint32 wSignatureBlobType; uint32 wSignatureBlobLen; + uint8* sigdata; + int sigdatalen; + /* -4, because we need to include dwVersion */ + sigdata = stream_get_tail(s) - 4; stream_read_uint32(s, dwSigAlgId); stream_read_uint32(s, dwKeyAlgId); - if (!(dwSigAlgId == 1 && dwKeyAlgId == 1)) + if (!(dwSigAlgId == SIGNATURE_ALG_RSA && dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)) { printf("certificate_read_server_proprietary_certificate: parse error 1\n"); return false; @@ -296,6 +339,7 @@ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certific printf("certificate_read_server_proprietary_certificate: parse error 3\n"); return false; } + sigdatalen = stream_get_tail(s) - sigdata; stream_read_uint16(s, wSignatureBlobType); if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB) { @@ -303,7 +347,11 @@ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certific return false; } stream_read_uint16(s, wSignatureBlobLen); - if (!certificate_process_server_public_signature(certificate, s, wSignatureBlobLen)) + if (wSignatureBlobLen != 72) { + printf("certificate_process_server_public_signature: invalid signature length (got %d, expected %d)\n", wSignatureBlobLen, 64); + return false; + } + if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s, wSignatureBlobLen)) { printf("certificate_read_server_proprietary_certificate: parse error 5\n"); return false; diff --git a/libfreerdp-core/certificate.h b/libfreerdp-core/certificate.h index b3006e0cc..82962663e 100644 --- a/libfreerdp-core/certificate.h +++ b/libfreerdp-core/certificate.h @@ -36,6 +36,9 @@ #define CERT_PERMANENTLY_ISSUED 0x00000000 #define CERT_TEMPORARILY_ISSUED 0x80000000 +#define SIGNATURE_ALG_RSA 0x00000001 +#define KEY_EXCHANGE_ALG_RSA 0x00000001 + #define BB_RSA_KEY_BLOB 6 #define BB_RSA_SIGNATURE_BLOB 8 diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 3aa60e5ae..3d4634e2b 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -203,7 +203,7 @@ static boolean rdp_establish_keys(rdpRdp* rdp) key_len = rdp->settings->server_cert->cert_info.modulus.length; mod = rdp->settings->server_cert->cert_info.modulus.data; exp = rdp->settings->server_cert->cert_info.exponent; - crypto_rsa_encrypt(client_random, 32, key_len, mod, exp, crypt_client_random); + crypto_rsa_public_encrypt(client_random, 32, key_len, mod, exp, crypt_client_random); /* send crypt client random to server */ length = 7 + 8 + 4 + 4 + key_len + 8; @@ -480,7 +480,7 @@ boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s) ret = transport_accept_nla(rdp->transport); else if (rdp->nego->selected_protocol & PROTOCOL_TLS) ret = transport_accept_tls(rdp->transport); - else if (rdp->nego->selected_protocol & PROTOCOL_RDP) + else if (rdp->nego->selected_protocol == PROTOCOL_RDP) /* 0 */ ret = transport_accept_rdp(rdp->transport); if (!ret) diff --git a/libfreerdp-core/crypto.c b/libfreerdp-core/crypto.c index 046fa9562..426481c92 100644 --- a/libfreerdp-core/crypto.c +++ b/libfreerdp-core/crypto.c @@ -188,7 +188,35 @@ exit: return status; } -void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) +/* + * Terminal Services Signing Keys. + * Yes, Terminal Services Private Key is publically available. + */ +const uint8 tssk_modulus[] = { + 0x3d, 0x3a, 0x5e, 0xbd, 0x72, 0x43, 0x3e, 0xc9, + 0x4d, 0xbb, 0xc1, 0x1e, 0x4a, 0xba, 0x5f, 0xcb, + 0x3e, 0x88, 0x20, 0x87, 0xef, 0xf5, 0xc1, 0xe2, + 0xd7, 0xb7, 0x6b, 0x9a, 0xf2, 0x52, 0x45, 0x95, + 0xce, 0x63, 0x65, 0x6b, 0x58, 0x3a, 0xfe, 0xef, + 0x7c, 0xe7, 0xbf, 0xfe, 0x3d, 0xf6, 0x5c, 0x7d, + 0x6c, 0x5e, 0x06, 0x09, 0x1a, 0xf5, 0x61, 0xbb, + 0x20, 0x93, 0x09, 0x5f, 0x05, 0x6d, 0xea, 0x87 +}; +const uint8 tssk_privateExponent[] = { + 0x87, 0xa7, 0x19, 0x32, 0xda, 0x11, 0x87, 0x55, + 0x58, 0x00, 0x16, 0x16, 0x25, 0x65, 0x68, 0xf8, + 0x24, 0x3e, 0xe6, 0xfa, 0xe9, 0x67, 0x49, 0x94, + 0xcf, 0x92, 0xcc, 0x33, 0x99, 0xe8, 0x08, 0x60, + 0x17, 0x9a, 0x12, 0x9f, 0x24, 0xdd, 0xb1, 0x24, + 0x99, 0xc7, 0x3a, 0xb8, 0x0a, 0x7b, 0x0d, 0xdd, + 0x35, 0x07, 0x79, 0x17, 0x0b, 0x51, 0x9b, 0xb3, + 0xc7, 0x10, 0x01, 0x13, 0xe7, 0x3f, 0xf3, 0x5f +}; +const uint8 tssk_exponent[] = { + 0x5b, 0x7b, 0x88, 0xc0 +}; + +static void crypto_rsa_common(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, int exponent_size, uint8* output) { BN_CTX* ctx; int output_length; @@ -197,14 +225,14 @@ void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* exponent_reverse; BIGNUM mod, exp, x, y; - input_reverse = (uint8*) xmalloc(2 * MODULUS_MAX_SIZE + EXPONENT_MAX_SIZE); - modulus_reverse = input_reverse + MODULUS_MAX_SIZE; - exponent_reverse = modulus_reverse + MODULUS_MAX_SIZE; + input_reverse = (uint8*) xmalloc(2 * key_length + exponent_size); + modulus_reverse = input_reverse + key_length; + exponent_reverse = modulus_reverse + key_length; memcpy(modulus_reverse, modulus, key_length); crypto_reverse(modulus_reverse, key_length); - memcpy(exponent_reverse, exponent, EXPONENT_MAX_SIZE); - crypto_reverse(exponent_reverse, EXPONENT_MAX_SIZE); + memcpy(exponent_reverse, exponent, exponent_size); + crypto_reverse(exponent_reverse, exponent_size); memcpy(input_reverse, input, length); crypto_reverse(input_reverse, length); @@ -215,7 +243,7 @@ void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const BN_init(&y); BN_bin2bn(modulus_reverse, key_length, &mod); - BN_bin2bn(exponent_reverse, EXPONENT_MAX_SIZE, &exp); + BN_bin2bn(exponent_reverse, exponent_size, &exp); BN_bin2bn(input_reverse, length, &x); BN_mod_exp(&y, &x, &exp, &mod, ctx); @@ -233,6 +261,48 @@ void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const xfree(input_reverse); } +static void crypto_rsa_public(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) +{ + + crypto_rsa_common(input, length, key_length, modulus, exponent, EXPONENT_MAX_SIZE, output); +} + +static void crypto_rsa_private(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) +{ + + crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); +} + +void crypto_rsa_public_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) +{ + + crypto_rsa_public(input, length, key_length, modulus, exponent, output); +} + +void crypto_rsa_public_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) +{ + + crypto_rsa_public(input, length, key_length, modulus, exponent, output); +} + +void crypto_rsa_private_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) +{ + + crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); +} + +void crypto_rsa_private_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) +{ + + crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); +} + +void crypto_rsa_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output) +{ + + crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, output); +} + void crypto_reverse(uint8* data, int length) { int i, j; diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h index 47322d5e6..6b4d30b74 100644 --- a/libfreerdp-core/crypto.h +++ b/libfreerdp-core/crypto.h @@ -78,11 +78,13 @@ struct crypto_cert_struct X509 * px509; }; +#define CRYPTO_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH typedef struct crypto_sha1_struct* CryptoSha1; CryptoSha1 crypto_sha1_init(void); void crypto_sha1_update(CryptoSha1 sha1, const uint8* data, uint32 length); void crypto_sha1_final(CryptoSha1 sha1, uint8* out_data); +#define CRYPTO_MD5_DIGEST_LENGTH MD5_DIGEST_LENGTH typedef struct crypto_md5_struct* CryptoMd5; CryptoMd5 crypto_md5_init(void); void crypto_md5_update(CryptoMd5 md5, const uint8* data, uint32 length); @@ -118,7 +120,15 @@ boolean x509_verify_cert(CryptoCert cert, rdpSettings* settings); rdpCertData* crypto_get_cert_data(X509* xcert, char* hostname); boolean crypto_cert_get_public_key(CryptoCert cert, rdpBlob* public_key); -void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); +#define TSSK_KEY_LENGTH 64 +extern const uint8 tssk_modulus[]; +extern const uint8 tssk_privateExponent[]; +extern const uint8 tssk_exponent[]; + +void crypto_rsa_public_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); +void crypto_rsa_public_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); +void crypto_rsa_private_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output); +void crypto_rsa_private_decrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* private_exponent, uint8* output); void crypto_reverse(uint8* data, int length); void crypto_nonce(uint8* nonce, int size); diff --git a/libfreerdp-core/license.c b/libfreerdp-core/license.c index 690dafdc5..016b0225f 100644 --- a/libfreerdp-core/license.c +++ b/libfreerdp-core/license.c @@ -329,7 +329,7 @@ void license_encrypt_premaster_secret(rdpLicense* license) encrypted_premaster_secret = (uint8*) xmalloc(MODULUS_MAX_SIZE); memset(encrypted_premaster_secret, 0, MODULUS_MAX_SIZE); - crypto_rsa_encrypt(license->premaster_secret, PREMASTER_SECRET_LENGTH, + crypto_rsa_public_encrypt(license->premaster_secret, PREMASTER_SECRET_LENGTH, key_length, modulus, exponent, encrypted_premaster_secret); license->encrypted_premaster_secret->type = BB_RANDOM_BLOB; diff --git a/libfreerdp-core/mcs.c b/libfreerdp-core/mcs.c index af5f15b72..b2524c6c1 100644 --- a/libfreerdp-core/mcs.c +++ b/libfreerdp-core/mcs.c @@ -273,26 +273,22 @@ boolean mcs_read_domain_parameters(STREAM* s, DomainParameters* domainParameters void mcs_write_domain_parameters(STREAM* s, DomainParameters* domainParameters) { int length; - uint8 *bm, *em; + STREAM* tmps; - stream_get_mark(s, bm); - stream_seek(s, 2); - - ber_write_integer(s, domainParameters->maxChannelIds); - ber_write_integer(s, domainParameters->maxUserIds); - ber_write_integer(s, domainParameters->maxTokenIds); - ber_write_integer(s, domainParameters->numPriorities); - ber_write_integer(s, domainParameters->minThroughput); - ber_write_integer(s, domainParameters->maxHeight); - ber_write_integer(s, domainParameters->maxMCSPDUsize); - ber_write_integer(s, domainParameters->protocolVersion); - - stream_get_mark(s, em); - length = (em - bm) - 2; - stream_set_mark(s, bm); + tmps = stream_new(stream_get_size(s)); + ber_write_integer(tmps, domainParameters->maxChannelIds); + ber_write_integer(tmps, domainParameters->maxUserIds); + ber_write_integer(tmps, domainParameters->maxTokenIds); + ber_write_integer(tmps, domainParameters->numPriorities); + ber_write_integer(tmps, domainParameters->minThroughput); + ber_write_integer(tmps, domainParameters->maxHeight); + ber_write_integer(tmps, domainParameters->maxMCSPDUsize); + ber_write_integer(tmps, domainParameters->protocolVersion); + length = stream_get_length(tmps); ber_write_sequence_tag(s, length); - stream_set_mark(s, em); + stream_write(s, stream_get_head(tmps), length); + stream_free(tmps); } /** @@ -377,41 +373,36 @@ boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s) void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data) { int length; - uint8 *bm, *em; + STREAM* tmps; - int gcc_CCrq_length = stream_get_length(user_data); - - stream_get_mark(s, bm); - stream_seek(s, 5); + tmps = stream_new(stream_get_size(s)); /* callingDomainSelector (OCTET_STRING) */ - ber_write_octet_string(s, callingDomainSelector, sizeof(callingDomainSelector)); + ber_write_octet_string(tmps, callingDomainSelector, sizeof(callingDomainSelector)); /* calledDomainSelector (OCTET_STRING) */ - ber_write_octet_string(s, calledDomainSelector, sizeof(calledDomainSelector)); + ber_write_octet_string(tmps, calledDomainSelector, sizeof(calledDomainSelector)); /* upwardFlag (BOOLEAN) */ - ber_write_boolean(s, true); + ber_write_boolean(tmps, true); /* targetParameters (DomainParameters) */ - mcs_write_domain_parameters(s, &mcs->targetParameters); + mcs_write_domain_parameters(tmps, &mcs->targetParameters); /* minimumParameters (DomainParameters) */ - mcs_write_domain_parameters(s, &mcs->minimumParameters); + mcs_write_domain_parameters(tmps, &mcs->minimumParameters); /* maximumParameters (DomainParameters) */ - mcs_write_domain_parameters(s, &mcs->maximumParameters); + mcs_write_domain_parameters(tmps, &mcs->maximumParameters); /* userData (OCTET_STRING) */ - ber_write_octet_string(s, user_data->data, gcc_CCrq_length); - - stream_get_mark(s, em); - length = (em - bm) - 5; - stream_set_mark(s, bm); + ber_write_octet_string(tmps, user_data->data, stream_get_length(user_data)); + length = stream_get_length(tmps); /* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */ ber_write_application_tag(s, MCS_TYPE_CONNECT_INITIAL, length); - stream_set_mark(s, em); + stream_write(s, stream_get_head(tmps), length); + stream_free(tmps); } /** @@ -425,28 +416,20 @@ void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data) void mcs_write_connect_response(STREAM* s, rdpMcs* mcs, STREAM* user_data) { int length; - uint8 *bm, *em; - - int gcc_CCrsp_length = stream_get_length(user_data); - - stream_get_mark(s, bm); - stream_seek(s, 3); - - ber_write_enumerated(s, 0, MCS_Result_enum_length); - ber_write_integer(s, 0); /* calledConnectId */ + STREAM* tmps; + tmps = stream_new(stream_get_size(s)); + ber_write_enumerated(tmps, 0, MCS_Result_enum_length); + ber_write_integer(tmps, 0); /* calledConnectId */ mcs->domainParameters = mcs->targetParameters; - mcs_write_domain_parameters(s, &(mcs->domainParameters)); - + mcs_write_domain_parameters(tmps, &(mcs->domainParameters)); /* userData (OCTET_STRING) */ - ber_write_octet_string(s, user_data->data, gcc_CCrsp_length); - - stream_get_mark(s, em); - length = (em - bm) - 3; - stream_set_mark(s, bm); + ber_write_octet_string(tmps, user_data->data, stream_get_length(user_data)); + length = stream_get_length(tmps); ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length); - stream_set_mark(s, em); + stream_write(s, stream_get_head(tmps), length); + stream_free(tmps); } /** diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index 723f15c53..83a87b539 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -274,8 +274,6 @@ void rdp_write_header(rdpRdp* rdp, STREAM* s, uint16 length, uint16 channel_id) static uint32 rdp_security_stream_out(rdpRdp* rdp, STREAM* s, int length) { - uint32 ml; - uint8* mk; uint8* data; uint32 sec_flags; uint32 pad = 0; @@ -314,10 +312,7 @@ static uint32 rdp_security_stream_out(rdpRdp* rdp, STREAM* s, int length) { data = s->p + 8; length = length - (data - s->data); - - mk = rdp->sign_key; - ml = rdp->rc4_key_len; - security_mac_signature(mk, ml, data, length, s->p); + security_mac_signature(rdp, data, length, s->p); stream_seek(s, 8); security_encrypt(s->p, length, rdp); } @@ -583,8 +578,6 @@ boolean rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, STREAM* s) boolean rdp_decrypt(rdpRdp* rdp, STREAM* s, int length) { uint8 cmac[8], wmac[8]; - uint32 ml; - uint8* mk; if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS) { @@ -621,9 +614,7 @@ boolean rdp_decrypt(rdpRdp* rdp, STREAM* s, int length) stream_read(s, wmac, sizeof(wmac)); length -= sizeof(wmac); security_decrypt(s->p, length, rdp); - mk = rdp->sign_key; - ml = rdp->rc4_key_len; - security_mac_signature(mk, ml, s->p, length, cmac); + security_mac_signature(rdp, s->p, length, cmac); if (memcmp(wmac, cmac, sizeof(wmac)) != 0) { printf("FATAL: invalid packet signature\n"); return false; diff --git a/libfreerdp-core/security.c b/libfreerdp-core/security.c index 0b17d7dc2..e003b213b 100644 --- a/libfreerdp-core/security.c +++ b/libfreerdp-core/security.c @@ -118,7 +118,7 @@ static void security_salted_hash(uint8* salt, uint8* input, int length, uint8* s { CryptoMd5 md5; CryptoSha1 sha1; - uint8 sha1_digest[20]; + uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1(Input + Salt + Salt1 + Salt2)) */ @@ -133,7 +133,7 @@ static void security_salted_hash(uint8* salt, uint8* input, int length, uint8* s /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */ md5 = crypto_md5_init(); crypto_md5_update(md5, salt, 48); /* Salt (48 bytes) */ - crypto_md5_update(md5, sha1_digest, 20); /* SHA1_Digest */ + crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, output); } @@ -201,7 +201,7 @@ void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* o CryptoMd5 md5; CryptoSha1 sha1; uint8 length_le[4]; - uint8 sha1_digest[20]; + uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; /* MacData = MD5(MacSaltKey + pad2 + SHA1(MacSaltKey + pad1 + length + data)) */ @@ -219,23 +219,23 @@ void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* o md5 = crypto_md5_init(); crypto_md5_update(md5, mac_salt_key, 16); /* MacSaltKey */ crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ - crypto_md5_update(md5, sha1_digest, 20); /* SHA1_Digest */ + crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, output); } -void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uint32 length, uint8* output) +void security_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, uint8* output) { CryptoMd5 md5; CryptoSha1 sha1; uint8 length_le[4]; - uint8 md5_digest[16]; - uint8 sha1_digest[20]; + uint8 md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; + uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; security_uint32_le(length_le, length); /* length must be little-endian */ /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ sha1 = crypto_sha1_init(); - crypto_sha1_update(sha1, mac_key, mac_key_length); /* MacKeyN */ + crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ crypto_sha1_update(sha1, data, length); /* data */ @@ -243,9 +243,43 @@ void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uin /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ md5 = crypto_md5_init(); - crypto_md5_update(md5, mac_key, mac_key_length); /* MacKeyN */ + crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ - crypto_md5_update(md5, sha1_digest, 20); /* SHA1_Digest */ + crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ + crypto_md5_final(md5, md5_digest); + + memcpy(output, md5_digest, 8); +} + +void security_salted_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, boolean encryption, uint8* output) +{ + CryptoMd5 md5; + CryptoSha1 sha1; + uint8 length_le[4]; + uint8 use_count_le[4]; + uint8 md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; + uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; + + security_uint32_le(length_le, length); /* length must be little-endian */ + if (encryption) + security_uint32_le(use_count_le, rdp->encrypt_use_count); + else + security_uint32_le(use_count_le, rdp->decrypt_use_count); + + /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ + sha1 = crypto_sha1_init(); + crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ + crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ + crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ + crypto_sha1_update(sha1, data, length); /* data */ + crypto_sha1_update(sha1, use_count_le, sizeof(use_count_le)); /* encryptionCount */ + crypto_sha1_final(sha1, sha1_digest); + + /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ + md5 = crypto_md5_init(); + crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ + crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ + crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ crypto_md5_final(md5, md5_digest); memcpy(output, md5_digest, 8); @@ -313,7 +347,8 @@ boolean security_establish_keys(uint8* client_random, rdpRdp* rdp) if (settings->encryption_method == ENCRYPTION_METHOD_FIPS) { CryptoSha1 sha1; - uint8 client_encrypt_key_t[21], client_decrypt_key_t[21]; + uint8 client_encrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1]; + uint8 client_decrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1]; printf("FIPS Compliant encryption level.\n"); @@ -379,7 +414,7 @@ boolean security_establish_keys(uint8* client_random, rdpRdp* rdp) boolean security_key_update(uint8* key, uint8* update_key, int key_len) { - uint8 sha1h[20]; + uint8 sha1h[CRYPTO_SHA1_DIGEST_LENGTH]; CryptoMd5 md5; CryptoSha1 sha1; CryptoRc4 rc4; @@ -394,7 +429,7 @@ boolean security_key_update(uint8* key, uint8* update_key, int key_len) 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_update(md5, sha1h, sizeof(sha1h)); crypto_md5_final(md5, key); rc4 = crypto_rc4_init(key, key_len); diff --git a/libfreerdp-core/security.h b/libfreerdp-core/security.h index 6d4b0f5d4..7f338d3fa 100644 --- a/libfreerdp-core/security.h +++ b/libfreerdp-core/security.h @@ -32,7 +32,8 @@ void security_mac_salt_key(uint8* session_key_blob, uint8* client_random, uint8* void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, 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(rdpRdp *rdp, uint8* data, uint32 length, uint8* output); +void security_salted_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, boolean encryption, uint8* output); boolean security_establish_keys(uint8* client_random, rdpRdp* rdp); boolean security_encrypt(uint8* data, int length, rdpRdp* rdp);