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 CERTIFICATE_TAG FREERDP_TAG("core.certificate")
64#define DEBUG_CERTIFICATE(...) WLog_DBG(TAG, __VA_ARGS__)
66#define DEBUG_CERTIFICATE(...) \
72#define TSSK_KEY_LENGTH 64
79typedef struct rdp_CertBlob rdpCertBlob;
81struct rdp_X509CertChain
86typedef struct rdp_X509CertChain rdpX509CertChain;
91 STACK_OF(X509) * chain;
93 rdpCertInfo cert_info;
94 rdpX509CertChain x509_cert_chain;
185static const char rsa_magic[4] = {
'R',
'S',
'A',
'1' };
187static const char* certificate_read_errors[] = {
"Certificate tag",
189 "Explicit Contextual Tag [0]",
191 "CertificateSerialNumber",
192 "AlgorithmIdentifier",
196 "SubjectPublicKeyInfo Tag",
197 "subjectPublicKeyInfo::AlgorithmIdentifier",
198 "subjectPublicKeyInfo::subjectPublicKey",
204 "publicExponent length",
207static const BYTE initial_signature[] = {
208 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
209 0x00, 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, 0xff, 0xff,
211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01
214#if defined(CERT_VALIDATE_RSA)
215static const BYTE tssk_exponent[] = { 0x5b, 0x7b, 0x88, 0xc0 };
218static void certificate_free_int(rdpCertificate* certificate);
219static BOOL cert_clone_int(rdpCertificate* dst,
const rdpCertificate* src);
225static BOOL cert_blob_copy(rdpCertBlob* dst,
const rdpCertBlob* src);
226static void cert_blob_free(rdpCertBlob* blob);
227static BOOL cert_blob_write(
const rdpCertBlob* blob,
wStream* s);
228static BOOL cert_blob_read(rdpCertBlob* blob,
wStream* s);
230BOOL cert_blob_read(rdpCertBlob* blob,
wStream* s)
232 UINT32 certLength = 0;
234 cert_blob_free(blob);
236 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
239 Stream_Read_UINT32(s, certLength);
241 if (!Stream_CheckAndLogRequiredLength(TAG, s, certLength))
244 DEBUG_CERTIFICATE(
"X.509 Certificate length:%" PRIu32
"", certLength);
245 blob->data = (BYTE*)malloc(certLength);
250 Stream_Read(s, blob->data, certLength);
251 blob->length = certLength;
256 cert_blob_free(blob);
260BOOL cert_blob_write(
const rdpCertBlob* blob,
wStream* s)
264 if (!Stream_EnsureRemainingCapacity(s, 4 + blob->length))
267 Stream_Write_UINT32(s, blob->length);
268 Stream_Write(s, blob->data, blob->length);
272void cert_blob_free(rdpCertBlob* blob)
277 blob->data =
nullptr;
285static BOOL is_rsa_key(
const X509* x509)
287 EVP_PKEY* evp = X509_get0_pubkey(x509);
291 return (EVP_PKEY_id(evp) == EVP_PKEY_RSA);
294static BOOL certificate_read_x509_certificate(
const rdpCertBlob* cert, rdpCertInfo* info)
296 wStream sbuffer = WINPR_C_ARRAY_INIT;
301 size_t modulus_length = 0;
302 size_t exponent_length = 0;
308 cert_info_free(info);
310 s = Stream_StaticConstInit(&sbuffer, cert->data, cert->length);
315 if (!ber_read_sequence_tag(s, &length))
320 if (!ber_read_sequence_tag(s, &length))
325 if (!ber_read_contextual_tag(s, 0, &length, TRUE))
330 if (!ber_read_integer(s, &version))
337 if (!ber_read_integer(s,
nullptr))
343 if (!ber_read_sequence_tag(s, &length) ||
344 !Stream_SafeSeek(s, length))
350 if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length))
356 if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length))
362 if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length))
368 if (!ber_read_sequence_tag(s, &length))
374 if (!ber_read_sequence_tag(s, &length) ||
375 !Stream_SafeSeek(s, length))
381 if (!ber_read_bit_string(s, &length, &padding))
387 if (!ber_read_sequence_tag(s, &length))
392 if (!ber_read_integer_length(s, &modulus_length))
400 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
403 Stream_Peek_UINT8(s, padding);
407 if (!Stream_SafeSeek(s, 1))
412 }
while (padding == 0);
416 if (!cert_info_read_modulus(info, modulus_length, s))
421 if (!ber_read_integer_length(s, &exponent_length))
426 if (!cert_info_read_exponent(info, exponent_length, s))
430 WLog_ERR(TAG,
"error reading when reading certificate: part=%s error=%d",
431 certificate_read_errors[error], error);
432 cert_info_free(info);
442static BOOL certificate_new_x509_certificate_chain(UINT32 count,
wStream* s,
443 rdpX509CertChain* chain)
447 rdpX509CertChain x509_cert_chain = WINPR_C_ARRAY_INIT;
448 *chain = x509_cert_chain;
450 if (!Stream_CheckAndLogRequiredCapacityOfSize(TAG, s, count,
sizeof(rdpCertBlob)))
456 x509_cert_chain.array = (rdpCertBlob*)calloc(count,
sizeof(rdpCertBlob));
457 if (!x509_cert_chain.array)
460 x509_cert_chain.count = count;
462 *chain = x509_cert_chain;
471static void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain)
473 if (!x509_cert_chain)
476 if (x509_cert_chain->array)
478 for (UINT32 i = 0; i < x509_cert_chain->count; i++)
480 rdpCertBlob* element = &x509_cert_chain->array[i];
481 cert_blob_free(element);
485 free(x509_cert_chain->array);
486 x509_cert_chain->array =
nullptr;
487 x509_cert_chain->count = 0;
490#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
491static OSSL_PARAM* get_params(
const BIGNUM* e,
const BIGNUM* mod)
496 OSSL_PARAM* parameters =
nullptr;
497 OSSL_PARAM_BLD* param = OSSL_PARAM_BLD_new();
500 WLog_ERR(TAG,
"OSSL_PARAM_BLD_new() failed");
504 const int bits = BN_num_bits(e);
505 if ((bits < 0) || (bits > 32))
507 WLog_ERR(TAG,
"BN_num_bits(e) out of range: 0 <= %d <= 32", bits);
514 const int ne = BN_bn2nativepad(e, (BYTE*)&ie,
sizeof(ie));
515 if ((ne < 0) || (ne > 4))
518 "BN_bn2nativepad(e, (BYTE*)&ie, sizeof(ie)) out of range: 0<= %d <= 4",
524 if (OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) != 1)
526 WLog_ERR(TAG,
"OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) failed");
529 if (OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) != 1)
531 WLog_ERR(TAG,
"OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) failed");
536 parameters = OSSL_PARAM_BLD_to_param(param);
538 WLog_ERR(TAG,
"OSSL_PARAM_BLD_to_param(param) failed");
540 OSSL_PARAM_BLD_free(param);
546static BOOL update_x509_from_info(rdpCertificate* cert)
552 X509_free(cert->x509);
553 cert->x509 =
nullptr;
555 rdpCertInfo* info = &cert->cert_info;
557 BIGNUM* e = BN_new();
558 BIGNUM* mod = BN_new();
559#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
560 RSA* rsa = RSA_new();
563 WLog_ERR(TAG,
"RSA_new() failed");
570 WLog_ERR(TAG,
"failure: mod=%p, e=%p", WINPR_CXX_COMPAT_CAST(
const void*, mod),
571 WINPR_CXX_COMPAT_CAST(
const void*, e));
575 WINPR_ASSERT(info->ModulusLength <= INT_MAX);
576 if (!BN_bin2bn(info->Modulus, (
int)info->ModulusLength, mod))
578 WLog_ERR(TAG,
"BN_bin2bn(info->Modulus, (int)info->ModulusLength, mod) failed");
582 if (!BN_bin2bn(info->exponent, (
int)
sizeof(info->exponent), e))
584 WLog_ERR(TAG,
"BN_bin2bn(info->exponent, (int)sizeof(info->exponent), e) failed");
588#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
589 const int rec = RSA_set0_key(rsa, mod, e,
nullptr);
592 WLog_ERR(TAG,
"RSA_set0_key(rsa, mod, e, nullptr) failed");
596 cert->x509 = x509_from_rsa(rsa);
599 EVP_PKEY* pkey =
nullptr;
600 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA,
nullptr);
603 WLog_ERR(TAG,
"EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr) failed");
608 const int xx = EVP_PKEY_fromdata_init(ctx);
611 WLog_ERR(TAG,
"EVP_PKEY_fromdata_init(ctx) failed");
617 OSSL_PARAM* parameters = get_params(e, mod);
622 const int rc2 = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters);
623 OSSL_PARAM_free(parameters);
628 "EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters) failed");
634 cert->x509 = X509_new();
637 WLog_ERR(TAG,
"X509_new() failed");
641 if (X509_set_pubkey(cert->x509, pkey) != 1)
643 WLog_ERR(TAG,
"X509_set_pubkey(cert->x509, pkey) failed");
644 X509_free(cert->x509);
645 cert->x509 =
nullptr;
649 EVP_PKEY_CTX_free(ctx);
659 WLog_ERR(TAG,
"failed to update x509 from rdpCertInfo");
661#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
673static BOOL certificate_process_server_public_key(rdpCertificate* cert,
wStream* s,
674 WINPR_ATTR_UNUSED UINT32 length)
676 char magic[
sizeof(rsa_magic)] = WINPR_C_ARRAY_INIT;
684 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
687 Stream_Read(s, magic,
sizeof(magic));
689 if (memcmp(magic, rsa_magic,
sizeof(magic)) != 0)
691 WLog_ERR(TAG,
"invalid RSA magic bytes");
695 rdpCertInfo* info = &cert->cert_info;
696 cert_info_free(info);
698 Stream_Read_UINT32(s, keylen);
699 Stream_Read_UINT32(s, bitlen);
700 Stream_Read_UINT32(s, datalen);
701 Stream_Read(s, info->exponent, 4);
705 WLog_ERR(TAG,
"Invalid RSA keylen=%" PRIu32
" <= 8", keylen);
708 if (!Stream_CheckAndLogRequiredLength(TAG, s, keylen))
710 if (keylen != (bitlen / 8ull) + 8ull)
712 WLog_ERR(TAG,
"Invalid RSA key bitlen %" PRIu32
", expected %" PRIu32, bitlen,
716 if (datalen != (bitlen / 8ull) - 1ull)
718 WLog_ERR(TAG,
"Invalid RSA key datalen %" PRIu32
", expected %llu", datalen,
719 (1ull * bitlen / 8ull) - 1ull);
722 info->ModulusLength = keylen - 8;
723 BYTE* tmp = realloc(info->Modulus, info->ModulusLength);
727 WLog_ERR(TAG,
"Failed to reallocate modulus of length %" PRIu32, info->ModulusLength);
732 Stream_Read(s, info->Modulus, info->ModulusLength);
734 return update_x509_from_info(cert);
737static BOOL certificate_process_server_public_signature(rdpCertificate* certificate,
738 const BYTE* sigdata,
size_t sigdatalen,
741 WINPR_ASSERT(certificate);
742#if defined(CERT_VALIDATE_RSA)
743 BYTE sig[TSSK_KEY_LENGTH];
745 BYTE encsig[TSSK_KEY_LENGTH + 8];
746#if defined(CERT_VALIDATE_MD5) && defined(CERT_VALIDATE_RSA)
747 BYTE md5hash[WINPR_MD5_DIGEST_LENGTH];
749#if !defined(CERT_VALIDATE_MD5) || !defined(CERT_VALIDATE_RSA)
760#if defined(CERT_VALIDATE_MD5)
762 if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash,
sizeof(md5hash)))
766 Stream_Read(s, encsig, siglen);
770 WLog_WARN(TAG,
"public signature too short: %" PRIu32, siglen);
775#if defined(CERT_VALIDATE_PADDING)
778 for (
size_t i =
sizeof(encsig) - 8; i <
sizeof(encsig); i++)
783 WLog_ERR(TAG,
"invalid signature");
788#if defined(CERT_VALIDATE_RSA)
790 if (crypto_rsa_public_decrypt(encsig, siglen - 8, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent,
793 WLog_ERR(TAG,
"invalid RSA decrypt");
799#if defined(CERT_VALIDATE_MD5)
801 if (memcmp(md5hash, sig,
sizeof(md5hash)) != 0)
803 WLog_ERR(TAG,
"invalid signature");
816 for (
size_t i = 17; i < 62; i++)
819 if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01)
821 WLog_ERR(TAG,
"invalid signature");
829static BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate,
wStream* s)
831 UINT32 dwSigAlgId = 0;
832 UINT32 dwKeyAlgId = 0;
833 UINT16 wPublicKeyBlobType = 0;
834 UINT16 wPublicKeyBlobLen = 0;
835 UINT16 wSignatureBlobType = 0;
836 UINT16 wSignatureBlobLen = 0;
837 size_t sigdatalen = 0;
839 WINPR_ASSERT(certificate);
840 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
844 const BYTE* sigdata = Stream_PointerAs(s,
const BYTE) - 4;
845 Stream_Read_UINT32(s, dwSigAlgId);
846 Stream_Read_UINT32(s, dwKeyAlgId);
848 if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
851 "unsupported signature or key algorithm, dwSigAlgId=%" PRIu32
852 " dwKeyAlgId=%" PRIu32
"",
853 dwSigAlgId, dwKeyAlgId);
857 Stream_Read_UINT16(s, wPublicKeyBlobType);
859 if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
861 WLog_ERR(TAG,
"unsupported public key blob type %" PRIu16
"", wPublicKeyBlobType);
865 Stream_Read_UINT16(s, wPublicKeyBlobLen);
867 if (!Stream_CheckAndLogRequiredLength(TAG, s, wPublicKeyBlobLen))
870 if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
873 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
876 sigdatalen = WINPR_ASSERTING_INT_CAST(
size_t, Stream_PointerAs(s,
const BYTE) - sigdata);
877 Stream_Read_UINT16(s, wSignatureBlobType);
879 if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
881 WLog_ERR(TAG,
"unsupported blob signature %" PRIu16
"", wSignatureBlobType);
885 Stream_Read_UINT16(s, wSignatureBlobLen);
887 if (!Stream_CheckAndLogRequiredLength(TAG, s, wSignatureBlobLen))
890 if (wSignatureBlobLen != 72)
892 WLog_ERR(TAG,
"invalid signature length (got %" PRIu16
", expected 72)", wSignatureBlobLen);
896 if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s,
899 WLog_ERR(TAG,
"unable to parse server public signature");
906static BOOL cert_write_rsa_public_key(
wStream* s,
const rdpCertificate* cert)
909 WINPR_ASSERT(freerdp_certificate_is_rsa(cert));
911 const rdpCertInfo* info = &cert->cert_info;
913 const UINT32 keyLen = info->ModulusLength + 8;
914 const UINT32 bitLen = info->ModulusLength * 8;
915 const UINT32 dataLen = (bitLen / 8) - 1;
916 const size_t pubExpLen =
sizeof(info->exponent);
917 const BYTE* pubExp = info->exponent;
918 const BYTE* modulus = info->Modulus;
920 const size_t wPublicKeyBlobLen = 16 + pubExpLen + keyLen;
921 WINPR_ASSERT(wPublicKeyBlobLen <= UINT16_MAX);
922 if (!Stream_EnsureRemainingCapacity(s, 2 + wPublicKeyBlobLen))
924 Stream_Write_UINT16(s, (UINT16)wPublicKeyBlobLen);
925 Stream_Write(s, rsa_magic,
sizeof(rsa_magic));
926 Stream_Write_UINT32(s, keyLen);
927 Stream_Write_UINT32(s, bitLen);
928 Stream_Write_UINT32(s, dataLen);
929 Stream_Write(s, pubExp, pubExpLen);
930 Stream_Write(s, modulus, info->ModulusLength);
935static BOOL cert_write_rsa_signature(
wStream* s,
const void* sigData,
size_t sigDataLen)
937 BYTE encryptedSignature[TSSK_KEY_LENGTH] = WINPR_C_ARRAY_INIT;
938 BYTE signature[
sizeof(initial_signature)] = WINPR_C_ARRAY_INIT;
940 memcpy(signature, initial_signature,
sizeof(initial_signature));
941 if (!winpr_Digest(WINPR_MD_MD5, sigData, sigDataLen, signature,
sizeof(signature)))
944 if (crypto_rsa_private_encrypt(signature,
sizeof(signature), priv_key_tssk, encryptedSignature,
945 sizeof(encryptedSignature)) < 0)
948 if (!Stream_EnsureRemainingCapacity(s, 2 *
sizeof(UINT16) +
sizeof(encryptedSignature) + 8))
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]);
1533static BOOL bio_read_pem(BIO* bio,
char** ppem,
size_t* plength)
1540 const size_t blocksize = 2048;
1542 size_t length = blocksize;
1543 char* pem =
nullptr;
1549 while (offset < length)
1551 char* tmp = realloc(pem, length + 1);
1558 const int status = BIO_read(bio, &pem[offset], (
int)(length - offset));
1561 WLog_ERR(TAG,
"failed to read certificate");
1568 offset += (size_t)status;
1569 if (length - offset > 0)
1571 length += blocksize;
1576 if (offset >= length)
1591char* freerdp_certificate_get_pem(
const rdpCertificate* cert,
size_t* pLength)
1593 return freerdp_certificate_get_pem_ex(cert, pLength, TRUE);
1596char* freerdp_certificate_get_pem_ex(
const rdpCertificate* cert,
size_t* pLength,
1608 BIO* bio = BIO_new(BIO_s_mem());
1612 WLog_ERR(TAG,
"BIO_new() failure");
1616 char* pem =
nullptr;
1618 const int status = PEM_write_bio_X509(bio, cert->x509);
1621 WLog_ERR(TAG,
"PEM_write_bio_X509 failure: %d", status);
1625 if (cert->chain && withCertChain)
1627 const int count = sk_X509_num(cert->chain);
1628 for (
int x = 0; x < count; x++)
1630 X509* c = sk_X509_value(cert->chain, x);
1631 const int rc = PEM_write_bio_X509(bio, c);
1634 WLog_ERR(TAG,
"PEM_write_bio_X509 failure: %d", rc);
1640 (void)bio_read_pem(bio, &pem, pLength);
1647char* freerdp_certificate_get_subject(
const rdpCertificate* cert)
1650 return x509_utils_get_subject(cert->x509);
1653char* freerdp_certificate_get_issuer(
const rdpCertificate* cert)
1656 return x509_utils_get_issuer(cert->x509);
1659char* freerdp_certificate_get_upn(
const rdpCertificate* cert)
1662 return x509_utils_get_upn(cert->x509);
1665char* freerdp_certificate_get_email(
const rdpCertificate* cert)
1668 return x509_utils_get_email(cert->x509);
1671char* freerdp_certificate_get_validity(
const rdpCertificate* cert, BOOL startDate)
1674 return x509_utils_get_date(cert->x509, startDate);
1677BOOL freerdp_certificate_check_eku(
const rdpCertificate* cert,
int nid)
1680 return x509_utils_check_eku(cert->x509, nid);
1683BOOL freerdp_certificate_get_public_key(
const rdpCertificate* cert, BYTE** PublicKey,
1684 DWORD* PublicKeyLength)
1686 BYTE* ptr =
nullptr;
1687 BYTE* optr =
nullptr;
1689 BOOL status = FALSE;
1690 EVP_PKEY* pkey =
nullptr;
1694 pkey = X509_get0_pubkey(cert->x509);
1698 WLog_ERR(TAG,
"X509_get_pubkey() failed");
1702 length = i2d_PublicKey(pkey,
nullptr);
1706 WLog_ERR(TAG,
"i2d_PublicKey() failed");
1710 *PublicKey = optr = ptr = (BYTE*)calloc(WINPR_ASSERTING_INT_CAST(
size_t, length),
sizeof(BYTE));
1716 const int length2 = i2d_PublicKey(pkey, &ptr);
1717 if (length != length2)
1719 *PublicKeyLength = (DWORD)length2;
1730BOOL freerdp_certificate_verify(
const rdpCertificate* cert,
const char* certificate_store_path)
1733 return x509_utils_verify(cert->x509, cert->chain, certificate_store_path);
1736char** freerdp_certificate_get_dns_names(
const rdpCertificate* cert,
size_t* pcount,
1740 return x509_utils_get_dns_names(cert->x509, pcount, pplengths);
1743char* freerdp_certificate_get_common_name(
const rdpCertificate* cert,
size_t* plength)
1746 return x509_utils_get_common_name(cert->x509, plength);
1749WINPR_MD_TYPE freerdp_certificate_get_signature_alg(
const rdpCertificate* cert)
1752 return x509_utils_get_signature_alg(cert->x509);
1755void freerdp_certificate_free_dns_names(
size_t count,
size_t* lengths,
char** names)
1757 x509_utils_dns_names_free(count, lengths, names);
1760char* freerdp_certificate_get_hash(
const rdpCertificate* cert,
const char* hash,
size_t* plength)
1763 return (
char*)x509_utils_get_hash(cert->x509, hash, plength);
1766X509* freerdp_certificate_get_x509(rdpCertificate* cert)
1772BOOL freerdp_certificate_publickey_encrypt(
const rdpCertificate* cert,
const BYTE* input,
1773 size_t cbInput, BYTE** poutput,
size_t* pcbOutput)
1776 WINPR_ASSERT(input);
1777 WINPR_ASSERT(poutput);
1778 WINPR_ASSERT(pcbOutput);
1781 BYTE* output =
nullptr;
1782 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1786 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey,
nullptr);
1790 size_t outputSize = WINPR_ASSERTING_INT_CAST(
size_t, EVP_PKEY_size(pkey));
1791 output = malloc(outputSize);
1792 if (output ==
nullptr)
1794 *pcbOutput = outputSize;
1796 if (EVP_PKEY_encrypt_init(ctx) != 1 ||
1797 EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) != 1 ||
1798 EVP_PKEY_encrypt(ctx, output, pcbOutput, input, cbInput) != 1)
1800 WLog_ERR(TAG,
"error when setting up public key");
1808 EVP_PKEY_CTX_free(ctx);
1813#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1814static RSA* freerdp_certificate_get_RSA(
const rdpCertificate* cert)
1818 if (!freerdp_certificate_is_rsa(cert))
1821 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1825 return EVP_PKEY_get1_RSA(pubkey);
1829BYTE* freerdp_certificate_get_der(
const rdpCertificate* cert,
size_t* pLength)
1836 const int rc = i2d_X509(cert->x509,
nullptr);
1840 BYTE* ptr = calloc(WINPR_ASSERTING_INT_CAST(
size_t, rc) + 1,
sizeof(BYTE));
1843 BYTE* i2d_ptr = ptr;
1845 const int rc2 = i2d_X509(cert->x509, &i2d_ptr);
1853 *pLength = (size_t)rc2;
1857BOOL freerdp_certificate_is_rsa(
const rdpCertificate* cert)
1860 return is_rsa_key(cert->x509);
1863BOOL freerdp_certificate_is_rdp_security_compatible(
const rdpCertificate* cert)
1865 const rdpCertInfo* info = freerdp_certificate_get_info(cert);
1866 if (!freerdp_certificate_is_rsa(cert) || !info || (info->ModulusLength != 2048 / 8))
1868 WLog_INFO(TAG,
"certificate is not RSA 2048, RDP security not supported.");
1874char* freerdp_certificate_get_param(
const rdpCertificate* cert,
enum FREERDP_CERT_PARAM what,
1878 WINPR_ASSERT(psize);
1882#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1883 const BIGNUM* bn =
nullptr;
1884 RSA* rsa = freerdp_certificate_get_RSA(cert);
1887 case FREERDP_CERT_RSA_E:
1888 RSA_get0_key(rsa,
nullptr, &bn,
nullptr);
1890 case FREERDP_CERT_RSA_N:
1891 RSA_get0_key(rsa, &bn,
nullptr,
nullptr);
1899 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1903 BIGNUM* bn =
nullptr;
1906 case FREERDP_CERT_RSA_E:
1907 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn))
1910 case FREERDP_CERT_RSA_N:
1911 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn))
1919 const size_t bnsize = WINPR_ASSERTING_INT_CAST(
size_t, BN_num_bytes(bn));
1920 char* rc = calloc(bnsize + 1,
sizeof(
char));
1923 BN_bn2bin(bn, (BYTE*)rc);
1927#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR < 3)
1933size_t freerdp_certificate_get_chain_len(rdpCertificate* certificate)
1935 WINPR_ASSERT(certificate);
1936 if (!certificate->chain)
1939 return WINPR_ASSERTING_INT_CAST(
size_t, sk_X509_num(certificate->chain));
1942X509* freerdp_certificate_get_chain_at(rdpCertificate* certificate,
size_t offset)
1944 WINPR_ASSERT(certificate);
1945 WINPR_ASSERT(freerdp_certificate_get_chain_len(certificate) > offset);
1946 const int ioff = WINPR_ASSERTING_INT_CAST(
int, offset);
1947 return sk_X509_value(certificate->chain, ioff);