FreeRDP
Loading...
Searching...
No Matches
certificate.c
1
25#include <freerdp/config.h>
26
27#include <errno.h>
28#include <stdio.h>
29#include <string.h>
30
31#include <winpr/assert.h>
32#include <winpr/wtypes.h>
33#include <winpr/crt.h>
34#include <winpr/file.h>
35#include <winpr/print.h>
36#include <winpr/crypto.h>
37
38#include <freerdp/crypto/certificate.h>
39
40#include <openssl/err.h>
41#include <openssl/pem.h>
42#include <openssl/rsa.h>
43#include <openssl/bn.h>
44
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>
50#endif
51
52#include "certificate.h"
53#include "cert_common.h"
54#include "crypto.h"
55
56#include "x509_utils.h"
57#include "privatekey.h"
58#include "opensslcompat.h"
59
60#define TAG FREERDP_TAG("core")
61
62#ifdef WITH_DEBUG_CERTIFICATE
63#define CERTIFICATE_TAG FREERDP_TAG("core.certificate")
64#define DEBUG_CERTIFICATE(...) WLog_DBG(TAG, __VA_ARGS__)
65#else
66#define DEBUG_CERTIFICATE(...) \
67 do \
68 { \
69 } while (0)
70#endif
71
72#define TSSK_KEY_LENGTH 64
73
74struct rdp_CertBlob
75{
76 UINT32 length;
77 BYTE* data;
78};
79typedef struct rdp_CertBlob rdpCertBlob;
80
81struct rdp_X509CertChain
82{
83 UINT32 count;
84 rdpCertBlob* array;
85};
86typedef struct rdp_X509CertChain rdpX509CertChain;
87
88struct rdp_certificate
89{
90 X509* x509;
91 STACK_OF(X509) * chain;
92
93 rdpCertInfo cert_info;
94 rdpX509CertChain x509_cert_chain;
95};
96
185static const char rsa_magic[4] = { 'R', 'S', 'A', '1' };
186
187static const char* certificate_read_errors[] = { "Certificate tag",
188 "TBSCertificate",
189 "Explicit Contextual Tag [0]",
190 "version",
191 "CertificateSerialNumber",
192 "AlgorithmIdentifier",
193 "Issuer Name",
194 "Validity",
195 "Subject Name",
196 "SubjectPublicKeyInfo Tag",
197 "subjectPublicKeyInfo::AlgorithmIdentifier",
198 "subjectPublicKeyInfo::subjectPublicKey",
199 "RSAPublicKey Tag",
200 "modulusLength",
201 "zero padding",
202 "modulusLength",
203 "modulus",
204 "publicExponent length",
205 "publicExponent" };
206
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
212};
213
214#if defined(CERT_VALIDATE_RSA)
215static const BYTE tssk_exponent[] = { 0x5b, 0x7b, 0x88, 0xc0 };
216#endif
217
218static void certificate_free_int(rdpCertificate* certificate);
219static BOOL cert_clone_int(rdpCertificate* dst, const rdpCertificate* src);
220
221/* [MS-RDPBCGR] 5.3.3.2 X.509 Certificate Chains:
222 *
223 * More detail[MS-RDPELE] section 2.2.1.4.2.
224 */
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);
229
230BOOL cert_blob_read(rdpCertBlob* blob, wStream* s)
231{
232 UINT32 certLength = 0;
233 WINPR_ASSERT(blob);
234 cert_blob_free(blob);
235
236 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
237 goto fail;
238
239 Stream_Read_UINT32(s, certLength);
240
241 if (!Stream_CheckAndLogRequiredLength(TAG, s, certLength))
242 goto fail;
243
244 DEBUG_CERTIFICATE("X.509 Certificate length:%" PRIu32 "", certLength);
245 blob->data = (BYTE*)malloc(certLength);
246
247 if (!blob->data)
248 goto fail;
249
250 Stream_Read(s, blob->data, certLength);
251 blob->length = certLength;
252
253 return TRUE;
254
255fail:
256 cert_blob_free(blob);
257 return FALSE;
258}
259
260BOOL cert_blob_write(const rdpCertBlob* blob, wStream* s)
261{
262 WINPR_ASSERT(blob);
263
264 if (!Stream_EnsureRemainingCapacity(s, 4 + blob->length))
265 return FALSE;
266
267 Stream_Write_UINT32(s, blob->length);
268 Stream_Write(s, blob->data, blob->length);
269 return TRUE;
270}
271
272void cert_blob_free(rdpCertBlob* blob)
273{
274 if (!blob)
275 return;
276 free(blob->data);
277 blob->data = nullptr;
278 blob->length = 0;
279}
280
285static BOOL is_rsa_key(const X509* x509)
286{
287 EVP_PKEY* evp = X509_get0_pubkey(x509);
288 if (!evp)
289 return FALSE;
290
291 return (EVP_PKEY_id(evp) == EVP_PKEY_RSA);
292}
293
294static BOOL certificate_read_x509_certificate(const rdpCertBlob* cert, rdpCertInfo* info)
295{
296 wStream sbuffer = WINPR_C_ARRAY_INIT;
297 wStream* s = nullptr;
298 size_t length = 0;
299 BYTE padding = 0;
300 UINT32 version = 0;
301 size_t modulus_length = 0;
302 size_t exponent_length = 0;
303 int error = 0;
304
305 WINPR_ASSERT(cert);
306 WINPR_ASSERT(info);
307
308 cert_info_free(info);
309
310 s = Stream_StaticConstInit(&sbuffer, cert->data, cert->length);
311
312 if (!s)
313 return FALSE;
314
315 if (!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */
316 goto error;
317
318 error++;
319
320 if (!ber_read_sequence_tag(s, &length)) /* TBSCertificate (SEQUENCE) */
321 goto error;
322
323 error++;
324
325 if (!ber_read_contextual_tag(s, 0, &length, TRUE)) /* Explicit Contextual Tag [0] */
326 goto error;
327
328 error++;
329
330 if (!ber_read_integer(s, &version)) /* version (INTEGER) */
331 goto error;
332
333 error++;
334 version++;
335
336 /* serialNumber */
337 if (!ber_read_integer(s, nullptr)) /* CertificateSerialNumber (INTEGER) */
338 goto error;
339
340 error++;
341
342 /* signature */
343 if (!ber_read_sequence_tag(s, &length) ||
344 !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */
345 goto error;
346
347 error++;
348
349 /* issuer */
350 if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */
351 goto error;
352
353 error++;
354
355 /* validity */
356 if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Validity (SEQUENCE) */
357 goto error;
358
359 error++;
360
361 /* subject */
362 if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */
363 goto error;
364
365 error++;
366
367 /* subjectPublicKeyInfo */
368 if (!ber_read_sequence_tag(s, &length)) /* SubjectPublicKeyInfo (SEQUENCE) */
369 goto error;
370
371 error++;
372
373 /* subjectPublicKeyInfo::AlgorithmIdentifier */
374 if (!ber_read_sequence_tag(s, &length) ||
375 !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */
376 goto error;
377
378 error++;
379
380 /* subjectPublicKeyInfo::subjectPublicKey */
381 if (!ber_read_bit_string(s, &length, &padding)) /* BIT_STRING */
382 goto error;
383
384 error++;
385
386 /* RSAPublicKey (SEQUENCE) */
387 if (!ber_read_sequence_tag(s, &length)) /* SEQUENCE */
388 goto error;
389
390 error++;
391
392 if (!ber_read_integer_length(s, &modulus_length)) /* modulus (INTEGER) */
393 goto error;
394
395 error++;
396
397 /* skip zero padding, if any */
398 do
399 {
400 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
401 goto error;
402
403 Stream_Peek_UINT8(s, padding);
404
405 if (padding == 0)
406 {
407 if (!Stream_SafeSeek(s, 1))
408 goto error;
409
410 modulus_length--;
411 }
412 } while (padding == 0);
413
414 error++;
415
416 if (!cert_info_read_modulus(info, modulus_length, s))
417 goto error;
418
419 error++;
420
421 if (!ber_read_integer_length(s, &exponent_length)) /* publicExponent (INTEGER) */
422 goto error;
423
424 error++;
425
426 if (!cert_info_read_exponent(info, exponent_length, s))
427 goto error;
428 return TRUE;
429error:
430 WLog_ERR(TAG, "error reading when reading certificate: part=%s error=%d",
431 certificate_read_errors[error], error);
432 cert_info_free(info);
433 return FALSE;
434}
435
442static BOOL certificate_new_x509_certificate_chain(UINT32 count, wStream* s,
443 rdpX509CertChain* chain)
444{
445 WINPR_ASSERT(chain);
446
447 rdpX509CertChain x509_cert_chain = WINPR_C_ARRAY_INIT;
448 *chain = x509_cert_chain;
449
450 if (!Stream_CheckAndLogRequiredCapacityOfSize(TAG, s, count, sizeof(rdpCertBlob)))
451 return FALSE;
452
453 if (count == 0)
454 return TRUE;
455
456 x509_cert_chain.array = (rdpCertBlob*)calloc(count, sizeof(rdpCertBlob));
457 if (!x509_cert_chain.array)
458 return FALSE;
459
460 x509_cert_chain.count = count;
461
462 *chain = x509_cert_chain;
463 return TRUE;
464}
465
471static void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain)
472{
473 if (!x509_cert_chain)
474 return;
475
476 if (x509_cert_chain->array)
477 {
478 for (UINT32 i = 0; i < x509_cert_chain->count; i++)
479 {
480 rdpCertBlob* element = &x509_cert_chain->array[i];
481 cert_blob_free(element);
482 }
483 }
484
485 free(x509_cert_chain->array);
486 x509_cert_chain->array = nullptr;
487 x509_cert_chain->count = 0;
488}
489
490#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
491static OSSL_PARAM* get_params(const BIGNUM* e, const BIGNUM* mod)
492{
493 WINPR_ASSERT(e);
494 WINPR_ASSERT(mod);
495
496 OSSL_PARAM* parameters = nullptr;
497 OSSL_PARAM_BLD* param = OSSL_PARAM_BLD_new();
498 if (!param)
499 {
500 WLog_ERR(TAG, "OSSL_PARAM_BLD_new() failed");
501 return nullptr;
502 }
503
504 const int bits = BN_num_bits(e);
505 if ((bits < 0) || (bits > 32))
506 {
507 WLog_ERR(TAG, "BN_num_bits(e) out of range: 0 <= %d <= 32", bits);
508 goto fail;
509 }
510
511 {
512 UINT ie = 0;
513 {
514 const int ne = BN_bn2nativepad(e, (BYTE*)&ie, sizeof(ie));
515 if ((ne < 0) || (ne > 4))
516 {
517 WLog_ERR(TAG,
518 "BN_bn2nativepad(e, (BYTE*)&ie, sizeof(ie)) out of range: 0<= %d <= 4",
519 ne);
520 goto fail;
521 }
522 }
523
524 if (OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) != 1)
525 {
526 WLog_ERR(TAG, "OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) failed");
527 goto fail;
528 }
529 if (OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) != 1)
530 {
531 WLog_ERR(TAG, "OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) failed");
532 goto fail;
533 }
534 }
535
536 parameters = OSSL_PARAM_BLD_to_param(param);
537 if (!parameters)
538 WLog_ERR(TAG, "OSSL_PARAM_BLD_to_param(param) failed");
539fail:
540 OSSL_PARAM_BLD_free(param);
541
542 return parameters;
543}
544#endif
545
546static BOOL update_x509_from_info(rdpCertificate* cert)
547{
548 BOOL rc = FALSE;
549
550 WINPR_ASSERT(cert);
551
552 X509_free(cert->x509);
553 cert->x509 = nullptr;
554
555 rdpCertInfo* info = &cert->cert_info;
556
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();
561 if (!rsa)
562 {
563 WLog_ERR(TAG, "RSA_new() failed");
564 goto fail;
565 }
566#endif
567
568 if (!mod || !e)
569 {
570 WLog_ERR(TAG, "failure: mod=%p, e=%p", WINPR_CXX_COMPAT_CAST(const void*, mod),
571 WINPR_CXX_COMPAT_CAST(const void*, e));
572 goto fail;
573 }
574
575 WINPR_ASSERT(info->ModulusLength <= INT_MAX);
576 if (!BN_bin2bn(info->Modulus, (int)info->ModulusLength, mod))
577 {
578 WLog_ERR(TAG, "BN_bin2bn(info->Modulus, (int)info->ModulusLength, mod) failed");
579 goto fail;
580 }
581
582 if (!BN_bin2bn(info->exponent, (int)sizeof(info->exponent), e))
583 {
584 WLog_ERR(TAG, "BN_bin2bn(info->exponent, (int)sizeof(info->exponent), e) failed");
585 goto fail;
586 }
587
588#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
589 const int rec = RSA_set0_key(rsa, mod, e, nullptr);
590 if (rec != 1)
591 {
592 WLog_ERR(TAG, "RSA_set0_key(rsa, mod, e, nullptr) failed");
593 goto fail;
594 }
595
596 cert->x509 = x509_from_rsa(rsa);
597#else
598 {
599 EVP_PKEY* pkey = nullptr;
600 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr);
601 if (!ctx)
602 {
603 WLog_ERR(TAG, "EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr) failed");
604 goto fail2;
605 }
606
607 {
608 const int xx = EVP_PKEY_fromdata_init(ctx);
609 if (xx != 1)
610 {
611 WLog_ERR(TAG, "EVP_PKEY_fromdata_init(ctx) failed");
612 goto fail2;
613 }
614 }
615
616 {
617 OSSL_PARAM* parameters = get_params(e, mod);
618 if (!parameters)
619 goto fail2;
620
621 {
622 const int rc2 = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters);
623 OSSL_PARAM_free(parameters);
624 if (rc2 <= 0)
625 {
626 WLog_ERR(
627 TAG,
628 "EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters) failed");
629 goto fail2;
630 }
631 }
632 }
633
634 cert->x509 = X509_new();
635 if (!cert->x509)
636 {
637 WLog_ERR(TAG, "X509_new() failed");
638 goto fail2;
639 }
640
641 if (X509_set_pubkey(cert->x509, pkey) != 1)
642 {
643 WLog_ERR(TAG, "X509_set_pubkey(cert->x509, pkey) failed");
644 X509_free(cert->x509);
645 cert->x509 = nullptr;
646 }
647 fail2:
648 EVP_PKEY_free(pkey);
649 EVP_PKEY_CTX_free(ctx);
650 }
651#endif
652 if (!cert->x509)
653 goto fail;
654
655 rc = TRUE;
656
657fail:
658 if (!rc)
659 WLog_ERR(TAG, "failed to update x509 from rdpCertInfo");
660
661#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
662 if (rsa)
663 RSA_free(rsa);
664 else
665#endif
666 {
667 BN_free(mod);
668 BN_free(e);
669 }
670 return rc;
671}
672
673static BOOL certificate_process_server_public_key(rdpCertificate* cert, wStream* s,
674 WINPR_ATTR_UNUSED UINT32 length)
675{
676 char magic[sizeof(rsa_magic)] = WINPR_C_ARRAY_INIT;
677 UINT32 keylen = 0;
678 UINT32 bitlen = 0;
679 UINT32 datalen = 0;
680
681 WINPR_ASSERT(cert);
682 WINPR_ASSERT(s);
683
684 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
685 return FALSE;
686
687 Stream_Read(s, magic, sizeof(magic));
688
689 if (memcmp(magic, rsa_magic, sizeof(magic)) != 0)
690 {
691 WLog_ERR(TAG, "invalid RSA magic bytes");
692 return FALSE;
693 }
694
695 rdpCertInfo* info = &cert->cert_info;
696 cert_info_free(info);
697
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);
702
703 if (keylen <= 8)
704 {
705 WLog_ERR(TAG, "Invalid RSA keylen=%" PRIu32 " <= 8", keylen);
706 return FALSE;
707 }
708 if (!Stream_CheckAndLogRequiredLength(TAG, s, keylen))
709 return FALSE;
710 if (keylen != (bitlen / 8ull) + 8ull)
711 {
712 WLog_ERR(TAG, "Invalid RSA key bitlen %" PRIu32 ", expected %" PRIu32, bitlen,
713 (keylen - 8) * 8);
714 return FALSE;
715 }
716 if (datalen != (bitlen / 8ull) - 1ull)
717 {
718 WLog_ERR(TAG, "Invalid RSA key datalen %" PRIu32 ", expected %llu", datalen,
719 (1ull * bitlen / 8ull) - 1ull);
720 return FALSE;
721 }
722 info->ModulusLength = keylen - 8;
723 BYTE* tmp = realloc(info->Modulus, info->ModulusLength);
724
725 if (!tmp)
726 {
727 WLog_ERR(TAG, "Failed to reallocate modulus of length %" PRIu32, info->ModulusLength);
728 return FALSE;
729 }
730 info->Modulus = tmp;
731
732 Stream_Read(s, info->Modulus, info->ModulusLength);
733 Stream_Seek(s, 8); /* 8 bytes of zero padding */
734 return update_x509_from_info(cert);
735}
736
737static BOOL certificate_process_server_public_signature(rdpCertificate* certificate,
738 const BYTE* sigdata, size_t sigdatalen,
739 wStream* s, UINT32 siglen)
740{
741 WINPR_ASSERT(certificate);
742#if defined(CERT_VALIDATE_RSA)
743 BYTE sig[TSSK_KEY_LENGTH];
744#endif
745 BYTE encsig[TSSK_KEY_LENGTH + 8];
746#if defined(CERT_VALIDATE_MD5) && defined(CERT_VALIDATE_RSA)
747 BYTE md5hash[WINPR_MD5_DIGEST_LENGTH];
748#endif
749#if !defined(CERT_VALIDATE_MD5) || !defined(CERT_VALIDATE_RSA)
750 (void)sigdata;
751 (void)sigdatalen;
752#endif
753 (void)certificate;
754 /* Do not bother with validation of server proprietary certificate. The use of MD5 here is not
755 * allowed under FIPS. Since the validation is not protecting against anything since the
756 * private/public keys are well known and documented in MS-RDPBCGR section 5.3.3.1, we are not
757 * gaining any security by using MD5 for signature comparison. Rather then use MD5
758 * here we just don't do the validation to avoid its use. Historically, freerdp has been
759 * ignoring a failed validation anyways. */
760#if defined(CERT_VALIDATE_MD5)
761
762 if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash, sizeof(md5hash)))
763 return FALSE;
764
765#endif
766 Stream_Read(s, encsig, siglen);
767
768 if (siglen < 8)
769 {
770 WLog_WARN(TAG, "public signature too short: %" PRIu32, siglen);
771 return FALSE;
772 }
773
774 /* Last 8 bytes shall be all zero. */
775#if defined(CERT_VALIDATE_PADDING)
776 {
777 size_t sum = 0;
778 for (size_t i = sizeof(encsig) - 8; i < sizeof(encsig); i++)
779 sum += encsig[i];
780
781 if (sum != 0)
782 {
783 WLog_ERR(TAG, "invalid signature");
784 return FALSE;
785 }
786 }
787#endif
788#if defined(CERT_VALIDATE_RSA)
789
790 if (crypto_rsa_public_decrypt(encsig, siglen - 8, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent,
791 sig) <= 0)
792 {
793 WLog_ERR(TAG, "invalid RSA decrypt");
794 return FALSE;
795 }
796
797 /* Verify signature. */
798 /* Do not bother with validation of server proprietary certificate as described above. */
799#if defined(CERT_VALIDATE_MD5)
800
801 if (memcmp(md5hash, sig, sizeof(md5hash)) != 0)
802 {
803 WLog_ERR(TAG, "invalid signature");
804 return FALSE;
805 }
806
807#endif
808 /*
809 * Verify rest of decrypted data:
810 * The 17th byte is 0x00.
811 * The 18th through 62nd bytes are each 0xFF.
812 * The 63rd byte is 0x01.
813 */
814 {
815 size_t sum = 0;
816 for (size_t i = 17; i < 62; i++)
817 sum += sig[i];
818
819 if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01)
820 {
821 WLog_ERR(TAG, "invalid signature");
822 return FALSE;
823 }
824 }
825#endif
826 return TRUE;
827}
828
829static BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate, wStream* s)
830{
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;
838
839 WINPR_ASSERT(certificate);
840 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
841 return FALSE;
842
843 /* -4, because we need to include dwVersion */
844 const BYTE* sigdata = Stream_PointerAs(s, const BYTE) - 4;
845 Stream_Read_UINT32(s, dwSigAlgId);
846 Stream_Read_UINT32(s, dwKeyAlgId);
847
848 if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
849 {
850 WLog_ERR(TAG,
851 "unsupported signature or key algorithm, dwSigAlgId=%" PRIu32
852 " dwKeyAlgId=%" PRIu32 "",
853 dwSigAlgId, dwKeyAlgId);
854 return FALSE;
855 }
856
857 Stream_Read_UINT16(s, wPublicKeyBlobType);
858
859 if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
860 {
861 WLog_ERR(TAG, "unsupported public key blob type %" PRIu16 "", wPublicKeyBlobType);
862 return FALSE;
863 }
864
865 Stream_Read_UINT16(s, wPublicKeyBlobLen);
866
867 if (!Stream_CheckAndLogRequiredLength(TAG, s, wPublicKeyBlobLen))
868 return FALSE;
869
870 if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
871 return FALSE;
872
873 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
874 return FALSE;
875
876 sigdatalen = WINPR_ASSERTING_INT_CAST(size_t, Stream_PointerAs(s, const BYTE) - sigdata);
877 Stream_Read_UINT16(s, wSignatureBlobType);
878
879 if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
880 {
881 WLog_ERR(TAG, "unsupported blob signature %" PRIu16 "", wSignatureBlobType);
882 return FALSE;
883 }
884
885 Stream_Read_UINT16(s, wSignatureBlobLen);
886
887 if (!Stream_CheckAndLogRequiredLength(TAG, s, wSignatureBlobLen))
888 return FALSE;
889
890 if (wSignatureBlobLen != 72)
891 {
892 WLog_ERR(TAG, "invalid signature length (got %" PRIu16 ", expected 72)", wSignatureBlobLen);
893 return FALSE;
894 }
895
896 if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s,
897 wSignatureBlobLen))
898 {
899 WLog_ERR(TAG, "unable to parse server public signature");
900 return FALSE;
901 }
902 return TRUE;
903}
904
905/* [MS-RDPBCGR] 2.2.1.4.3.1.1.1 RSA Public Key (RSA_PUBLIC_KEY) */
906static BOOL cert_write_rsa_public_key(wStream* s, const rdpCertificate* cert)
907{
908 WINPR_ASSERT(cert);
909 WINPR_ASSERT(freerdp_certificate_is_rsa(cert));
910
911 const rdpCertInfo* info = &cert->cert_info;
912
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;
919
920 const size_t wPublicKeyBlobLen = 16 + pubExpLen + keyLen;
921 WINPR_ASSERT(wPublicKeyBlobLen <= UINT16_MAX);
922 if (!Stream_EnsureRemainingCapacity(s, 2 + wPublicKeyBlobLen))
923 return FALSE;
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);
931 Stream_Zero(s, 8);
932 return TRUE;
933}
934
935static BOOL cert_write_rsa_signature(wStream* s, const void* sigData, size_t sigDataLen)
936{
937 BYTE encryptedSignature[TSSK_KEY_LENGTH] = WINPR_C_ARRAY_INIT;
938 BYTE signature[sizeof(initial_signature)] = WINPR_C_ARRAY_INIT;
939
940 memcpy(signature, initial_signature, sizeof(initial_signature));
941 if (!winpr_Digest(WINPR_MD_MD5, sigData, sigDataLen, signature, sizeof(signature)))
942 return FALSE;
943
944 if (crypto_rsa_private_encrypt(signature, sizeof(signature), priv_key_tssk, encryptedSignature,
945 sizeof(encryptedSignature)) < 0)
946 return FALSE;
947
948 if (!Stream_EnsureRemainingCapacity(s, 2 * sizeof(UINT16) + sizeof(encryptedSignature) + 8))
949 return FALSE;
950 Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB);
951 Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */
952 Stream_Write(s, encryptedSignature, sizeof(encryptedSignature));
953 Stream_Zero(s, 8);
954 return TRUE;
955}
956
957/* [MS-RDPBCGR] 2.2.1.4.3.1.1 Server Proprietary Certificate (PROPRIETARYSERVERCERTIFICATE) */
958static BOOL cert_write_server_certificate_v1(wStream* s, const rdpCertificate* certificate)
959{
960 const size_t start = Stream_GetPosition(s);
961 const BYTE* sigData = Stream_PointerAs(s, const BYTE) - sizeof(UINT32);
962
963 WINPR_ASSERT(start >= 4);
964 if (!Stream_EnsureRemainingCapacity(s, 10))
965 return FALSE;
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))
970 return FALSE;
971
972 const size_t end = Stream_GetPosition(s);
973 return cert_write_rsa_signature(s, sigData, end - start + sizeof(UINT32));
974}
975
976static BOOL cert_write_server_certificate_v2(wStream* s, const rdpCertificate* certificate)
977{
978 WINPR_ASSERT(certificate);
979
980 const rdpX509CertChain* chain = &certificate->x509_cert_chain;
981 const size_t padding = 8ull + 4ull * chain->count;
982
983 if (!Stream_EnsureRemainingCapacity(s, sizeof(UINT32)))
984 return FALSE;
985
986 Stream_Write_UINT32(s, chain->count);
987 for (UINT32 x = 0; x < chain->count; x++)
988 {
989 const rdpCertBlob* cert = &chain->array[x];
990 if (!cert_blob_write(cert, s))
991 return FALSE;
992 }
993
994 if (!Stream_EnsureRemainingCapacity(s, padding))
995 return FALSE;
996 Stream_Zero(s, padding);
997 return TRUE;
998}
999
1000SSIZE_T freerdp_certificate_write_server_cert(const rdpCertificate* certificate, UINT32 dwVersion,
1001 wStream* s)
1002{
1003 if (!certificate)
1004 return -1;
1005
1006 const size_t start = Stream_GetPosition(s);
1007 if (!Stream_EnsureRemainingCapacity(s, 4))
1008 return -1;
1009 Stream_Write_UINT32(s, dwVersion);
1010
1011 switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1012 {
1013 case CERT_CHAIN_VERSION_1:
1014 if (!cert_write_server_certificate_v1(s, certificate))
1015 return -1;
1016 break;
1017 case CERT_CHAIN_VERSION_2:
1018 if (!cert_write_server_certificate_v2(s, certificate))
1019 return -1;
1020 break;
1021 default:
1022 WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
1023 dwVersion & CERT_CHAIN_VERSION_MASK);
1024 return -1;
1025 }
1026
1027 const size_t end = Stream_GetPosition(s);
1028 if (start > end)
1029 return -1;
1030
1031 const size_t diff = end - start;
1032 WINPR_ASSERT(diff <= SSIZE_MAX);
1033 return (SSIZE_T)diff;
1034}
1035
1043static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* cert, wStream* s)
1044{
1045 UINT32 numCertBlobs = 0;
1046 DEBUG_CERTIFICATE("Server X.509 Certificate Chain");
1047
1048 WINPR_ASSERT(cert);
1049 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1050 return FALSE;
1051
1052 Stream_Read_UINT32(s, numCertBlobs); /* numCertBlobs */
1053 certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1054 if (!certificate_new_x509_certificate_chain(numCertBlobs, s, &cert->x509_cert_chain))
1055 return FALSE;
1056
1057 for (UINT32 i = 0; i < cert->x509_cert_chain.count; i++)
1058 {
1059 rdpCertBlob* blob = &cert->x509_cert_chain.array[i];
1060 if (!cert_blob_read(blob, s))
1061 return FALSE;
1062
1063 if (numCertBlobs - i == 1)
1064 {
1065 DEBUG_CERTIFICATE("Terminal Server Certificate");
1066
1067 BOOL res = certificate_read_x509_certificate(blob, &cert->cert_info);
1068
1069 if (res)
1070 {
1071 if (!update_x509_from_info(cert))
1072 res = FALSE;
1073 }
1074
1075 if (!res)
1076 {
1077 WLog_ERR(TAG, "Failed to read x509 certificate");
1078 return FALSE;
1079 }
1080
1081 DEBUG_CERTIFICATE("modulus length:%" PRIu32 "", cert->cert_info.ModulusLength);
1082 }
1083 }
1084
1085 return update_x509_from_info(cert);
1086}
1087
1095BOOL freerdp_certificate_read_server_cert(rdpCertificate* certificate, const BYTE* server_cert,
1096 size_t length)
1097{
1098 BOOL ret = FALSE;
1099 wStream* s = nullptr;
1100 wStream sbuffer;
1101 UINT32 dwVersion = 0;
1102
1103 WINPR_ASSERT(certificate);
1104 if (length < 4) /* nullptr certificate is not an error see #1795 */
1105 {
1106 WLog_DBG(TAG, "Received empty certificate, ignoring...");
1107 return TRUE;
1108 }
1109
1110 WINPR_ASSERT(server_cert);
1111 s = Stream_StaticConstInit(&sbuffer, server_cert, length);
1112
1113 if (!s)
1114 {
1115 WLog_ERR(TAG, "Stream_New failed!");
1116 return FALSE;
1117 }
1118
1119 Stream_Read_UINT32(s, dwVersion); /* dwVersion (4 bytes) */
1120
1121 switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1122 {
1123 case CERT_CHAIN_VERSION_1:
1124 ret = certificate_read_server_proprietary_certificate(certificate, s);
1125 break;
1126
1127 case CERT_CHAIN_VERSION_2:
1128 ret = certificate_read_server_x509_certificate_chain(certificate, s);
1129 break;
1130
1131 default:
1132 WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
1133 dwVersion & CERT_CHAIN_VERSION_MASK);
1134 ret = FALSE;
1135 break;
1136 }
1137
1138 return ret;
1139}
1140
1141static BOOL cert_blob_copy(rdpCertBlob* dst, const rdpCertBlob* src)
1142{
1143 WINPR_ASSERT(dst);
1144 WINPR_ASSERT(src);
1145
1146 cert_blob_free(dst);
1147 if (src->length > 0)
1148 {
1149 dst->data = malloc(src->length);
1150 if (!dst->data)
1151 return FALSE;
1152 dst->length = src->length;
1153 memcpy(dst->data, src->data, src->length);
1154 }
1155
1156 return TRUE;
1157}
1158
1159static BOOL cert_x509_chain_copy(rdpX509CertChain* cert, const rdpX509CertChain* src)
1160{
1161 WINPR_ASSERT(cert);
1162
1163 certificate_free_x509_certificate_chain(cert);
1164 if (!src)
1165 return TRUE;
1166
1167 if (src->count > 0)
1168 {
1169 cert->array = calloc(src->count, sizeof(rdpCertBlob));
1170 if (!cert->array)
1171 {
1172 return FALSE;
1173 }
1174 cert->count = src->count;
1175
1176 for (UINT32 x = 0; x < cert->count; x++)
1177 {
1178 const rdpCertBlob* srcblob = &src->array[x];
1179 rdpCertBlob* dstblob = &cert->array[x];
1180
1181 if (!cert_blob_copy(dstblob, srcblob))
1182 {
1183 certificate_free_x509_certificate_chain(cert);
1184 return FALSE;
1185 }
1186 }
1187 }
1188
1189 return TRUE;
1190}
1191
1192BOOL cert_clone_int(rdpCertificate* dst, const rdpCertificate* src)
1193{
1194 WINPR_ASSERT(dst);
1195 WINPR_ASSERT(src);
1196
1197 if (!cert_info_clone(&dst->cert_info, &src->cert_info))
1198 return FALSE;
1199
1200 if (src->x509)
1201 {
1202 dst->x509 = X509_dup(src->x509);
1203 if (!dst->x509)
1204 {
1205 /* Workaround for SSL deprecation issues:
1206 * some security modes use weak RSA ciphers where X509_dup fails.
1207 * In that case recreate the X509 from the raw RSA data
1208 */
1209 if (!update_x509_from_info(dst))
1210 {
1211 WLog_ERR(TAG, "X509_dup failed, SSL configuration bug?");
1212 return FALSE;
1213 }
1214 }
1215 }
1216
1217 if (src->chain)
1218 {
1219 if (dst->chain)
1220 sk_X509_pop_free(dst->chain, X509_free);
1221
1222 dst->chain = sk_X509_deep_copy(src->chain, X509_const_dup, X509_free);
1223 }
1224 return cert_x509_chain_copy(&dst->x509_cert_chain, &src->x509_cert_chain);
1225}
1226
1227rdpCertificate* freerdp_certificate_clone(const rdpCertificate* certificate)
1228{
1229 if (!certificate)
1230 return nullptr;
1231
1232 rdpCertificate* _certificate = freerdp_certificate_new();
1233
1234 if (!_certificate)
1235 return nullptr;
1236
1237 if (!cert_clone_int(_certificate, certificate))
1238 goto out_fail;
1239
1240 return _certificate;
1241out_fail:
1242
1243 freerdp_certificate_free(_certificate);
1244 return nullptr;
1245}
1246
1252rdpCertificate* freerdp_certificate_new(void)
1253{
1254 return (rdpCertificate*)calloc(1, sizeof(rdpCertificate));
1255}
1256
1257void certificate_free_int(rdpCertificate* cert)
1258{
1259 WINPR_ASSERT(cert);
1260
1261 if (cert->x509)
1262 X509_free(cert->x509);
1263 if (cert->chain)
1264 sk_X509_pop_free(cert->chain, X509_free);
1265
1266 certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1267 cert_info_free(&cert->cert_info);
1268}
1269
1275void freerdp_certificate_free(rdpCertificate* cert)
1276{
1277 if (!cert)
1278 return;
1279
1280 certificate_free_int(cert);
1281 free(cert);
1282}
1283
1284static BOOL freerdp_rsa_from_x509(rdpCertificate* cert)
1285{
1286 BOOL rc = FALSE;
1287
1288 WINPR_ASSERT(cert);
1289
1290 if (!freerdp_certificate_is_rsa(cert))
1291 return TRUE;
1292
1293#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1294 RSA* rsa = nullptr;
1295 const BIGNUM* rsa_n = nullptr;
1296 const BIGNUM* rsa_e = nullptr;
1297#else
1298 BIGNUM* rsa_n = nullptr;
1299 BIGNUM* rsa_e = nullptr;
1300#endif
1301 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1302 if (!pubkey)
1303 goto fail;
1304
1305#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1306 rsa = EVP_PKEY_get1_RSA(pubkey);
1307
1308 /* If this is not a RSA key return success */
1309 rc = TRUE;
1310 if (!rsa)
1311 goto fail;
1312
1313 /* Now we return failure again if something is wrong. */
1314 rc = FALSE;
1315
1316 RSA_get0_key(rsa, &rsa_n, &rsa_e, nullptr);
1317#else
1318 if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &rsa_e))
1319 goto fail;
1320 if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &rsa_n))
1321 goto fail;
1322#endif
1323 if (!rsa_n || !rsa_e)
1324 goto fail;
1325 if (!cert_info_create(&cert->cert_info, rsa_n, rsa_e))
1326 goto fail;
1327 rc = TRUE;
1328fail:
1329#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1330 RSA_free(rsa);
1331#else
1332 BN_free(rsa_n);
1333 BN_free(rsa_e);
1334#endif
1335 return rc;
1336}
1337
1338rdpCertificate* freerdp_certificate_new_from_der(const BYTE* data, size_t length)
1339{
1340 rdpCertificate* cert = freerdp_certificate_new();
1341
1342 if (!cert || !data || (length == 0) || (length > INT_MAX))
1343 goto fail;
1344
1345 {
1346 const BYTE* ptr = data;
1347 cert->x509 = d2i_X509(nullptr, &ptr, (int)length);
1348 }
1349
1350 if (!cert->x509)
1351 goto fail;
1352 if (!freerdp_rsa_from_x509(cert))
1353 goto fail;
1354 return cert;
1355fail:
1356 freerdp_certificate_free(cert);
1357 return nullptr;
1358}
1359
1360rdpCertificate* freerdp_certificate_new_from_x509(const X509* xcert, const STACK_OF(X509) * chain)
1361{
1362 WINPR_ASSERT(xcert);
1363
1364 rdpCertificate* cert = freerdp_certificate_new();
1365 if (!cert)
1366 return nullptr;
1367
1368 X509* wcert = WINPR_CAST_CONST_PTR_AWAY(xcert, X509*);
1369 cert->x509 = X509_dup(wcert);
1370 if (!cert->x509)
1371 goto fail;
1372
1373 if (!freerdp_rsa_from_x509(cert))
1374 goto fail;
1375
1376 if (chain)
1377 cert->chain = sk_X509_deep_copy(chain, X509_const_dup, X509_free);
1378
1379 return cert;
1380fail:
1381 freerdp_certificate_free(cert);
1382 return nullptr;
1383}
1384
1385static STACK_OF(X509) * extract_chain_from_pem(const char* pem, BOOL isFile)
1386{
1387 if (!pem)
1388 {
1389 return nullptr;
1390 }
1391
1392 BIO* bio = nullptr;
1393 if (isFile)
1394 bio = BIO_new_file(pem, "rb");
1395 else
1396 {
1397 const size_t len = strlen(pem);
1398 bio = BIO_new_mem_buf(pem, WINPR_ASSERTING_INT_CAST(int, len));
1399 }
1400
1401 if (!bio)
1402 {
1403 return nullptr;
1404 }
1405
1406 X509* leaf = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
1407 if (!leaf)
1408 {
1409 BIO_free(bio);
1410 return nullptr;
1411 }
1412
1413 STACK_OF(X509)* chain = sk_X509_new_null();
1414 if (!chain)
1415 {
1416 X509_free(leaf);
1417 BIO_free(bio);
1418 return nullptr;
1419 }
1420
1421 X509* cert = nullptr;
1422 while ((cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr)) != nullptr)
1423 {
1424 sk_X509_push(chain, cert);
1425 }
1426
1427 X509_free(leaf);
1428 BIO_free(bio);
1429 return chain;
1430}
1431
1432static rdpCertificate* freerdp_certificate_new_from(const char* file, BOOL isFile)
1433{
1434 X509* x509 = x509_utils_from_pem(file, strlen(file), isFile);
1435 if (!x509)
1436 return nullptr;
1437 STACK_OF(X509)* chain = extract_chain_from_pem(file, isFile);
1438 rdpCertificate* cert = freerdp_certificate_new_from_x509(x509, chain);
1439 if (chain)
1440 sk_X509_pop_free(chain, X509_free);
1441 X509_free(x509);
1442 return cert;
1443}
1444
1445rdpCertificate* freerdp_certificate_new_from_file(const char* file)
1446{
1447 return freerdp_certificate_new_from(file, TRUE);
1448}
1449
1450rdpCertificate* freerdp_certificate_new_from_pem(const char* pem)
1451{
1452 return freerdp_certificate_new_from(pem, FALSE);
1453}
1454
1455const rdpCertInfo* freerdp_certificate_get_info(const rdpCertificate* cert)
1456{
1457 WINPR_ASSERT(cert);
1458 if (!freerdp_certificate_is_rsa(cert))
1459 return nullptr;
1460 return &cert->cert_info;
1461}
1462
1463char* freerdp_certificate_get_fingerprint(const rdpCertificate* cert)
1464{
1465 return freerdp_certificate_get_fingerprint_by_hash(cert, "sha256");
1466}
1467
1468char* freerdp_certificate_get_fingerprint_by_hash(const rdpCertificate* cert, const char* hash)
1469{
1470 return freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, TRUE);
1471}
1472
1473char* freerdp_certificate_get_fingerprint_by_hash_ex(const rdpCertificate* cert, const char* hash,
1474 BOOL separator)
1475{
1476 size_t fp_len = 0;
1477 size_t pos = 0;
1478 size_t size = 0;
1479 BYTE* fp = nullptr;
1480 char* fp_buffer = nullptr;
1481 if (!cert || !cert->x509)
1482 {
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));
1485 return nullptr;
1486 }
1487 if (!hash)
1488 {
1489 WLog_ERR(TAG, "Invalid certificate hash %p", WINPR_CXX_COMPAT_CAST(const void*, hash));
1490 return nullptr;
1491 }
1492 fp = x509_utils_get_hash(cert->x509, hash, &fp_len);
1493 if (!fp)
1494 return nullptr;
1495
1496 if (fp_len < 1)
1497 goto fail;
1498
1499 size = fp_len * 3 + 1;
1500 fp_buffer = calloc(size, sizeof(char));
1501 if (!fp_buffer)
1502 goto fail;
1503
1504 pos = 0;
1505
1506 {
1507 size_t i = 0;
1508 for (; i < (fp_len - 1); i++)
1509 {
1510 int rc = 0;
1511 char* p = &fp_buffer[pos];
1512 if (separator)
1513 rc = sprintf_s(p, size - pos, "%02" PRIx8 ":", fp[i]);
1514 else
1515 rc = sprintf_s(p, size - pos, "%02" PRIx8, fp[i]);
1516 if (rc <= 0)
1517 goto fail;
1518 pos += (size_t)rc;
1519 }
1520
1521 (void)sprintf_s(&fp_buffer[pos], size - pos, "%02" PRIx8 "", fp[i]);
1522 }
1523
1524 free(fp);
1525
1526 return fp_buffer;
1527fail:
1528 free(fp);
1529 free(fp_buffer);
1530 return nullptr;
1531}
1532
1533static BOOL bio_read_pem(BIO* bio, char** ppem, size_t* plength)
1534{
1535 BOOL rc = FALSE;
1536
1537 WINPR_ASSERT(bio);
1538 WINPR_ASSERT(ppem);
1539
1540 const size_t blocksize = 2048;
1541 size_t offset = 0;
1542 size_t length = blocksize;
1543 char* pem = nullptr;
1544
1545 *ppem = nullptr;
1546 if (plength)
1547 *plength = 0;
1548
1549 while (offset < length)
1550 {
1551 char* tmp = realloc(pem, length + 1);
1552 if (!tmp)
1553 goto fail;
1554 pem = tmp;
1555
1556 ERR_clear_error();
1557
1558 const int status = BIO_read(bio, &pem[offset], (int)(length - offset));
1559 if (status < 0)
1560 {
1561 WLog_ERR(TAG, "failed to read certificate");
1562 goto fail;
1563 }
1564
1565 if (status == 0)
1566 break;
1567
1568 offset += (size_t)status;
1569 if (length - offset > 0)
1570 break;
1571 length += blocksize;
1572 }
1573
1574 if (pem)
1575 {
1576 if (offset >= length)
1577 goto fail;
1578 pem[offset] = '\0';
1579 }
1580 *ppem = pem;
1581 if (plength)
1582 *plength = offset;
1583 rc = TRUE;
1584fail:
1585 if (!rc)
1586 free(pem);
1587
1588 return rc;
1589}
1590
1591char* freerdp_certificate_get_pem(const rdpCertificate* cert, size_t* pLength)
1592{
1593 return freerdp_certificate_get_pem_ex(cert, pLength, TRUE);
1594}
1595
1596char* freerdp_certificate_get_pem_ex(const rdpCertificate* cert, size_t* pLength,
1597 BOOL withCertChain)
1598{
1599 WINPR_ASSERT(cert);
1600
1601 if (!cert->x509)
1602 return nullptr;
1603
1608 BIO* bio = BIO_new(BIO_s_mem());
1609
1610 if (!bio)
1611 {
1612 WLog_ERR(TAG, "BIO_new() failure");
1613 return nullptr;
1614 }
1615
1616 char* pem = nullptr;
1617
1618 const int status = PEM_write_bio_X509(bio, cert->x509);
1619 if (status < 0)
1620 {
1621 WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
1622 goto fail;
1623 }
1624
1625 if (cert->chain && withCertChain)
1626 {
1627 const int count = sk_X509_num(cert->chain);
1628 for (int x = 0; x < count; x++)
1629 {
1630 X509* c = sk_X509_value(cert->chain, x);
1631 const int rc = PEM_write_bio_X509(bio, c);
1632 if (rc < 0)
1633 {
1634 WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", rc);
1635 goto fail;
1636 }
1637 }
1638 }
1639
1640 (void)bio_read_pem(bio, &pem, pLength);
1641
1642fail:
1643 BIO_free_all(bio);
1644 return pem;
1645}
1646
1647char* freerdp_certificate_get_subject(const rdpCertificate* cert)
1648{
1649 WINPR_ASSERT(cert);
1650 return x509_utils_get_subject(cert->x509);
1651}
1652
1653char* freerdp_certificate_get_issuer(const rdpCertificate* cert)
1654{
1655 WINPR_ASSERT(cert);
1656 return x509_utils_get_issuer(cert->x509);
1657}
1658
1659char* freerdp_certificate_get_upn(const rdpCertificate* cert)
1660{
1661 WINPR_ASSERT(cert);
1662 return x509_utils_get_upn(cert->x509);
1663}
1664
1665char* freerdp_certificate_get_email(const rdpCertificate* cert)
1666{
1667 WINPR_ASSERT(cert);
1668 return x509_utils_get_email(cert->x509);
1669}
1670
1671char* freerdp_certificate_get_validity(const rdpCertificate* cert, BOOL startDate)
1672{
1673 WINPR_ASSERT(cert);
1674 return x509_utils_get_date(cert->x509, startDate);
1675}
1676
1677BOOL freerdp_certificate_check_eku(const rdpCertificate* cert, int nid)
1678{
1679 WINPR_ASSERT(cert);
1680 return x509_utils_check_eku(cert->x509, nid);
1681}
1682
1683BOOL freerdp_certificate_get_public_key(const rdpCertificate* cert, BYTE** PublicKey,
1684 DWORD* PublicKeyLength)
1685{
1686 BYTE* ptr = nullptr;
1687 BYTE* optr = nullptr;
1688 int length = 0;
1689 BOOL status = FALSE;
1690 EVP_PKEY* pkey = nullptr;
1691
1692 WINPR_ASSERT(cert);
1693
1694 pkey = X509_get0_pubkey(cert->x509);
1695
1696 if (!pkey)
1697 {
1698 WLog_ERR(TAG, "X509_get_pubkey() failed");
1699 goto exit;
1700 }
1701
1702 length = i2d_PublicKey(pkey, nullptr);
1703
1704 if (length < 1)
1705 {
1706 WLog_ERR(TAG, "i2d_PublicKey() failed");
1707 goto exit;
1708 }
1709
1710 *PublicKey = optr = ptr = (BYTE*)calloc(WINPR_ASSERTING_INT_CAST(size_t, length), sizeof(BYTE));
1711
1712 if (!ptr)
1713 goto exit;
1714
1715 {
1716 const int length2 = i2d_PublicKey(pkey, &ptr);
1717 if (length != length2)
1718 goto exit;
1719 *PublicKeyLength = (DWORD)length2;
1720 }
1721 status = TRUE;
1722exit:
1723
1724 if (!status)
1725 free(optr);
1726
1727 return status;
1728}
1729
1730BOOL freerdp_certificate_verify(const rdpCertificate* cert, const char* certificate_store_path)
1731{
1732 WINPR_ASSERT(cert);
1733 return x509_utils_verify(cert->x509, cert->chain, certificate_store_path);
1734}
1735
1736char** freerdp_certificate_get_dns_names(const rdpCertificate* cert, size_t* pcount,
1737 size_t** pplengths)
1738{
1739 WINPR_ASSERT(cert);
1740 return x509_utils_get_dns_names(cert->x509, pcount, pplengths);
1741}
1742
1743char* freerdp_certificate_get_common_name(const rdpCertificate* cert, size_t* plength)
1744{
1745 WINPR_ASSERT(cert);
1746 return x509_utils_get_common_name(cert->x509, plength);
1747}
1748
1749WINPR_MD_TYPE freerdp_certificate_get_signature_alg(const rdpCertificate* cert)
1750{
1751 WINPR_ASSERT(cert);
1752 return x509_utils_get_signature_alg(cert->x509);
1753}
1754
1755void freerdp_certificate_free_dns_names(size_t count, size_t* lengths, char** names)
1756{
1757 x509_utils_dns_names_free(count, lengths, names);
1758}
1759
1760char* freerdp_certificate_get_hash(const rdpCertificate* cert, const char* hash, size_t* plength)
1761{
1762 WINPR_ASSERT(cert);
1763 return (char*)x509_utils_get_hash(cert->x509, hash, plength);
1764}
1765
1766X509* freerdp_certificate_get_x509(rdpCertificate* cert)
1767{
1768 WINPR_ASSERT(cert);
1769 return cert->x509;
1770}
1771
1772BOOL freerdp_certificate_publickey_encrypt(const rdpCertificate* cert, const BYTE* input,
1773 size_t cbInput, BYTE** poutput, size_t* pcbOutput)
1774{
1775 WINPR_ASSERT(cert);
1776 WINPR_ASSERT(input);
1777 WINPR_ASSERT(poutput);
1778 WINPR_ASSERT(pcbOutput);
1779
1780 BOOL ret = FALSE;
1781 BYTE* output = nullptr;
1782 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1783 if (!pkey)
1784 return FALSE;
1785
1786 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, nullptr);
1787 if (!ctx)
1788 return FALSE;
1789
1790 size_t outputSize = WINPR_ASSERTING_INT_CAST(size_t, EVP_PKEY_size(pkey));
1791 output = malloc(outputSize);
1792 if (output == nullptr)
1793 goto out;
1794 *pcbOutput = outputSize;
1795
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)
1799 {
1800 WLog_ERR(TAG, "error when setting up public key");
1801 goto out;
1802 }
1803
1804 *poutput = output;
1805 output = nullptr;
1806 ret = TRUE;
1807out:
1808 EVP_PKEY_CTX_free(ctx);
1809 free(output);
1810 return ret;
1811}
1812
1813#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1814static RSA* freerdp_certificate_get_RSA(const rdpCertificate* cert)
1815{
1816 WINPR_ASSERT(cert);
1817
1818 if (!freerdp_certificate_is_rsa(cert))
1819 return nullptr;
1820
1821 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1822 if (!pubkey)
1823 return nullptr;
1824
1825 return EVP_PKEY_get1_RSA(pubkey);
1826}
1827#endif
1828
1829BYTE* freerdp_certificate_get_der(const rdpCertificate* cert, size_t* pLength)
1830{
1831 WINPR_ASSERT(cert);
1832
1833 if (pLength)
1834 *pLength = 0;
1835
1836 const int rc = i2d_X509(cert->x509, nullptr);
1837 if (rc <= 0)
1838 return nullptr;
1839
1840 BYTE* ptr = calloc(WINPR_ASSERTING_INT_CAST(size_t, rc) + 1, sizeof(BYTE));
1841 if (!ptr)
1842 return nullptr;
1843 BYTE* i2d_ptr = ptr;
1844
1845 const int rc2 = i2d_X509(cert->x509, &i2d_ptr);
1846 if (rc2 <= 0)
1847 {
1848 free(ptr);
1849 return nullptr;
1850 }
1851
1852 if (pLength)
1853 *pLength = (size_t)rc2;
1854 return ptr;
1855}
1856
1857BOOL freerdp_certificate_is_rsa(const rdpCertificate* cert)
1858{
1859 WINPR_ASSERT(cert);
1860 return is_rsa_key(cert->x509);
1861}
1862
1863BOOL freerdp_certificate_is_rdp_security_compatible(const rdpCertificate* cert)
1864{
1865 const rdpCertInfo* info = freerdp_certificate_get_info(cert);
1866 if (!freerdp_certificate_is_rsa(cert) || !info || (info->ModulusLength != 2048 / 8))
1867 {
1868 WLog_INFO(TAG, "certificate is not RSA 2048, RDP security not supported.");
1869 return FALSE;
1870 }
1871 return TRUE;
1872}
1873
1874char* freerdp_certificate_get_param(const rdpCertificate* cert, enum FREERDP_CERT_PARAM what,
1875 size_t* psize)
1876{
1877 WINPR_ASSERT(cert);
1878 WINPR_ASSERT(psize);
1879
1880 *psize = 0;
1881
1882#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1883 const BIGNUM* bn = nullptr;
1884 RSA* rsa = freerdp_certificate_get_RSA(cert);
1885 switch (what)
1886 {
1887 case FREERDP_CERT_RSA_E:
1888 RSA_get0_key(rsa, nullptr, &bn, nullptr);
1889 break;
1890 case FREERDP_CERT_RSA_N:
1891 RSA_get0_key(rsa, &bn, nullptr, nullptr);
1892 break;
1893 default:
1894 RSA_free(rsa);
1895 return nullptr;
1896 }
1897 RSA_free(rsa);
1898#else
1899 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1900 if (!pkey)
1901 return nullptr;
1902
1903 BIGNUM* bn = nullptr;
1904 switch (what)
1905 {
1906 case FREERDP_CERT_RSA_E:
1907 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn))
1908 return nullptr;
1909 break;
1910 case FREERDP_CERT_RSA_N:
1911 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn))
1912 return nullptr;
1913 break;
1914 default:
1915 return nullptr;
1916 }
1917#endif
1918
1919 const size_t bnsize = WINPR_ASSERTING_INT_CAST(size_t, BN_num_bytes(bn));
1920 char* rc = calloc(bnsize + 1, sizeof(char));
1921 if (!rc)
1922 goto fail;
1923 BN_bn2bin(bn, (BYTE*)rc);
1924 *psize = bnsize;
1925
1926fail:
1927#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR < 3)
1928 BN_free(bn);
1929#endif
1930 return rc;
1931}
1932
1933size_t freerdp_certificate_get_chain_len(rdpCertificate* certificate)
1934{
1935 WINPR_ASSERT(certificate);
1936 if (!certificate->chain)
1937 return 0;
1938
1939 return WINPR_ASSERTING_INT_CAST(size_t, sk_X509_num(certificate->chain));
1940}
1941
1942X509* freerdp_certificate_get_chain_at(rdpCertificate* certificate, size_t offset)
1943{
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);
1948}