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 = NULL;
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 = { 0 };
297 wStream* s = NULL;
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, NULL)) /* 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 rdpX509CertChain certificate_new_x509_certificate_chain(UINT32 count)
443{
444 rdpX509CertChain x509_cert_chain = { 0 };
445
446 x509_cert_chain.array = (rdpCertBlob*)calloc(count, sizeof(rdpCertBlob));
447
448 if (x509_cert_chain.array)
449 x509_cert_chain.count = count;
450
451 return x509_cert_chain;
452}
453
459static void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain)
460{
461 if (!x509_cert_chain)
462 return;
463
464 if (x509_cert_chain->array)
465 {
466 for (UINT32 i = 0; i < x509_cert_chain->count; i++)
467 {
468 rdpCertBlob* element = &x509_cert_chain->array[i];
469 cert_blob_free(element);
470 }
471 }
472
473 free(x509_cert_chain->array);
474 x509_cert_chain->array = NULL;
475 x509_cert_chain->count = 0;
476}
477
478#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
479static OSSL_PARAM* get_params(const BIGNUM* e, const BIGNUM* mod)
480{
481 WINPR_ASSERT(e);
482 WINPR_ASSERT(mod);
483
484 OSSL_PARAM* parameters = NULL;
485 OSSL_PARAM_BLD* param = OSSL_PARAM_BLD_new();
486 if (!param)
487 {
488 WLog_ERR(TAG, "OSSL_PARAM_BLD_new() failed");
489 return NULL;
490 }
491
492 const int bits = BN_num_bits(e);
493 if ((bits < 0) || (bits > 32))
494 {
495 WLog_ERR(TAG, "BN_num_bits(e) out of range: 0 <= %d <= 32", bits);
496 goto fail;
497 }
498
499 {
500 UINT ie = 0;
501 {
502 const int ne = BN_bn2nativepad(e, (BYTE*)&ie, sizeof(ie));
503 if ((ne < 0) || (ne > 4))
504 {
505 WLog_ERR(TAG,
506 "BN_bn2nativepad(e, (BYTE*)&ie, sizeof(ie)) out of range: 0<= %d <= 4",
507 ne);
508 goto fail;
509 }
510 }
511
512 if (OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) != 1)
513 {
514 WLog_ERR(TAG, "OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) failed");
515 goto fail;
516 }
517 if (OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) != 1)
518 {
519 WLog_ERR(TAG, "OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) failed");
520 goto fail;
521 }
522 }
523
524 parameters = OSSL_PARAM_BLD_to_param(param);
525 if (!parameters)
526 WLog_ERR(TAG, "OSSL_PARAM_BLD_to_param(param) failed");
527fail:
528 OSSL_PARAM_BLD_free(param);
529
530 return parameters;
531}
532#endif
533
534static BOOL update_x509_from_info(rdpCertificate* cert)
535{
536 BOOL rc = FALSE;
537
538 WINPR_ASSERT(cert);
539
540 X509_free(cert->x509);
541 cert->x509 = NULL;
542
543 rdpCertInfo* info = &cert->cert_info;
544
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();
549 if (!rsa)
550 {
551 WLog_ERR(TAG, "RSA_new() failed");
552 goto fail;
553 }
554#endif
555
556 if (!mod || !e)
557 {
558 WLog_ERR(TAG, "failure: mod=%p, e=%p", WINPR_CXX_COMPAT_CAST(const void*, mod),
559 WINPR_CXX_COMPAT_CAST(const void*, e));
560 goto fail;
561 }
562
563 WINPR_ASSERT(info->ModulusLength <= INT_MAX);
564 if (!BN_bin2bn(info->Modulus, (int)info->ModulusLength, mod))
565 {
566 WLog_ERR(TAG, "BN_bin2bn(info->Modulus, (int)info->ModulusLength, mod) failed");
567 goto fail;
568 }
569
570 if (!BN_bin2bn(info->exponent, (int)sizeof(info->exponent), e))
571 {
572 WLog_ERR(TAG, "BN_bin2bn(info->exponent, (int)sizeof(info->exponent), e) failed");
573 goto fail;
574 }
575
576#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
577 const int rec = RSA_set0_key(rsa, mod, e, NULL);
578 if (rec != 1)
579 {
580 WLog_ERR(TAG, "RSA_set0_key(rsa, mod, e, NULL) failed");
581 goto fail;
582 }
583
584 cert->x509 = x509_from_rsa(rsa);
585#else
586 {
587 EVP_PKEY* pkey = NULL;
588 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
589 if (!ctx)
590 {
591 WLog_ERR(TAG, "EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL) failed");
592 goto fail2;
593 }
594
595 {
596 const int xx = EVP_PKEY_fromdata_init(ctx);
597 if (xx != 1)
598 {
599 WLog_ERR(TAG, "EVP_PKEY_fromdata_init(ctx) failed");
600 goto fail2;
601 }
602 }
603
604 {
605 OSSL_PARAM* parameters = get_params(e, mod);
606 if (!parameters)
607 goto fail2;
608
609 {
610 const int rc2 = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters);
611 OSSL_PARAM_free(parameters);
612 if (rc2 <= 0)
613 {
614 WLog_ERR(
615 TAG,
616 "EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters) failed");
617 goto fail2;
618 }
619 }
620 }
621
622 cert->x509 = X509_new();
623 if (!cert->x509)
624 {
625 WLog_ERR(TAG, "X509_new() failed");
626 goto fail2;
627 }
628
629 if (X509_set_pubkey(cert->x509, pkey) != 1)
630 {
631 WLog_ERR(TAG, "X509_set_pubkey(cert->x509, pkey) failed");
632 X509_free(cert->x509);
633 cert->x509 = NULL;
634 }
635 fail2:
636 EVP_PKEY_free(pkey);
637 EVP_PKEY_CTX_free(ctx);
638 }
639#endif
640 if (!cert->x509)
641 goto fail;
642
643 rc = TRUE;
644
645fail:
646 if (!rc)
647 WLog_ERR(TAG, "failed to update x509 from rdpCertInfo");
648
649#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
650 if (rsa)
651 RSA_free(rsa);
652 else
653#endif
654 {
655 BN_free(mod);
656 BN_free(e);
657 }
658 return rc;
659}
660
661static BOOL certificate_process_server_public_key(rdpCertificate* cert, wStream* s,
662 WINPR_ATTR_UNUSED UINT32 length)
663{
664 char magic[sizeof(rsa_magic)] = { 0 };
665 UINT32 keylen = 0;
666 UINT32 bitlen = 0;
667 UINT32 datalen = 0;
668
669 WINPR_ASSERT(cert);
670 WINPR_ASSERT(s);
671
672 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
673 return FALSE;
674
675 Stream_Read(s, magic, sizeof(magic));
676
677 if (memcmp(magic, rsa_magic, sizeof(magic)) != 0)
678 {
679 WLog_ERR(TAG, "invalid RSA magic bytes");
680 return FALSE;
681 }
682
683 rdpCertInfo* info = &cert->cert_info;
684 cert_info_free(info);
685
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);
690
691 if (keylen <= 8)
692 {
693 WLog_ERR(TAG, "Invalid RSA keylen=%" PRIu32 " <= 8", keylen);
694 return FALSE;
695 }
696 if (!Stream_CheckAndLogRequiredLength(TAG, s, keylen))
697 return FALSE;
698 if (keylen != (bitlen / 8ull) + 8ull)
699 {
700 WLog_ERR(TAG, "Invalid RSA key bitlen %" PRIu32 ", expected %" PRIu32, bitlen,
701 (keylen - 8) * 8);
702 return FALSE;
703 }
704 if (datalen != (bitlen / 8ull) - 1ull)
705 {
706 WLog_ERR(TAG, "Invalid RSA key datalen %" PRIu32 ", expected %llu", datalen,
707 (1ull * bitlen / 8ull) - 1ull);
708 return FALSE;
709 }
710 info->ModulusLength = keylen - 8;
711 BYTE* tmp = realloc(info->Modulus, info->ModulusLength);
712
713 if (!tmp)
714 {
715 WLog_ERR(TAG, "Failed to reallocate modulus of length %" PRIu32, info->ModulusLength);
716 return FALSE;
717 }
718 info->Modulus = tmp;
719
720 Stream_Read(s, info->Modulus, info->ModulusLength);
721 Stream_Seek(s, 8); /* 8 bytes of zero padding */
722 return update_x509_from_info(cert);
723}
724
725static BOOL certificate_process_server_public_signature(rdpCertificate* certificate,
726 const BYTE* sigdata, size_t sigdatalen,
727 wStream* s, UINT32 siglen)
728{
729 WINPR_ASSERT(certificate);
730#if defined(CERT_VALIDATE_RSA)
731 BYTE sig[TSSK_KEY_LENGTH];
732#endif
733 BYTE encsig[TSSK_KEY_LENGTH + 8];
734#if defined(CERT_VALIDATE_MD5) && defined(CERT_VALIDATE_RSA)
735 BYTE md5hash[WINPR_MD5_DIGEST_LENGTH];
736#endif
737#if !defined(CERT_VALIDATE_MD5) || !defined(CERT_VALIDATE_RSA)
738 (void)sigdata;
739 (void)sigdatalen;
740#endif
741 (void)certificate;
742 /* Do not bother with validation of server proprietary certificate. The use of MD5 here is not
743 * allowed under FIPS. Since the validation is not protecting against anything since the
744 * private/public keys are well known and documented in MS-RDPBCGR section 5.3.3.1, we are not
745 * gaining any security by using MD5 for signature comparison. Rather then use MD5
746 * here we just don't do the validation to avoid its use. Historically, freerdp has been
747 * ignoring a failed validation anyways. */
748#if defined(CERT_VALIDATE_MD5)
749
750 if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash, sizeof(md5hash)))
751 return FALSE;
752
753#endif
754 Stream_Read(s, encsig, siglen);
755
756 if (siglen < 8)
757 return FALSE;
758
759 /* Last 8 bytes shall be all zero. */
760#if defined(CERT_VALIDATE_PADDING)
761 {
762 size_t sum = 0;
763 for (size_t i = sizeof(encsig) - 8; i < sizeof(encsig); i++)
764 sum += encsig[i];
765
766 if (sum != 0)
767 {
768 WLog_ERR(TAG, "invalid signature");
769 return FALSE;
770 }
771 }
772#endif
773#if defined(CERT_VALIDATE_RSA)
774
775 if (crypto_rsa_public_decrypt(encsig, siglen - 8, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent,
776 sig) <= 0)
777 {
778 WLog_ERR(TAG, "invalid RSA decrypt");
779 return FALSE;
780 }
781
782 /* Verify signature. */
783 /* Do not bother with validation of server proprietary certificate as described above. */
784#if defined(CERT_VALIDATE_MD5)
785
786 if (memcmp(md5hash, sig, sizeof(md5hash)) != 0)
787 {
788 WLog_ERR(TAG, "invalid signature");
789 return FALSE;
790 }
791
792#endif
793 /*
794 * Verify rest of decrypted data:
795 * The 17th byte is 0x00.
796 * The 18th through 62nd bytes are each 0xFF.
797 * The 63rd byte is 0x01.
798 */
799 {
800 size_t sum = 0;
801 for (size_t i = 17; i < 62; i++)
802 sum += sig[i];
803
804 if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01)
805 {
806 WLog_ERR(TAG, "invalid signature");
807 return FALSE;
808 }
809 }
810#endif
811 return TRUE;
812}
813
814static BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate, wStream* s)
815{
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;
823
824 WINPR_ASSERT(certificate);
825 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
826 return FALSE;
827
828 /* -4, because we need to include dwVersion */
829 const BYTE* sigdata = Stream_PointerAs(s, const BYTE) - 4;
830 Stream_Read_UINT32(s, dwSigAlgId);
831 Stream_Read_UINT32(s, dwKeyAlgId);
832
833 if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
834 {
835 WLog_ERR(TAG,
836 "unsupported signature or key algorithm, dwSigAlgId=%" PRIu32
837 " dwKeyAlgId=%" PRIu32 "",
838 dwSigAlgId, dwKeyAlgId);
839 return FALSE;
840 }
841
842 Stream_Read_UINT16(s, wPublicKeyBlobType);
843
844 if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
845 {
846 WLog_ERR(TAG, "unsupported public key blob type %" PRIu16 "", wPublicKeyBlobType);
847 return FALSE;
848 }
849
850 Stream_Read_UINT16(s, wPublicKeyBlobLen);
851
852 if (!Stream_CheckAndLogRequiredLength(TAG, s, wPublicKeyBlobLen))
853 return FALSE;
854
855 if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
856 return FALSE;
857
858 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
859 return FALSE;
860
861 sigdatalen = WINPR_ASSERTING_INT_CAST(size_t, Stream_PointerAs(s, const BYTE) - sigdata);
862 Stream_Read_UINT16(s, wSignatureBlobType);
863
864 if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
865 {
866 WLog_ERR(TAG, "unsupported blob signature %" PRIu16 "", wSignatureBlobType);
867 return FALSE;
868 }
869
870 Stream_Read_UINT16(s, wSignatureBlobLen);
871
872 if (!Stream_CheckAndLogRequiredLength(TAG, s, wSignatureBlobLen))
873 return FALSE;
874
875 if (wSignatureBlobLen != 72)
876 {
877 WLog_ERR(TAG, "invalid signature length (got %" PRIu16 ", expected 72)", wSignatureBlobLen);
878 return FALSE;
879 }
880
881 if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s,
882 wSignatureBlobLen))
883 {
884 WLog_ERR(TAG, "unable to parse server public signature");
885 return FALSE;
886 }
887 return TRUE;
888}
889
890/* [MS-RDPBCGR] 2.2.1.4.3.1.1.1 RSA Public Key (RSA_PUBLIC_KEY) */
891static BOOL cert_write_rsa_public_key(wStream* s, const rdpCertificate* cert)
892{
893 WINPR_ASSERT(cert);
894 WINPR_ASSERT(freerdp_certificate_is_rsa(cert));
895
896 const rdpCertInfo* info = &cert->cert_info;
897
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;
904
905 const size_t wPublicKeyBlobLen = 16 + pubExpLen + keyLen;
906 WINPR_ASSERT(wPublicKeyBlobLen <= UINT16_MAX);
907 if (!Stream_EnsureRemainingCapacity(s, 2 + wPublicKeyBlobLen))
908 return FALSE;
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);
916 Stream_Zero(s, 8);
917 return TRUE;
918}
919
920static BOOL cert_write_rsa_signature(wStream* s, const void* sigData, size_t sigDataLen)
921{
922 BYTE encryptedSignature[TSSK_KEY_LENGTH] = { 0 };
923 BYTE signature[sizeof(initial_signature)] = { 0 };
924
925 memcpy(signature, initial_signature, sizeof(initial_signature));
926 if (!winpr_Digest(WINPR_MD_MD5, sigData, sigDataLen, signature, sizeof(signature)))
927 return FALSE;
928
929 crypto_rsa_private_encrypt(signature, sizeof(signature), priv_key_tssk, encryptedSignature,
930 sizeof(encryptedSignature));
931
932 if (!Stream_EnsureRemainingCapacity(s, 2 * sizeof(UINT16) + sizeof(encryptedSignature) + 8))
933 return FALSE;
934 Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB);
935 Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */
936 Stream_Write(s, encryptedSignature, sizeof(encryptedSignature));
937 Stream_Zero(s, 8);
938 return TRUE;
939}
940
941/* [MS-RDPBCGR] 2.2.1.4.3.1.1 Server Proprietary Certificate (PROPRIETARYSERVERCERTIFICATE) */
942static BOOL cert_write_server_certificate_v1(wStream* s, const rdpCertificate* certificate)
943{
944 const size_t start = Stream_GetPosition(s);
945 const BYTE* sigData = Stream_PointerAs(s, const BYTE) - sizeof(UINT32);
946
947 WINPR_ASSERT(start >= 4);
948 if (!Stream_EnsureRemainingCapacity(s, 10))
949 return FALSE;
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))
954 return FALSE;
955
956 const size_t end = Stream_GetPosition(s);
957 return cert_write_rsa_signature(s, sigData, end - start + sizeof(UINT32));
958}
959
960static BOOL cert_write_server_certificate_v2(wStream* s, const rdpCertificate* certificate)
961{
962 WINPR_ASSERT(certificate);
963
964 const rdpX509CertChain* chain = &certificate->x509_cert_chain;
965 const size_t padding = 8ull + 4ull * chain->count;
966
967 if (!Stream_EnsureRemainingCapacity(s, sizeof(UINT32)))
968 return FALSE;
969
970 Stream_Write_UINT32(s, chain->count);
971 for (UINT32 x = 0; x < chain->count; x++)
972 {
973 const rdpCertBlob* cert = &chain->array[x];
974 if (!cert_blob_write(cert, s))
975 return FALSE;
976 }
977
978 if (!Stream_EnsureRemainingCapacity(s, padding))
979 return FALSE;
980 Stream_Zero(s, padding);
981 return TRUE;
982}
983
984SSIZE_T freerdp_certificate_write_server_cert(const rdpCertificate* certificate, UINT32 dwVersion,
985 wStream* s)
986{
987 if (!certificate)
988 return -1;
989
990 const size_t start = Stream_GetPosition(s);
991 if (!Stream_EnsureRemainingCapacity(s, 4))
992 return -1;
993 Stream_Write_UINT32(s, dwVersion);
994
995 switch (dwVersion & CERT_CHAIN_VERSION_MASK)
996 {
997 case CERT_CHAIN_VERSION_1:
998 if (!cert_write_server_certificate_v1(s, certificate))
999 return -1;
1000 break;
1001 case CERT_CHAIN_VERSION_2:
1002 if (!cert_write_server_certificate_v2(s, certificate))
1003 return -1;
1004 break;
1005 default:
1006 WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
1007 dwVersion & CERT_CHAIN_VERSION_MASK);
1008 return -1;
1009 }
1010
1011 const size_t end = Stream_GetPosition(s);
1012 if (start > end)
1013 return -1;
1014
1015 const size_t diff = end - start;
1016 WINPR_ASSERT(diff <= SSIZE_MAX);
1017 return (SSIZE_T)diff;
1018}
1019
1027static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* cert, wStream* s)
1028{
1029 UINT32 numCertBlobs = 0;
1030 DEBUG_CERTIFICATE("Server X.509 Certificate Chain");
1031
1032 WINPR_ASSERT(cert);
1033 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1034 return FALSE;
1035
1036 Stream_Read_UINT32(s, numCertBlobs); /* numCertBlobs */
1037 certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1038 cert->x509_cert_chain = certificate_new_x509_certificate_chain(numCertBlobs);
1039
1040 for (UINT32 i = 0; i < cert->x509_cert_chain.count; i++)
1041 {
1042 rdpCertBlob* blob = &cert->x509_cert_chain.array[i];
1043 if (!cert_blob_read(blob, s))
1044 return FALSE;
1045
1046 if (numCertBlobs - i == 1)
1047 {
1048 DEBUG_CERTIFICATE("Terminal Server Certificate");
1049
1050 BOOL res = certificate_read_x509_certificate(blob, &cert->cert_info);
1051
1052 if (res)
1053 {
1054 if (!update_x509_from_info(cert))
1055 res = FALSE;
1056 }
1057
1058 if (!res)
1059 {
1060 WLog_ERR(TAG, "Failed to read x509 certificate");
1061 return FALSE;
1062 }
1063
1064 DEBUG_CERTIFICATE("modulus length:%" PRIu32 "", cert->cert_info.ModulusLength);
1065 }
1066 }
1067
1068 return update_x509_from_info(cert);
1069}
1070
1078BOOL freerdp_certificate_read_server_cert(rdpCertificate* certificate, const BYTE* server_cert,
1079 size_t length)
1080{
1081 BOOL ret = FALSE;
1082 wStream* s = NULL;
1083 wStream sbuffer;
1084 UINT32 dwVersion = 0;
1085
1086 WINPR_ASSERT(certificate);
1087 if (length < 4) /* NULL certificate is not an error see #1795 */
1088 {
1089 WLog_DBG(TAG, "Received empty certificate, ignoring...");
1090 return TRUE;
1091 }
1092
1093 WINPR_ASSERT(server_cert);
1094 s = Stream_StaticConstInit(&sbuffer, server_cert, length);
1095
1096 if (!s)
1097 {
1098 WLog_ERR(TAG, "Stream_New failed!");
1099 return FALSE;
1100 }
1101
1102 Stream_Read_UINT32(s, dwVersion); /* dwVersion (4 bytes) */
1103
1104 switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1105 {
1106 case CERT_CHAIN_VERSION_1:
1107 ret = certificate_read_server_proprietary_certificate(certificate, s);
1108 break;
1109
1110 case CERT_CHAIN_VERSION_2:
1111 ret = certificate_read_server_x509_certificate_chain(certificate, s);
1112 break;
1113
1114 default:
1115 WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
1116 dwVersion & CERT_CHAIN_VERSION_MASK);
1117 ret = FALSE;
1118 break;
1119 }
1120
1121 return ret;
1122}
1123
1124static BOOL cert_blob_copy(rdpCertBlob* dst, const rdpCertBlob* src)
1125{
1126 WINPR_ASSERT(dst);
1127 WINPR_ASSERT(src);
1128
1129 cert_blob_free(dst);
1130 if (src->length > 0)
1131 {
1132 dst->data = malloc(src->length);
1133 if (!dst->data)
1134 return FALSE;
1135 dst->length = src->length;
1136 memcpy(dst->data, src->data, src->length);
1137 }
1138
1139 return TRUE;
1140}
1141
1142static BOOL cert_x509_chain_copy(rdpX509CertChain* cert, const rdpX509CertChain* src)
1143{
1144 WINPR_ASSERT(cert);
1145
1146 certificate_free_x509_certificate_chain(cert);
1147 if (!src)
1148 return TRUE;
1149
1150 if (src->count > 0)
1151 {
1152 cert->array = calloc(src->count, sizeof(rdpCertBlob));
1153 if (!cert->array)
1154 {
1155 return FALSE;
1156 }
1157 cert->count = src->count;
1158
1159 for (UINT32 x = 0; x < cert->count; x++)
1160 {
1161 const rdpCertBlob* srcblob = &src->array[x];
1162 rdpCertBlob* dstblob = &cert->array[x];
1163
1164 if (!cert_blob_copy(dstblob, srcblob))
1165 {
1166 certificate_free_x509_certificate_chain(cert);
1167 return FALSE;
1168 }
1169 }
1170 }
1171
1172 return TRUE;
1173}
1174
1175BOOL cert_clone_int(rdpCertificate* dst, const rdpCertificate* src)
1176{
1177 WINPR_ASSERT(dst);
1178 WINPR_ASSERT(src);
1179
1180 if (!cert_info_clone(&dst->cert_info, &src->cert_info))
1181 return FALSE;
1182
1183 if (src->x509)
1184 {
1185 dst->x509 = X509_dup(src->x509);
1186 if (!dst->x509)
1187 {
1188 /* Workaround for SSL deprecation issues:
1189 * some security modes use weak RSA ciphers where X509_dup fails.
1190 * In that case recreate the X509 from the raw RSA data
1191 */
1192 if (!update_x509_from_info(dst))
1193 {
1194 WLog_ERR(TAG, "X509_dup failed, SSL configuration bug?");
1195 return FALSE;
1196 }
1197 }
1198 }
1199
1200 if (src->chain)
1201 {
1202 if (dst->chain)
1203 sk_X509_pop_free(dst->chain, X509_free);
1204
1205 dst->chain = sk_X509_deep_copy(src->chain, X509_const_dup, X509_free);
1206 }
1207 return cert_x509_chain_copy(&dst->x509_cert_chain, &src->x509_cert_chain);
1208}
1209
1210rdpCertificate* freerdp_certificate_clone(const rdpCertificate* certificate)
1211{
1212 if (!certificate)
1213 return NULL;
1214
1215 rdpCertificate* _certificate = freerdp_certificate_new();
1216
1217 if (!_certificate)
1218 return NULL;
1219
1220 if (!cert_clone_int(_certificate, certificate))
1221 goto out_fail;
1222
1223 return _certificate;
1224out_fail:
1225
1226 freerdp_certificate_free(_certificate);
1227 return NULL;
1228}
1229
1235rdpCertificate* freerdp_certificate_new(void)
1236{
1237 return (rdpCertificate*)calloc(1, sizeof(rdpCertificate));
1238}
1239
1240void certificate_free_int(rdpCertificate* cert)
1241{
1242 WINPR_ASSERT(cert);
1243
1244 if (cert->x509)
1245 X509_free(cert->x509);
1246 if (cert->chain)
1247 sk_X509_pop_free(cert->chain, X509_free);
1248
1249 certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1250 cert_info_free(&cert->cert_info);
1251}
1252
1258void freerdp_certificate_free(rdpCertificate* cert)
1259{
1260 if (!cert)
1261 return;
1262
1263 certificate_free_int(cert);
1264 free(cert);
1265}
1266
1267static BOOL freerdp_rsa_from_x509(rdpCertificate* cert)
1268{
1269 BOOL rc = FALSE;
1270
1271 WINPR_ASSERT(cert);
1272
1273 if (!freerdp_certificate_is_rsa(cert))
1274 return TRUE;
1275
1276#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1277 RSA* rsa = NULL;
1278 const BIGNUM* rsa_n = NULL;
1279 const BIGNUM* rsa_e = NULL;
1280#else
1281 BIGNUM* rsa_n = NULL;
1282 BIGNUM* rsa_e = NULL;
1283#endif
1284 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1285 if (!pubkey)
1286 goto fail;
1287
1288#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1289 rsa = EVP_PKEY_get1_RSA(pubkey);
1290
1291 /* If this is not a RSA key return success */
1292 rc = TRUE;
1293 if (!rsa)
1294 goto fail;
1295
1296 /* Now we return failure again if something is wrong. */
1297 rc = FALSE;
1298
1299 RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
1300#else
1301 if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &rsa_e))
1302 goto fail;
1303 if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &rsa_n))
1304 goto fail;
1305#endif
1306 if (!rsa_n || !rsa_e)
1307 goto fail;
1308 if (!cert_info_create(&cert->cert_info, rsa_n, rsa_e))
1309 goto fail;
1310 rc = TRUE;
1311fail:
1312#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1313 RSA_free(rsa);
1314#else
1315 BN_free(rsa_n);
1316 BN_free(rsa_e);
1317#endif
1318 return rc;
1319}
1320
1321rdpCertificate* freerdp_certificate_new_from_der(const BYTE* data, size_t length)
1322{
1323 rdpCertificate* cert = freerdp_certificate_new();
1324
1325 if (!cert || !data || (length == 0) || (length > INT_MAX))
1326 goto fail;
1327
1328 {
1329 const BYTE* ptr = data;
1330 cert->x509 = d2i_X509(NULL, &ptr, (int)length);
1331 }
1332
1333 if (!cert->x509)
1334 goto fail;
1335 if (!freerdp_rsa_from_x509(cert))
1336 goto fail;
1337 return cert;
1338fail:
1339 freerdp_certificate_free(cert);
1340 return NULL;
1341}
1342
1343rdpCertificate* freerdp_certificate_new_from_x509(const X509* xcert, const STACK_OF(X509) * chain)
1344{
1345 WINPR_ASSERT(xcert);
1346
1347 rdpCertificate* cert = freerdp_certificate_new();
1348 if (!cert)
1349 return NULL;
1350
1351 X509* wcert = WINPR_CAST_CONST_PTR_AWAY(xcert, X509*);
1352 cert->x509 = X509_dup(wcert);
1353 if (!cert->x509)
1354 goto fail;
1355
1356 if (!freerdp_rsa_from_x509(cert))
1357 goto fail;
1358
1359 if (chain)
1360 cert->chain = sk_X509_deep_copy(chain, X509_const_dup, X509_free);
1361
1362 return cert;
1363fail:
1364 freerdp_certificate_free(cert);
1365 return NULL;
1366}
1367
1368static STACK_OF(X509) * extract_chain_from_pem(const char* pem, BOOL isFile)
1369{
1370 if (!pem)
1371 {
1372 return NULL;
1373 }
1374
1375 BIO* bio = NULL;
1376 if (isFile)
1377 bio = BIO_new_file(pem, "rb");
1378 else
1379 {
1380 const size_t len = strlen(pem);
1381 bio = BIO_new_mem_buf(pem, WINPR_ASSERTING_INT_CAST(int, len));
1382 }
1383
1384 if (!bio)
1385 {
1386 return NULL;
1387 }
1388
1389 X509* leaf = PEM_read_bio_X509(bio, NULL, NULL, NULL);
1390 if (!leaf)
1391 {
1392 BIO_free(bio);
1393 return NULL;
1394 }
1395
1396 STACK_OF(X509)* chain = sk_X509_new_null();
1397 if (!chain)
1398 {
1399 X509_free(leaf);
1400 BIO_free(bio);
1401 return NULL;
1402 }
1403
1404 X509* cert = NULL;
1405 while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL)
1406 {
1407 sk_X509_push(chain, cert);
1408 }
1409
1410 X509_free(leaf);
1411 BIO_free(bio);
1412 return chain;
1413}
1414
1415static rdpCertificate* freerdp_certificate_new_from(const char* file, BOOL isFile)
1416{
1417 X509* x509 = x509_utils_from_pem(file, strlen(file), isFile);
1418 if (!x509)
1419 return NULL;
1420 STACK_OF(X509)* chain = extract_chain_from_pem(file, isFile);
1421 rdpCertificate* cert = freerdp_certificate_new_from_x509(x509, chain);
1422 if (chain)
1423 sk_X509_pop_free(chain, X509_free);
1424 X509_free(x509);
1425 return cert;
1426}
1427
1428rdpCertificate* freerdp_certificate_new_from_file(const char* file)
1429{
1430 return freerdp_certificate_new_from(file, TRUE);
1431}
1432
1433rdpCertificate* freerdp_certificate_new_from_pem(const char* pem)
1434{
1435 return freerdp_certificate_new_from(pem, FALSE);
1436}
1437
1438const rdpCertInfo* freerdp_certificate_get_info(const rdpCertificate* cert)
1439{
1440 WINPR_ASSERT(cert);
1441 if (!freerdp_certificate_is_rsa(cert))
1442 return NULL;
1443 return &cert->cert_info;
1444}
1445
1446char* freerdp_certificate_get_fingerprint(const rdpCertificate* cert)
1447{
1448 return freerdp_certificate_get_fingerprint_by_hash(cert, "sha256");
1449}
1450
1451char* freerdp_certificate_get_fingerprint_by_hash(const rdpCertificate* cert, const char* hash)
1452{
1453 return freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, TRUE);
1454}
1455
1456char* freerdp_certificate_get_fingerprint_by_hash_ex(const rdpCertificate* cert, const char* hash,
1457 BOOL separator)
1458{
1459 size_t fp_len = 0;
1460 size_t pos = 0;
1461 size_t size = 0;
1462 BYTE* fp = NULL;
1463 char* fp_buffer = NULL;
1464 if (!cert || !cert->x509)
1465 {
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));
1468 return NULL;
1469 }
1470 if (!hash)
1471 {
1472 WLog_ERR(TAG, "Invalid certificate hash %p", WINPR_CXX_COMPAT_CAST(const void*, hash));
1473 return NULL;
1474 }
1475 fp = x509_utils_get_hash(cert->x509, hash, &fp_len);
1476 if (!fp)
1477 return NULL;
1478
1479 if (fp_len < 1)
1480 goto fail;
1481
1482 size = fp_len * 3 + 1;
1483 fp_buffer = calloc(size, sizeof(char));
1484 if (!fp_buffer)
1485 goto fail;
1486
1487 pos = 0;
1488
1489 {
1490 size_t i = 0;
1491 for (; i < (fp_len - 1); i++)
1492 {
1493 int rc = 0;
1494 char* p = &fp_buffer[pos];
1495 if (separator)
1496 rc = sprintf_s(p, size - pos, "%02" PRIx8 ":", fp[i]);
1497 else
1498 rc = sprintf_s(p, size - pos, "%02" PRIx8, fp[i]);
1499 if (rc <= 0)
1500 goto fail;
1501 pos += (size_t)rc;
1502 }
1503
1504 (void)sprintf_s(&fp_buffer[pos], size - pos, "%02" PRIx8 "", fp[i]);
1505 }
1506
1507 free(fp);
1508
1509 return fp_buffer;
1510fail:
1511 free(fp);
1512 free(fp_buffer);
1513 return NULL;
1514}
1515
1516static BOOL bio_read_pem(BIO* bio, char** ppem, size_t* plength)
1517{
1518 BOOL rc = FALSE;
1519
1520 WINPR_ASSERT(bio);
1521 WINPR_ASSERT(ppem);
1522
1523 const size_t blocksize = 2048;
1524 size_t offset = 0;
1525 size_t length = blocksize;
1526 char* pem = NULL;
1527
1528 *ppem = NULL;
1529 if (plength)
1530 *plength = 0;
1531
1532 while (offset < length)
1533 {
1534 char* tmp = realloc(pem, length + 1);
1535 if (!tmp)
1536 goto fail;
1537 pem = tmp;
1538
1539 ERR_clear_error();
1540
1541 const int status = BIO_read(bio, &pem[offset], (int)(length - offset));
1542 if (status < 0)
1543 {
1544 WLog_ERR(TAG, "failed to read certificate");
1545 goto fail;
1546 }
1547
1548 if (status == 0)
1549 break;
1550
1551 offset += (size_t)status;
1552 if (length - offset > 0)
1553 break;
1554 length += blocksize;
1555 }
1556
1557 if (pem)
1558 {
1559 if (offset >= length)
1560 goto fail;
1561 pem[offset] = '\0';
1562 }
1563 *ppem = pem;
1564 if (plength)
1565 *plength = offset;
1566 rc = TRUE;
1567fail:
1568 if (!rc)
1569 free(pem);
1570
1571 return rc;
1572}
1573
1574char* freerdp_certificate_get_pem(const rdpCertificate* cert, size_t* pLength)
1575{
1576 return freerdp_certificate_get_pem_ex(cert, pLength, TRUE);
1577}
1578
1579char* freerdp_certificate_get_pem_ex(const rdpCertificate* cert, size_t* pLength,
1580 BOOL withCertChain)
1581{
1582 WINPR_ASSERT(cert);
1583
1584 if (!cert->x509)
1585 return NULL;
1586
1591 BIO* bio = BIO_new(BIO_s_mem());
1592
1593 if (!bio)
1594 {
1595 WLog_ERR(TAG, "BIO_new() failure");
1596 return NULL;
1597 }
1598
1599 char* pem = NULL;
1600
1601 const int status = PEM_write_bio_X509(bio, cert->x509);
1602 if (status < 0)
1603 {
1604 WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
1605 goto fail;
1606 }
1607
1608 if (cert->chain && withCertChain)
1609 {
1610 const int count = sk_X509_num(cert->chain);
1611 for (int x = 0; x < count; x++)
1612 {
1613 X509* c = sk_X509_value(cert->chain, x);
1614 const int rc = PEM_write_bio_X509(bio, c);
1615 if (rc < 0)
1616 {
1617 WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", rc);
1618 goto fail;
1619 }
1620 }
1621 }
1622
1623 (void)bio_read_pem(bio, &pem, pLength);
1624
1625fail:
1626 BIO_free_all(bio);
1627 return pem;
1628}
1629
1630char* freerdp_certificate_get_subject(const rdpCertificate* cert)
1631{
1632 WINPR_ASSERT(cert);
1633 return x509_utils_get_subject(cert->x509);
1634}
1635
1636char* freerdp_certificate_get_issuer(const rdpCertificate* cert)
1637{
1638 WINPR_ASSERT(cert);
1639 return x509_utils_get_issuer(cert->x509);
1640}
1641
1642char* freerdp_certificate_get_upn(const rdpCertificate* cert)
1643{
1644 WINPR_ASSERT(cert);
1645 return x509_utils_get_upn(cert->x509);
1646}
1647
1648char* freerdp_certificate_get_email(const rdpCertificate* cert)
1649{
1650 WINPR_ASSERT(cert);
1651 return x509_utils_get_email(cert->x509);
1652}
1653
1654char* freerdp_certificate_get_validity(const rdpCertificate* cert, BOOL startDate)
1655{
1656 WINPR_ASSERT(cert);
1657 return x509_utils_get_date(cert->x509, startDate);
1658}
1659
1660BOOL freerdp_certificate_check_eku(const rdpCertificate* cert, int nid)
1661{
1662 WINPR_ASSERT(cert);
1663 return x509_utils_check_eku(cert->x509, nid);
1664}
1665
1666BOOL freerdp_certificate_get_public_key(const rdpCertificate* cert, BYTE** PublicKey,
1667 DWORD* PublicKeyLength)
1668{
1669 BYTE* ptr = NULL;
1670 BYTE* optr = NULL;
1671 int length = 0;
1672 BOOL status = FALSE;
1673 EVP_PKEY* pkey = NULL;
1674
1675 WINPR_ASSERT(cert);
1676
1677 pkey = X509_get0_pubkey(cert->x509);
1678
1679 if (!pkey)
1680 {
1681 WLog_ERR(TAG, "X509_get_pubkey() failed");
1682 goto exit;
1683 }
1684
1685 length = i2d_PublicKey(pkey, NULL);
1686
1687 if (length < 1)
1688 {
1689 WLog_ERR(TAG, "i2d_PublicKey() failed");
1690 goto exit;
1691 }
1692
1693 *PublicKey = optr = ptr = (BYTE*)calloc(WINPR_ASSERTING_INT_CAST(size_t, length), sizeof(BYTE));
1694
1695 if (!ptr)
1696 goto exit;
1697
1698 {
1699 const int length2 = i2d_PublicKey(pkey, &ptr);
1700 if (length != length2)
1701 goto exit;
1702 *PublicKeyLength = (DWORD)length2;
1703 }
1704 status = TRUE;
1705exit:
1706
1707 if (!status)
1708 free(optr);
1709
1710 return status;
1711}
1712
1713BOOL freerdp_certificate_verify(const rdpCertificate* cert, const char* certificate_store_path)
1714{
1715 WINPR_ASSERT(cert);
1716 return x509_utils_verify(cert->x509, cert->chain, certificate_store_path);
1717}
1718
1719char** freerdp_certificate_get_dns_names(const rdpCertificate* cert, size_t* pcount,
1720 size_t** pplengths)
1721{
1722 WINPR_ASSERT(cert);
1723 return x509_utils_get_dns_names(cert->x509, pcount, pplengths);
1724}
1725
1726char* freerdp_certificate_get_common_name(const rdpCertificate* cert, size_t* plength)
1727{
1728 WINPR_ASSERT(cert);
1729 return x509_utils_get_common_name(cert->x509, plength);
1730}
1731
1732WINPR_MD_TYPE freerdp_certificate_get_signature_alg(const rdpCertificate* cert)
1733{
1734 WINPR_ASSERT(cert);
1735 return x509_utils_get_signature_alg(cert->x509);
1736}
1737
1738void freerdp_certificate_free_dns_names(size_t count, size_t* lengths, char** names)
1739{
1740 x509_utils_dns_names_free(count, lengths, names);
1741}
1742
1743char* freerdp_certificate_get_hash(const rdpCertificate* cert, const char* hash, size_t* plength)
1744{
1745 WINPR_ASSERT(cert);
1746 return (char*)x509_utils_get_hash(cert->x509, hash, plength);
1747}
1748
1749X509* freerdp_certificate_get_x509(rdpCertificate* cert)
1750{
1751 WINPR_ASSERT(cert);
1752 return cert->x509;
1753}
1754
1755BOOL freerdp_certificate_publickey_encrypt(const rdpCertificate* cert, const BYTE* input,
1756 size_t cbInput, BYTE** poutput, size_t* pcbOutput)
1757{
1758 WINPR_ASSERT(cert);
1759 WINPR_ASSERT(input);
1760 WINPR_ASSERT(poutput);
1761 WINPR_ASSERT(pcbOutput);
1762
1763 BOOL ret = FALSE;
1764 BYTE* output = NULL;
1765 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1766 if (!pkey)
1767 return FALSE;
1768
1769 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
1770 if (!ctx)
1771 return FALSE;
1772
1773 size_t outputSize = WINPR_ASSERTING_INT_CAST(size_t, EVP_PKEY_size(pkey));
1774 output = malloc(outputSize);
1775 if (output == NULL)
1776 goto out;
1777 *pcbOutput = outputSize;
1778
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)
1782 {
1783 WLog_ERR(TAG, "error when setting up public key");
1784 goto out;
1785 }
1786
1787 *poutput = output;
1788 output = NULL;
1789 ret = TRUE;
1790out:
1791 EVP_PKEY_CTX_free(ctx);
1792 free(output);
1793 return ret;
1794}
1795
1796#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1797static RSA* freerdp_certificate_get_RSA(const rdpCertificate* cert)
1798{
1799 WINPR_ASSERT(cert);
1800
1801 if (!freerdp_certificate_is_rsa(cert))
1802 return NULL;
1803
1804 EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1805 if (!pubkey)
1806 return NULL;
1807
1808 return EVP_PKEY_get1_RSA(pubkey);
1809}
1810#endif
1811
1812BYTE* freerdp_certificate_get_der(const rdpCertificate* cert, size_t* pLength)
1813{
1814 WINPR_ASSERT(cert);
1815
1816 if (pLength)
1817 *pLength = 0;
1818
1819 const int rc = i2d_X509(cert->x509, NULL);
1820 if (rc <= 0)
1821 return NULL;
1822
1823 BYTE* ptr = calloc(WINPR_ASSERTING_INT_CAST(size_t, rc) + 1, sizeof(BYTE));
1824 if (!ptr)
1825 return NULL;
1826 BYTE* i2d_ptr = ptr;
1827
1828 const int rc2 = i2d_X509(cert->x509, &i2d_ptr);
1829 if (rc2 <= 0)
1830 {
1831 free(ptr);
1832 return NULL;
1833 }
1834
1835 if (pLength)
1836 *pLength = (size_t)rc2;
1837 return ptr;
1838}
1839
1840BOOL freerdp_certificate_is_rsa(const rdpCertificate* cert)
1841{
1842 WINPR_ASSERT(cert);
1843 return is_rsa_key(cert->x509);
1844}
1845
1846BOOL freerdp_certificate_is_rdp_security_compatible(const rdpCertificate* cert)
1847{
1848 const rdpCertInfo* info = freerdp_certificate_get_info(cert);
1849 if (!freerdp_certificate_is_rsa(cert) || !info || (info->ModulusLength != 2048 / 8))
1850 {
1851 WLog_INFO(TAG, "certificate is not RSA 2048, RDP security not supported.");
1852 return FALSE;
1853 }
1854 return TRUE;
1855}
1856
1857char* freerdp_certificate_get_param(const rdpCertificate* cert, enum FREERDP_CERT_PARAM what,
1858 size_t* psize)
1859{
1860 WINPR_ASSERT(cert);
1861 WINPR_ASSERT(psize);
1862
1863 *psize = 0;
1864
1865#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1866 const BIGNUM* bn = NULL;
1867 RSA* rsa = freerdp_certificate_get_RSA(cert);
1868 switch (what)
1869 {
1870 case FREERDP_CERT_RSA_E:
1871 RSA_get0_key(rsa, NULL, &bn, NULL);
1872 break;
1873 case FREERDP_CERT_RSA_N:
1874 RSA_get0_key(rsa, &bn, NULL, NULL);
1875 break;
1876 default:
1877 RSA_free(rsa);
1878 return NULL;
1879 }
1880 RSA_free(rsa);
1881#else
1882 EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1883 if (!pkey)
1884 return NULL;
1885
1886 BIGNUM* bn = NULL;
1887 switch (what)
1888 {
1889 case FREERDP_CERT_RSA_E:
1890 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn))
1891 return NULL;
1892 break;
1893 case FREERDP_CERT_RSA_N:
1894 if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn))
1895 return NULL;
1896 break;
1897 default:
1898 return NULL;
1899 }
1900#endif
1901
1902 const size_t bnsize = WINPR_ASSERTING_INT_CAST(size_t, BN_num_bytes(bn));
1903 char* rc = calloc(bnsize + 1, sizeof(char));
1904 if (!rc)
1905 goto fail;
1906 BN_bn2bin(bn, (BYTE*)rc);
1907 *psize = bnsize;
1908
1909fail:
1910#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR < 3)
1911 BN_free(bn);
1912#endif
1913 return rc;
1914}
1915
1916size_t freerdp_certificate_get_chain_len(rdpCertificate* certificate)
1917{
1918 WINPR_ASSERT(certificate);
1919 if (!certificate->chain)
1920 return 0;
1921
1922 return WINPR_ASSERTING_INT_CAST(size_t, sk_X509_num(certificate->chain));
1923}
1924
1925X509* freerdp_certificate_get_chain_at(rdpCertificate* certificate, size_t offset)
1926{
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);
1931}