[emu,scard] use rdpCertificate and rdpRsaKey

This commit is contained in:
akallabeth 2023-02-03 11:52:12 +01:00 committed by akallabeth
parent b5d1ea7138
commit 67bd1d08d3

View File

@ -24,13 +24,12 @@
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <openssl/bn.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/rand.h>
#include <freerdp/crypto/crypto.h>
#include <zlib.h>
#include "../../crypto/certificate.h"
#include "../../crypto/privatekey.h"
#include "smartcard_virtual_gids.h"
#define TAG CHANNELS_TAG("smartcard.vgids")
@ -140,10 +139,8 @@ struct vgids_context
BOOL pinVerified;
vgidsSE currentSE;
X509* certificate;
RSA* publicKey;
RSA* privateKey;
rdpCertificate* certificate;
rdpRsaKey* privateKey;
wArrayList* files;
};
@ -444,41 +441,34 @@ static BOOL vgids_prepare_fstable(const vgidsFilesysTableEntry* fstable, DWORD n
return TRUE;
}
static BOOL vgids_prepare_certificate(X509* cert, BYTE** kxc, DWORD* kxcSize)
static BOOL vgids_prepare_certificate(const rdpCertificate* cert, BYTE** kxc, DWORD* kxcSize)
{
/* Key exchange container:
UINT16 compression version: 0001
UINT16 source size
ZLIB compressed cert
*/
BYTE* i2dParam;
uLongf destSize;
wStream* s = NULL;
BYTE* certData = NULL;
BYTE* comprData = NULL;
int certSize = i2d_X509(cert, NULL);
if (certSize < 0)
WINPR_ASSERT(cert);
size_t certSize = 0;
BYTE* certData = freerdp_certificate_get_der(cert, &certSize);
if (!certData || (certSize == 0))
{
WLog_ERR(TAG, "Failed to get certificate size");
goto handle_error;
}
certData = malloc(certSize);
comprData = malloc(certSize);
if (!certData || !comprData)
if (!comprData)
{
WLog_ERR(TAG, "Failed to allocate certificate buffer");
goto handle_error;
}
/* serialize certificate to buffer (out buffer pointer is modified so pass a copy!) */
i2dParam = certData;
if (i2d_X509(cert, &i2dParam) < 0)
{
WLog_ERR(TAG, "Failed to encode X509 certificate to DER");
goto handle_error;
}
/* compress certificate data */
destSize = certSize;
if (compress(comprData, &destSize, certData, certSize) != Z_OK)
@ -511,8 +501,12 @@ handle_error:
static BYTE vgids_get_algid(vgidsContext* p_Ctx)
{
int modulusSize = RSA_size(p_Ctx->privateKey);
switch (modulusSize)
WINPR_ASSERT(p_Ctx);
const rdpCertInfo* info = freerdp_key_get_info(p_Ctx->privateKey);
WINPR_ASSERT(info);
switch (info->ModulusLength)
{
case (1024 / 8):
return VGIDS_ALGID_RSA_1024;
@ -799,13 +793,15 @@ static BOOL vgids_get_public_key(vgidsContext* context, UINT16 doTag)
BYTE* buf = NULL;
wStream* pubKey = NULL;
wStream* response = NULL;
const BIGNUM *n, *e;
int nSize, eSize;
WINPR_ASSERT(context);
/* Get key components */
RSA_get0_key(context->publicKey, &n, &e, NULL);
nSize = BN_num_bytes(n);
eSize = BN_num_bytes(e);
const rdpCertInfo* info = freerdp_certificate_get_info(context->certificate);
WINPR_ASSERT(info);
const size_t nSize = info->ModulusLength;
const size_t eSize = sizeof(info->exponent);
buf = malloc(nSize > eSize ? nSize : eSize);
if (!buf)
@ -829,12 +825,10 @@ static BOOL vgids_get_public_key(vgidsContext* context, UINT16 doTag)
}
/* write modulus and exponent DOs */
BN_bn2bin(n, buf);
if (!vgids_write_tlv(pubKey, 0x81, buf, nSize))
if (!vgids_write_tlv(pubKey, 0x81, info->Modulus, nSize))
goto handle_error;
BN_bn2bin(e, buf);
if (!vgids_write_tlv(pubKey, 0x82, buf, eSize))
if (!vgids_write_tlv(pubKey, 0x82, info->exponent, eSize))
goto handle_error;
/* write ISO public key template */
@ -1035,7 +1029,7 @@ static BOOL vgids_perform_digital_signature(vgidsContext* context)
size_t sigSize, msgSize;
EVP_PKEY_CTX* ctx = NULL;
EVP_PKEY* pk = EVP_PKEY_new();
vgidsDigestInfoMap gidsDigestInfo[VGIDS_MAX_DIGEST_INFO] = {
const vgidsDigestInfoMap gidsDigestInfo[VGIDS_MAX_DIGEST_INFO] = {
{ g_PKCS1_SHA1, sizeof(g_PKCS1_SHA1), EVP_sha1() },
{ g_PKCS1_SHA224, sizeof(g_PKCS1_SHA224), EVP_sha224() },
{ g_PKCS1_SHA256, sizeof(g_PKCS1_SHA256), EVP_sha256() },
@ -1051,7 +1045,8 @@ static BOOL vgids_perform_digital_signature(vgidsContext* context)
return FALSE;
}
EVP_PKEY_set1_RSA(pk, context->privateKey);
RSA* rsa = freerdp_key_get_RSA(context->privateKey);
EVP_PKEY_set1_RSA(pk, rsa);
vgids_reset_context_response(context);
/* for each digest info */
@ -1129,6 +1124,7 @@ static BOOL vgids_perform_digital_signature(vgidsContext* context)
}
EVP_PKEY_free(pk);
RSA_free(rsa);
vgids_reset_context_command_data(context);
return TRUE;
@ -1154,7 +1150,10 @@ static BOOL vgids_perform_decrypt(vgidsContext* context)
padding = RSA_PKCS1_OAEP_PADDING;
/* init response buffer */
context->responseData = Stream_New(NULL, RSA_size(context->privateKey));
const rdpCertInfo* info = freerdp_key_get_info(context->privateKey);
WINPR_ASSERT(info);
context->responseData = Stream_New(NULL, info->ModulusLength);
if (!context->responseData)
{
WLog_ERR(TAG, "Failed to create decryption buffer");
@ -1162,9 +1161,12 @@ static BOOL vgids_perform_decrypt(vgidsContext* context)
}
/* Determine buffer length */
RSA* rsa = freerdp_key_get_RSA(context->privateKey);
res = RSA_private_decrypt((int)Stream_Length(context->commandData),
Stream_Buffer(context->commandData),
Stream_Buffer(context->responseData), context->privateKey, padding);
Stream_Buffer(context->responseData), rsa, padding);
RSA_free(rsa);
if (res < 0)
{
WLog_ERR(TAG, "Failed to decrypt data");
@ -1417,12 +1419,9 @@ BOOL vgids_init(vgidsContext* ctx, const char* cert, const char* privateKey, con
DWORD keymapSize;
DWORD fsTableSize;
BOOL rc = FALSE;
BIO* certBio = NULL;
BIO* privateKeyBio = NULL;
BYTE* kxc = NULL;
BYTE* keymap = NULL;
BYTE* fsTable = NULL;
EVP_PKEY* pubKey = NULL;
vgidsEF* masterEF = NULL;
vgidsEF* cardidEF = NULL;
vgidsEF* commonEF = NULL;
@ -1452,23 +1451,11 @@ BOOL vgids_init(vgidsContext* ctx, const char* cert, const char* privateKey, con
}
/* Convert PEM input to DER certificate/public key/private key */
certBio = BIO_new_mem_buf((const void*)cert, (int)strlen(cert));
if (!certBio)
goto init_failed;
ctx->certificate = PEM_read_bio_X509(certBio, NULL, NULL, NULL);
ctx->certificate = freerdp_certificate_new_from_pem(cert);
if (!ctx->certificate)
goto init_failed;
pubKey = X509_get_pubkey(ctx->certificate);
if (!pubKey)
goto init_failed;
ctx->publicKey = EVP_PKEY_get1_RSA(pubKey);
if (!ctx->publicKey)
goto init_failed;
privateKeyBio = BIO_new_mem_buf((const void*)privateKey, (int)strlen(privateKey));
if (!privateKeyBio)
goto init_failed;
ctx->privateKey = PEM_read_bio_RSAPrivateKey(privateKeyBio, NULL, NULL, NULL);
ctx->privateKey = freerdp_key_new_from_pem(privateKey);
if (!ctx->privateKey)
goto init_failed;
@ -1481,7 +1468,7 @@ BOOL vgids_init(vgidsContext* ctx, const char* cert, const char* privateKey, con
cardidEF = vgids_ef_new(ctx, VGIDS_EFID_CARDID);
if (!cardidEF)
goto init_failed;
RAND_bytes(cardid, sizeof(cardid));
winpr_RAND(cardid, sizeof(cardid));
if (!vgids_ef_write_do(cardidEF, VGIDS_DO_CARDID, cardid, sizeof(cardid)))
goto init_failed;
@ -1495,7 +1482,10 @@ BOOL vgids_init(vgidsContext* ctx, const char* cert, const char* privateKey, con
goto init_failed;
/* write container map DO */
cmrec.wKeyExchangeKeySizeBits = (WORD)(RSA_size(ctx->privateKey) * 8);
const rdpCertInfo* info = freerdp_key_get_info(ctx->privateKey);
if (!info)
goto init_failed;
cmrec.wKeyExchangeKeySizeBits = (WORD)info->ModulusLength;
if (!vgids_ef_write_do(commonEF, VGIDS_DO_CMAPFILE, (BYTE*)&cmrec, sizeof(cmrec)))
goto init_failed;
@ -1531,9 +1521,6 @@ BOOL vgids_init(vgidsContext* ctx, const char* cert, const char* privateKey, con
rc = TRUE;
init_failed:
EVP_PKEY_free(pubKey);
BIO_free_all(certBio);
BIO_free_all(privateKeyBio);
free(kxc);
free(keymap);
free(fsTable);
@ -1589,9 +1576,8 @@ void vgids_free(vgidsContext* context)
{
if (context)
{
RSA_free(context->privateKey);
RSA_free(context->publicKey);
X509_free(context->certificate);
freerdp_key_free(context->privateKey);
freerdp_certificate_free(context->certificate);
Stream_Free(context->commandData, TRUE);
Stream_Free(context->responseData, TRUE);
free(context->pin);