From af5501cdc561a4a5aba98ac02bcdc964f25c8544 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 04:33:38 +0100 Subject: [PATCH 1/7] Introduce CRYPTO_SHA1_DIGEST_LENGTH and CRYPTO_MD5_DIGEST_LENGTH that hold number of bytes needed for a given hash. --- libfreerdp-core/crypto.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h index 47322d5e6..f4eab4130 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); From 3bbd2f28c725b252b75d4b7c5b0d0782dd2b9311 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 04:34:48 +0100 Subject: [PATCH 2/7] Use CRYPTO_*_DIGEST_LENGTH defines instead of magic values. --- libfreerdp-core/security.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libfreerdp-core/security.c b/libfreerdp-core/security.c index 0b17d7dc2..223173281 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,7 +219,7 @@ 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); } @@ -228,8 +228,8 @@ void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uin 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 */ @@ -245,7 +245,7 @@ void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uin md5 = crypto_md5_init(); crypto_md5_update(md5, mac_key, mac_key_length); /* 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); @@ -313,7 +313,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 +380,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 +395,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); From a118afa8791bd9acdc502737342121a0b6ecd465 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 04:39:31 +0100 Subject: [PATCH 3/7] Add Terminal Services Signing Keys. --- libfreerdp-core/crypto.c | 28 ++++++++++++++++++++++++++++ libfreerdp-core/crypto.h | 5 +++++ 2 files changed, 33 insertions(+) diff --git a/libfreerdp-core/crypto.c b/libfreerdp-core/crypto.c index 046fa9562..e9a5f63b5 100644 --- a/libfreerdp-core/crypto.c +++ b/libfreerdp-core/crypto.c @@ -188,6 +188,34 @@ exit: return status; } +/* + * 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 +}; + void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) { BN_CTX* ctx; diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h index f4eab4130..74d48f775 100644 --- a/libfreerdp-core/crypto.h +++ b/libfreerdp-core/crypto.h @@ -120,6 +120,11 @@ 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); +#define TSSK_KEY_LENGTH 64 +extern const uint8 tssk_modulus[]; +extern const uint8 tssk_privateExponent[]; +extern const uint8 tssk_exponent[]; + void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); void crypto_reverse(uint8* data, int length); void crypto_nonce(uint8* nonce, int size); From 44663ab332dd4b49205844dcd4ad17bae11f71e1 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 04:40:29 +0100 Subject: [PATCH 4/7] Introduce more complete RSA API that implements: - crypto_rsa_public_encrypt() - crypto_rsa_public_decrypt() - crypto_rsa_private_encrypt() - crypto_rsa_private_decrypt() --- libfreerdp-core/connection.c | 2 +- libfreerdp-core/crypto.c | 56 +++++++++++++++++++++++++++++++----- libfreerdp-core/crypto.h | 5 +++- libfreerdp-core/license.c | 2 +- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index e32c4f8a6..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; diff --git a/libfreerdp-core/crypto.c b/libfreerdp-core/crypto.c index e9a5f63b5..da0f1f310 100644 --- a/libfreerdp-core/crypto.c +++ b/libfreerdp-core/crypto.c @@ -216,7 +216,7 @@ const uint8 tssk_exponent[] = { 0x5b, 0x7b, 0x88, 0xc0 }; -void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) +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; @@ -225,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); @@ -243,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); @@ -261,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 74d48f775..6b4d30b74 100644 --- a/libfreerdp-core/crypto.h +++ b/libfreerdp-core/crypto.h @@ -125,7 +125,10 @@ extern const uint8 tssk_modulus[]; extern const uint8 tssk_privateExponent[]; extern const uint8 tssk_exponent[]; -void crypto_rsa_encrypt(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output); +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; From ab4beb787f38f2b8d00e2576833215c3e4fd87dd Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 04:42:19 +0100 Subject: [PATCH 5/7] Implement signature verification in Server Security Data packet. Because this signature doesn't protect against anything, only warn the user if it is invalid. --- libfreerdp-core/certificate.c | 54 +++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/libfreerdp-core/certificate.c b/libfreerdp-core/certificate.c index fcea2611b..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,7 +315,11 @@ 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 == SIGNATURE_ALG_RSA && dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)) @@ -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; From 8238f2369dd62da7c10ca4cbdaeb136468810033 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 05:07:30 +0100 Subject: [PATCH 6/7] - Simplify security_mac_signature() API. - Introduce implementation of security_salted_mac_signature() that would be used to handle packets with SEC_SECURE_CHECKSUM flag. --- libfreerdp-core/rdp.c | 13 ++----------- libfreerdp-core/security.c | 40 +++++++++++++++++++++++++++++++++++--- libfreerdp-core/security.h | 3 ++- 3 files changed, 41 insertions(+), 15 deletions(-) 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 223173281..e003b213b 100644 --- a/libfreerdp-core/security.c +++ b/libfreerdp-core/security.c @@ -223,7 +223,7 @@ void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* o 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; @@ -235,7 +235,7 @@ void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uin /* 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,7 +243,41 @@ 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, 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); 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); From 164c8a0a67a514abd9626970516dbe77315079b3 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 19 Jan 2012 05:36:23 +0100 Subject: [PATCH 7/7] Whitespace fixes. --- libfreerdp-core/crypto.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libfreerdp-core/crypto.c b/libfreerdp-core/crypto.c index da0f1f310..426481c92 100644 --- a/libfreerdp-core/crypto.c +++ b/libfreerdp-core/crypto.c @@ -193,14 +193,14 @@ exit: * 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 + 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,