Coverage Report

Created: 2026-01-09 06:43

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