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