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"
55#include "../core/utils.h"
57#include "x509_utils.h"
58#include "privatekey.h"
59#include "opensslcompat.h"
61#define TAG FREERDP_TAG("core")
63#ifdef WITH_DEBUG_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, 4ull + 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, 2ull + 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,
949 2ull *
sizeof(UINT16) +
sizeof(encryptedSignature) + 8ull))
951 Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB);
952 Stream_Write_UINT16(s,
sizeof(encryptedSignature) + 8);
953 Stream_Write(s, encryptedSignature,
sizeof(encryptedSignature));
959static BOOL cert_write_server_certificate_v1(
wStream* s,
const rdpCertificate* certificate)
961 const size_t start = Stream_GetPosition(s);
963 WINPR_ASSERT(start >= 4);
964 if (!Stream_EnsureRemainingCapacity(s, 10))
967 Stream_Write_UINT32(s, SIGNATURE_ALG_RSA);
968 Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA);
969 Stream_Write_UINT16(s, BB_RSA_KEY_BLOB);
970 if (!cert_write_rsa_public_key(s, certificate))
975 const BYTE* sigData = Stream_BufferAs(s,
const BYTE) + start -
sizeof(UINT32);
976 const size_t end = Stream_GetPosition(s);
977 return cert_write_rsa_signature(s, sigData, end - start +
sizeof(UINT32));
980static BOOL cert_write_server_certificate_v2(
wStream* s,
const rdpCertificate* certificate)
982 WINPR_ASSERT(certificate);
984 const rdpX509CertChain* chain = &certificate->x509_cert_chain;
985 const size_t padding = 8ull + 4ull * chain->count;
987 if (!Stream_EnsureRemainingCapacity(s,
sizeof(UINT32)))
990 Stream_Write_UINT32(s, chain->count);
991 for (UINT32 x = 0; x < chain->count; x++)
993 const rdpCertBlob* cert = &chain->array[x];
994 if (!cert_blob_write(cert, s))
998 if (!Stream_EnsureRemainingCapacity(s, padding))
1000 Stream_Zero(s, padding);
1004SSIZE_T freerdp_certificate_write_server_cert(
const rdpCertificate* certificate, UINT32 dwVersion,
1010 const size_t start = Stream_GetPosition(s);
1011 if (!Stream_EnsureRemainingCapacity(s, 4))
1013 Stream_Write_UINT32(s, dwVersion);
1015 switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1017 case CERT_CHAIN_VERSION_1:
1018 if (!cert_write_server_certificate_v1(s, certificate))
1021 case CERT_CHAIN_VERSION_2:
1022 if (!cert_write_server_certificate_v2(s, certificate))
1026 WLog_ERR(TAG,
"invalid certificate chain version:%" PRIu32
"",
1027 dwVersion & CERT_CHAIN_VERSION_MASK);
1031 const size_t end = Stream_GetPosition(s);
1035 const size_t diff = end - start;
1036 WINPR_ASSERT(diff <= SSIZE_MAX);
1037 return (SSIZE_T)diff;
1047static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* cert,
wStream* s)
1049 UINT32 numCertBlobs = 0;
1050 DEBUG_CERTIFICATE(
"Server X.509 Certificate Chain");
1053 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1056 Stream_Read_UINT32(s, numCertBlobs);
1057 certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1058 if (!certificate_new_x509_certificate_chain(numCertBlobs, s, &cert->x509_cert_chain))
1061 for (UINT32 i = 0; i < cert->x509_cert_chain.count; i++)
1063 rdpCertBlob* blob = &cert->x509_cert_chain.array[i];
1064 if (!cert_blob_read(blob, s))
1067 if (numCertBlobs - i == 1)
1069 DEBUG_CERTIFICATE(
"Terminal Server Certificate");
1071 BOOL res = certificate_read_x509_certificate(blob, &cert->cert_info);
1075 if (!update_x509_from_info(cert))
1081 WLog_ERR(TAG,
"Failed to read x509 certificate");
1085 DEBUG_CERTIFICATE(
"modulus length:%" PRIu32
"", cert->cert_info.ModulusLength);
1089 return update_x509_from_info(cert);
1099BOOL freerdp_certificate_read_server_cert(rdpCertificate* certificate,
const BYTE* server_cert,
1105 UINT32 dwVersion = 0;
1107 WINPR_ASSERT(certificate);
1110 WLog_DBG(TAG,
"Received empty certificate, ignoring...");
1114 WINPR_ASSERT(server_cert);
1115 s = Stream_StaticConstInit(&sbuffer, server_cert, length);
1119 WLog_ERR(TAG,
"Stream_New failed!");
1123 Stream_Read_UINT32(s, dwVersion);
1125 switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1127 case CERT_CHAIN_VERSION_1:
1128 ret = certificate_read_server_proprietary_certificate(certificate, s);
1131 case CERT_CHAIN_VERSION_2:
1132 ret = certificate_read_server_x509_certificate_chain(certificate, s);
1136 WLog_ERR(TAG,
"invalid certificate chain version:%" PRIu32
"",
1137 dwVersion & CERT_CHAIN_VERSION_MASK);
1145static BOOL cert_blob_copy(rdpCertBlob* dst,
const rdpCertBlob* src)
1150 cert_blob_free(dst);
1151 if (src->length > 0)
1153 dst->data = malloc(src->length);
1156 dst->length = src->length;
1157 memcpy(dst->data, src->data, src->length);
1163static BOOL cert_x509_chain_copy(rdpX509CertChain* cert,
const rdpX509CertChain* src)
1167 certificate_free_x509_certificate_chain(cert);
1173 cert->array = calloc(src->count,
sizeof(rdpCertBlob));
1178 cert->count = src->count;
1180 for (UINT32 x = 0; x < cert->count; x++)
1182 const rdpCertBlob* srcblob = &src->array[x];
1183 rdpCertBlob* dstblob = &cert->array[x];
1185 if (!cert_blob_copy(dstblob, srcblob))
1187 certificate_free_x509_certificate_chain(cert);
1196BOOL cert_clone_int(rdpCertificate* dst,
const rdpCertificate* src)
1201 if (!cert_info_clone(&dst->cert_info, &src->cert_info))
1206 dst->x509 = X509_dup(src->x509);
1213 if (!update_x509_from_info(dst))
1215 WLog_ERR(TAG,
"X509_dup failed, SSL configuration bug?");
1224 sk_X509_pop_free(dst->chain, X509_free);
1226 dst->chain = sk_X509_deep_copy(src->chain, X509_const_dup, X509_free);
1228 return cert_x509_chain_copy(&dst->x509_cert_chain, &src->x509_cert_chain);
1231rdpCertificate* freerdp_certificate_clone(
const rdpCertificate* certificate)
1236 rdpCertificate* _certificate = freerdp_certificate_new();
1241 if (!cert_clone_int(_certificate, certificate))
1244 return _certificate;
1247 freerdp_certificate_free(_certificate);
1256rdpCertificate* freerdp_certificate_new(
void)
1258 return (rdpCertificate*)calloc(1,
sizeof(rdpCertificate));
1261void certificate_free_int(rdpCertificate* cert)
1266 X509_free(cert->x509);
1268 sk_X509_pop_free(cert->chain, X509_free);
1270 certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1271 cert_info_free(&cert->cert_info);
1279void freerdp_certificate_free(rdpCertificate* cert)
1284 certificate_free_int(cert);
1288static BOOL freerdp_rsa_from_x509(rdpCertificate* cert)
1294 if (!freerdp_certificate_is_rsa(cert))
1297#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1299 const BIGNUM* rsa_n =
nullptr;
1300 const BIGNUM* rsa_e =
nullptr;
1302 BIGNUM* rsa_n =
nullptr;
1303 BIGNUM* rsa_e =
nullptr;
1305 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1309#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1310 rsa = EVP_PKEY_get1_RSA(pubkey);
1320 RSA_get0_key(rsa, &rsa_n, &rsa_e,
nullptr);
1322 if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &rsa_e))
1324 if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &rsa_n))
1327 if (!rsa_n || !rsa_e)
1329 if (!cert_info_create(&cert->cert_info, rsa_n, rsa_e))
1333#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1342rdpCertificate* freerdp_certificate_new_from_der(
const BYTE* data,
size_t length)
1344 rdpCertificate* cert = freerdp_certificate_new();
1346 if (!cert || !data || (length == 0) || (length > INT_MAX))
1350 const BYTE* ptr = data;
1351 cert->x509 = d2i_X509(
nullptr, &ptr, (
int)length);
1356 if (!freerdp_rsa_from_x509(cert))
1360 freerdp_certificate_free(cert);
1364rdpCertificate* freerdp_certificate_new_from_x509(
const X509* xcert,
const STACK_OF(X509) * chain)
1366 WINPR_ASSERT(xcert);
1368 rdpCertificate* cert = freerdp_certificate_new();
1372 X509* wcert = WINPR_CAST_CONST_PTR_AWAY(xcert, X509*);
1373 cert->x509 = X509_dup(wcert);
1377 if (!freerdp_rsa_from_x509(cert))
1381 cert->chain = sk_X509_deep_copy(chain, X509_const_dup, X509_free);
1385 freerdp_certificate_free(cert);
1389static STACK_OF(X509) * extract_chain_from_pem(
const char* pem, BOOL isFile)
1398 bio = BIO_new_file(pem,
"rb");
1401 const size_t len = strlen(pem);
1402 bio = BIO_new_mem_buf(pem, WINPR_ASSERTING_INT_CAST(
int, len));
1410 X509* leaf = PEM_read_bio_X509(bio,
nullptr,
nullptr,
nullptr);
1417 STACK_OF(X509)* chain = sk_X509_new_null();
1425 X509* cert =
nullptr;
1426 while ((cert = PEM_read_bio_X509(bio,
nullptr,
nullptr,
nullptr)) !=
nullptr)
1428 sk_X509_push(chain, cert);
1436static rdpCertificate* freerdp_certificate_new_from(
const char* file, BOOL isFile)
1438 X509* x509 = x509_utils_from_pem(file, strlen(file), isFile);
1441 STACK_OF(X509)* chain = extract_chain_from_pem(file, isFile);
1442 rdpCertificate* cert = freerdp_certificate_new_from_x509(x509, chain);
1444 sk_X509_pop_free(chain, X509_free);
1449rdpCertificate* freerdp_certificate_new_from_file(
const char* file)
1451 return freerdp_certificate_new_from(file, TRUE);
1454rdpCertificate* freerdp_certificate_new_from_pem(
const char* pem)
1456 return freerdp_certificate_new_from(pem, FALSE);
1459const rdpCertInfo* freerdp_certificate_get_info(
const rdpCertificate* cert)
1462 if (!freerdp_certificate_is_rsa(cert))
1464 return &cert->cert_info;
1467char* freerdp_certificate_get_fingerprint(
const rdpCertificate* cert)
1469 return freerdp_certificate_get_fingerprint_by_hash(cert,
"sha256");
1472char* freerdp_certificate_get_fingerprint_by_hash(
const rdpCertificate* cert,
const char* hash)
1474 return freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, TRUE);
1477char* freerdp_certificate_get_fingerprint_by_hash_ex(
const rdpCertificate* cert,
const char* hash,
1484 char* fp_buffer =
nullptr;
1485 if (!cert || !cert->x509)
1487 WLog_ERR(TAG,
"Invalid certificate [%p, %p]", WINPR_CXX_COMPAT_CAST(
const void*, cert),
1488 WINPR_CXX_COMPAT_CAST(
const void*, cert ? cert->x509 : nullptr));
1493 WLog_ERR(TAG,
"Invalid certificate hash %p", WINPR_CXX_COMPAT_CAST(
const void*, hash));
1496 fp = x509_utils_get_hash(cert->x509, hash, &fp_len);
1503 size = fp_len * 3 + 1;
1504 fp_buffer = calloc(size,
sizeof(
char));
1512 for (; i < (fp_len - 1); i++)
1515 char* p = &fp_buffer[pos];
1517 rc = sprintf_s(p, size - pos,
"%02" PRIx8
":", fp[i]);
1519 rc = sprintf_s(p, size - pos,
"%02" PRIx8, fp[i]);
1525 (void)sprintf_s(&fp_buffer[pos], size - pos,
"%02" PRIx8
"", fp[i]);
1537char* freerdp_certificate_get_pem(
const rdpCertificate* cert,
size_t* pLength)
1539 return freerdp_certificate_get_pem_ex(cert, pLength, TRUE);
1542char* freerdp_certificate_get_pem_ex(
const rdpCertificate* cert,
size_t* pLength,
1554 BIO* bio = BIO_new(BIO_s_mem());
1558 WLog_ERR(TAG,
"BIO_new() failure");
1562 char* pem =
nullptr;
1564 const int status = PEM_write_bio_X509(bio, cert->x509);
1567 WLog_ERR(TAG,
"PEM_write_bio_X509 failure: %d", status);
1571 if (cert->chain && withCertChain)
1573 const int count = sk_X509_num(cert->chain);
1574 for (
int x = 0; x < count; x++)
1576 X509* c = sk_X509_value(cert->chain, x);
1577 const int rc = PEM_write_bio_X509(bio, c);
1580 WLog_ERR(TAG,
"PEM_write_bio_X509 failure: %d", rc);
1586 pem = x509_utils_bio_read(bio, pLength);
1593char* freerdp_certificate_get_subject(
const rdpCertificate* cert)
1596 return x509_utils_get_subject(cert->x509);
1599char* freerdp_certificate_get_issuer(
const rdpCertificate* cert)
1602 return x509_utils_get_issuer(cert->x509);
1605char* freerdp_certificate_get_upn(
const rdpCertificate* cert)
1608 return x509_utils_get_upn(cert->x509);
1611char* freerdp_certificate_get_email(
const rdpCertificate* cert)
1614 return x509_utils_get_email(cert->x509);
1617char* freerdp_certificate_get_validity(
const rdpCertificate* cert, BOOL startDate)
1620 return x509_utils_get_date(cert->x509, startDate);
1623BOOL freerdp_certificate_check_eku(
const rdpCertificate* cert,
int nid)
1626 return x509_utils_check_eku(cert->x509, nid);
1629BOOL freerdp_certificate_get_public_key(
const rdpCertificate* cert, BYTE** PublicKey,
1630 DWORD* PublicKeyLength)
1632 BYTE* ptr =
nullptr;
1633 BYTE* optr =
nullptr;
1635 BOOL status = FALSE;
1636 EVP_PKEY* pkey =
nullptr;
1640 pkey = X509_get0_pubkey(cert->x509);
1644 WLog_ERR(TAG,
"X509_get_pubkey() failed");
1648 length = i2d_PublicKey(pkey,
nullptr);
1652 WLog_ERR(TAG,
"i2d_PublicKey() failed");
1656 *PublicKey = optr = ptr = (BYTE*)calloc(WINPR_ASSERTING_INT_CAST(
size_t, length),
sizeof(BYTE));
1662 const int length2 = i2d_PublicKey(pkey, &ptr);
1663 if (length != length2)
1665 *PublicKeyLength = (DWORD)length2;
1676BOOL freerdp_certificate_verify(
const rdpCertificate* cert,
const char* certificate_store_path)
1679 return x509_utils_verify(cert->x509, cert->chain, certificate_store_path);
1682char** freerdp_certificate_get_dns_names(
const rdpCertificate* cert,
size_t* pcount,
1686 return x509_utils_get_dns_names(cert->x509, pcount, pplengths);
1689char** freerdp_certificate_get_ip_names(
const rdpCertificate* cert,
size_t* pcount,
1693 return x509_utils_get_ip_names(cert->x509, pcount, pplengths);
1696char* freerdp_certificate_get_common_name(
const rdpCertificate* cert,
size_t* plength)
1699 return x509_utils_get_common_name(cert->x509, plength);
1702WINPR_MD_TYPE freerdp_certificate_get_signature_alg(
const rdpCertificate* cert)
1705 return x509_utils_get_signature_alg(cert->x509);
1708void freerdp_certificate_free_dns_names(
size_t count,
size_t* lengths,
char** names)
1710 x509_utils_dns_names_free(count, lengths, names);
1713void freerdp_certificate_free_ip_names(
size_t count,
size_t* lengths,
char** names)
1715 x509_utils_ip_names_free(count, lengths, names);
1718char* freerdp_certificate_get_hash(
const rdpCertificate* cert,
const char* hash,
size_t* plength)
1721 return (
char*)x509_utils_get_hash(cert->x509, hash, plength);
1724X509* freerdp_certificate_get_x509(rdpCertificate* cert)
1730BOOL freerdp_certificate_publickey_encrypt(
const rdpCertificate* cert,
const BYTE* input,
1731 size_t cbInput, BYTE** poutput,
size_t* pcbOutput)
1734 WINPR_ASSERT(input);
1735 WINPR_ASSERT(poutput);
1736 WINPR_ASSERT(pcbOutput);
1739 BYTE* output =
nullptr;
1740 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1744 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey,
nullptr);
1748 size_t outputSize = WINPR_ASSERTING_INT_CAST(
size_t, EVP_PKEY_size(pkey));
1749 output = malloc(outputSize);
1750 if (output ==
nullptr)
1752 *pcbOutput = outputSize;
1754 if (EVP_PKEY_encrypt_init(ctx) != 1 ||
1755 EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) != 1 ||
1756 EVP_PKEY_encrypt(ctx, output, pcbOutput, input, cbInput) != 1)
1758 WLog_ERR(TAG,
"error when setting up public key");
1766 EVP_PKEY_CTX_free(ctx);
1771#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1772static RSA* freerdp_certificate_get_RSA(
const rdpCertificate* cert)
1776 if (!freerdp_certificate_is_rsa(cert))
1779 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1783 return EVP_PKEY_get1_RSA(pubkey);
1787BYTE* freerdp_certificate_get_der(
const rdpCertificate* cert,
size_t* pLength)
1794 const int rc = i2d_X509(cert->x509,
nullptr);
1798 BYTE* ptr = calloc(WINPR_ASSERTING_INT_CAST(
size_t, rc) + 1,
sizeof(BYTE));
1801 BYTE* i2d_ptr = ptr;
1803 const int rc2 = i2d_X509(cert->x509, &i2d_ptr);
1811 *pLength = (size_t)rc2;
1815BOOL freerdp_certificate_is_rsa(
const rdpCertificate* cert)
1818 return is_rsa_key(cert->x509);
1821BOOL freerdp_certificate_is_rdp_security_compatible(
const rdpCertificate* cert)
1823 const rdpCertInfo* info = freerdp_certificate_get_info(cert);
1824 if (!freerdp_certificate_is_rsa(cert) || !info || (info->ModulusLength != 2048 / 8))
1826 WLog_INFO(TAG,
"certificate is not RSA 2048, RDP security not supported.");
1832char* freerdp_certificate_get_param(
const rdpCertificate* cert,
enum FREERDP_CERT_PARAM what,
1836 WINPR_ASSERT(psize);
1840#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1841 const BIGNUM* bn =
nullptr;
1842 RSA* rsa = freerdp_certificate_get_RSA(cert);
1845 case FREERDP_CERT_RSA_E:
1846 RSA_get0_key(rsa,
nullptr, &bn,
nullptr);
1848 case FREERDP_CERT_RSA_N:
1849 RSA_get0_key(rsa, &bn,
nullptr,
nullptr);
1857 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1861 BIGNUM* bn =
nullptr;
1864 case FREERDP_CERT_RSA_E:
1865 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn))
1868 case FREERDP_CERT_RSA_N:
1869 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn))
1877 const size_t bnsize = WINPR_ASSERTING_INT_CAST(
size_t, BN_num_bytes(bn));
1878 char* rc = calloc(bnsize + 1,
sizeof(
char));
1881 BN_bn2bin(bn, (BYTE*)rc);
1885#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR < 3)
1891size_t freerdp_certificate_get_chain_len(rdpCertificate* certificate)
1893 WINPR_ASSERT(certificate);
1894 if (!certificate->chain)
1897 return WINPR_ASSERTING_INT_CAST(
size_t, sk_X509_num(certificate->chain));
1900X509* freerdp_certificate_get_chain_at(rdpCertificate* certificate,
size_t offset)
1902 WINPR_ASSERT(certificate);
1903 WINPR_ASSERT(freerdp_certificate_get_chain_len(certificate) > offset);
1904 const int ioff = WINPR_ASSERTING_INT_CAST(
int, offset);
1905 return sk_X509_value(certificate->chain, ioff);
1909static BOOL tls_match_hostname(
const char* pattern,
const size_t pattern_length,
1910 const char* hostname)
1912 WINPR_ASSERT(hostname);
1913 WINPR_ASSERT(pattern || (pattern_length == 0));
1915 const size_t hlen = strlen(hostname);
1916 if (hlen == pattern_length)
1918 if (_strnicmp(hostname, pattern, pattern_length) == 0)
1922 if ((pattern_length > 2) && (pattern[0] ==
'*') && (pattern[1] ==
'.') &&
1923 (hlen >= pattern_length))
1926 const size_t prefixlen = hlen - pattern_length;
1927 for (
size_t x = 0; x < prefixlen; x++)
1929 char cur = hostname[x];
1935 const char* check_hostname = &hostname[prefixlen + 1];
1936 return _strnicmp(check_hostname, &pattern[1], pattern_length - 1) == 0;
1942BOOL freerdp_certificate_matches_hostname(
const rdpCertificate* cert,
const char* hostname,
1946 size_t common_name_length = 0;
1947 size_t dns_names_count = 0;
1948 size_t* dns_names_lengths =
nullptr;
1949 size_t ip_names_count = 0;
1950 size_t* ip_names_lengths =
nullptr;
1952 char* common_name = freerdp_certificate_get_common_name(cert, &common_name_length);
1954 freerdp_certificate_get_dns_names(cert, &dns_names_count, &dns_names_lengths);
1955 char** ip_names = freerdp_certificate_get_ip_names(cert, &ip_names_count, &ip_names_lengths);
1957 BOOL hostname_match = FALSE;
1959 if (utils_is_valid_ip(hostname))
1961 if ((hostlen != 0) && ip_names && (ip_names_count > 0))
1963 for (
size_t index = 0; index < ip_names_count; index++)
1965 if (utils_compare_ip_strings(ip_names[index], ip_names_lengths[index], hostname,
1968 hostname_match = TRUE;
1977 if (!skip && dns_names)
1979 for (
size_t index = 0; index < dns_names_count; index++)
1981 if (tls_match_hostname(dns_names[index], dns_names_lengths[index], hostname))
1983 hostname_match = TRUE;
1991 if (!skip && common_name)
1993 if (tls_match_hostname(common_name, common_name_length, hostname))
1994 hostname_match = TRUE;
1997 freerdp_certificate_free_dns_names(dns_names_count, dns_names_lengths, dns_names);
1998 freerdp_certificate_free_ip_names(ip_names_count, ip_names_lengths, ip_names);
2000 return hostname_match;