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)
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)
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, NULL))
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 rdpX509CertChain certificate_new_x509_certificate_chain(UINT32 count)
444 rdpX509CertChain x509_cert_chain = { 0 };
446 x509_cert_chain.array = (rdpCertBlob*)calloc(count,
sizeof(rdpCertBlob));
448 if (x509_cert_chain.array)
449 x509_cert_chain.count = count;
451 return x509_cert_chain;
459static void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain)
461 if (!x509_cert_chain)
464 if (x509_cert_chain->array)
466 for (UINT32 i = 0; i < x509_cert_chain->count; i++)
468 rdpCertBlob* element = &x509_cert_chain->array[i];
469 cert_blob_free(element);
473 free(x509_cert_chain->array);
474 x509_cert_chain->array = NULL;
475 x509_cert_chain->count = 0;
478#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
479static OSSL_PARAM* get_params(
const BIGNUM* e,
const BIGNUM* mod)
484 OSSL_PARAM* parameters = NULL;
485 OSSL_PARAM_BLD* param = OSSL_PARAM_BLD_new();
488 WLog_ERR(TAG,
"OSSL_PARAM_BLD_new() failed");
492 const int bits = BN_num_bits(e);
493 if ((bits < 0) || (bits > 32))
495 WLog_ERR(TAG,
"BN_num_bits(e) out of range: 0 <= %d <= 32", bits);
502 const int ne = BN_bn2nativepad(e, (BYTE*)&ie,
sizeof(ie));
503 if ((ne < 0) || (ne > 4))
506 "BN_bn2nativepad(e, (BYTE*)&ie, sizeof(ie)) out of range: 0<= %d <= 4",
512 if (OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) != 1)
514 WLog_ERR(TAG,
"OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) failed");
517 if (OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) != 1)
519 WLog_ERR(TAG,
"OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) failed");
524 parameters = OSSL_PARAM_BLD_to_param(param);
526 WLog_ERR(TAG,
"OSSL_PARAM_BLD_to_param(param) failed");
528 OSSL_PARAM_BLD_free(param);
534static BOOL update_x509_from_info(rdpCertificate* cert)
540 X509_free(cert->x509);
543 rdpCertInfo* info = &cert->cert_info;
545 BIGNUM* e = BN_new();
546 BIGNUM* mod = BN_new();
547#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
548 RSA* rsa = RSA_new();
551 WLog_ERR(TAG,
"RSA_new() failed");
558 WLog_ERR(TAG,
"failure: mod=%p, e=%p", WINPR_CXX_COMPAT_CAST(
const void*, mod),
559 WINPR_CXX_COMPAT_CAST(
const void*, e));
563 WINPR_ASSERT(info->ModulusLength <= INT_MAX);
564 if (!BN_bin2bn(info->Modulus, (
int)info->ModulusLength, mod))
566 WLog_ERR(TAG,
"BN_bin2bn(info->Modulus, (int)info->ModulusLength, mod) failed");
570 if (!BN_bin2bn(info->exponent, (
int)
sizeof(info->exponent), e))
572 WLog_ERR(TAG,
"BN_bin2bn(info->exponent, (int)sizeof(info->exponent), e) failed");
576#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
577 const int rec = RSA_set0_key(rsa, mod, e, NULL);
580 WLog_ERR(TAG,
"RSA_set0_key(rsa, mod, e, NULL) failed");
584 cert->x509 = x509_from_rsa(rsa);
587 EVP_PKEY* pkey = NULL;
588 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
591 WLog_ERR(TAG,
"EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL) failed");
596 const int xx = EVP_PKEY_fromdata_init(ctx);
599 WLog_ERR(TAG,
"EVP_PKEY_fromdata_init(ctx) failed");
605 OSSL_PARAM* parameters = get_params(e, mod);
610 const int rc2 = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters);
611 OSSL_PARAM_free(parameters);
616 "EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters) failed");
622 cert->x509 = X509_new();
625 WLog_ERR(TAG,
"X509_new() failed");
629 if (X509_set_pubkey(cert->x509, pkey) != 1)
631 WLog_ERR(TAG,
"X509_set_pubkey(cert->x509, pkey) failed");
632 X509_free(cert->x509);
637 EVP_PKEY_CTX_free(ctx);
647 WLog_ERR(TAG,
"failed to update x509 from rdpCertInfo");
649#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
661static BOOL certificate_process_server_public_key(rdpCertificate* cert,
wStream* s,
662 WINPR_ATTR_UNUSED UINT32 length)
664 char magic[
sizeof(rsa_magic)] = { 0 };
672 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
675 Stream_Read(s, magic,
sizeof(magic));
677 if (memcmp(magic, rsa_magic,
sizeof(magic)) != 0)
679 WLog_ERR(TAG,
"invalid RSA magic bytes");
683 rdpCertInfo* info = &cert->cert_info;
684 cert_info_free(info);
686 Stream_Read_UINT32(s, keylen);
687 Stream_Read_UINT32(s, bitlen);
688 Stream_Read_UINT32(s, datalen);
689 Stream_Read(s, info->exponent, 4);
693 WLog_ERR(TAG,
"Invalid RSA keylen=%" PRIu32
" <= 8", keylen);
696 if (!Stream_CheckAndLogRequiredLength(TAG, s, keylen))
698 if (keylen != (bitlen / 8ull) + 8ull)
700 WLog_ERR(TAG,
"Invalid RSA key bitlen %" PRIu32
", expected %" PRIu32, bitlen,
704 if (datalen != (bitlen / 8ull) - 1ull)
706 WLog_ERR(TAG,
"Invalid RSA key datalen %" PRIu32
", expected %llu", datalen,
707 (1ull * bitlen / 8ull) - 1ull);
710 info->ModulusLength = keylen - 8;
711 BYTE* tmp = realloc(info->Modulus, info->ModulusLength);
715 WLog_ERR(TAG,
"Failed to reallocate modulus of length %" PRIu32, info->ModulusLength);
720 Stream_Read(s, info->Modulus, info->ModulusLength);
722 return update_x509_from_info(cert);
725static BOOL certificate_process_server_public_signature(rdpCertificate* certificate,
726 const BYTE* sigdata,
size_t sigdatalen,
729 WINPR_ASSERT(certificate);
730#if defined(CERT_VALIDATE_RSA)
731 BYTE sig[TSSK_KEY_LENGTH];
733 BYTE encsig[TSSK_KEY_LENGTH + 8];
734#if defined(CERT_VALIDATE_MD5) && defined(CERT_VALIDATE_RSA)
735 BYTE md5hash[WINPR_MD5_DIGEST_LENGTH];
737#if !defined(CERT_VALIDATE_MD5) || !defined(CERT_VALIDATE_RSA)
748#if defined(CERT_VALIDATE_MD5)
750 if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash,
sizeof(md5hash)))
754 Stream_Read(s, encsig, siglen);
760#if defined(CERT_VALIDATE_PADDING)
763 for (
size_t i =
sizeof(encsig) - 8; i <
sizeof(encsig); i++)
768 WLog_ERR(TAG,
"invalid signature");
773#if defined(CERT_VALIDATE_RSA)
775 if (crypto_rsa_public_decrypt(encsig, siglen - 8, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent,
778 WLog_ERR(TAG,
"invalid RSA decrypt");
784#if defined(CERT_VALIDATE_MD5)
786 if (memcmp(md5hash, sig,
sizeof(md5hash)) != 0)
788 WLog_ERR(TAG,
"invalid signature");
801 for (
size_t i = 17; i < 62; i++)
804 if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01)
806 WLog_ERR(TAG,
"invalid signature");
814static BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate,
wStream* s)
816 UINT32 dwSigAlgId = 0;
817 UINT32 dwKeyAlgId = 0;
818 UINT16 wPublicKeyBlobType = 0;
819 UINT16 wPublicKeyBlobLen = 0;
820 UINT16 wSignatureBlobType = 0;
821 UINT16 wSignatureBlobLen = 0;
822 size_t sigdatalen = 0;
824 WINPR_ASSERT(certificate);
825 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
829 const BYTE* sigdata = Stream_PointerAs(s,
const BYTE) - 4;
830 Stream_Read_UINT32(s, dwSigAlgId);
831 Stream_Read_UINT32(s, dwKeyAlgId);
833 if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
836 "unsupported signature or key algorithm, dwSigAlgId=%" PRIu32
837 " dwKeyAlgId=%" PRIu32
"",
838 dwSigAlgId, dwKeyAlgId);
842 Stream_Read_UINT16(s, wPublicKeyBlobType);
844 if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
846 WLog_ERR(TAG,
"unsupported public key blob type %" PRIu16
"", wPublicKeyBlobType);
850 Stream_Read_UINT16(s, wPublicKeyBlobLen);
852 if (!Stream_CheckAndLogRequiredLength(TAG, s, wPublicKeyBlobLen))
855 if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
858 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
861 sigdatalen = WINPR_ASSERTING_INT_CAST(
size_t, Stream_PointerAs(s,
const BYTE) - sigdata);
862 Stream_Read_UINT16(s, wSignatureBlobType);
864 if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
866 WLog_ERR(TAG,
"unsupported blob signature %" PRIu16
"", wSignatureBlobType);
870 Stream_Read_UINT16(s, wSignatureBlobLen);
872 if (!Stream_CheckAndLogRequiredLength(TAG, s, wSignatureBlobLen))
875 if (wSignatureBlobLen != 72)
877 WLog_ERR(TAG,
"invalid signature length (got %" PRIu16
", expected 72)", wSignatureBlobLen);
881 if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s,
884 WLog_ERR(TAG,
"unable to parse server public signature");
891static BOOL cert_write_rsa_public_key(
wStream* s,
const rdpCertificate* cert)
894 WINPR_ASSERT(freerdp_certificate_is_rsa(cert));
896 const rdpCertInfo* info = &cert->cert_info;
898 const UINT32 keyLen = info->ModulusLength + 8;
899 const UINT32 bitLen = info->ModulusLength * 8;
900 const UINT32 dataLen = (bitLen / 8) - 1;
901 const size_t pubExpLen =
sizeof(info->exponent);
902 const BYTE* pubExp = info->exponent;
903 const BYTE* modulus = info->Modulus;
905 const size_t wPublicKeyBlobLen = 16 + pubExpLen + keyLen;
906 WINPR_ASSERT(wPublicKeyBlobLen <= UINT16_MAX);
907 if (!Stream_EnsureRemainingCapacity(s, 2 + wPublicKeyBlobLen))
909 Stream_Write_UINT16(s, (UINT16)wPublicKeyBlobLen);
910 Stream_Write(s, rsa_magic,
sizeof(rsa_magic));
911 Stream_Write_UINT32(s, keyLen);
912 Stream_Write_UINT32(s, bitLen);
913 Stream_Write_UINT32(s, dataLen);
914 Stream_Write(s, pubExp, pubExpLen);
915 Stream_Write(s, modulus, info->ModulusLength);
920static BOOL cert_write_rsa_signature(
wStream* s,
const void* sigData,
size_t sigDataLen)
922 BYTE encryptedSignature[TSSK_KEY_LENGTH] = { 0 };
923 BYTE signature[
sizeof(initial_signature)] = { 0 };
925 memcpy(signature, initial_signature,
sizeof(initial_signature));
926 if (!winpr_Digest(WINPR_MD_MD5, sigData, sigDataLen, signature,
sizeof(signature)))
929 crypto_rsa_private_encrypt(signature,
sizeof(signature), priv_key_tssk, encryptedSignature,
930 sizeof(encryptedSignature));
932 if (!Stream_EnsureRemainingCapacity(s, 2 *
sizeof(UINT16) +
sizeof(encryptedSignature) + 8))
934 Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB);
935 Stream_Write_UINT16(s,
sizeof(encryptedSignature) + 8);
936 Stream_Write(s, encryptedSignature,
sizeof(encryptedSignature));
942static BOOL cert_write_server_certificate_v1(
wStream* s,
const rdpCertificate* certificate)
944 const size_t start = Stream_GetPosition(s);
945 const BYTE* sigData = Stream_PointerAs(s,
const BYTE) -
sizeof(UINT32);
947 WINPR_ASSERT(start >= 4);
948 if (!Stream_EnsureRemainingCapacity(s, 10))
950 Stream_Write_UINT32(s, SIGNATURE_ALG_RSA);
951 Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA);
952 Stream_Write_UINT16(s, BB_RSA_KEY_BLOB);
953 if (!cert_write_rsa_public_key(s, certificate))
956 const size_t end = Stream_GetPosition(s);
957 return cert_write_rsa_signature(s, sigData, end - start +
sizeof(UINT32));
960static BOOL cert_write_server_certificate_v2(
wStream* s,
const rdpCertificate* certificate)
962 WINPR_ASSERT(certificate);
964 const rdpX509CertChain* chain = &certificate->x509_cert_chain;
965 const size_t padding = 8ull + 4ull * chain->count;
967 if (!Stream_EnsureRemainingCapacity(s,
sizeof(UINT32)))
970 Stream_Write_UINT32(s, chain->count);
971 for (UINT32 x = 0; x < chain->count; x++)
973 const rdpCertBlob* cert = &chain->array[x];
974 if (!cert_blob_write(cert, s))
978 if (!Stream_EnsureRemainingCapacity(s, padding))
980 Stream_Zero(s, padding);
984SSIZE_T freerdp_certificate_write_server_cert(
const rdpCertificate* certificate, UINT32 dwVersion,
990 const size_t start = Stream_GetPosition(s);
991 if (!Stream_EnsureRemainingCapacity(s, 4))
993 Stream_Write_UINT32(s, dwVersion);
995 switch (dwVersion & CERT_CHAIN_VERSION_MASK)
997 case CERT_CHAIN_VERSION_1:
998 if (!cert_write_server_certificate_v1(s, certificate))
1001 case CERT_CHAIN_VERSION_2:
1002 if (!cert_write_server_certificate_v2(s, certificate))
1006 WLog_ERR(TAG,
"invalid certificate chain version:%" PRIu32
"",
1007 dwVersion & CERT_CHAIN_VERSION_MASK);
1011 const size_t end = Stream_GetPosition(s);
1015 const size_t diff = end - start;
1016 WINPR_ASSERT(diff <= SSIZE_MAX);
1017 return (SSIZE_T)diff;
1027static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* cert,
wStream* s)
1029 UINT32 numCertBlobs = 0;
1030 DEBUG_CERTIFICATE(
"Server X.509 Certificate Chain");
1033 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1036 Stream_Read_UINT32(s, numCertBlobs);
1037 certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1038 cert->x509_cert_chain = certificate_new_x509_certificate_chain(numCertBlobs);
1040 for (UINT32 i = 0; i < cert->x509_cert_chain.count; i++)
1042 rdpCertBlob* blob = &cert->x509_cert_chain.array[i];
1043 if (!cert_blob_read(blob, s))
1046 if (numCertBlobs - i == 1)
1048 DEBUG_CERTIFICATE(
"Terminal Server Certificate");
1050 BOOL res = certificate_read_x509_certificate(blob, &cert->cert_info);
1054 if (!update_x509_from_info(cert))
1060 WLog_ERR(TAG,
"Failed to read x509 certificate");
1064 DEBUG_CERTIFICATE(
"modulus length:%" PRIu32
"", cert->cert_info.ModulusLength);
1068 return update_x509_from_info(cert);
1078BOOL freerdp_certificate_read_server_cert(rdpCertificate* certificate,
const BYTE* server_cert,
1084 UINT32 dwVersion = 0;
1086 WINPR_ASSERT(certificate);
1089 WLog_DBG(TAG,
"Received empty certificate, ignoring...");
1093 WINPR_ASSERT(server_cert);
1094 s = Stream_StaticConstInit(&sbuffer, server_cert, length);
1098 WLog_ERR(TAG,
"Stream_New failed!");
1102 Stream_Read_UINT32(s, dwVersion);
1104 switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1106 case CERT_CHAIN_VERSION_1:
1107 ret = certificate_read_server_proprietary_certificate(certificate, s);
1110 case CERT_CHAIN_VERSION_2:
1111 ret = certificate_read_server_x509_certificate_chain(certificate, s);
1115 WLog_ERR(TAG,
"invalid certificate chain version:%" PRIu32
"",
1116 dwVersion & CERT_CHAIN_VERSION_MASK);
1124static BOOL cert_blob_copy(rdpCertBlob* dst,
const rdpCertBlob* src)
1129 cert_blob_free(dst);
1130 if (src->length > 0)
1132 dst->data = malloc(src->length);
1135 dst->length = src->length;
1136 memcpy(dst->data, src->data, src->length);
1142static BOOL cert_x509_chain_copy(rdpX509CertChain* cert,
const rdpX509CertChain* src)
1146 certificate_free_x509_certificate_chain(cert);
1152 cert->array = calloc(src->count,
sizeof(rdpCertBlob));
1157 cert->count = src->count;
1159 for (UINT32 x = 0; x < cert->count; x++)
1161 const rdpCertBlob* srcblob = &src->array[x];
1162 rdpCertBlob* dstblob = &cert->array[x];
1164 if (!cert_blob_copy(dstblob, srcblob))
1166 certificate_free_x509_certificate_chain(cert);
1175BOOL cert_clone_int(rdpCertificate* dst,
const rdpCertificate* src)
1180 if (!cert_info_clone(&dst->cert_info, &src->cert_info))
1185 dst->x509 = X509_dup(src->x509);
1192 if (!update_x509_from_info(dst))
1194 WLog_ERR(TAG,
"X509_dup failed, SSL configuration bug?");
1203 sk_X509_pop_free(dst->chain, X509_free);
1205 dst->chain = sk_X509_deep_copy(src->chain, X509_const_dup, X509_free);
1207 return cert_x509_chain_copy(&dst->x509_cert_chain, &src->x509_cert_chain);
1210rdpCertificate* freerdp_certificate_clone(
const rdpCertificate* certificate)
1215 rdpCertificate* _certificate = freerdp_certificate_new();
1220 if (!cert_clone_int(_certificate, certificate))
1223 return _certificate;
1226 freerdp_certificate_free(_certificate);
1235rdpCertificate* freerdp_certificate_new(
void)
1237 return (rdpCertificate*)calloc(1,
sizeof(rdpCertificate));
1240void certificate_free_int(rdpCertificate* cert)
1245 X509_free(cert->x509);
1247 sk_X509_pop_free(cert->chain, X509_free);
1249 certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1250 cert_info_free(&cert->cert_info);
1258void freerdp_certificate_free(rdpCertificate* cert)
1263 certificate_free_int(cert);
1267static BOOL freerdp_rsa_from_x509(rdpCertificate* cert)
1273 if (!freerdp_certificate_is_rsa(cert))
1276#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1278 const BIGNUM* rsa_n = NULL;
1279 const BIGNUM* rsa_e = NULL;
1281 BIGNUM* rsa_n = NULL;
1282 BIGNUM* rsa_e = NULL;
1284 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1288#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1289 rsa = EVP_PKEY_get1_RSA(pubkey);
1299 RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
1301 if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &rsa_e))
1303 if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &rsa_n))
1306 if (!rsa_n || !rsa_e)
1308 if (!cert_info_create(&cert->cert_info, rsa_n, rsa_e))
1312#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1321rdpCertificate* freerdp_certificate_new_from_der(
const BYTE* data,
size_t length)
1323 rdpCertificate* cert = freerdp_certificate_new();
1325 if (!cert || !data || (length == 0) || (length > INT_MAX))
1329 const BYTE* ptr = data;
1330 cert->x509 = d2i_X509(NULL, &ptr, (
int)length);
1335 if (!freerdp_rsa_from_x509(cert))
1339 freerdp_certificate_free(cert);
1343rdpCertificate* freerdp_certificate_new_from_x509(
const X509* xcert,
const STACK_OF(X509) * chain)
1345 WINPR_ASSERT(xcert);
1347 rdpCertificate* cert = freerdp_certificate_new();
1351 X509* wcert = WINPR_CAST_CONST_PTR_AWAY(xcert, X509*);
1352 cert->x509 = X509_dup(wcert);
1356 if (!freerdp_rsa_from_x509(cert))
1360 cert->chain = sk_X509_deep_copy(chain, X509_const_dup, X509_free);
1364 freerdp_certificate_free(cert);
1368static STACK_OF(X509) * extract_chain_from_pem(
const char* pem, BOOL isFile)
1377 bio = BIO_new_file(pem,
"rb");
1380 const size_t len = strlen(pem);
1381 bio = BIO_new_mem_buf(pem, WINPR_ASSERTING_INT_CAST(
int, len));
1389 X509* leaf = PEM_read_bio_X509(bio, NULL, NULL, NULL);
1396 STACK_OF(X509)* chain = sk_X509_new_null();
1405 while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL)
1407 sk_X509_push(chain, cert);
1415static rdpCertificate* freerdp_certificate_new_from(
const char* file, BOOL isFile)
1417 X509* x509 = x509_utils_from_pem(file, strlen(file), isFile);
1420 STACK_OF(X509)* chain = extract_chain_from_pem(file, isFile);
1421 rdpCertificate* cert = freerdp_certificate_new_from_x509(x509, chain);
1423 sk_X509_pop_free(chain, X509_free);
1428rdpCertificate* freerdp_certificate_new_from_file(
const char* file)
1430 return freerdp_certificate_new_from(file, TRUE);
1433rdpCertificate* freerdp_certificate_new_from_pem(
const char* pem)
1435 return freerdp_certificate_new_from(pem, FALSE);
1438const rdpCertInfo* freerdp_certificate_get_info(
const rdpCertificate* cert)
1441 if (!freerdp_certificate_is_rsa(cert))
1443 return &cert->cert_info;
1446char* freerdp_certificate_get_fingerprint(
const rdpCertificate* cert)
1448 return freerdp_certificate_get_fingerprint_by_hash(cert,
"sha256");
1451char* freerdp_certificate_get_fingerprint_by_hash(
const rdpCertificate* cert,
const char* hash)
1453 return freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, TRUE);
1456char* freerdp_certificate_get_fingerprint_by_hash_ex(
const rdpCertificate* cert,
const char* hash,
1463 char* fp_buffer = NULL;
1464 if (!cert || !cert->x509)
1466 WLog_ERR(TAG,
"Invalid certificate [%p, %p]", WINPR_CXX_COMPAT_CAST(
const void*, cert),
1467 WINPR_CXX_COMPAT_CAST(
const void*, cert ? cert->x509 : NULL));
1472 WLog_ERR(TAG,
"Invalid certificate hash %p", WINPR_CXX_COMPAT_CAST(
const void*, hash));
1475 fp = x509_utils_get_hash(cert->x509, hash, &fp_len);
1482 size = fp_len * 3 + 1;
1483 fp_buffer = calloc(size,
sizeof(
char));
1491 for (; i < (fp_len - 1); i++)
1494 char* p = &fp_buffer[pos];
1496 rc = sprintf_s(p, size - pos,
"%02" PRIx8
":", fp[i]);
1498 rc = sprintf_s(p, size - pos,
"%02" PRIx8, fp[i]);
1504 (void)sprintf_s(&fp_buffer[pos], size - pos,
"%02" PRIx8
"", fp[i]);
1516static BOOL bio_read_pem(BIO* bio,
char** ppem,
size_t* plength)
1523 const size_t blocksize = 2048;
1525 size_t length = blocksize;
1532 while (offset < length)
1534 char* tmp = realloc(pem, length + 1);
1541 const int status = BIO_read(bio, &pem[offset], (
int)(length - offset));
1544 WLog_ERR(TAG,
"failed to read certificate");
1551 offset += (size_t)status;
1552 if (length - offset > 0)
1554 length += blocksize;
1559 if (offset >= length)
1574char* freerdp_certificate_get_pem(
const rdpCertificate* cert,
size_t* pLength)
1576 return freerdp_certificate_get_pem_ex(cert, pLength, TRUE);
1579char* freerdp_certificate_get_pem_ex(
const rdpCertificate* cert,
size_t* pLength,
1591 BIO* bio = BIO_new(BIO_s_mem());
1595 WLog_ERR(TAG,
"BIO_new() failure");
1601 const int status = PEM_write_bio_X509(bio, cert->x509);
1604 WLog_ERR(TAG,
"PEM_write_bio_X509 failure: %d", status);
1608 if (cert->chain && withCertChain)
1610 const int count = sk_X509_num(cert->chain);
1611 for (
int x = 0; x < count; x++)
1613 X509* c = sk_X509_value(cert->chain, x);
1614 const int rc = PEM_write_bio_X509(bio, c);
1617 WLog_ERR(TAG,
"PEM_write_bio_X509 failure: %d", rc);
1623 (void)bio_read_pem(bio, &pem, pLength);
1630char* freerdp_certificate_get_subject(
const rdpCertificate* cert)
1633 return x509_utils_get_subject(cert->x509);
1636char* freerdp_certificate_get_issuer(
const rdpCertificate* cert)
1639 return x509_utils_get_issuer(cert->x509);
1642char* freerdp_certificate_get_upn(
const rdpCertificate* cert)
1645 return x509_utils_get_upn(cert->x509);
1648char* freerdp_certificate_get_email(
const rdpCertificate* cert)
1651 return x509_utils_get_email(cert->x509);
1654char* freerdp_certificate_get_validity(
const rdpCertificate* cert, BOOL startDate)
1657 return x509_utils_get_date(cert->x509, startDate);
1660BOOL freerdp_certificate_check_eku(
const rdpCertificate* cert,
int nid)
1663 return x509_utils_check_eku(cert->x509, nid);
1666BOOL freerdp_certificate_get_public_key(
const rdpCertificate* cert, BYTE** PublicKey,
1667 DWORD* PublicKeyLength)
1672 BOOL status = FALSE;
1673 EVP_PKEY* pkey = NULL;
1677 pkey = X509_get0_pubkey(cert->x509);
1681 WLog_ERR(TAG,
"X509_get_pubkey() failed");
1685 length = i2d_PublicKey(pkey, NULL);
1689 WLog_ERR(TAG,
"i2d_PublicKey() failed");
1693 *PublicKey = optr = ptr = (BYTE*)calloc(WINPR_ASSERTING_INT_CAST(
size_t, length),
sizeof(BYTE));
1699 const int length2 = i2d_PublicKey(pkey, &ptr);
1700 if (length != length2)
1702 *PublicKeyLength = (DWORD)length2;
1713BOOL freerdp_certificate_verify(
const rdpCertificate* cert,
const char* certificate_store_path)
1716 return x509_utils_verify(cert->x509, cert->chain, certificate_store_path);
1719char** freerdp_certificate_get_dns_names(
const rdpCertificate* cert,
size_t* pcount,
1723 return x509_utils_get_dns_names(cert->x509, pcount, pplengths);
1726char* freerdp_certificate_get_common_name(
const rdpCertificate* cert,
size_t* plength)
1729 return x509_utils_get_common_name(cert->x509, plength);
1732WINPR_MD_TYPE freerdp_certificate_get_signature_alg(
const rdpCertificate* cert)
1735 return x509_utils_get_signature_alg(cert->x509);
1738void freerdp_certificate_free_dns_names(
size_t count,
size_t* lengths,
char** names)
1740 x509_utils_dns_names_free(count, lengths, names);
1743char* freerdp_certificate_get_hash(
const rdpCertificate* cert,
const char* hash,
size_t* plength)
1746 return (
char*)x509_utils_get_hash(cert->x509, hash, plength);
1749X509* freerdp_certificate_get_x509(rdpCertificate* cert)
1755BOOL freerdp_certificate_publickey_encrypt(
const rdpCertificate* cert,
const BYTE* input,
1756 size_t cbInput, BYTE** poutput,
size_t* pcbOutput)
1759 WINPR_ASSERT(input);
1760 WINPR_ASSERT(poutput);
1761 WINPR_ASSERT(pcbOutput);
1764 BYTE* output = NULL;
1765 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1769 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
1773 size_t outputSize = WINPR_ASSERTING_INT_CAST(
size_t, EVP_PKEY_size(pkey));
1774 output = malloc(outputSize);
1777 *pcbOutput = outputSize;
1779 if (EVP_PKEY_encrypt_init(ctx) != 1 ||
1780 EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) != 1 ||
1781 EVP_PKEY_encrypt(ctx, output, pcbOutput, input, cbInput) != 1)
1783 WLog_ERR(TAG,
"error when setting up public key");
1791 EVP_PKEY_CTX_free(ctx);
1796#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1797static RSA* freerdp_certificate_get_RSA(
const rdpCertificate* cert)
1801 if (!freerdp_certificate_is_rsa(cert))
1804 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1808 return EVP_PKEY_get1_RSA(pubkey);
1812BYTE* freerdp_certificate_get_der(
const rdpCertificate* cert,
size_t* pLength)
1819 const int rc = i2d_X509(cert->x509, NULL);
1823 BYTE* ptr = calloc(WINPR_ASSERTING_INT_CAST(
size_t, rc) + 1,
sizeof(BYTE));
1826 BYTE* i2d_ptr = ptr;
1828 const int rc2 = i2d_X509(cert->x509, &i2d_ptr);
1836 *pLength = (size_t)rc2;
1840BOOL freerdp_certificate_is_rsa(
const rdpCertificate* cert)
1843 return is_rsa_key(cert->x509);
1846BOOL freerdp_certificate_is_rdp_security_compatible(
const rdpCertificate* cert)
1848 const rdpCertInfo* info = freerdp_certificate_get_info(cert);
1849 if (!freerdp_certificate_is_rsa(cert) || !info || (info->ModulusLength != 2048 / 8))
1851 WLog_INFO(TAG,
"certificate is not RSA 2048, RDP security not supported.");
1857char* freerdp_certificate_get_param(
const rdpCertificate* cert,
enum FREERDP_CERT_PARAM what,
1861 WINPR_ASSERT(psize);
1865#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1866 const BIGNUM* bn = NULL;
1867 RSA* rsa = freerdp_certificate_get_RSA(cert);
1870 case FREERDP_CERT_RSA_E:
1871 RSA_get0_key(rsa, NULL, &bn, NULL);
1873 case FREERDP_CERT_RSA_N:
1874 RSA_get0_key(rsa, &bn, NULL, NULL);
1882 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1889 case FREERDP_CERT_RSA_E:
1890 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn))
1893 case FREERDP_CERT_RSA_N:
1894 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn))
1902 const size_t bnsize = WINPR_ASSERTING_INT_CAST(
size_t, BN_num_bytes(bn));
1903 char* rc = calloc(bnsize + 1,
sizeof(
char));
1906 BN_bn2bin(bn, (BYTE*)rc);
1910#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR < 3)
1916size_t freerdp_certificate_get_chain_len(rdpCertificate* certificate)
1918 WINPR_ASSERT(certificate);
1919 if (!certificate->chain)
1922 return WINPR_ASSERTING_INT_CAST(
size_t, sk_X509_num(certificate->chain));
1925X509* freerdp_certificate_get_chain_at(rdpCertificate* certificate,
size_t offset)
1927 WINPR_ASSERT(certificate);
1928 WINPR_ASSERT(freerdp_certificate_get_chain_len(certificate) > offset);
1929 const int ioff = WINPR_ASSERTING_INT_CAST(
int, offset);
1930 return sk_X509_value(certificate->chain, ioff);