Coverage Report

Created: 2025-07-01 06:46

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