[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:
akallabeth
2023-01-28 12:42:54 +01:00
committed by akallabeth
parent 2af9758173
commit a3152871ab
5 changed files with 76 additions and 69 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)