diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index 677a98090..1295e5055 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -92,17 +92,17 @@ extern "C" DWORD* PublicKeyLength); FREERDP_API SSIZE_T crypto_rsa_public_encrypt(const BYTE* input, size_t length, - size_t key_length, const BYTE* modulus, - const BYTE* exponent, BYTE* output); + const rdpCertInfo* cert, BYTE* output, + size_t output_length); FREERDP_API SSIZE_T crypto_rsa_public_decrypt(const BYTE* input, size_t length, - size_t key_length, const BYTE* modulus, - const BYTE* exponent, BYTE* output); + const rdpCertInfo* cert, BYTE* output, + size_t output_length); FREERDP_API SSIZE_T crypto_rsa_private_encrypt(const BYTE* input, size_t length, - size_t key_length, const BYTE* modulus, - const BYTE* private_exponent, BYTE* output); + const rdpRsaKey* key, BYTE* output, + size_t output_length); FREERDP_API SSIZE_T crypto_rsa_private_decrypt(const BYTE* input, size_t length, - size_t key_length, const BYTE* modulus, - const BYTE* private_exponent, BYTE* output); + const rdpRsaKey* key, BYTE* output, + size_t output_length); FREERDP_API void crypto_reverse(BYTE* data, size_t length); FREERDP_API char* crypto_base64_encode(const BYTE* data, size_t length); diff --git a/libfreerdp/core/certificate.c b/libfreerdp/core/certificate.c index ce981fe5c..d6eacbe64 100644 --- a/libfreerdp/core/certificate.c +++ b/libfreerdp/core/certificate.c @@ -164,20 +164,25 @@ static const BYTE initial_signature[] = { * Yes, Terminal Services Private Key is publicly available. */ -static const BYTE 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 -}; +static BYTE 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 }; -static const BYTE tssk_privateExponent[] = { +static BYTE 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 }; +static const rdpRsaKey tssk = { .PrivateExponent = tssk_privateExponent, + .PrivateExponentLength = sizeof(tssk_privateExponent), + .cert = { .Modulus = tssk_modulus, + .ModulusLength = sizeof(tssk_modulus) } }; + #if defined(CERT_VALIDATE_RSA) static const BYTE tssk_exponent[] = { 0x5b, 0x7b, 0x88, 0xc0 }; #endif @@ -677,8 +682,8 @@ static BOOL cert_write_rsa_signature(wStream* s, const void* sigData, size_t sig if (!winpr_Digest(WINPR_MD_MD5, sigData, sigDataLen, signature, sizeof(signature))) return FALSE; - crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH, tssk_modulus, - tssk_privateExponent, encryptedSignature); + crypto_rsa_private_encrypt(signature, sizeof(signature), &tssk, encryptedSignature, + sizeof(encryptedSignature)); if (!Stream_EnsureRemainingCapacity(s, 2 * sizeof(UINT16) + sizeof(encryptedSignature) + 8)) return FALSE; diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 5bf3acec0..9a6f9b045 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -726,20 +726,21 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) return FALSE; winpr_RAND(settings->ClientRandom, settings->ClientRandomLength); - key_len = settings->RdpServerCertificate->cert_info.ModulusLength; - mod = settings->RdpServerCertificate->cert_info.Modulus; - exp = settings->RdpServerCertificate->cert_info.exponent; + + WINPR_ASSERT(settings->RdpServerCertificate); + const rdpCertInfo* info = &settings->RdpServerCertificate->cert_info; + /* * client random must be (bitlen / 8) + 8 - see [MS-RDPBCGR] 5.3.4.1 * for details */ - crypt_client_random = calloc(key_len + 8, 1); + crypt_client_random = calloc(info->ModulusLength + 8, 1); if (!crypt_client_random) return FALSE; - crypto_rsa_public_encrypt(settings->ClientRandom, settings->ClientRandomLength, key_len, mod, - exp, crypt_client_random); + crypto_rsa_public_encrypt(settings->ClientRandom, settings->ClientRandomLength, info, + crypt_client_random, info->ModulusLength + 8); /* send crypt client random to server */ length = RDP_PACKET_HEADER_MAX_LENGTH + RDP_SECURITY_HEADER_LENGTH + 4 + key_len + 8; s = Stream_New(NULL, length); @@ -834,11 +835,7 @@ static BOOL rdp_update_client_random(rdpSettings* settings, const BYTE* crypt_ra const rdpCertInfo* cinfo = &rsa->cert; WINPR_ASSERT(cinfo); - const DWORD key_len = cinfo->ModulusLength; - const BYTE* mod = cinfo->Modulus; - const BYTE* priv_exp = rsa->PrivateExponent; - - if (crypt_random_len != key_len + 8) + if (crypt_random_len != cinfo->ModulusLength + 8) { WLog_ERR(TAG, "invalid encrypted client random length"); return FALSE; @@ -848,8 +845,8 @@ static BOOL rdp_update_client_random(rdpSettings* settings, const BYTE* crypt_ra BYTE* client_random = freerdp_settings_get_pointer(settings, FreeRDP_ClientRandom); WINPR_ASSERT(client_random); - return crypto_rsa_private_decrypt(crypt_random, crypt_random_len - 8, key_len, mod, priv_exp, - client_random) > 0; + return crypto_rsa_private_decrypt(crypt_random, crypt_random_len - 8, rsa, client_random, + length) > 0; } BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index 7c565a978..146f18691 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -1156,9 +1156,9 @@ BOOL license_encrypt_premaster_secret(rdpLicense* license) license->EncryptedPremasterSecret->length = PREMASTER_SECRET_LENGTH; #ifndef LICENSE_NULL_PREMASTER_SECRET { - const SSIZE_T length = crypto_rsa_public_encrypt( - license->PremasterSecret, PREMASTER_SECRET_LENGTH, info->ModulusLength, info->Modulus, - info->exponent, EncryptedPremasterSecret); + const SSIZE_T length = + crypto_rsa_public_encrypt(license->PremasterSecret, sizeof(license->PremasterSecret), + info, EncryptedPremasterSecret, info->ModulusLength); if ((length < 0) || (length > UINT16_MAX)) return FALSE; license->EncryptedPremasterSecret->length = (UINT16)length; diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index d791a9608..88d5eb463 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -112,7 +112,7 @@ exit: static SSIZE_T crypto_rsa_common(const BYTE* input, size_t length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, size_t exponent_size, - BYTE* output) + BYTE* output, size_t out_length) { BN_CTX* ctx = NULL; int output_length = -1; @@ -123,15 +123,15 @@ static SSIZE_T crypto_rsa_common(const BYTE* input, size_t length, UINT32 key_le BIGNUM* exp = NULL; BIGNUM* x = NULL; BIGNUM* y = NULL; - size_t bufferSize; + size_t bufferSize = 0; if (!input || !modulus || !exponent || !output) return -1; - if ((size_t)exponent_size > SIZE_MAX / 2) + if ((size_t)exponent_size > INT_MAX / 2) return -1; - if (key_length >= SIZE_MAX / 2 - exponent_size) + if (key_length >= INT_MAX / 2 - exponent_size) return -1; bufferSize = 2ULL * key_length + exponent_size; @@ -153,19 +153,19 @@ static SSIZE_T crypto_rsa_common(const BYTE* input, size_t length, UINT32 key_le crypto_reverse(input_reverse, length); if (!(ctx = BN_CTX_new())) - goto fail_bn_ctx; + goto fail; if (!(mod = BN_new())) - goto fail_bn_mod; + goto fail; if (!(exp = BN_new())) - goto fail_bn_exp; + goto fail; if (!(x = BN_new())) - goto fail_bn_x; + goto fail; if (!(y = BN_new())) - goto fail_bn_y; + goto fail; if (!BN_bin2bn(modulus_reverse, key_length, mod)) goto fail; @@ -179,62 +179,67 @@ static SSIZE_T crypto_rsa_common(const BYTE* input, size_t length, UINT32 key_le output_length = BN_bn2bin(y, output); if (output_length < 0) goto fail; + if ((size_t)output_length > out_length) + goto fail; crypto_reverse(output, output_length); - if ((UINT32)output_length < key_length) - memset(output + output_length, 0, key_length - output_length); + if ((size_t)output_length < key_length) + { + size_t diff = key_length - output_length; + if ((size_t)output_length + diff > out_length) + diff = out_length - (size_t)output_length; + memset(output + output_length, 0, diff); + } fail: BN_free(y); -fail_bn_y: BN_clear_free(x); -fail_bn_x: BN_free(exp); -fail_bn_exp: BN_free(mod); -fail_bn_mod: BN_CTX_free(ctx); -fail_bn_ctx: free(input_reverse); return output_length; } -static int crypto_rsa_public(const BYTE* input, size_t length, size_t key_length, - const BYTE* modulus, const BYTE* exponent, BYTE* output) +static SSIZE_T crypto_rsa_public(const BYTE* input, size_t length, const rdpCertInfo* cert, + BYTE* output, size_t output_length) { - return crypto_rsa_common(input, length, key_length, modulus, exponent, EXPONENT_MAX_SIZE, - output); + WINPR_ASSERT(cert); + return crypto_rsa_common(input, length, cert->ModulusLength, cert->Modulus, cert->exponent, + sizeof(cert->exponent), output, output_length); } -static int crypto_rsa_private(const BYTE* input, size_t length, size_t key_length, - const BYTE* modulus, const BYTE* private_exponent, BYTE* output) +static SSIZE_T crypto_rsa_private(const BYTE* input, size_t length, const rdpRsaKey* key, + BYTE* output, size_t output_length) { - return crypto_rsa_common(input, length, key_length, modulus, private_exponent, key_length, - output); + WINPR_ASSERT(key); + return crypto_rsa_common(input, length, key->cert.ModulusLength, key->cert.Modulus, + key->PrivateExponent, key->PrivateExponentLength, output, + output_length); } -SSIZE_T crypto_rsa_public_encrypt(const BYTE* input, size_t length, size_t key_length, - const BYTE* modulus, const BYTE* exponent, BYTE* output) +SSIZE_T crypto_rsa_public_encrypt(const BYTE* input, size_t length, const rdpCertInfo* cert, + BYTE* output, size_t output_length) { - return crypto_rsa_public(input, length, key_length, modulus, exponent, output); + return crypto_rsa_public(input, length, cert, output, output_length); } -SSIZE_T crypto_rsa_public_decrypt(const BYTE* input, size_t length, size_t key_length, - const BYTE* modulus, const BYTE* exponent, BYTE* output) +SSIZE_T crypto_rsa_public_decrypt(const BYTE* input, size_t length, const rdpCertInfo* cert, + BYTE* output, size_t output_length) { - return crypto_rsa_public(input, length, key_length, modulus, exponent, output); + return crypto_rsa_public(input, length, cert, output, output_length); } -SSIZE_T crypto_rsa_private_encrypt(const BYTE* input, size_t length, size_t key_length, - const BYTE* modulus, const BYTE* private_exponent, BYTE* output) +SSIZE_T crypto_rsa_private_encrypt(const BYTE* input, size_t length, const rdpRsaKey* key, + BYTE* output, size_t output_length) { - return crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); + return crypto_rsa_private(input, length, key, output, output_length); } -SSIZE_T crypto_rsa_private_decrypt(const BYTE* input, size_t length, size_t key_length, - const BYTE* modulus, const BYTE* private_exponent, BYTE* output) +SSIZE_T crypto_rsa_private_decrypt(const BYTE* input, size_t length, const rdpRsaKey* key, + BYTE* output, size_t output_length) { - return crypto_rsa_private(input, length, key_length, modulus, private_exponent, output); + return crypto_rsa_private(input, length, key, output, output_length); } void crypto_reverse(BYTE* data, size_t length)