diff --git a/libfreerdp-core/certificate.c b/libfreerdp-core/certificate.c index ab2255cc0..5fd0b5995 100644 --- a/libfreerdp-core/certificate.c +++ b/libfreerdp-core/certificate.c @@ -261,8 +261,8 @@ void certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, { printf(", Terminal Server Certificate\n"); freerdp_hexdump(certificate->x509_cert_chain->array[i].data, certificate->x509_cert_chain->array[i].length); - certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &certificate->termserv_cert_info); - printf("modulus length:%d\n", certificate->termserv_cert_info.modulus.length); + certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &certificate->cert_info); + printf("modulus length:%d\n", certificate->cert_info.modulus.length); } else printf("\n"); diff --git a/libfreerdp-core/certificate.h b/libfreerdp-core/certificate.h index 0a8f9adab..f50497c40 100644 --- a/libfreerdp-core/certificate.h +++ b/libfreerdp-core/certificate.h @@ -58,7 +58,7 @@ typedef struct struct rdp_certificate { struct rdp_rdp* rdp; - CERT_INFO termserv_cert_info; + CERT_INFO cert_info; X509_CERT_CHAIN* x509_cert_chain; }; diff --git a/libfreerdp-core/crypto.c b/libfreerdp-core/crypto.c index 65455ec47..c26965760 100644 --- a/libfreerdp-core/crypto.c +++ b/libfreerdp-core/crypto.c @@ -127,6 +127,31 @@ exit: return status; } +void crypto_rsa(int length, uint8* in, uint8* out, uint32 modulus_length, uint8* modulus, uint8* exponent) +{ + BN_CTX* ctx; + int out_length; + BIGNUM mod, exp, x, y; + + ctx = BN_CTX_new(); + BN_init(&mod); + BN_init(&exp); + BN_init(&x); + BN_init(&y); + + BN_bin2bn(modulus, modulus_length, &mod); + BN_bin2bn(exponent, 4, &exp); + BN_bin2bn(in, length, &x); + BN_mod_exp(&y, &x, &exp, &mod, ctx); + out_length = BN_bn2bin(&y, out); + + BN_free(&y); + BN_clear_free(&x); + BN_free(&exp); + BN_free(&mod); + BN_CTX_free(ctx); +} + void crypto_nonce(uint8* nonce, int size) { RAND_bytes((void*) nonce, size); diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h index a972b5c3f..b0ba59324 100644 --- a/libfreerdp-core/crypto.h +++ b/libfreerdp-core/crypto.h @@ -80,6 +80,8 @@ void crypto_cert_free(CryptoCert cert); boolean crypto_cert_verify(CryptoCert server_cert, CryptoCert cacert); boolean crypto_cert_get_public_key(CryptoCert cert, BLOB* public_key); +void crypto_rsa(int length, uint8* in, uint8* out, uint32 modulus_length, uint8* modulus, uint8* exponent); + void crypto_nonce(uint8* nonce, int size); #endif /* __CRYPTO_H */ diff --git a/libfreerdp-core/license.c b/libfreerdp-core/license.c index 5d007fa29..cdba1a2fc 100644 --- a/libfreerdp-core/license.c +++ b/libfreerdp-core/license.c @@ -161,8 +161,17 @@ void license_generate_keys(rdpLicense* license) security_licensing_encryption_key(license->session_key_blob, license->client_random, license->server_random, license->licensing_encryption_key); /* LicensingEncryptionKey */ + /* EncryptedPremasterSecret */ + license->encrypted_pre_master_secret->length = 72; + license->encrypted_pre_master_secret->type = BB_ANY_BLOB; license->encrypted_pre_master_secret->data = (uint8*) xzalloc(72); + +#if 0 + crypto_rsa(PREMASTER_SECRET_LENGTH, license->premaster_secret, license->encrypted_pre_master_secret->data, + license->certificate->cert_info.modulus.length, license->certificate->cert_info.modulus.data, + license->certificate->cert_info.exponent); +#endif } /** @@ -408,6 +417,9 @@ void license_read_license_request_packet(rdpLicense* license, STREAM* s) /* Parse Server Certificate */ certificate_read_server_certificate(license->certificate, license->server_certificate->data, license->server_certificate->length); + + license_generate_keys(license); + license_generate_hwid(license); } /** @@ -419,14 +431,35 @@ void license_read_license_request_packet(rdpLicense* license, STREAM* s) void license_read_platform_challenge_packet(rdpLicense* license, STREAM* s) { + CryptoRc4 rc4; + uint8* platform_challenge; + DEBUG_LICENSE("Receiving Platform Challenge Packet"); stream_seek(s, 4); /* ConnectFlags, Reserved (4 bytes) */ /* EncryptedPlatformChallenge */ - + license_read_binary_blob(s, license->encrypted_platform_challenge); /* MACData (16 bytes) */ + stream_seek(s, 16); + + printf("encrypted platform challenge\n", license->encrypted_platform_challenge->length); + freerdp_hexdump(license->encrypted_platform_challenge->data, license->encrypted_platform_challenge->length); + + platform_challenge = (uint8*) xmalloc(license->encrypted_platform_challenge->length); + + rc4 = crypto_rc4_init(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH); + + crypto_rc4(rc4, license->encrypted_platform_challenge->length, + license->encrypted_platform_challenge->data, platform_challenge); + + printf("decrypted platform challenge\n", license->encrypted_platform_challenge->length); + freerdp_hexdump(platform_challenge, license->encrypted_platform_challenge->length); + + license->encrypted_platform_challenge->type = BB_ENCRYPTED_DATA_BLOB; + + crypto_rc4_free(rc4); } /** @@ -515,8 +548,6 @@ void license_send_new_license_request_packet(rdpLicense* license) license->client_machine_name->data = license->rdp->settings->hostname; license->client_machine_name->length = strlen(license->rdp->settings->hostname); - license_generate_keys(license); - license_write_new_license_request_packet(license, s); license_send(license, s, NEW_LICENSE_REQUEST); @@ -533,18 +564,19 @@ void license_send_new_license_request_packet(rdpLicense* license) * @msdn{cc241922} * @param license license module * @param s stream + * @param mac_data signature */ -void license_write_platform_challenge_response_packet(rdpLicense* license, STREAM* s) +void license_write_platform_challenge_response_packet(rdpLicense* license, STREAM* s, uint8* mac_data) { - license_generate_hwid(license); - /* EncryptedPlatformChallengeResponse */ - license_read_binary_blob(s, license->encrypted_platform_challenge); + license_write_binary_blob(s, license->encrypted_platform_challenge); /* EncryptedHWID */ + license_write_binary_blob(s, license->encrypted_hwid); /* MACData */ + stream_write(s, mac_data, 16); } /** @@ -556,11 +588,27 @@ void license_write_platform_challenge_response_packet(rdpLicense* license, STREA void license_send_platform_challenge_response_packet(rdpLicense* license) { STREAM* s; + int length; + uint8* buffer; + CryptoRc4 rc4; + uint8 mac_data[16]; s = license_send_stream_init(license); DEBUG_LICENSE("Sending Platform Challenge Response Packet"); - license_write_platform_challenge_response_packet(license, s); + length = license->encrypted_platform_challenge->length + license->encrypted_hwid->length; + buffer = (uint8*) xmalloc(length); + security_mac_data(license->mac_salt_key, buffer, length, mac_data); + xfree(buffer); + + buffer = (uint8*) xmalloc(HWID_LENGTH); + rc4 = crypto_rc4_init(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH); + crypto_rc4(rc4, HWID_LENGTH, license->hwid, buffer); + + license->encrypted_hwid->data = buffer; + license->encrypted_hwid->length = HWID_LENGTH; + + license_write_platform_challenge_response_packet(license, s, mac_data); license_send(license, s, PLATFORM_CHALLENGE_RESPONSE); } @@ -588,6 +636,7 @@ rdpLicense* license_new(rdpRdp* rdp) license->client_user_name = license_new_binary_blob(BB_CLIENT_USER_NAME_BLOB); license->client_machine_name = license_new_binary_blob(BB_CLIENT_MACHINE_NAME_BLOB); license->encrypted_platform_challenge = license_new_binary_blob(BB_ANY_BLOB); + license->encrypted_hwid = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB); license->scope_list = license_new_scope_list(); } @@ -611,6 +660,7 @@ void license_free(rdpLicense* license) license_free_binary_blob(license->client_user_name); license_free_binary_blob(license->client_machine_name); license_free_binary_blob(license->encrypted_platform_challenge); + license_free_binary_blob(license->encrypted_hwid); license_free_scope_list(license->scope_list); xfree(license); } diff --git a/libfreerdp-core/license.h b/libfreerdp-core/license.h index 16f438f14..d41fd6ef3 100644 --- a/libfreerdp-core/license.h +++ b/libfreerdp-core/license.h @@ -121,6 +121,7 @@ struct rdp_license LICENSE_BLOB* client_machine_name; LICENSE_BLOB* encrypted_pre_master_secret; LICENSE_BLOB* encrypted_platform_challenge; + LICENSE_BLOB* encrypted_hwid; SCOPE_LIST* scope_list; }; @@ -153,7 +154,7 @@ void license_read_error_alert_packet(rdpLicense* license, STREAM* s); void license_write_new_license_request_packet(rdpLicense* license, STREAM* s); void license_send_new_license_request_packet(rdpLicense* license); -void license_write_platform_challenge_response_packet(rdpLicense* license, STREAM* s); +void license_write_platform_challenge_response_packet(rdpLicense* license, STREAM* s, uint8* mac_data); void license_send_platform_challenge_response_packet(rdpLicense* license); rdpLicense* license_new(rdpRdp* rdp); diff --git a/libfreerdp-core/security.c b/libfreerdp-core/security.c index 4d13bcc93..4a1360c26 100644 --- a/libfreerdp-core/security.c +++ b/libfreerdp-core/security.c @@ -19,6 +19,27 @@ #include "security.h" +/* 0x36 repeated 40 times */ +static uint8 pad1[40] = +{ + "\x36\x36\x36\x36\x36\x36\x36\x36" + "\x36\x36\x36\x36\x36\x36\x36\x36" + "\x36\x36\x36\x36\x36\x36\x36\x36" + "\x36\x36\x36\x36\x36\x36\x36\x36" + "\x36\x36\x36\x36\x36\x36\x36\x36" +}; + +/* 0x5C repeated 48 times */ +static uint8 pad2[48] = +{ + "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" + "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" + "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" + "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" + "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" + "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" +}; + void security_salted_hash(uint8* salt, uint8* input, int length, uint8* client_random, uint8* server_random, uint8* output) { CryptoMd5 md5; @@ -89,3 +110,38 @@ void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_ra crypto_md5_final(md5, output); } +void security_uint32_le(uint8* output, uint32 value) +{ + output[0] = (value) & 0xFF; + output[1] = (value >> 8) & 0xFF; + output[2] = (value >> 16) & 0xFF; + output[3] = (value >> 24) & 0xFF; +} + +void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* output) +{ + CryptoMd5 md5; + CryptoSha1 sha1; + uint8 length_le[4]; + uint8 sha1_digest[20]; + + /* MacData = MD5(MacSaltKey + pad2 + SHA1(MacSaltKey + pad1 + length + data)) */ + + security_uint32_le(length_le, length); /* length must be little-endian */ + + /* SHA1_Digest = SHA1(MacSaltKey + pad1 + length + data) */ + sha1 = crypto_sha1_init(); + crypto_sha1_update(sha1, mac_salt_key, 16); /* MacSaltKey */ + 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_final(sha1, sha1_digest); + + /* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */ + 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_final(md5, output); +} + diff --git a/libfreerdp-core/security.h b/libfreerdp-core/security.h index 6ec922c18..130b255ea 100644 --- a/libfreerdp-core/security.h +++ b/libfreerdp-core/security.h @@ -33,5 +33,6 @@ void security_master_hash(uint8* input, int length, uint8* master_secret, uint8* void security_session_key_blob(uint8* master_secret, 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); 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); #endif /* __SECURITY_H */