25#include <freerdp/config.h>
31#include <winpr/assert.h>
32#include <winpr/wtypes.h>
34#include <winpr/file.h>
35#include <winpr/print.h>
36#include <winpr/crypto.h>
38#include <freerdp/crypto/certificate.h>
40#include <openssl/err.h>
41#include <openssl/pem.h>
42#include <openssl/rsa.h>
43#include <openssl/bn.h>
45#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
46#include <openssl/core_names.h>
47#include <openssl/param_build.h>
48#include <openssl/evp.h>
49#include <openssl/x509.h>
52#include "certificate.h"
53#include "cert_common.h"
56#include "x509_utils.h"
57#include "privatekey.h"
58#include "opensslcompat.h"
60#define TAG FREERDP_TAG("core")
62#ifdef WITH_DEBUG_CERTIFICATE
63#define DEBUG_CERTIFICATE(...) WLog_DBG(TAG, __VA_ARGS__)
65#define DEBUG_CERTIFICATE(...) \
71#define TSSK_KEY_LENGTH 64
78typedef struct rdp_CertBlob rdpCertBlob;
80struct rdp_X509CertChain
85typedef struct rdp_X509CertChain rdpX509CertChain;
90 STACK_OF(X509) * chain;
92 rdpCertInfo cert_info;
93 rdpX509CertChain x509_cert_chain;
184static const char rsa_magic[4] = {
'R',
'S',
'A',
'1' };
186static const char* certificate_read_errors[] = {
"Certificate tag",
188 "Explicit Contextual Tag [0]",
190 "CertificateSerialNumber",
191 "AlgorithmIdentifier",
195 "SubjectPublicKeyInfo Tag",
196 "subjectPublicKeyInfo::AlgorithmIdentifier",
197 "subjectPublicKeyInfo::subjectPublicKey",
203 "publicExponent length",
206static const BYTE initial_signature[] = {
207 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
208 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
209 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
210 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01
213#if defined(CERT_VALIDATE_RSA)
214static const BYTE tssk_exponent[] = { 0x5b, 0x7b, 0x88, 0xc0 };
217static void certificate_free_int(rdpCertificate* certificate);
218static BOOL cert_clone_int(rdpCertificate* dst,
const rdpCertificate* src);
224static BOOL cert_blob_copy(rdpCertBlob* dst,
const rdpCertBlob* src);
225static void cert_blob_free(rdpCertBlob* blob);
226static BOOL cert_blob_write(
const rdpCertBlob* blob,
wStream* s);
227static BOOL cert_blob_read(rdpCertBlob* blob,
wStream* s);
229BOOL cert_blob_read(rdpCertBlob* blob,
wStream* s)
231 UINT32 certLength = 0;
233 cert_blob_free(blob);
235 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
238 Stream_Read_UINT32(s, certLength);
240 if (!Stream_CheckAndLogRequiredLength(TAG, s, certLength))
243 DEBUG_CERTIFICATE(
"X.509 Certificate length:%" PRIu32
"", certLength);
244 blob->data = (BYTE*)malloc(certLength);
249 Stream_Read(s, blob->data, certLength);
250 blob->length = certLength;
255 cert_blob_free(blob);
259BOOL cert_blob_write(
const rdpCertBlob* blob,
wStream* s)
263 if (!Stream_EnsureRemainingCapacity(s, 4ull + blob->length))
266 Stream_Write_UINT32(s, blob->length);
267 Stream_Write(s, blob->data, blob->length);
271void cert_blob_free(rdpCertBlob* blob)
276 blob->data =
nullptr;
284static BOOL is_rsa_key(
const X509* x509)
286 EVP_PKEY* evp = X509_get0_pubkey(x509);
290 return (EVP_PKEY_id(evp) == EVP_PKEY_RSA);
293static BOOL certificate_read_x509_certificate(
const rdpCertBlob* cert, rdpCertInfo* info)
295 wStream sbuffer = WINPR_C_ARRAY_INIT;
300 size_t modulus_length = 0;
301 size_t exponent_length = 0;
307 cert_info_free(info);
309 s = Stream_StaticConstInit(&sbuffer, cert->data, cert->length);
314 if (!ber_read_sequence_tag(s, &length))
319 if (!ber_read_sequence_tag(s, &length))
324 if (!ber_read_contextual_tag(s, 0, &length, TRUE))
329 if (!ber_read_integer(s, &version))
336 if (!ber_read_integer(s,
nullptr))
342 if (!ber_read_sequence_tag(s, &length) ||
343 !Stream_SafeSeek(s, length))
349 if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length))
355 if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length))
361 if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length))
367 if (!ber_read_sequence_tag(s, &length))
373 if (!ber_read_sequence_tag(s, &length) ||
374 !Stream_SafeSeek(s, length))
380 if (!ber_read_bit_string(s, &length, &padding))
386 if (!ber_read_sequence_tag(s, &length))
391 if (!ber_read_integer_length(s, &modulus_length))
399 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
402 Stream_Peek_UINT8(s, padding);
406 if (!Stream_SafeSeek(s, 1))
411 }
while (padding == 0);
415 if (!cert_info_read_modulus(info, modulus_length, s))
420 if (!ber_read_integer_length(s, &exponent_length))
425 if (!cert_info_read_exponent(info, exponent_length, s))
429 WLog_ERR(TAG,
"error reading when reading certificate: part=%s error=%d",
430 certificate_read_errors[error], error);
431 cert_info_free(info);
441static BOOL certificate_new_x509_certificate_chain(UINT32 count,
wStream* s,
442 rdpX509CertChain* chain)
446 rdpX509CertChain x509_cert_chain = WINPR_C_ARRAY_INIT;
447 *chain = x509_cert_chain;
449 if (!Stream_CheckAndLogRequiredCapacityOfSize(TAG, s, count,
sizeof(rdpCertBlob)))
455 x509_cert_chain.array = (rdpCertBlob*)calloc(count,
sizeof(rdpCertBlob));
456 if (!x509_cert_chain.array)
459 x509_cert_chain.count = count;
461 *chain = x509_cert_chain;
470static void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain)
472 if (!x509_cert_chain)
475 if (x509_cert_chain->array)
477 for (UINT32 i = 0; i < x509_cert_chain->count; i++)
479 rdpCertBlob* element = &x509_cert_chain->array[i];
480 cert_blob_free(element);
484 free(x509_cert_chain->array);
485 x509_cert_chain->array =
nullptr;
486 x509_cert_chain->count = 0;
489#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
490static OSSL_PARAM* get_params(
const BIGNUM* e,
const BIGNUM* mod)
495 OSSL_PARAM* parameters =
nullptr;
496 OSSL_PARAM_BLD* param = OSSL_PARAM_BLD_new();
499 WLog_ERR(TAG,
"OSSL_PARAM_BLD_new() failed");
503 const int bits = BN_num_bits(e);
504 if ((bits < 0) || (bits > 32))
506 WLog_ERR(TAG,
"BN_num_bits(e) out of range: 0 <= %d <= 32", bits);
513 const int ne = BN_bn2nativepad(e, (BYTE*)&ie,
sizeof(ie));
514 if ((ne < 0) || (ne > 4))
517 "BN_bn2nativepad(e, (BYTE*)&ie, sizeof(ie)) out of range: 0<= %d <= 4",
523 if (OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) != 1)
525 WLog_ERR(TAG,
"OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) failed");
528 if (OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) != 1)
530 WLog_ERR(TAG,
"OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) failed");
535 parameters = OSSL_PARAM_BLD_to_param(param);
537 WLog_ERR(TAG,
"OSSL_PARAM_BLD_to_param(param) failed");
539 OSSL_PARAM_BLD_free(param);
545static BOOL update_x509_from_info(rdpCertificate* cert)
551 X509_free(cert->x509);
552 cert->x509 =
nullptr;
554 rdpCertInfo* info = &cert->cert_info;
556 BIGNUM* e = BN_new();
557 BIGNUM* mod = BN_new();
558#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
559 RSA* rsa = RSA_new();
562 WLog_ERR(TAG,
"RSA_new() failed");
569 WLog_ERR(TAG,
"failure: mod=%p, e=%p", WINPR_CXX_COMPAT_CAST(
const void*, mod),
570 WINPR_CXX_COMPAT_CAST(
const void*, e));
574 WINPR_ASSERT(info->ModulusLength <= INT_MAX);
575 if (!BN_bin2bn(info->Modulus, (
int)info->ModulusLength, mod))
577 WLog_ERR(TAG,
"BN_bin2bn(info->Modulus, (int)info->ModulusLength, mod) failed");
581 if (!BN_bin2bn(info->exponent, (
int)
sizeof(info->exponent), e))
583 WLog_ERR(TAG,
"BN_bin2bn(info->exponent, (int)sizeof(info->exponent), e) failed");
587#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
588 const int rec = RSA_set0_key(rsa, mod, e,
nullptr);
591 WLog_ERR(TAG,
"RSA_set0_key(rsa, mod, e, nullptr) failed");
595 cert->x509 = x509_from_rsa(rsa);
598 EVP_PKEY* pkey =
nullptr;
599 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA,
nullptr);
602 WLog_ERR(TAG,
"EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr) failed");
607 const int xx = EVP_PKEY_fromdata_init(ctx);
610 WLog_ERR(TAG,
"EVP_PKEY_fromdata_init(ctx) failed");
616 OSSL_PARAM* parameters = get_params(e, mod);
621 const int rc2 = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters);
622 OSSL_PARAM_free(parameters);
627 "EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters) failed");
633 cert->x509 = X509_new();
636 WLog_ERR(TAG,
"X509_new() failed");
640 if (X509_set_pubkey(cert->x509, pkey) != 1)
642 WLog_ERR(TAG,
"X509_set_pubkey(cert->x509, pkey) failed");
643 X509_free(cert->x509);
644 cert->x509 =
nullptr;
648 EVP_PKEY_CTX_free(ctx);
658 WLog_ERR(TAG,
"failed to update x509 from rdpCertInfo");
660#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
672static BOOL certificate_process_server_public_key(rdpCertificate* cert,
wStream* s,
673 WINPR_ATTR_UNUSED UINT32 length)
675 char magic[
sizeof(rsa_magic)] = WINPR_C_ARRAY_INIT;
683 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
686 Stream_Read(s, magic,
sizeof(magic));
688 if (memcmp(magic, rsa_magic,
sizeof(magic)) != 0)
690 WLog_ERR(TAG,
"invalid RSA magic bytes");
694 rdpCertInfo* info = &cert->cert_info;
695 cert_info_free(info);
697 Stream_Read_UINT32(s, keylen);
698 Stream_Read_UINT32(s, bitlen);
699 Stream_Read_UINT32(s, datalen);
700 Stream_Read(s, info->exponent, 4);
704 WLog_ERR(TAG,
"Invalid RSA keylen=%" PRIu32
" <= 8", keylen);
707 if (!Stream_CheckAndLogRequiredLength(TAG, s, keylen))
709 if (keylen != (bitlen / 8ull) + 8ull)
711 WLog_ERR(TAG,
"Invalid RSA key bitlen %" PRIu32
", expected %" PRIu32, bitlen,
715 if (datalen != (bitlen / 8ull) - 1ull)
717 WLog_ERR(TAG,
"Invalid RSA key datalen %" PRIu32
", expected %llu", datalen,
718 (1ull * bitlen / 8ull) - 1ull);
721 info->ModulusLength = keylen - 8;
722 BYTE* tmp = realloc(info->Modulus, info->ModulusLength);
726 WLog_ERR(TAG,
"Failed to reallocate modulus of length %" PRIu32, info->ModulusLength);
731 Stream_Read(s, info->Modulus, info->ModulusLength);
733 return update_x509_from_info(cert);
736static BOOL certificate_process_server_public_signature(rdpCertificate* certificate,
737 const BYTE* sigdata,
size_t sigdatalen,
740 WINPR_ASSERT(certificate);
741#if defined(CERT_VALIDATE_RSA)
742 BYTE sig[TSSK_KEY_LENGTH];
744 BYTE encsig[TSSK_KEY_LENGTH + 8];
745#if defined(CERT_VALIDATE_MD5) && defined(CERT_VALIDATE_RSA)
746 BYTE md5hash[WINPR_MD5_DIGEST_LENGTH];
748#if !defined(CERT_VALIDATE_MD5) || !defined(CERT_VALIDATE_RSA)
759#if defined(CERT_VALIDATE_MD5)
761 if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash,
sizeof(md5hash)))
765 Stream_Read(s, encsig, siglen);
769 WLog_WARN(TAG,
"public signature too short: %" PRIu32, siglen);
774#if defined(CERT_VALIDATE_PADDING)
777 for (
size_t i =
sizeof(encsig) - 8; i <
sizeof(encsig); i++)
782 WLog_ERR(TAG,
"invalid signature");
787#if defined(CERT_VALIDATE_RSA)
789 if (crypto_rsa_public_decrypt(encsig, siglen - 8, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent,
792 WLog_ERR(TAG,
"invalid RSA decrypt");
798#if defined(CERT_VALIDATE_MD5)
800 if (memcmp(md5hash, sig,
sizeof(md5hash)) != 0)
802 WLog_ERR(TAG,
"invalid signature");
815 for (
size_t i = 17; i < 62; i++)
818 if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01)
820 WLog_ERR(TAG,
"invalid signature");
828static BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate,
wStream* s)
830 UINT32 dwSigAlgId = 0;
831 UINT32 dwKeyAlgId = 0;
832 UINT16 wPublicKeyBlobType = 0;
833 UINT16 wPublicKeyBlobLen = 0;
834 UINT16 wSignatureBlobType = 0;
835 UINT16 wSignatureBlobLen = 0;
836 size_t sigdatalen = 0;
838 WINPR_ASSERT(certificate);
839 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
843 const BYTE* sigdata = Stream_PointerAs(s,
const BYTE) - 4;
844 Stream_Read_UINT32(s, dwSigAlgId);
845 Stream_Read_UINT32(s, dwKeyAlgId);
847 if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
850 "unsupported signature or key algorithm, dwSigAlgId=%" PRIu32
851 " dwKeyAlgId=%" PRIu32
"",
852 dwSigAlgId, dwKeyAlgId);
856 Stream_Read_UINT16(s, wPublicKeyBlobType);
858 if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
860 WLog_ERR(TAG,
"unsupported public key blob type %" PRIu16
"", wPublicKeyBlobType);
864 Stream_Read_UINT16(s, wPublicKeyBlobLen);
866 if (!Stream_CheckAndLogRequiredLength(TAG, s, wPublicKeyBlobLen))
869 if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
872 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
875 sigdatalen = WINPR_ASSERTING_INT_CAST(
size_t, Stream_PointerAs(s,
const BYTE) - sigdata);
876 Stream_Read_UINT16(s, wSignatureBlobType);
878 if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
880 WLog_ERR(TAG,
"unsupported blob signature %" PRIu16
"", wSignatureBlobType);
884 Stream_Read_UINT16(s, wSignatureBlobLen);
886 if (!Stream_CheckAndLogRequiredLength(TAG, s, wSignatureBlobLen))
889 if (wSignatureBlobLen != 72)
891 WLog_ERR(TAG,
"invalid signature length (got %" PRIu16
", expected 72)", wSignatureBlobLen);
895 if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s,
898 WLog_ERR(TAG,
"unable to parse server public signature");
905static BOOL cert_write_rsa_public_key(
wStream* s,
const rdpCertificate* cert)
908 WINPR_ASSERT(freerdp_certificate_is_rsa(cert));
910 const rdpCertInfo* info = &cert->cert_info;
912 const UINT32 keyLen = info->ModulusLength + 8;
913 const UINT32 bitLen = info->ModulusLength * 8;
914 const UINT32 dataLen = (bitLen / 8) - 1;
915 const size_t pubExpLen =
sizeof(info->exponent);
916 const BYTE* pubExp = info->exponent;
917 const BYTE* modulus = info->Modulus;
919 const size_t wPublicKeyBlobLen = 16 + pubExpLen + keyLen;
920 WINPR_ASSERT(wPublicKeyBlobLen <= UINT16_MAX);
921 if (!Stream_EnsureRemainingCapacity(s, 2ull + wPublicKeyBlobLen))
923 Stream_Write_UINT16(s, (UINT16)wPublicKeyBlobLen);
924 Stream_Write(s, rsa_magic,
sizeof(rsa_magic));
925 Stream_Write_UINT32(s, keyLen);
926 Stream_Write_UINT32(s, bitLen);
927 Stream_Write_UINT32(s, dataLen);
928 Stream_Write(s, pubExp, pubExpLen);
929 Stream_Write(s, modulus, info->ModulusLength);
934static BOOL cert_write_rsa_signature(
wStream* s,
const void* sigData,
size_t sigDataLen)
936 BYTE encryptedSignature[TSSK_KEY_LENGTH] = WINPR_C_ARRAY_INIT;
937 BYTE signature[
sizeof(initial_signature)] = WINPR_C_ARRAY_INIT;
939 memcpy(signature, initial_signature,
sizeof(initial_signature));
940 if (!winpr_Digest(WINPR_MD_MD5, sigData, sigDataLen, signature,
sizeof(signature)))
943 if (crypto_rsa_private_encrypt(signature,
sizeof(signature), priv_key_tssk, encryptedSignature,
944 sizeof(encryptedSignature)) < 0)
947 if (!Stream_EnsureRemainingCapacity(s,
948 2ull *
sizeof(UINT16) +
sizeof(encryptedSignature) + 8ull))
950 Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB);
951 Stream_Write_UINT16(s,
sizeof(encryptedSignature) + 8);
952 Stream_Write(s, encryptedSignature,
sizeof(encryptedSignature));
958static BOOL cert_write_server_certificate_v1(
wStream* s,
const rdpCertificate* certificate)
960 const size_t start = Stream_GetPosition(s);
961 const BYTE* sigData = Stream_PointerAs(s,
const BYTE) -
sizeof(UINT32);
963 WINPR_ASSERT(start >= 4);
964 if (!Stream_EnsureRemainingCapacity(s, 10))
966 Stream_Write_UINT32(s, SIGNATURE_ALG_RSA);
967 Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA);
968 Stream_Write_UINT16(s, BB_RSA_KEY_BLOB);
969 if (!cert_write_rsa_public_key(s, certificate))
972 const size_t end = Stream_GetPosition(s);
973 return cert_write_rsa_signature(s, sigData, end - start +
sizeof(UINT32));
976static BOOL cert_write_server_certificate_v2(
wStream* s,
const rdpCertificate* certificate)
978 WINPR_ASSERT(certificate);
980 const rdpX509CertChain* chain = &certificate->x509_cert_chain;
981 const size_t padding = 8ull + 4ull * chain->count;
983 if (!Stream_EnsureRemainingCapacity(s,
sizeof(UINT32)))
986 Stream_Write_UINT32(s, chain->count);
987 for (UINT32 x = 0; x < chain->count; x++)
989 const rdpCertBlob* cert = &chain->array[x];
990 if (!cert_blob_write(cert, s))
994 if (!Stream_EnsureRemainingCapacity(s, padding))
996 Stream_Zero(s, padding);
1000SSIZE_T freerdp_certificate_write_server_cert(
const rdpCertificate* certificate, UINT32 dwVersion,
1006 const size_t start = Stream_GetPosition(s);
1007 if (!Stream_EnsureRemainingCapacity(s, 4))
1009 Stream_Write_UINT32(s, dwVersion);
1011 switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1013 case CERT_CHAIN_VERSION_1:
1014 if (!cert_write_server_certificate_v1(s, certificate))
1017 case CERT_CHAIN_VERSION_2:
1018 if (!cert_write_server_certificate_v2(s, certificate))
1022 WLog_ERR(TAG,
"invalid certificate chain version:%" PRIu32
"",
1023 dwVersion & CERT_CHAIN_VERSION_MASK);
1027 const size_t end = Stream_GetPosition(s);
1031 const size_t diff = end - start;
1032 WINPR_ASSERT(diff <= SSIZE_MAX);
1033 return (SSIZE_T)diff;
1043static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* cert,
wStream* s)
1045 UINT32 numCertBlobs = 0;
1046 DEBUG_CERTIFICATE(
"Server X.509 Certificate Chain");
1049 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1052 Stream_Read_UINT32(s, numCertBlobs);
1053 certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1054 if (!certificate_new_x509_certificate_chain(numCertBlobs, s, &cert->x509_cert_chain))
1057 for (UINT32 i = 0; i < cert->x509_cert_chain.count; i++)
1059 rdpCertBlob* blob = &cert->x509_cert_chain.array[i];
1060 if (!cert_blob_read(blob, s))
1063 if (numCertBlobs - i == 1)
1065 DEBUG_CERTIFICATE(
"Terminal Server Certificate");
1067 BOOL res = certificate_read_x509_certificate(blob, &cert->cert_info);
1071 if (!update_x509_from_info(cert))
1077 WLog_ERR(TAG,
"Failed to read x509 certificate");
1081 DEBUG_CERTIFICATE(
"modulus length:%" PRIu32
"", cert->cert_info.ModulusLength);
1085 return update_x509_from_info(cert);
1095BOOL freerdp_certificate_read_server_cert(rdpCertificate* certificate,
const BYTE* server_cert,
1101 UINT32 dwVersion = 0;
1103 WINPR_ASSERT(certificate);
1106 WLog_DBG(TAG,
"Received empty certificate, ignoring...");
1110 WINPR_ASSERT(server_cert);
1111 s = Stream_StaticConstInit(&sbuffer, server_cert, length);
1115 WLog_ERR(TAG,
"Stream_New failed!");
1119 Stream_Read_UINT32(s, dwVersion);
1121 switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1123 case CERT_CHAIN_VERSION_1:
1124 ret = certificate_read_server_proprietary_certificate(certificate, s);
1127 case CERT_CHAIN_VERSION_2:
1128 ret = certificate_read_server_x509_certificate_chain(certificate, s);
1132 WLog_ERR(TAG,
"invalid certificate chain version:%" PRIu32
"",
1133 dwVersion & CERT_CHAIN_VERSION_MASK);
1141static BOOL cert_blob_copy(rdpCertBlob* dst,
const rdpCertBlob* src)
1146 cert_blob_free(dst);
1147 if (src->length > 0)
1149 dst->data = malloc(src->length);
1152 dst->length = src->length;
1153 memcpy(dst->data, src->data, src->length);
1159static BOOL cert_x509_chain_copy(rdpX509CertChain* cert,
const rdpX509CertChain* src)
1163 certificate_free_x509_certificate_chain(cert);
1169 cert->array = calloc(src->count,
sizeof(rdpCertBlob));
1174 cert->count = src->count;
1176 for (UINT32 x = 0; x < cert->count; x++)
1178 const rdpCertBlob* srcblob = &src->array[x];
1179 rdpCertBlob* dstblob = &cert->array[x];
1181 if (!cert_blob_copy(dstblob, srcblob))
1183 certificate_free_x509_certificate_chain(cert);
1192BOOL cert_clone_int(rdpCertificate* dst,
const rdpCertificate* src)
1197 if (!cert_info_clone(&dst->cert_info, &src->cert_info))
1202 dst->x509 = X509_dup(src->x509);
1209 if (!update_x509_from_info(dst))
1211 WLog_ERR(TAG,
"X509_dup failed, SSL configuration bug?");
1220 sk_X509_pop_free(dst->chain, X509_free);
1222 dst->chain = sk_X509_deep_copy(src->chain, X509_const_dup, X509_free);
1224 return cert_x509_chain_copy(&dst->x509_cert_chain, &src->x509_cert_chain);
1227rdpCertificate* freerdp_certificate_clone(
const rdpCertificate* certificate)
1232 rdpCertificate* _certificate = freerdp_certificate_new();
1237 if (!cert_clone_int(_certificate, certificate))
1240 return _certificate;
1243 freerdp_certificate_free(_certificate);
1252rdpCertificate* freerdp_certificate_new(
void)
1254 return (rdpCertificate*)calloc(1,
sizeof(rdpCertificate));
1257void certificate_free_int(rdpCertificate* cert)
1262 X509_free(cert->x509);
1264 sk_X509_pop_free(cert->chain, X509_free);
1266 certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1267 cert_info_free(&cert->cert_info);
1275void freerdp_certificate_free(rdpCertificate* cert)
1280 certificate_free_int(cert);
1284static BOOL freerdp_rsa_from_x509(rdpCertificate* cert)
1290 if (!freerdp_certificate_is_rsa(cert))
1293#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1295 const BIGNUM* rsa_n =
nullptr;
1296 const BIGNUM* rsa_e =
nullptr;
1298 BIGNUM* rsa_n =
nullptr;
1299 BIGNUM* rsa_e =
nullptr;
1301 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1305#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1306 rsa = EVP_PKEY_get1_RSA(pubkey);
1316 RSA_get0_key(rsa, &rsa_n, &rsa_e,
nullptr);
1318 if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &rsa_e))
1320 if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &rsa_n))
1323 if (!rsa_n || !rsa_e)
1325 if (!cert_info_create(&cert->cert_info, rsa_n, rsa_e))
1329#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1338rdpCertificate* freerdp_certificate_new_from_der(
const BYTE* data,
size_t length)
1340 rdpCertificate* cert = freerdp_certificate_new();
1342 if (!cert || !data || (length == 0) || (length > INT_MAX))
1346 const BYTE* ptr = data;
1347 cert->x509 = d2i_X509(
nullptr, &ptr, (
int)length);
1352 if (!freerdp_rsa_from_x509(cert))
1356 freerdp_certificate_free(cert);
1360rdpCertificate* freerdp_certificate_new_from_x509(
const X509* xcert,
const STACK_OF(X509) * chain)
1362 WINPR_ASSERT(xcert);
1364 rdpCertificate* cert = freerdp_certificate_new();
1368 X509* wcert = WINPR_CAST_CONST_PTR_AWAY(xcert, X509*);
1369 cert->x509 = X509_dup(wcert);
1373 if (!freerdp_rsa_from_x509(cert))
1377 cert->chain = sk_X509_deep_copy(chain, X509_const_dup, X509_free);
1381 freerdp_certificate_free(cert);
1385static STACK_OF(X509) * extract_chain_from_pem(
const char* pem, BOOL isFile)
1394 bio = BIO_new_file(pem,
"rb");
1397 const size_t len = strlen(pem);
1398 bio = BIO_new_mem_buf(pem, WINPR_ASSERTING_INT_CAST(
int, len));
1406 X509* leaf = PEM_read_bio_X509(bio,
nullptr,
nullptr,
nullptr);
1413 STACK_OF(X509)* chain = sk_X509_new_null();
1421 X509* cert =
nullptr;
1422 while ((cert = PEM_read_bio_X509(bio,
nullptr,
nullptr,
nullptr)) !=
nullptr)
1424 sk_X509_push(chain, cert);
1432static rdpCertificate* freerdp_certificate_new_from(
const char* file, BOOL isFile)
1434 X509* x509 = x509_utils_from_pem(file, strlen(file), isFile);
1437 STACK_OF(X509)* chain = extract_chain_from_pem(file, isFile);
1438 rdpCertificate* cert = freerdp_certificate_new_from_x509(x509, chain);
1440 sk_X509_pop_free(chain, X509_free);
1445rdpCertificate* freerdp_certificate_new_from_file(
const char* file)
1447 return freerdp_certificate_new_from(file, TRUE);
1450rdpCertificate* freerdp_certificate_new_from_pem(
const char* pem)
1452 return freerdp_certificate_new_from(pem, FALSE);
1455const rdpCertInfo* freerdp_certificate_get_info(
const rdpCertificate* cert)
1458 if (!freerdp_certificate_is_rsa(cert))
1460 return &cert->cert_info;
1463char* freerdp_certificate_get_fingerprint(
const rdpCertificate* cert)
1465 return freerdp_certificate_get_fingerprint_by_hash(cert,
"sha256");
1468char* freerdp_certificate_get_fingerprint_by_hash(
const rdpCertificate* cert,
const char* hash)
1470 return freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, TRUE);
1473char* freerdp_certificate_get_fingerprint_by_hash_ex(
const rdpCertificate* cert,
const char* hash,
1480 char* fp_buffer =
nullptr;
1481 if (!cert || !cert->x509)
1483 WLog_ERR(TAG,
"Invalid certificate [%p, %p]", WINPR_CXX_COMPAT_CAST(
const void*, cert),
1484 WINPR_CXX_COMPAT_CAST(
const void*, cert ? cert->x509 : nullptr));
1489 WLog_ERR(TAG,
"Invalid certificate hash %p", WINPR_CXX_COMPAT_CAST(
const void*, hash));
1492 fp = x509_utils_get_hash(cert->x509, hash, &fp_len);
1499 size = fp_len * 3 + 1;
1500 fp_buffer = calloc(size,
sizeof(
char));
1508 for (; i < (fp_len - 1); i++)
1511 char* p = &fp_buffer[pos];
1513 rc = sprintf_s(p, size - pos,
"%02" PRIx8
":", fp[i]);
1515 rc = sprintf_s(p, size - pos,
"%02" PRIx8, fp[i]);
1521 (void)sprintf_s(&fp_buffer[pos], size - pos,
"%02" PRIx8
"", fp[i]);
1533char* freerdp_certificate_get_pem(
const rdpCertificate* cert,
size_t* pLength)
1535 return freerdp_certificate_get_pem_ex(cert, pLength, TRUE);
1538char* freerdp_certificate_get_pem_ex(
const rdpCertificate* cert,
size_t* pLength,
1550 BIO* bio = BIO_new(BIO_s_mem());
1554 WLog_ERR(TAG,
"BIO_new() failure");
1558 char* pem =
nullptr;
1560 const int status = PEM_write_bio_X509(bio, cert->x509);
1563 WLog_ERR(TAG,
"PEM_write_bio_X509 failure: %d", status);
1567 if (cert->chain && withCertChain)
1569 const int count = sk_X509_num(cert->chain);
1570 for (
int x = 0; x < count; x++)
1572 X509* c = sk_X509_value(cert->chain, x);
1573 const int rc = PEM_write_bio_X509(bio, c);
1576 WLog_ERR(TAG,
"PEM_write_bio_X509 failure: %d", rc);
1582 pem = x509_utils_bio_read(bio, pLength);
1589char* freerdp_certificate_get_subject(
const rdpCertificate* cert)
1592 return x509_utils_get_subject(cert->x509);
1595char* freerdp_certificate_get_issuer(
const rdpCertificate* cert)
1598 return x509_utils_get_issuer(cert->x509);
1601char* freerdp_certificate_get_upn(
const rdpCertificate* cert)
1604 return x509_utils_get_upn(cert->x509);
1607char* freerdp_certificate_get_email(
const rdpCertificate* cert)
1610 return x509_utils_get_email(cert->x509);
1613char* freerdp_certificate_get_validity(
const rdpCertificate* cert, BOOL startDate)
1616 return x509_utils_get_date(cert->x509, startDate);
1619BOOL freerdp_certificate_check_eku(
const rdpCertificate* cert,
int nid)
1622 return x509_utils_check_eku(cert->x509, nid);
1625BOOL freerdp_certificate_get_public_key(
const rdpCertificate* cert, BYTE** PublicKey,
1626 DWORD* PublicKeyLength)
1628 BYTE* ptr =
nullptr;
1629 BYTE* optr =
nullptr;
1631 BOOL status = FALSE;
1632 EVP_PKEY* pkey =
nullptr;
1636 pkey = X509_get0_pubkey(cert->x509);
1640 WLog_ERR(TAG,
"X509_get_pubkey() failed");
1644 length = i2d_PublicKey(pkey,
nullptr);
1648 WLog_ERR(TAG,
"i2d_PublicKey() failed");
1652 *PublicKey = optr = ptr = (BYTE*)calloc(WINPR_ASSERTING_INT_CAST(
size_t, length),
sizeof(BYTE));
1658 const int length2 = i2d_PublicKey(pkey, &ptr);
1659 if (length != length2)
1661 *PublicKeyLength = (DWORD)length2;
1672BOOL freerdp_certificate_verify(
const rdpCertificate* cert,
const char* certificate_store_path)
1675 return x509_utils_verify(cert->x509, cert->chain, certificate_store_path);
1678char** freerdp_certificate_get_dns_names(
const rdpCertificate* cert,
size_t* pcount,
1682 return x509_utils_get_dns_names(cert->x509, pcount, pplengths);
1685char* freerdp_certificate_get_common_name(
const rdpCertificate* cert,
size_t* plength)
1688 return x509_utils_get_common_name(cert->x509, plength);
1691WINPR_MD_TYPE freerdp_certificate_get_signature_alg(
const rdpCertificate* cert)
1694 return x509_utils_get_signature_alg(cert->x509);
1697void freerdp_certificate_free_dns_names(
size_t count,
size_t* lengths,
char** names)
1699 x509_utils_dns_names_free(count, lengths, names);
1702char* freerdp_certificate_get_hash(
const rdpCertificate* cert,
const char* hash,
size_t* plength)
1705 return (
char*)x509_utils_get_hash(cert->x509, hash, plength);
1708X509* freerdp_certificate_get_x509(rdpCertificate* cert)
1714BOOL freerdp_certificate_publickey_encrypt(
const rdpCertificate* cert,
const BYTE* input,
1715 size_t cbInput, BYTE** poutput,
size_t* pcbOutput)
1718 WINPR_ASSERT(input);
1719 WINPR_ASSERT(poutput);
1720 WINPR_ASSERT(pcbOutput);
1723 BYTE* output =
nullptr;
1724 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1728 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey,
nullptr);
1732 size_t outputSize = WINPR_ASSERTING_INT_CAST(
size_t, EVP_PKEY_size(pkey));
1733 output = malloc(outputSize);
1734 if (output ==
nullptr)
1736 *pcbOutput = outputSize;
1738 if (EVP_PKEY_encrypt_init(ctx) != 1 ||
1739 EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) != 1 ||
1740 EVP_PKEY_encrypt(ctx, output, pcbOutput, input, cbInput) != 1)
1742 WLog_ERR(TAG,
"error when setting up public key");
1750 EVP_PKEY_CTX_free(ctx);
1755#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1756static RSA* freerdp_certificate_get_RSA(
const rdpCertificate* cert)
1760 if (!freerdp_certificate_is_rsa(cert))
1763 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1767 return EVP_PKEY_get1_RSA(pubkey);
1771BYTE* freerdp_certificate_get_der(
const rdpCertificate* cert,
size_t* pLength)
1778 const int rc = i2d_X509(cert->x509,
nullptr);
1782 BYTE* ptr = calloc(WINPR_ASSERTING_INT_CAST(
size_t, rc) + 1,
sizeof(BYTE));
1785 BYTE* i2d_ptr = ptr;
1787 const int rc2 = i2d_X509(cert->x509, &i2d_ptr);
1795 *pLength = (size_t)rc2;
1799BOOL freerdp_certificate_is_rsa(
const rdpCertificate* cert)
1802 return is_rsa_key(cert->x509);
1805BOOL freerdp_certificate_is_rdp_security_compatible(
const rdpCertificate* cert)
1807 const rdpCertInfo* info = freerdp_certificate_get_info(cert);
1808 if (!freerdp_certificate_is_rsa(cert) || !info || (info->ModulusLength != 2048 / 8))
1810 WLog_INFO(TAG,
"certificate is not RSA 2048, RDP security not supported.");
1816char* freerdp_certificate_get_param(
const rdpCertificate* cert,
enum FREERDP_CERT_PARAM what,
1820 WINPR_ASSERT(psize);
1824#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1825 const BIGNUM* bn =
nullptr;
1826 RSA* rsa = freerdp_certificate_get_RSA(cert);
1829 case FREERDP_CERT_RSA_E:
1830 RSA_get0_key(rsa,
nullptr, &bn,
nullptr);
1832 case FREERDP_CERT_RSA_N:
1833 RSA_get0_key(rsa, &bn,
nullptr,
nullptr);
1841 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1845 BIGNUM* bn =
nullptr;
1848 case FREERDP_CERT_RSA_E:
1849 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn))
1852 case FREERDP_CERT_RSA_N:
1853 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn))
1861 const size_t bnsize = WINPR_ASSERTING_INT_CAST(
size_t, BN_num_bytes(bn));
1862 char* rc = calloc(bnsize + 1,
sizeof(
char));
1865 BN_bn2bin(bn, (BYTE*)rc);
1869#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR < 3)
1875size_t freerdp_certificate_get_chain_len(rdpCertificate* certificate)
1877 WINPR_ASSERT(certificate);
1878 if (!certificate->chain)
1881 return WINPR_ASSERTING_INT_CAST(
size_t, sk_X509_num(certificate->chain));
1884X509* freerdp_certificate_get_chain_at(rdpCertificate* certificate,
size_t offset)
1886 WINPR_ASSERT(certificate);
1887 WINPR_ASSERT(freerdp_certificate_get_chain_len(certificate) > offset);
1888 const int ioff = WINPR_ASSERTING_INT_CAST(
int, offset);
1889 return sk_X509_value(certificate->chain, ioff);