Coverage Report

Created: 2026-10-15 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/libfreerdp/crypto/certificate.c
Line
Count
Source
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Certificate Handling
4
 *
5
 * Copyright 2011 Jiten Pathy
6
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7
 * Copyright 2015 Thincast Technologies GmbH
8
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
9
 * Copyright 2023 Armin Novak <anovak@thincast.com>
10
 * Copyright 2023 Thincast Technologies GmbH
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 *     http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24
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
#include "../core/utils.h"
56
57
#include "x509_utils.h"
58
#include "privatekey.h"
59
#include "opensslcompat.h"
60
61
#define TAG FREERDP_TAG("core")
62
63
#ifdef WITH_DEBUG_CERTIFICATE
64
#define DEBUG_CERTIFICATE(...) WLog_DBG(TAG, __VA_ARGS__)
65
#else
66
#define DEBUG_CERTIFICATE(...) \
67
0
  do                         \
68
0
  {                          \
69
0
  } 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
97
/**
98
 *
99
 * X.509 Certificate Structure
100
 *
101
 * Certificate ::= SEQUENCE
102
 * {
103
 *  tbsCertificate      TBSCertificate,
104
 *  signatureAlgorithm    AlgorithmIdentifier,
105
 *  signatureValue      BIT_STRING
106
 * }
107
 *
108
 * TBSCertificate ::= SEQUENCE
109
 * {
110
 *  version     [0] EXPLICIT Version DEFAULT v1,
111
 *  serialNumber      CertificateSerialNumber,
112
 *  signature     AlgorithmIdentifier,
113
 *  issuer        Name,
114
 *  validity      Validity,
115
 *  subject       Name,
116
 *  subjectPublicKeyInfo    SubjectPublicKeyInfo,
117
 *  issuerUniqueID    [1] IMPLICIT UniqueIdentifier OPTIONAL,
118
 *  subjectUniqueId   [2] IMPLICIT UniqueIdentifier OPTIONAL,
119
 *  extensions    [3] EXPLICIT Extensions OPTIONAL
120
 * }
121
 *
122
 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
123
 *
124
 * CertificateSerialNumber ::= INTEGER
125
 *
126
 * AlgorithmIdentifier ::= SEQUENCE
127
 * {
128
 *  algorithm     OBJECT_IDENTIFIER,
129
 *  parameters      ANY DEFINED BY algorithm OPTIONAL
130
 * }
131
 *
132
 * Name ::= CHOICE { RDNSequence }
133
 *
134
 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
135
 *
136
 * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
137
 *
138
 * AttributeTypeAndValue ::= SEQUENCE
139
 * {
140
 *  type        AttributeType,
141
 *  value       AttributeValue
142
 * }
143
 *
144
 * AttributeType ::= OBJECT_IDENTIFIER
145
 *
146
 * AttributeValue ::= ANY DEFINED BY AttributeType
147
 *
148
 * Validity ::= SEQUENCE
149
 * {
150
 *  notBefore     Time,
151
 *  notAfter      Time
152
 * }
153
 *
154
 * Time ::= CHOICE
155
 * {
156
 *  utcTime       UTCTime,
157
 *  generalTime     GeneralizedTime
158
 * }
159
 *
160
 * UniqueIdentifier ::= BIT_STRING
161
 *
162
 * SubjectPublicKeyInfo ::= SEQUENCE
163
 * {
164
 *  algorithm     AlgorithmIdentifier,
165
 *  subjectPublicKey    BIT_STRING
166
 * }
167
 *
168
 * RSAPublicKey ::= SEQUENCE
169
 * {
170
 *  modulus       INTEGER
171
 *  publicExponent      INTEGER
172
 * }
173
 *
174
 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
175
 *
176
 * Extension ::= SEQUENCE
177
 * {
178
 *  extnID        OBJECT_IDENTIFIER
179
 *  critical      BOOLEAN DEFAULT FALSE,
180
 *  extnValue     OCTET_STRING
181
 * }
182
 *
183
 */
184
185
static const char rsa_magic[4] = { 'R', 'S', 'A', '1' };
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
0
{
232
0
  UINT32 certLength = 0;
233
0
  WINPR_ASSERT(blob);
234
0
  cert_blob_free(blob);
235
236
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
237
0
    goto fail;
238
239
0
  Stream_Read_UINT32(s, certLength);
240
241
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, certLength))
242
0
    goto fail;
243
244
0
  DEBUG_CERTIFICATE("X.509 Certificate length:%" PRIu32 "", certLength);
245
0
  blob->data = (BYTE*)malloc(certLength);
246
247
0
  if (!blob->data)
248
0
    goto fail;
249
250
0
  Stream_Read(s, blob->data, certLength);
251
0
  blob->length = certLength;
252
253
0
  return TRUE;
254
255
0
fail:
256
0
  cert_blob_free(blob);
257
0
  return FALSE;
258
0
}
259
260
BOOL cert_blob_write(const rdpCertBlob* blob, wStream* s)
261
0
{
262
0
  WINPR_ASSERT(blob);
263
264
0
  if (!Stream_EnsureRemainingCapacity(s, 4ull + blob->length))
265
0
    return FALSE;
266
267
0
  Stream_Write_UINT32(s, blob->length);
268
0
  Stream_Write(s, blob->data, blob->length);
269
0
  return TRUE;
270
0
}
271
272
void cert_blob_free(rdpCertBlob* blob)
273
0
{
274
0
  if (!blob)
275
0
    return;
276
0
  free(blob->data);
277
0
  blob->data = nullptr;
278
0
  blob->length = 0;
279
0
}
280
281
/**
282
 * Read X.509 Certificate
283
 */
284
285
static BOOL is_rsa_key(const X509* x509)
286
0
{
287
0
  EVP_PKEY* evp = X509_get0_pubkey(x509);
288
0
  if (!evp)
289
0
    return FALSE;
290
291
0
  return (EVP_PKEY_id(evp) == EVP_PKEY_RSA);
292
0
}
293
294
static BOOL certificate_read_x509_certificate(const rdpCertBlob* cert, rdpCertInfo* info)
295
0
{
296
0
  wStream sbuffer = WINPR_C_ARRAY_INIT;
297
0
  wStream* s = nullptr;
298
0
  size_t length = 0;
299
0
  BYTE padding = 0;
300
0
  UINT32 version = 0;
301
0
  size_t modulus_length = 0;
302
0
  size_t exponent_length = 0;
303
0
  int error = 0;
304
305
0
  WINPR_ASSERT(cert);
306
0
  WINPR_ASSERT(info);
307
308
0
  cert_info_free(info);
309
310
0
  s = Stream_StaticConstInit(&sbuffer, cert->data, cert->length);
311
312
0
  if (!s)
313
0
    return FALSE;
314
315
0
  if (!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */
316
0
    goto error;
317
318
0
  error++;
319
320
0
  if (!ber_read_sequence_tag(s, &length)) /* TBSCertificate (SEQUENCE) */
321
0
    goto error;
322
323
0
  error++;
324
325
0
  if (!ber_read_contextual_tag(s, 0, &length, TRUE)) /* Explicit Contextual Tag [0] */
326
0
    goto error;
327
328
0
  error++;
329
330
0
  if (!ber_read_integer(s, &version)) /* version (INTEGER) */
331
0
    goto error;
332
333
0
  error++;
334
0
  version++;
335
336
  /* serialNumber */
337
0
  if (!ber_read_integer(s, nullptr)) /* CertificateSerialNumber (INTEGER) */
338
0
    goto error;
339
340
0
  error++;
341
342
  /* signature */
343
0
  if (!ber_read_sequence_tag(s, &length) ||
344
0
      !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */
345
0
    goto error;
346
347
0
  error++;
348
349
  /* issuer */
350
0
  if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */
351
0
    goto error;
352
353
0
  error++;
354
355
  /* validity */
356
0
  if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Validity (SEQUENCE) */
357
0
    goto error;
358
359
0
  error++;
360
361
  /* subject */
362
0
  if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */
363
0
    goto error;
364
365
0
  error++;
366
367
  /* subjectPublicKeyInfo */
368
0
  if (!ber_read_sequence_tag(s, &length)) /* SubjectPublicKeyInfo (SEQUENCE) */
369
0
    goto error;
370
371
0
  error++;
372
373
  /* subjectPublicKeyInfo::AlgorithmIdentifier */
374
0
  if (!ber_read_sequence_tag(s, &length) ||
375
0
      !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */
376
0
    goto error;
377
378
0
  error++;
379
380
  /* subjectPublicKeyInfo::subjectPublicKey */
381
0
  if (!ber_read_bit_string(s, &length, &padding)) /* BIT_STRING */
382
0
    goto error;
383
384
0
  error++;
385
386
  /* RSAPublicKey (SEQUENCE) */
387
0
  if (!ber_read_sequence_tag(s, &length)) /* SEQUENCE */
388
0
    goto error;
389
390
0
  error++;
391
392
0
  if (!ber_read_integer_length(s, &modulus_length)) /* modulus (INTEGER) */
393
0
    goto error;
394
395
0
  error++;
396
397
  /* skip zero padding, if any */
398
0
  do
399
0
  {
400
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
401
0
      goto error;
402
403
0
    Stream_Peek_UINT8(s, padding);
404
405
0
    if (padding == 0)
406
0
    {
407
0
      if (!Stream_SafeSeek(s, 1))
408
0
        goto error;
409
410
0
      modulus_length--;
411
0
    }
412
0
  } while (padding == 0);
413
414
0
  error++;
415
416
0
  if (!cert_info_read_modulus(info, modulus_length, s))
417
0
    goto error;
418
419
0
  error++;
420
421
0
  if (!ber_read_integer_length(s, &exponent_length)) /* publicExponent (INTEGER) */
422
0
    goto error;
423
424
0
  error++;
425
426
0
  if (!cert_info_read_exponent(info, exponent_length, s))
427
0
    goto error;
428
0
  return TRUE;
429
0
error:
430
0
  WLog_ERR(TAG, "error reading when reading certificate: part=%s error=%d",
431
0
           certificate_read_errors[error], error);
432
0
  cert_info_free(info);
433
0
  return FALSE;
434
0
}
435
436
/**
437
 * Instantiate new X.509 Certificate Chain.
438
 * @param count certificate chain count
439
 * @return new X.509 certificate chain
440
 */
441
442
static BOOL certificate_new_x509_certificate_chain(UINT32 count, wStream* s,
443
                                                   rdpX509CertChain* chain)
444
0
{
445
0
  WINPR_ASSERT(chain);
446
447
0
  rdpX509CertChain x509_cert_chain = WINPR_C_ARRAY_INIT;
448
0
  *chain = x509_cert_chain;
449
450
0
  if (!Stream_CheckAndLogRequiredCapacityOfSize(TAG, s, count, sizeof(rdpCertBlob)))
451
0
    return FALSE;
452
453
0
  if (count == 0)
454
0
    return TRUE;
455
456
0
  x509_cert_chain.array = (rdpCertBlob*)calloc(count, sizeof(rdpCertBlob));
457
0
  if (!x509_cert_chain.array)
458
0
    return FALSE;
459
460
0
  x509_cert_chain.count = count;
461
462
0
  *chain = x509_cert_chain;
463
0
  return TRUE;
464
0
}
465
466
/**
467
 * Free X.509 Certificate Chain.
468
 * @param x509_cert_chain X.509 certificate chain to be freed
469
 */
470
471
static void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain)
472
1.20k
{
473
1.20k
  if (!x509_cert_chain)
474
0
    return;
475
476
1.20k
  if (x509_cert_chain->array)
477
0
  {
478
0
    for (UINT32 i = 0; i < x509_cert_chain->count; i++)
479
0
    {
480
0
      rdpCertBlob* element = &x509_cert_chain->array[i];
481
0
      cert_blob_free(element);
482
0
    }
483
0
  }
484
485
1.20k
  free(x509_cert_chain->array);
486
1.20k
  x509_cert_chain->array = nullptr;
487
1.20k
  x509_cert_chain->count = 0;
488
1.20k
}
489
490
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
491
static 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");
539
fail:
540
  OSSL_PARAM_BLD_free(param);
541
542
  return parameters;
543
}
544
#endif
545
546
static BOOL update_x509_from_info(rdpCertificate* cert)
547
0
{
548
0
  BOOL rc = FALSE;
549
550
0
  WINPR_ASSERT(cert);
551
552
0
  X509_free(cert->x509);
553
0
  cert->x509 = nullptr;
554
555
0
  rdpCertInfo* info = &cert->cert_info;
556
557
0
  BIGNUM* e = BN_new();
558
0
  BIGNUM* mod = BN_new();
559
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
560
0
  RSA* rsa = RSA_new();
561
0
  if (!rsa)
562
0
  {
563
0
    WLog_ERR(TAG, "RSA_new() failed");
564
0
    goto fail;
565
0
  }
566
0
#endif
567
568
0
  if (!mod || !e)
569
0
  {
570
0
    WLog_ERR(TAG, "failure: mod=%p, e=%p", WINPR_CXX_COMPAT_CAST(const void*, mod),
571
0
             WINPR_CXX_COMPAT_CAST(const void*, e));
572
0
    goto fail;
573
0
  }
574
575
0
  WINPR_ASSERT(info->ModulusLength <= INT_MAX);
576
0
  if (!BN_bin2bn(info->Modulus, (int)info->ModulusLength, mod))
577
0
  {
578
0
    WLog_ERR(TAG, "BN_bin2bn(info->Modulus, (int)info->ModulusLength, mod) failed");
579
0
    goto fail;
580
0
  }
581
582
0
  if (!BN_bin2bn(info->exponent, (int)sizeof(info->exponent), e))
583
0
  {
584
0
    WLog_ERR(TAG, "BN_bin2bn(info->exponent, (int)sizeof(info->exponent), e) failed");
585
0
    goto fail;
586
0
  }
587
588
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
589
0
  const int rec = RSA_set0_key(rsa, mod, e, nullptr);
590
0
  if (rec != 1)
591
0
  {
592
0
    WLog_ERR(TAG, "RSA_set0_key(rsa, mod, e, nullptr) failed");
593
0
    goto fail;
594
0
  }
595
596
0
  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
0
  if (!cert->x509)
653
0
    goto fail;
654
655
0
  rc = TRUE;
656
657
0
fail:
658
0
  if (!rc)
659
0
    WLog_ERR(TAG, "failed to update x509 from rdpCertInfo");
660
661
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
662
0
  if (rsa)
663
0
    RSA_free(rsa);
664
0
  else
665
0
#endif
666
0
  {
667
0
    BN_free(mod);
668
0
    BN_free(e);
669
0
  }
670
0
  return rc;
671
0
}
672
673
static BOOL certificate_process_server_public_key(rdpCertificate* cert, wStream* s,
674
                                                  WINPR_ATTR_UNUSED UINT32 length)
675
0
{
676
0
  char magic[sizeof(rsa_magic)] = WINPR_C_ARRAY_INIT;
677
0
  UINT32 keylen = 0;
678
0
  UINT32 bitlen = 0;
679
0
  UINT32 datalen = 0;
680
681
0
  WINPR_ASSERT(cert);
682
0
  WINPR_ASSERT(s);
683
684
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
685
0
    return FALSE;
686
687
0
  Stream_Read(s, magic, sizeof(magic));
688
689
0
  if (memcmp(magic, rsa_magic, sizeof(magic)) != 0)
690
0
  {
691
0
    WLog_ERR(TAG, "invalid RSA magic bytes");
692
0
    return FALSE;
693
0
  }
694
695
0
  rdpCertInfo* info = &cert->cert_info;
696
0
  cert_info_free(info);
697
698
0
  Stream_Read_UINT32(s, keylen);
699
0
  Stream_Read_UINT32(s, bitlen);
700
0
  Stream_Read_UINT32(s, datalen);
701
0
  Stream_Read(s, info->exponent, 4);
702
703
0
  if (keylen <= 8)
704
0
  {
705
0
    WLog_ERR(TAG, "Invalid RSA keylen=%" PRIu32 " <= 8", keylen);
706
0
    return FALSE;
707
0
  }
708
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, keylen))
709
0
    return FALSE;
710
0
  if (keylen != (bitlen / 8ull) + 8ull)
711
0
  {
712
0
    WLog_ERR(TAG, "Invalid RSA key bitlen %" PRIu32 ", expected %" PRIu32, bitlen,
713
0
             (keylen - 8) * 8);
714
0
    return FALSE;
715
0
  }
716
0
  if (datalen != (bitlen / 8ull) - 1ull)
717
0
  {
718
0
    WLog_ERR(TAG, "Invalid RSA key datalen %" PRIu32 ", expected %llu", datalen,
719
0
             (1ull * bitlen / 8ull) - 1ull);
720
0
    return FALSE;
721
0
  }
722
0
  info->ModulusLength = keylen - 8;
723
0
  BYTE* tmp = realloc(info->Modulus, info->ModulusLength);
724
725
0
  if (!tmp)
726
0
  {
727
0
    WLog_ERR(TAG, "Failed to reallocate modulus of length %" PRIu32, info->ModulusLength);
728
0
    return FALSE;
729
0
  }
730
0
  info->Modulus = tmp;
731
732
0
  Stream_Read(s, info->Modulus, info->ModulusLength);
733
0
  Stream_Seek(s, 8); /* 8 bytes of zero padding */
734
0
  return update_x509_from_info(cert);
735
0
}
736
737
static BOOL certificate_process_server_public_signature(rdpCertificate* certificate,
738
                                                        const BYTE* sigdata, size_t sigdatalen,
739
                                                        wStream* s, UINT32 siglen)
740
0
{
741
0
  WINPR_ASSERT(certificate);
742
#if defined(CERT_VALIDATE_RSA)
743
  BYTE sig[TSSK_KEY_LENGTH];
744
#endif
745
0
  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
0
#if !defined(CERT_VALIDATE_MD5) || !defined(CERT_VALIDATE_RSA)
750
0
  (void)sigdata;
751
0
  (void)sigdatalen;
752
0
#endif
753
0
  (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
0
  Stream_Read(s, encsig, siglen);
767
768
0
  if (siglen < 8)
769
0
  {
770
0
    WLog_WARN(TAG, "public signature too short: %" PRIu32, siglen);
771
0
    return FALSE;
772
0
  }
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
0
  return TRUE;
827
0
}
828
829
static BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate, wStream* s)
830
0
{
831
0
  UINT32 dwSigAlgId = 0;
832
0
  UINT32 dwKeyAlgId = 0;
833
0
  UINT16 wPublicKeyBlobType = 0;
834
0
  UINT16 wPublicKeyBlobLen = 0;
835
0
  UINT16 wSignatureBlobType = 0;
836
0
  UINT16 wSignatureBlobLen = 0;
837
0
  size_t sigdatalen = 0;
838
839
0
  WINPR_ASSERT(certificate);
840
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
841
0
    return FALSE;
842
843
  /* -4, because we need to include dwVersion */
844
0
  const BYTE* sigdata = Stream_PointerAs(s, const BYTE) - 4;
845
0
  Stream_Read_UINT32(s, dwSigAlgId);
846
0
  Stream_Read_UINT32(s, dwKeyAlgId);
847
848
0
  if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
849
0
  {
850
0
    WLog_ERR(TAG,
851
0
             "unsupported signature or key algorithm, dwSigAlgId=%" PRIu32
852
0
             " dwKeyAlgId=%" PRIu32 "",
853
0
             dwSigAlgId, dwKeyAlgId);
854
0
    return FALSE;
855
0
  }
856
857
0
  Stream_Read_UINT16(s, wPublicKeyBlobType);
858
859
0
  if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
860
0
  {
861
0
    WLog_ERR(TAG, "unsupported public key blob type %" PRIu16 "", wPublicKeyBlobType);
862
0
    return FALSE;
863
0
  }
864
865
0
  Stream_Read_UINT16(s, wPublicKeyBlobLen);
866
867
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, wPublicKeyBlobLen))
868
0
    return FALSE;
869
870
0
  if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
871
0
    return FALSE;
872
873
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
874
0
    return FALSE;
875
876
0
  sigdatalen = WINPR_ASSERTING_INT_CAST(size_t, Stream_PointerAs(s, const BYTE) - sigdata);
877
0
  Stream_Read_UINT16(s, wSignatureBlobType);
878
879
0
  if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
880
0
  {
881
0
    WLog_ERR(TAG, "unsupported blob signature %" PRIu16 "", wSignatureBlobType);
882
0
    return FALSE;
883
0
  }
884
885
0
  Stream_Read_UINT16(s, wSignatureBlobLen);
886
887
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, wSignatureBlobLen))
888
0
    return FALSE;
889
890
0
  if (wSignatureBlobLen != 72)
891
0
  {
892
0
    WLog_ERR(TAG, "invalid signature length (got %" PRIu16 ", expected 72)", wSignatureBlobLen);
893
0
    return FALSE;
894
0
  }
895
896
0
  if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s,
897
0
                                                   wSignatureBlobLen))
898
0
  {
899
0
    WLog_ERR(TAG, "unable to parse server public signature");
900
0
    return FALSE;
901
0
  }
902
0
  return TRUE;
903
0
}
904
905
/* [MS-RDPBCGR] 2.2.1.4.3.1.1.1 RSA Public Key (RSA_PUBLIC_KEY) */
906
static BOOL cert_write_rsa_public_key(wStream* s, const rdpCertificate* cert)
907
0
{
908
0
  WINPR_ASSERT(cert);
909
0
  WINPR_ASSERT(freerdp_certificate_is_rsa(cert));
910
911
0
  const rdpCertInfo* info = &cert->cert_info;
912
913
0
  const UINT32 keyLen = info->ModulusLength + 8;
914
0
  const UINT32 bitLen = info->ModulusLength * 8;
915
0
  const UINT32 dataLen = (bitLen / 8) - 1;
916
0
  const size_t pubExpLen = sizeof(info->exponent);
917
0
  const BYTE* pubExp = info->exponent;
918
0
  const BYTE* modulus = info->Modulus;
919
920
0
  const size_t wPublicKeyBlobLen = 16 + pubExpLen + keyLen;
921
0
  WINPR_ASSERT(wPublicKeyBlobLen <= UINT16_MAX);
922
0
  if (!Stream_EnsureRemainingCapacity(s, 2ull + wPublicKeyBlobLen))
923
0
    return FALSE;
924
0
  Stream_Write_UINT16(s, (UINT16)wPublicKeyBlobLen);
925
0
  Stream_Write(s, rsa_magic, sizeof(rsa_magic));
926
0
  Stream_Write_UINT32(s, keyLen);
927
0
  Stream_Write_UINT32(s, bitLen);
928
0
  Stream_Write_UINT32(s, dataLen);
929
0
  Stream_Write(s, pubExp, pubExpLen);
930
0
  Stream_Write(s, modulus, info->ModulusLength);
931
0
  Stream_Zero(s, 8);
932
0
  return TRUE;
933
0
}
934
935
static BOOL cert_write_rsa_signature(wStream* s, const void* sigData, size_t sigDataLen)
936
0
{
937
0
  BYTE encryptedSignature[TSSK_KEY_LENGTH] = WINPR_C_ARRAY_INIT;
938
0
  BYTE signature[sizeof(initial_signature)] = WINPR_C_ARRAY_INIT;
939
940
0
  memcpy(signature, initial_signature, sizeof(initial_signature));
941
0
  if (!winpr_Digest(WINPR_MD_MD5, sigData, sigDataLen, signature, sizeof(signature)))
942
0
    return FALSE;
943
944
0
  if (crypto_rsa_private_encrypt(signature, sizeof(signature), priv_key_tssk, encryptedSignature,
945
0
                                 sizeof(encryptedSignature)) < 0)
946
0
    return FALSE;
947
948
0
  if (!Stream_EnsureRemainingCapacity(s,
949
0
                                      2ull * sizeof(UINT16) + sizeof(encryptedSignature) + 8ull))
950
0
    return FALSE;
951
0
  Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB);
952
0
  Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */
953
0
  Stream_Write(s, encryptedSignature, sizeof(encryptedSignature));
954
0
  Stream_Zero(s, 8);
955
0
  return TRUE;
956
0
}
957
958
/* [MS-RDPBCGR] 2.2.1.4.3.1.1 Server Proprietary Certificate (PROPRIETARYSERVERCERTIFICATE) */
959
static BOOL cert_write_server_certificate_v1(wStream* s, const rdpCertificate* certificate)
960
0
{
961
0
  const size_t start = Stream_GetPosition(s);
962
963
0
  WINPR_ASSERT(start >= 4);
964
0
  if (!Stream_EnsureRemainingCapacity(s, 10))
965
0
    return FALSE;
966
967
0
  Stream_Write_UINT32(s, SIGNATURE_ALG_RSA);
968
0
  Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA);
969
0
  Stream_Write_UINT16(s, BB_RSA_KEY_BLOB);
970
0
  if (!cert_write_rsa_public_key(s, certificate))
971
0
    return FALSE;
972
973
  /* The writes above may have reallocated the stream buffer, so only take
974
   * the pointer to the signed data (starting at dwVersion) now. */
975
0
  const BYTE* sigData = Stream_BufferAs(s, const BYTE) + start - sizeof(UINT32);
976
0
  const size_t end = Stream_GetPosition(s);
977
0
  return cert_write_rsa_signature(s, sigData, end - start + sizeof(UINT32));
978
0
}
979
980
static BOOL cert_write_server_certificate_v2(wStream* s, const rdpCertificate* certificate)
981
0
{
982
0
  WINPR_ASSERT(certificate);
983
984
0
  const rdpX509CertChain* chain = &certificate->x509_cert_chain;
985
0
  const size_t padding = 8ull + 4ull * chain->count;
986
987
0
  if (!Stream_EnsureRemainingCapacity(s, sizeof(UINT32)))
988
0
    return FALSE;
989
990
0
  Stream_Write_UINT32(s, chain->count);
991
0
  for (UINT32 x = 0; x < chain->count; x++)
992
0
  {
993
0
    const rdpCertBlob* cert = &chain->array[x];
994
0
    if (!cert_blob_write(cert, s))
995
0
      return FALSE;
996
0
  }
997
998
0
  if (!Stream_EnsureRemainingCapacity(s, padding))
999
0
    return FALSE;
1000
0
  Stream_Zero(s, padding);
1001
0
  return TRUE;
1002
0
}
1003
1004
SSIZE_T freerdp_certificate_write_server_cert(const rdpCertificate* certificate, UINT32 dwVersion,
1005
                                              wStream* s)
1006
0
{
1007
0
  if (!certificate)
1008
0
    return -1;
1009
1010
0
  const size_t start = Stream_GetPosition(s);
1011
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
1012
0
    return -1;
1013
0
  Stream_Write_UINT32(s, dwVersion);
1014
1015
0
  switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1016
0
  {
1017
0
    case CERT_CHAIN_VERSION_1:
1018
0
      if (!cert_write_server_certificate_v1(s, certificate))
1019
0
        return -1;
1020
0
      break;
1021
0
    case CERT_CHAIN_VERSION_2:
1022
0
      if (!cert_write_server_certificate_v2(s, certificate))
1023
0
        return -1;
1024
0
      break;
1025
0
    default:
1026
0
      WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
1027
0
               dwVersion & CERT_CHAIN_VERSION_MASK);
1028
0
      return -1;
1029
0
  }
1030
1031
0
  const size_t end = Stream_GetPosition(s);
1032
0
  if (start > end)
1033
0
    return -1;
1034
1035
0
  const size_t diff = end - start;
1036
0
  WINPR_ASSERT(diff <= SSIZE_MAX);
1037
0
  return (SSIZE_T)diff;
1038
0
}
1039
1040
/**
1041
 * Read an X.509 Certificate Chain.
1042
 * @param cert certificate module
1043
 * @param s stream
1044
 * @return \b TRUE for success, \b FALSE otherwise.
1045
 */
1046
1047
static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* cert, wStream* s)
1048
0
{
1049
0
  UINT32 numCertBlobs = 0;
1050
0
  DEBUG_CERTIFICATE("Server X.509 Certificate Chain");
1051
1052
0
  WINPR_ASSERT(cert);
1053
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1054
0
    return FALSE;
1055
1056
0
  Stream_Read_UINT32(s, numCertBlobs); /* numCertBlobs */
1057
0
  certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1058
0
  if (!certificate_new_x509_certificate_chain(numCertBlobs, s, &cert->x509_cert_chain))
1059
0
    return FALSE;
1060
1061
0
  for (UINT32 i = 0; i < cert->x509_cert_chain.count; i++)
1062
0
  {
1063
0
    rdpCertBlob* blob = &cert->x509_cert_chain.array[i];
1064
0
    if (!cert_blob_read(blob, s))
1065
0
      return FALSE;
1066
1067
0
    if (numCertBlobs - i == 1)
1068
0
    {
1069
0
      DEBUG_CERTIFICATE("Terminal Server Certificate");
1070
1071
0
      BOOL res = certificate_read_x509_certificate(blob, &cert->cert_info);
1072
1073
0
      if (res)
1074
0
      {
1075
0
        if (!update_x509_from_info(cert))
1076
0
          res = FALSE;
1077
0
      }
1078
1079
0
      if (!res)
1080
0
      {
1081
0
        WLog_ERR(TAG, "Failed to read x509 certificate");
1082
0
        return FALSE;
1083
0
      }
1084
1085
0
      DEBUG_CERTIFICATE("modulus length:%" PRIu32 "", cert->cert_info.ModulusLength);
1086
0
    }
1087
0
  }
1088
1089
0
  return update_x509_from_info(cert);
1090
0
}
1091
1092
/**
1093
 * Read a Server Certificate.
1094
 * @param certificate certificate module
1095
 * @param server_cert server certificate
1096
 * @param length certificate length
1097
 */
1098
1099
BOOL freerdp_certificate_read_server_cert(rdpCertificate* certificate, const BYTE* server_cert,
1100
                                          size_t length)
1101
0
{
1102
0
  BOOL ret = FALSE;
1103
0
  wStream* s = nullptr;
1104
0
  wStream sbuffer;
1105
0
  UINT32 dwVersion = 0;
1106
1107
0
  WINPR_ASSERT(certificate);
1108
0
  if (length < 4) /* nullptr certificate is not an error see #1795 */
1109
0
  {
1110
0
    WLog_DBG(TAG, "Received empty certificate, ignoring...");
1111
0
    return TRUE;
1112
0
  }
1113
1114
0
  WINPR_ASSERT(server_cert);
1115
0
  s = Stream_StaticConstInit(&sbuffer, server_cert, length);
1116
1117
0
  if (!s)
1118
0
  {
1119
0
    WLog_ERR(TAG, "Stream_New failed!");
1120
0
    return FALSE;
1121
0
  }
1122
1123
0
  Stream_Read_UINT32(s, dwVersion); /* dwVersion (4 bytes) */
1124
1125
0
  switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1126
0
  {
1127
0
    case CERT_CHAIN_VERSION_1:
1128
0
      ret = certificate_read_server_proprietary_certificate(certificate, s);
1129
0
      break;
1130
1131
0
    case CERT_CHAIN_VERSION_2:
1132
0
      ret = certificate_read_server_x509_certificate_chain(certificate, s);
1133
0
      break;
1134
1135
0
    default:
1136
0
      WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
1137
0
               dwVersion & CERT_CHAIN_VERSION_MASK);
1138
0
      ret = FALSE;
1139
0
      break;
1140
0
  }
1141
1142
0
  return ret;
1143
0
}
1144
1145
static BOOL cert_blob_copy(rdpCertBlob* dst, const rdpCertBlob* src)
1146
0
{
1147
0
  WINPR_ASSERT(dst);
1148
0
  WINPR_ASSERT(src);
1149
1150
0
  cert_blob_free(dst);
1151
0
  if (src->length > 0)
1152
0
  {
1153
0
    dst->data = malloc(src->length);
1154
0
    if (!dst->data)
1155
0
      return FALSE;
1156
0
    dst->length = src->length;
1157
0
    memcpy(dst->data, src->data, src->length);
1158
0
  }
1159
1160
0
  return TRUE;
1161
0
}
1162
1163
static BOOL cert_x509_chain_copy(rdpX509CertChain* cert, const rdpX509CertChain* src)
1164
0
{
1165
0
  WINPR_ASSERT(cert);
1166
1167
0
  certificate_free_x509_certificate_chain(cert);
1168
0
  if (!src)
1169
0
    return TRUE;
1170
1171
0
  if (src->count > 0)
1172
0
  {
1173
0
    cert->array = calloc(src->count, sizeof(rdpCertBlob));
1174
0
    if (!cert->array)
1175
0
    {
1176
0
      return FALSE;
1177
0
    }
1178
0
    cert->count = src->count;
1179
1180
0
    for (UINT32 x = 0; x < cert->count; x++)
1181
0
    {
1182
0
      const rdpCertBlob* srcblob = &src->array[x];
1183
0
      rdpCertBlob* dstblob = &cert->array[x];
1184
1185
0
      if (!cert_blob_copy(dstblob, srcblob))
1186
0
      {
1187
0
        certificate_free_x509_certificate_chain(cert);
1188
0
        return FALSE;
1189
0
      }
1190
0
    }
1191
0
  }
1192
1193
0
  return TRUE;
1194
0
}
1195
1196
BOOL cert_clone_int(rdpCertificate* dst, const rdpCertificate* src)
1197
0
{
1198
0
  WINPR_ASSERT(dst);
1199
0
  WINPR_ASSERT(src);
1200
1201
0
  if (!cert_info_clone(&dst->cert_info, &src->cert_info))
1202
0
    return FALSE;
1203
1204
0
  if (src->x509)
1205
0
  {
1206
0
    dst->x509 = X509_dup(src->x509);
1207
0
    if (!dst->x509)
1208
0
    {
1209
      /* Workaround for SSL deprecation issues:
1210
       * some security modes use weak RSA ciphers where X509_dup fails.
1211
       * In that case recreate the X509 from the raw RSA data
1212
       */
1213
0
      if (!update_x509_from_info(dst))
1214
0
      {
1215
0
        WLog_ERR(TAG, "X509_dup failed, SSL configuration bug?");
1216
0
        return FALSE;
1217
0
      }
1218
0
    }
1219
0
  }
1220
1221
0
  if (src->chain)
1222
0
  {
1223
0
    if (dst->chain)
1224
0
      sk_X509_pop_free(dst->chain, X509_free);
1225
1226
0
    dst->chain = sk_X509_deep_copy(src->chain, X509_const_dup, X509_free);
1227
0
  }
1228
0
  return cert_x509_chain_copy(&dst->x509_cert_chain, &src->x509_cert_chain);
1229
0
}
1230
1231
rdpCertificate* freerdp_certificate_clone(const rdpCertificate* certificate)
1232
0
{
1233
0
  if (!certificate)
1234
0
    return nullptr;
1235
1236
0
  rdpCertificate* _certificate = freerdp_certificate_new();
1237
1238
0
  if (!_certificate)
1239
0
    return nullptr;
1240
1241
0
  if (!cert_clone_int(_certificate, certificate))
1242
0
    goto out_fail;
1243
1244
0
  return _certificate;
1245
0
out_fail:
1246
1247
0
  freerdp_certificate_free(_certificate);
1248
0
  return nullptr;
1249
0
}
1250
1251
/**
1252
 * Instantiate new certificate module.
1253
 * @return new certificate module
1254
 */
1255
1256
rdpCertificate* freerdp_certificate_new(void)
1257
1.20k
{
1258
1.20k
  return (rdpCertificate*)calloc(1, sizeof(rdpCertificate));
1259
1.20k
}
1260
1261
void certificate_free_int(rdpCertificate* cert)
1262
1.20k
{
1263
1.20k
  WINPR_ASSERT(cert);
1264
1265
1.20k
  if (cert->x509)
1266
0
    X509_free(cert->x509);
1267
1.20k
  if (cert->chain)
1268
0
    sk_X509_pop_free(cert->chain, X509_free);
1269
1270
1.20k
  certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1271
1.20k
  cert_info_free(&cert->cert_info);
1272
1.20k
}
1273
1274
/**
1275
 * Free certificate module.
1276
 * @param cert certificate module to be freed
1277
 */
1278
1279
void freerdp_certificate_free(rdpCertificate* cert)
1280
3.62k
{
1281
3.62k
  if (!cert)
1282
2.41k
    return;
1283
1284
1.20k
  certificate_free_int(cert);
1285
1.20k
  free(cert);
1286
1.20k
}
1287
1288
static BOOL freerdp_rsa_from_x509(rdpCertificate* cert)
1289
0
{
1290
0
  BOOL rc = FALSE;
1291
1292
0
  WINPR_ASSERT(cert);
1293
1294
0
  if (!freerdp_certificate_is_rsa(cert))
1295
0
    return TRUE;
1296
1297
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1298
0
  RSA* rsa = nullptr;
1299
0
  const BIGNUM* rsa_n = nullptr;
1300
0
  const BIGNUM* rsa_e = nullptr;
1301
#else
1302
  BIGNUM* rsa_n = nullptr;
1303
  BIGNUM* rsa_e = nullptr;
1304
#endif
1305
0
  EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1306
0
  if (!pubkey)
1307
0
    goto fail;
1308
1309
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1310
0
  rsa = EVP_PKEY_get1_RSA(pubkey);
1311
1312
  /* If this is not a RSA key return success */
1313
0
  rc = TRUE;
1314
0
  if (!rsa)
1315
0
    goto fail;
1316
1317
  /* Now we return failure again if something is wrong. */
1318
0
  rc = FALSE;
1319
1320
0
  RSA_get0_key(rsa, &rsa_n, &rsa_e, nullptr);
1321
#else
1322
  if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &rsa_e))
1323
    goto fail;
1324
  if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &rsa_n))
1325
    goto fail;
1326
#endif
1327
0
  if (!rsa_n || !rsa_e)
1328
0
    goto fail;
1329
0
  if (!cert_info_create(&cert->cert_info, rsa_n, rsa_e))
1330
0
    goto fail;
1331
0
  rc = TRUE;
1332
0
fail:
1333
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1334
0
  RSA_free(rsa);
1335
#else
1336
  BN_free(rsa_n);
1337
  BN_free(rsa_e);
1338
#endif
1339
0
  return rc;
1340
0
}
1341
1342
rdpCertificate* freerdp_certificate_new_from_der(const BYTE* data, size_t length)
1343
0
{
1344
0
  rdpCertificate* cert = freerdp_certificate_new();
1345
1346
0
  if (!cert || !data || (length == 0) || (length > INT_MAX))
1347
0
    goto fail;
1348
1349
0
  {
1350
0
    const BYTE* ptr = data;
1351
0
    cert->x509 = d2i_X509(nullptr, &ptr, (int)length);
1352
0
  }
1353
1354
0
  if (!cert->x509)
1355
0
    goto fail;
1356
0
  if (!freerdp_rsa_from_x509(cert))
1357
0
    goto fail;
1358
0
  return cert;
1359
0
fail:
1360
0
  freerdp_certificate_free(cert);
1361
0
  return nullptr;
1362
0
}
1363
1364
rdpCertificate* freerdp_certificate_new_from_x509(const X509* xcert, const STACK_OF(X509) * chain)
1365
0
{
1366
0
  WINPR_ASSERT(xcert);
1367
1368
0
  rdpCertificate* cert = freerdp_certificate_new();
1369
0
  if (!cert)
1370
0
    return nullptr;
1371
1372
0
  X509* wcert = WINPR_CAST_CONST_PTR_AWAY(xcert, X509*);
1373
0
  cert->x509 = X509_dup(wcert);
1374
0
  if (!cert->x509)
1375
0
    goto fail;
1376
1377
0
  if (!freerdp_rsa_from_x509(cert))
1378
0
    goto fail;
1379
1380
0
  if (chain)
1381
0
    cert->chain = sk_X509_deep_copy(chain, X509_const_dup, X509_free);
1382
1383
0
  return cert;
1384
0
fail:
1385
0
  freerdp_certificate_free(cert);
1386
0
  return nullptr;
1387
0
}
1388
1389
static STACK_OF(X509) * extract_chain_from_pem(const char* pem, BOOL isFile)
1390
0
{
1391
0
  if (!pem)
1392
0
  {
1393
0
    return nullptr;
1394
0
  }
1395
1396
0
  BIO* bio = nullptr;
1397
0
  if (isFile)
1398
0
    bio = BIO_new_file(pem, "rb");
1399
0
  else
1400
0
  {
1401
0
    const size_t len = strlen(pem);
1402
0
    bio = BIO_new_mem_buf(pem, WINPR_ASSERTING_INT_CAST(int, len));
1403
0
  }
1404
1405
0
  if (!bio)
1406
0
  {
1407
0
    return nullptr;
1408
0
  }
1409
1410
0
  X509* leaf = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
1411
0
  if (!leaf)
1412
0
  {
1413
0
    BIO_free(bio);
1414
0
    return nullptr;
1415
0
  }
1416
1417
0
  STACK_OF(X509)* chain = sk_X509_new_null();
1418
0
  if (!chain)
1419
0
  {
1420
0
    X509_free(leaf);
1421
0
    BIO_free(bio);
1422
0
    return nullptr;
1423
0
  }
1424
1425
0
  X509* cert = nullptr;
1426
0
  while ((cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr)) != nullptr)
1427
0
  {
1428
0
    sk_X509_push(chain, cert);
1429
0
  }
1430
1431
0
  X509_free(leaf);
1432
0
  BIO_free(bio);
1433
0
  return chain;
1434
0
}
1435
1436
static rdpCertificate* freerdp_certificate_new_from(const char* file, BOOL isFile)
1437
0
{
1438
0
  X509* x509 = x509_utils_from_pem(file, strlen(file), isFile);
1439
0
  if (!x509)
1440
0
    return nullptr;
1441
0
  STACK_OF(X509)* chain = extract_chain_from_pem(file, isFile);
1442
0
  rdpCertificate* cert = freerdp_certificate_new_from_x509(x509, chain);
1443
0
  if (chain)
1444
0
    sk_X509_pop_free(chain, X509_free);
1445
0
  X509_free(x509);
1446
0
  return cert;
1447
0
}
1448
1449
rdpCertificate* freerdp_certificate_new_from_file(const char* file)
1450
0
{
1451
0
  return freerdp_certificate_new_from(file, TRUE);
1452
0
}
1453
1454
rdpCertificate* freerdp_certificate_new_from_pem(const char* pem)
1455
0
{
1456
0
  return freerdp_certificate_new_from(pem, FALSE);
1457
0
}
1458
1459
const rdpCertInfo* freerdp_certificate_get_info(const rdpCertificate* cert)
1460
0
{
1461
0
  WINPR_ASSERT(cert);
1462
0
  if (!freerdp_certificate_is_rsa(cert))
1463
0
    return nullptr;
1464
0
  return &cert->cert_info;
1465
0
}
1466
1467
char* freerdp_certificate_get_fingerprint(const rdpCertificate* cert)
1468
0
{
1469
0
  return freerdp_certificate_get_fingerprint_by_hash(cert, "sha256");
1470
0
}
1471
1472
char* freerdp_certificate_get_fingerprint_by_hash(const rdpCertificate* cert, const char* hash)
1473
0
{
1474
0
  return freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, TRUE);
1475
0
}
1476
1477
char* freerdp_certificate_get_fingerprint_by_hash_ex(const rdpCertificate* cert, const char* hash,
1478
                                                     BOOL separator)
1479
0
{
1480
0
  size_t fp_len = 0;
1481
0
  size_t pos = 0;
1482
0
  size_t size = 0;
1483
0
  BYTE* fp = nullptr;
1484
0
  char* fp_buffer = nullptr;
1485
0
  if (!cert || !cert->x509)
1486
0
  {
1487
0
    WLog_ERR(TAG, "Invalid certificate [%p, %p]", WINPR_CXX_COMPAT_CAST(const void*, cert),
1488
0
             WINPR_CXX_COMPAT_CAST(const void*, cert ? cert->x509 : nullptr));
1489
0
    return nullptr;
1490
0
  }
1491
0
  if (!hash)
1492
0
  {
1493
0
    WLog_ERR(TAG, "Invalid certificate hash %p", WINPR_CXX_COMPAT_CAST(const void*, hash));
1494
0
    return nullptr;
1495
0
  }
1496
0
  fp = x509_utils_get_hash(cert->x509, hash, &fp_len);
1497
0
  if (!fp)
1498
0
    return nullptr;
1499
1500
0
  if (fp_len < 1)
1501
0
    goto fail;
1502
1503
0
  size = fp_len * 3 + 1;
1504
0
  fp_buffer = calloc(size, sizeof(char));
1505
0
  if (!fp_buffer)
1506
0
    goto fail;
1507
1508
0
  pos = 0;
1509
1510
0
  {
1511
0
    size_t i = 0;
1512
0
    for (; i < (fp_len - 1); i++)
1513
0
    {
1514
0
      int rc = 0;
1515
0
      char* p = &fp_buffer[pos];
1516
0
      if (separator)
1517
0
        rc = sprintf_s(p, size - pos, "%02" PRIx8 ":", fp[i]);
1518
0
      else
1519
0
        rc = sprintf_s(p, size - pos, "%02" PRIx8, fp[i]);
1520
0
      if (rc <= 0)
1521
0
        goto fail;
1522
0
      pos += (size_t)rc;
1523
0
    }
1524
1525
0
    (void)sprintf_s(&fp_buffer[pos], size - pos, "%02" PRIx8 "", fp[i]);
1526
0
  }
1527
1528
0
  free(fp);
1529
1530
0
  return fp_buffer;
1531
0
fail:
1532
0
  free(fp);
1533
0
  free(fp_buffer);
1534
0
  return nullptr;
1535
0
}
1536
1537
char* freerdp_certificate_get_pem(const rdpCertificate* cert, size_t* pLength)
1538
0
{
1539
0
  return freerdp_certificate_get_pem_ex(cert, pLength, TRUE);
1540
0
}
1541
1542
char* freerdp_certificate_get_pem_ex(const rdpCertificate* cert, size_t* pLength,
1543
                                     BOOL withCertChain)
1544
0
{
1545
0
  WINPR_ASSERT(cert);
1546
1547
0
  if (!cert->x509)
1548
0
    return nullptr;
1549
1550
  /**
1551
   * Don't manage certificates internally, leave it up entirely to the external client
1552
   * implementation
1553
   */
1554
0
  BIO* bio = BIO_new(BIO_s_mem());
1555
1556
0
  if (!bio)
1557
0
  {
1558
0
    WLog_ERR(TAG, "BIO_new() failure");
1559
0
    return nullptr;
1560
0
  }
1561
1562
0
  char* pem = nullptr;
1563
1564
0
  const int status = PEM_write_bio_X509(bio, cert->x509);
1565
0
  if (status < 0)
1566
0
  {
1567
0
    WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
1568
0
    goto fail;
1569
0
  }
1570
1571
0
  if (cert->chain && withCertChain)
1572
0
  {
1573
0
    const int count = sk_X509_num(cert->chain);
1574
0
    for (int x = 0; x < count; x++)
1575
0
    {
1576
0
      X509* c = sk_X509_value(cert->chain, x);
1577
0
      const int rc = PEM_write_bio_X509(bio, c);
1578
0
      if (rc < 0)
1579
0
      {
1580
0
        WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", rc);
1581
0
        goto fail;
1582
0
      }
1583
0
    }
1584
0
  }
1585
1586
0
  pem = x509_utils_bio_read(bio, pLength);
1587
1588
0
fail:
1589
0
  BIO_free_all(bio);
1590
0
  return pem;
1591
0
}
1592
1593
char* freerdp_certificate_get_subject(const rdpCertificate* cert)
1594
0
{
1595
0
  WINPR_ASSERT(cert);
1596
0
  return x509_utils_get_subject(cert->x509);
1597
0
}
1598
1599
char* freerdp_certificate_get_issuer(const rdpCertificate* cert)
1600
0
{
1601
0
  WINPR_ASSERT(cert);
1602
0
  return x509_utils_get_issuer(cert->x509);
1603
0
}
1604
1605
char* freerdp_certificate_get_upn(const rdpCertificate* cert)
1606
0
{
1607
0
  WINPR_ASSERT(cert);
1608
0
  return x509_utils_get_upn(cert->x509);
1609
0
}
1610
1611
char* freerdp_certificate_get_email(const rdpCertificate* cert)
1612
0
{
1613
0
  WINPR_ASSERT(cert);
1614
0
  return x509_utils_get_email(cert->x509);
1615
0
}
1616
1617
char* freerdp_certificate_get_validity(const rdpCertificate* cert, BOOL startDate)
1618
0
{
1619
0
  WINPR_ASSERT(cert);
1620
0
  return x509_utils_get_date(cert->x509, startDate);
1621
0
}
1622
1623
BOOL freerdp_certificate_check_eku(const rdpCertificate* cert, int nid)
1624
0
{
1625
0
  WINPR_ASSERT(cert);
1626
0
  return x509_utils_check_eku(cert->x509, nid);
1627
0
}
1628
1629
BOOL freerdp_certificate_get_public_key(const rdpCertificate* cert, BYTE** PublicKey,
1630
                                        DWORD* PublicKeyLength)
1631
0
{
1632
0
  BYTE* ptr = nullptr;
1633
0
  BYTE* optr = nullptr;
1634
0
  int length = 0;
1635
0
  BOOL status = FALSE;
1636
0
  EVP_PKEY* pkey = nullptr;
1637
1638
0
  WINPR_ASSERT(cert);
1639
1640
0
  pkey = X509_get0_pubkey(cert->x509);
1641
1642
0
  if (!pkey)
1643
0
  {
1644
0
    WLog_ERR(TAG, "X509_get_pubkey() failed");
1645
0
    goto exit;
1646
0
  }
1647
1648
0
  length = i2d_PublicKey(pkey, nullptr);
1649
1650
0
  if (length < 1)
1651
0
  {
1652
0
    WLog_ERR(TAG, "i2d_PublicKey() failed");
1653
0
    goto exit;
1654
0
  }
1655
1656
0
  *PublicKey = optr = ptr = (BYTE*)calloc(WINPR_ASSERTING_INT_CAST(size_t, length), sizeof(BYTE));
1657
1658
0
  if (!ptr)
1659
0
    goto exit;
1660
1661
0
  {
1662
0
    const int length2 = i2d_PublicKey(pkey, &ptr);
1663
0
    if (length != length2)
1664
0
      goto exit;
1665
0
    *PublicKeyLength = (DWORD)length2;
1666
0
  }
1667
0
  status = TRUE;
1668
0
exit:
1669
1670
0
  if (!status)
1671
0
    free(optr);
1672
1673
0
  return status;
1674
0
}
1675
1676
BOOL freerdp_certificate_verify(const rdpCertificate* cert, const char* certificate_store_path)
1677
0
{
1678
0
  WINPR_ASSERT(cert);
1679
0
  return x509_utils_verify(cert->x509, cert->chain, certificate_store_path);
1680
0
}
1681
1682
char** freerdp_certificate_get_dns_names(const rdpCertificate* cert, size_t* pcount,
1683
                                         size_t** pplengths)
1684
0
{
1685
0
  WINPR_ASSERT(cert);
1686
0
  return x509_utils_get_dns_names(cert->x509, pcount, pplengths);
1687
0
}
1688
1689
char** freerdp_certificate_get_ip_names(const rdpCertificate* cert, size_t* pcount,
1690
                                        size_t** pplengths)
1691
0
{
1692
0
  WINPR_ASSERT(cert);
1693
0
  return x509_utils_get_ip_names(cert->x509, pcount, pplengths);
1694
0
}
1695
1696
char* freerdp_certificate_get_common_name(const rdpCertificate* cert, size_t* plength)
1697
0
{
1698
0
  WINPR_ASSERT(cert);
1699
0
  return x509_utils_get_common_name(cert->x509, plength);
1700
0
}
1701
1702
WINPR_MD_TYPE freerdp_certificate_get_signature_alg(const rdpCertificate* cert)
1703
0
{
1704
0
  WINPR_ASSERT(cert);
1705
0
  return x509_utils_get_signature_alg(cert->x509);
1706
0
}
1707
1708
void freerdp_certificate_free_dns_names(size_t count, size_t* lengths, char** names)
1709
0
{
1710
0
  x509_utils_dns_names_free(count, lengths, names);
1711
0
}
1712
1713
void freerdp_certificate_free_ip_names(size_t count, size_t* lengths, char** names)
1714
0
{
1715
0
  x509_utils_ip_names_free(count, lengths, names);
1716
0
}
1717
1718
char* freerdp_certificate_get_hash(const rdpCertificate* cert, const char* hash, size_t* plength)
1719
0
{
1720
0
  WINPR_ASSERT(cert);
1721
0
  return (char*)x509_utils_get_hash(cert->x509, hash, plength);
1722
0
}
1723
1724
X509* freerdp_certificate_get_x509(rdpCertificate* cert)
1725
0
{
1726
0
  WINPR_ASSERT(cert);
1727
0
  return cert->x509;
1728
0
}
1729
1730
BOOL freerdp_certificate_publickey_encrypt(const rdpCertificate* cert, const BYTE* input,
1731
                                           size_t cbInput, BYTE** poutput, size_t* pcbOutput)
1732
0
{
1733
0
  WINPR_ASSERT(cert);
1734
0
  WINPR_ASSERT(input);
1735
0
  WINPR_ASSERT(poutput);
1736
0
  WINPR_ASSERT(pcbOutput);
1737
1738
0
  BOOL ret = FALSE;
1739
0
  BYTE* output = nullptr;
1740
0
  EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1741
0
  if (!pkey)
1742
0
    return FALSE;
1743
1744
0
  EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, nullptr);
1745
0
  if (!ctx)
1746
0
    return FALSE;
1747
1748
0
  size_t outputSize = WINPR_ASSERTING_INT_CAST(size_t, EVP_PKEY_size(pkey));
1749
0
  output = malloc(outputSize);
1750
0
  if (output == nullptr)
1751
0
    goto out;
1752
0
  *pcbOutput = outputSize;
1753
1754
0
  if (EVP_PKEY_encrypt_init(ctx) != 1 ||
1755
0
      EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) != 1 ||
1756
0
      EVP_PKEY_encrypt(ctx, output, pcbOutput, input, cbInput) != 1)
1757
0
  {
1758
0
    WLog_ERR(TAG, "error when setting up public key");
1759
0
    goto out;
1760
0
  }
1761
1762
0
  *poutput = output;
1763
0
  output = nullptr;
1764
0
  ret = TRUE;
1765
0
out:
1766
0
  EVP_PKEY_CTX_free(ctx);
1767
0
  free(output);
1768
0
  return ret;
1769
0
}
1770
1771
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1772
static RSA* freerdp_certificate_get_RSA(const rdpCertificate* cert)
1773
0
{
1774
0
  WINPR_ASSERT(cert);
1775
1776
0
  if (!freerdp_certificate_is_rsa(cert))
1777
0
    return nullptr;
1778
1779
0
  EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1780
0
  if (!pubkey)
1781
0
    return nullptr;
1782
1783
0
  return EVP_PKEY_get1_RSA(pubkey);
1784
0
}
1785
#endif
1786
1787
BYTE* freerdp_certificate_get_der(const rdpCertificate* cert, size_t* pLength)
1788
0
{
1789
0
  WINPR_ASSERT(cert);
1790
1791
0
  if (pLength)
1792
0
    *pLength = 0;
1793
1794
0
  const int rc = i2d_X509(cert->x509, nullptr);
1795
0
  if (rc <= 0)
1796
0
    return nullptr;
1797
1798
0
  BYTE* ptr = calloc(WINPR_ASSERTING_INT_CAST(size_t, rc) + 1, sizeof(BYTE));
1799
0
  if (!ptr)
1800
0
    return nullptr;
1801
0
  BYTE* i2d_ptr = ptr;
1802
1803
0
  const int rc2 = i2d_X509(cert->x509, &i2d_ptr);
1804
0
  if (rc2 <= 0)
1805
0
  {
1806
0
    free(ptr);
1807
0
    return nullptr;
1808
0
  }
1809
1810
0
  if (pLength)
1811
0
    *pLength = (size_t)rc2;
1812
0
  return ptr;
1813
0
}
1814
1815
BOOL freerdp_certificate_is_rsa(const rdpCertificate* cert)
1816
0
{
1817
0
  WINPR_ASSERT(cert);
1818
0
  return is_rsa_key(cert->x509);
1819
0
}
1820
1821
BOOL freerdp_certificate_is_rdp_security_compatible(const rdpCertificate* cert)
1822
0
{
1823
0
  const rdpCertInfo* info = freerdp_certificate_get_info(cert);
1824
0
  if (!freerdp_certificate_is_rsa(cert) || !info || (info->ModulusLength != 2048 / 8))
1825
0
  {
1826
0
    WLog_INFO(TAG, "certificate is not RSA 2048, RDP security not supported.");
1827
0
    return FALSE;
1828
0
  }
1829
0
  return TRUE;
1830
0
}
1831
1832
char* freerdp_certificate_get_param(const rdpCertificate* cert, enum FREERDP_CERT_PARAM what,
1833
                                    size_t* psize)
1834
0
{
1835
0
  WINPR_ASSERT(cert);
1836
0
  WINPR_ASSERT(psize);
1837
1838
0
  *psize = 0;
1839
1840
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1841
0
  const BIGNUM* bn = nullptr;
1842
0
  RSA* rsa = freerdp_certificate_get_RSA(cert);
1843
0
  switch (what)
1844
0
  {
1845
0
    case FREERDP_CERT_RSA_E:
1846
0
      RSA_get0_key(rsa, nullptr, &bn, nullptr);
1847
0
      break;
1848
0
    case FREERDP_CERT_RSA_N:
1849
0
      RSA_get0_key(rsa, &bn, nullptr, nullptr);
1850
0
      break;
1851
0
    default:
1852
0
      RSA_free(rsa);
1853
0
      return nullptr;
1854
0
  }
1855
0
  RSA_free(rsa);
1856
#else
1857
  EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1858
  if (!pkey)
1859
    return nullptr;
1860
1861
  BIGNUM* bn = nullptr;
1862
  switch (what)
1863
  {
1864
    case FREERDP_CERT_RSA_E:
1865
      if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn))
1866
        return nullptr;
1867
      break;
1868
    case FREERDP_CERT_RSA_N:
1869
      if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn))
1870
        return nullptr;
1871
      break;
1872
    default:
1873
      return nullptr;
1874
  }
1875
#endif
1876
1877
0
  const size_t bnsize = WINPR_ASSERTING_INT_CAST(size_t, BN_num_bytes(bn));
1878
0
  char* rc = calloc(bnsize + 1, sizeof(char));
1879
0
  if (!rc)
1880
0
    goto fail;
1881
0
  BN_bn2bin(bn, (BYTE*)rc);
1882
0
  *psize = bnsize;
1883
1884
0
fail:
1885
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR < 3)
1886
  BN_free(bn);
1887
#endif
1888
0
  return rc;
1889
0
}
1890
1891
size_t freerdp_certificate_get_chain_len(rdpCertificate* certificate)
1892
0
{
1893
0
  WINPR_ASSERT(certificate);
1894
0
  if (!certificate->chain)
1895
0
    return 0;
1896
1897
0
  return WINPR_ASSERTING_INT_CAST(size_t, sk_X509_num(certificate->chain));
1898
0
}
1899
1900
X509* freerdp_certificate_get_chain_at(rdpCertificate* certificate, size_t offset)
1901
0
{
1902
0
  WINPR_ASSERT(certificate);
1903
0
  WINPR_ASSERT(freerdp_certificate_get_chain_len(certificate) > offset);
1904
0
  const int ioff = WINPR_ASSERTING_INT_CAST(int, offset);
1905
0
  return sk_X509_value(certificate->chain, ioff);
1906
0
}
1907
1908
WINPR_ATTR_NODISCARD
1909
static BOOL tls_match_hostname(const char* pattern, const size_t pattern_length,
1910
                               const char* hostname)
1911
0
{
1912
0
  WINPR_ASSERT(hostname);
1913
0
  WINPR_ASSERT(pattern || (pattern_length == 0));
1914
1915
0
  const size_t hlen = strlen(hostname);
1916
0
  if (hlen == pattern_length)
1917
0
  {
1918
0
    if (_strnicmp(hostname, pattern, pattern_length) == 0)
1919
0
      return TRUE;
1920
0
  }
1921
1922
0
  if ((pattern_length > 2) && (pattern[0] == '*') && (pattern[1] == '.') &&
1923
0
      (hlen >= pattern_length))
1924
0
  {
1925
    /* Ensure wildcard only matches foo.example.com and not foo.bar.example.com */
1926
0
    const size_t prefixlen = hlen - pattern_length;
1927
0
    for (size_t x = 0; x < prefixlen; x++)
1928
0
    {
1929
0
      char cur = hostname[x];
1930
0
      if (cur == '.')
1931
0
        return FALSE;
1932
0
    }
1933
1934
    /* Check the hostname ends with the domain */
1935
0
    const char* check_hostname = &hostname[prefixlen + 1];
1936
0
    return _strnicmp(check_hostname, &pattern[1], pattern_length - 1) == 0;
1937
0
  }
1938
1939
0
  return FALSE;
1940
0
}
1941
1942
BOOL freerdp_certificate_matches_hostname(const rdpCertificate* cert, const char* hostname,
1943
                                          size_t hostlen)
1944
0
{
1945
  /* extra common name and alternative names */
1946
0
  size_t common_name_length = 0;
1947
0
  size_t dns_names_count = 0;
1948
0
  size_t* dns_names_lengths = nullptr;
1949
0
  size_t ip_names_count = 0;
1950
0
  size_t* ip_names_lengths = nullptr;
1951
1952
0
  char* common_name = freerdp_certificate_get_common_name(cert, &common_name_length);
1953
0
  char** dns_names =
1954
0
      freerdp_certificate_get_dns_names(cert, &dns_names_count, &dns_names_lengths);
1955
0
  char** ip_names = freerdp_certificate_get_ip_names(cert, &ip_names_count, &ip_names_lengths);
1956
1957
0
  BOOL hostname_match = FALSE;
1958
0
  BOOL skip = FALSE;
1959
0
  if (utils_is_valid_ip(hostname))
1960
0
  {
1961
0
    if ((hostlen != 0) && ip_names && (ip_names_count > 0))
1962
0
    {
1963
0
      for (size_t index = 0; index < ip_names_count; index++)
1964
0
      {
1965
0
        if (utils_compare_ip_strings(ip_names[index], ip_names_lengths[index], hostname,
1966
0
                                     hostlen))
1967
0
        {
1968
0
          hostname_match = TRUE;
1969
0
          break;
1970
0
        }
1971
0
      }
1972
0
      skip = TRUE;
1973
0
    }
1974
0
  }
1975
1976
  /* compare against alternative names */
1977
0
  if (!skip && dns_names)
1978
0
  {
1979
0
    for (size_t index = 0; index < dns_names_count; index++)
1980
0
    {
1981
0
      if (tls_match_hostname(dns_names[index], dns_names_lengths[index], hostname))
1982
0
      {
1983
0
        hostname_match = TRUE;
1984
0
        break;
1985
0
      }
1986
0
    }
1987
0
    skip = TRUE;
1988
0
  }
1989
1990
  /* compare against common name */
1991
0
  if (!skip && common_name)
1992
0
  {
1993
0
    if (tls_match_hostname(common_name, common_name_length, hostname))
1994
0
      hostname_match = TRUE;
1995
0
  }
1996
1997
0
  freerdp_certificate_free_dns_names(dns_names_count, dns_names_lengths, dns_names);
1998
0
  freerdp_certificate_free_ip_names(ip_names_count, ip_names_lengths, ip_names);
1999
0
  free(common_name);
2000
0
  return hostname_match;
2001
0
}