mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
[core,crypto] refactor rsa functions
* public encrypt/decrypt take rdpCertInfo data as argument * private encrypt/decrypt take rdpRsaKey as argument * Add missing length arguments
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user