Coverage Report

Created: 2023-09-25 06:56

/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
44
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
45
#include <openssl/core_names.h>
46
#include <openssl/param_build.h>
47
#include <openssl/evp.h>
48
#endif
49
50
#include "certificate.h"
51
#include "cert_common.h"
52
#include "crypto.h"
53
54
#include "x509_utils.h"
55
#include "privatekey.h"
56
#include "opensslcompat.h"
57
58
#define TAG FREERDP_TAG("core")
59
60
#define CERTIFICATE_TAG FREERDP_TAG("core.certificate")
61
#ifdef WITH_DEBUG_CERTIFICATE
62
#define DEBUG_CERTIFICATE(...) WLog_DBG(TAG, __VA_ARGS__)
63
#else
64
#define DEBUG_CERTIFICATE(...) \
65
0
  do                         \
66
0
  {                          \
67
0
  } while (0)
68
#endif
69
70
#define TSSK_KEY_LENGTH 64
71
72
struct rdp_CertBlob
73
{
74
  UINT32 length;
75
  BYTE* data;
76
};
77
typedef struct rdp_CertBlob rdpCertBlob;
78
79
struct rdp_X509CertChain
80
{
81
  UINT32 count;
82
  rdpCertBlob* array;
83
};
84
typedef struct rdp_X509CertChain rdpX509CertChain;
85
86
struct rdp_certificate
87
{
88
  X509* x509;
89
  STACK_OF(X509) * chain;
90
91
  rdpCertInfo cert_info;
92
  rdpX509CertChain x509_cert_chain;
93
};
94
95
/**
96
 *
97
 * X.509 Certificate Structure
98
 *
99
 * Certificate ::= SEQUENCE
100
 * {
101
 *  tbsCertificate      TBSCertificate,
102
 *  signatureAlgorithm    AlgorithmIdentifier,
103
 *  signatureValue      BIT_STRING
104
 * }
105
 *
106
 * TBSCertificate ::= SEQUENCE
107
 * {
108
 *  version     [0] EXPLICIT Version DEFAULT v1,
109
 *  serialNumber      CertificateSerialNumber,
110
 *  signature     AlgorithmIdentifier,
111
 *  issuer        Name,
112
 *  validity      Validity,
113
 *  subject       Name,
114
 *  subjectPublicKeyInfo    SubjectPublicKeyInfo,
115
 *  issuerUniqueID    [1] IMPLICIT UniqueIdentifier OPTIONAL,
116
 *  subjectUniqueId   [2] IMPLICIT UniqueIdentifier OPTIONAL,
117
 *  extensions    [3] EXPLICIT Extensions OPTIONAL
118
 * }
119
 *
120
 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
121
 *
122
 * CertificateSerialNumber ::= INTEGER
123
 *
124
 * AlgorithmIdentifier ::= SEQUENCE
125
 * {
126
 *  algorithm     OBJECT_IDENTIFIER,
127
 *  parameters      ANY DEFINED BY algorithm OPTIONAL
128
 * }
129
 *
130
 * Name ::= CHOICE { RDNSequence }
131
 *
132
 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
133
 *
134
 * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
135
 *
136
 * AttributeTypeAndValue ::= SEQUENCE
137
 * {
138
 *  type        AttributeType,
139
 *  value       AttributeValue
140
 * }
141
 *
142
 * AttributeType ::= OBJECT_IDENTIFIER
143
 *
144
 * AttributeValue ::= ANY DEFINED BY AttributeType
145
 *
146
 * Validity ::= SEQUENCE
147
 * {
148
 *  notBefore     Time,
149
 *  notAfter      Time
150
 * }
151
 *
152
 * Time ::= CHOICE
153
 * {
154
 *  utcTime       UTCTime,
155
 *  generalTime     GeneralizedTime
156
 * }
157
 *
158
 * UniqueIdentifier ::= BIT_STRING
159
 *
160
 * SubjectPublicKeyInfo ::= SEQUENCE
161
 * {
162
 *  algorithm     AlgorithmIdentifier,
163
 *  subjectPublicKey    BIT_STRING
164
 * }
165
 *
166
 * RSAPublicKey ::= SEQUENCE
167
 * {
168
 *  modulus       INTEGER
169
 *  publicExponent      INTEGER
170
 * }
171
 *
172
 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
173
 *
174
 * Extension ::= SEQUENCE
175
 * {
176
 *  extnID        OBJECT_IDENTIFIER
177
 *  critical      BOOLEAN DEFAULT FALSE,
178
 *  extnValue     OCTET_STRING
179
 * }
180
 *
181
 */
182
183
static const char rsa_magic[4] = "RSA1";
184
185
static const char* certificate_read_errors[] = { "Certificate tag",
186
                                               "TBSCertificate",
187
                                               "Explicit Contextual Tag [0]",
188
                                               "version",
189
                                               "CertificateSerialNumber",
190
                                               "AlgorithmIdentifier",
191
                                               "Issuer Name",
192
                                               "Validity",
193
                                               "Subject Name",
194
                                               "SubjectPublicKeyInfo Tag",
195
                                               "subjectPublicKeyInfo::AlgorithmIdentifier",
196
                                               "subjectPublicKeyInfo::subjectPublicKey",
197
                                               "RSAPublicKey Tag",
198
                                               "modulusLength",
199
                                               "zero padding",
200
                                               "modulusLength",
201
                                               "modulus",
202
                                               "publicExponent length",
203
                                               "publicExponent" };
204
205
static const BYTE initial_signature[] = {
206
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
207
  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
208
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
209
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01
210
};
211
212
#if defined(CERT_VALIDATE_RSA)
213
static const BYTE tssk_exponent[] = { 0x5b, 0x7b, 0x88, 0xc0 };
214
#endif
215
216
static void certificate_free_int(rdpCertificate* certificate);
217
static BOOL cert_clone_int(rdpCertificate* dst, const rdpCertificate* src);
218
219
/* [MS-RDPBCGR] 5.3.3.2 X.509 Certificate Chains:
220
 *
221
 * More detail[MS-RDPELE] section 2.2.1.4.2.
222
 */
223
static BOOL cert_blob_copy(rdpCertBlob* dst, const rdpCertBlob* src);
224
static void cert_blob_free(rdpCertBlob* blob);
225
static BOOL cert_blob_write(const rdpCertBlob* blob, wStream* s);
226
static BOOL cert_blob_read(rdpCertBlob* blob, wStream* s);
227
228
BOOL cert_blob_read(rdpCertBlob* blob, wStream* s)
229
0
{
230
0
  UINT32 certLength = 0;
231
0
  WINPR_ASSERT(blob);
232
0
  cert_blob_free(blob);
233
234
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
235
0
    goto fail;
236
237
0
  Stream_Read_UINT32(s, certLength);
238
239
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, certLength))
240
0
    goto fail;
241
242
0
  DEBUG_CERTIFICATE("X.509 Certificate length:%" PRIu32 "", certLength);
243
0
  blob->data = (BYTE*)malloc(certLength);
244
245
0
  if (!blob->data)
246
0
    goto fail;
247
248
0
  Stream_Read(s, blob->data, certLength);
249
0
  blob->length = certLength;
250
251
0
  return TRUE;
252
253
0
fail:
254
0
  cert_blob_free(blob);
255
0
  return FALSE;
256
0
}
257
258
BOOL cert_blob_write(const rdpCertBlob* blob, wStream* s)
259
0
{
260
0
  WINPR_ASSERT(blob);
261
262
0
  if (!Stream_EnsureRemainingCapacity(s, 4 + blob->length))
263
0
    return FALSE;
264
265
0
  Stream_Write_UINT32(s, blob->length);
266
0
  Stream_Write(s, blob->data, blob->length);
267
0
  return TRUE;
268
0
}
269
270
void cert_blob_free(rdpCertBlob* blob)
271
0
{
272
0
  if (!blob)
273
0
    return;
274
0
  free(blob->data);
275
0
  blob->data = NULL;
276
0
  blob->length = 0;
277
0
}
278
279
/**
280
 * Read X.509 Certificate
281
 */
282
283
static BOOL is_rsa_key(const X509* x509)
284
0
{
285
0
  EVP_PKEY* evp = X509_get0_pubkey(x509);
286
0
  if (!evp)
287
0
    return FALSE;
288
289
0
  return (EVP_PKEY_id(evp) == EVP_PKEY_RSA);
290
0
}
291
292
static BOOL certificate_read_x509_certificate(const rdpCertBlob* cert, rdpCertInfo* info)
293
0
{
294
0
  wStream sbuffer = { 0 };
295
0
  wStream* s = NULL;
296
0
  size_t length = 0;
297
0
  BYTE padding = 0;
298
0
  UINT32 version = 0;
299
0
  size_t modulus_length = 0;
300
0
  size_t exponent_length = 0;
301
0
  int error = 0;
302
303
0
  if (!cert || !info)
304
0
    return FALSE;
305
306
0
  cert_info_free(info);
307
308
0
  s = Stream_StaticConstInit(&sbuffer, cert->data, cert->length);
309
310
0
  if (!s)
311
0
    return FALSE;
312
313
0
  if (!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */
314
0
    goto error;
315
316
0
  error++;
317
318
0
  if (!ber_read_sequence_tag(s, &length)) /* TBSCertificate (SEQUENCE) */
319
0
    goto error;
320
321
0
  error++;
322
323
0
  if (!ber_read_contextual_tag(s, 0, &length, TRUE)) /* Explicit Contextual Tag [0] */
324
0
    goto error;
325
326
0
  error++;
327
328
0
  if (!ber_read_integer(s, &version)) /* version (INTEGER) */
329
0
    goto error;
330
331
0
  error++;
332
0
  version++;
333
334
  /* serialNumber */
335
0
  if (!ber_read_integer(s, NULL)) /* CertificateSerialNumber (INTEGER) */
336
0
    goto error;
337
338
0
  error++;
339
340
  /* signature */
341
0
  if (!ber_read_sequence_tag(s, &length) ||
342
0
      !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */
343
0
    goto error;
344
345
0
  error++;
346
347
  /* issuer */
348
0
  if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */
349
0
    goto error;
350
351
0
  error++;
352
353
  /* validity */
354
0
  if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Validity (SEQUENCE) */
355
0
    goto error;
356
357
0
  error++;
358
359
  /* subject */
360
0
  if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */
361
0
    goto error;
362
363
0
  error++;
364
365
  /* subjectPublicKeyInfo */
366
0
  if (!ber_read_sequence_tag(s, &length)) /* SubjectPublicKeyInfo (SEQUENCE) */
367
0
    goto error;
368
369
0
  error++;
370
371
  /* subjectPublicKeyInfo::AlgorithmIdentifier */
372
0
  if (!ber_read_sequence_tag(s, &length) ||
373
0
      !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */
374
0
    goto error;
375
376
0
  error++;
377
378
  /* subjectPublicKeyInfo::subjectPublicKey */
379
0
  if (!ber_read_bit_string(s, &length, &padding)) /* BIT_STRING */
380
0
    goto error;
381
382
0
  error++;
383
384
  /* RSAPublicKey (SEQUENCE) */
385
0
  if (!ber_read_sequence_tag(s, &length)) /* SEQUENCE */
386
0
    goto error;
387
388
0
  error++;
389
390
0
  if (!ber_read_integer_length(s, &modulus_length)) /* modulus (INTEGER) */
391
0
    goto error;
392
393
0
  error++;
394
395
  /* skip zero padding, if any */
396
0
  do
397
0
  {
398
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
399
0
      goto error;
400
401
0
    Stream_Peek_UINT8(s, padding);
402
403
0
    if (padding == 0)
404
0
    {
405
0
      if (!Stream_SafeSeek(s, 1))
406
0
        goto error;
407
408
0
      modulus_length--;
409
0
    }
410
0
  } while (padding == 0);
411
412
0
  error++;
413
414
0
  if (!cert_info_read_modulus(info, modulus_length, s))
415
0
    goto error;
416
417
0
  error++;
418
419
0
  if (!ber_read_integer_length(s, &exponent_length)) /* publicExponent (INTEGER) */
420
0
    goto error;
421
422
0
  error++;
423
424
0
  if (!cert_info_read_exponent(info, exponent_length, s))
425
0
    goto error;
426
0
  return TRUE;
427
0
error:
428
0
  WLog_ERR(TAG, "error reading when reading certificate: part=%s error=%d",
429
0
           certificate_read_errors[error], error);
430
0
  cert_info_free(info);
431
0
  return FALSE;
432
0
}
433
434
/**
435
 * Instantiate new X.509 Certificate Chain.
436
 * @param count certificate chain count
437
 * @return new X.509 certificate chain
438
 */
439
440
static rdpX509CertChain certificate_new_x509_certificate_chain(UINT32 count)
441
0
{
442
0
  rdpX509CertChain x509_cert_chain = { 0 };
443
444
0
  x509_cert_chain.array = (rdpCertBlob*)calloc(count, sizeof(rdpCertBlob));
445
446
0
  if (x509_cert_chain.array)
447
0
    x509_cert_chain.count = count;
448
449
0
  return x509_cert_chain;
450
0
}
451
452
/**
453
 * Free X.509 Certificate Chain.
454
 * @param x509_cert_chain X.509 certificate chain to be freed
455
 */
456
457
static void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain)
458
0
{
459
0
  if (!x509_cert_chain)
460
0
    return;
461
462
0
  if (x509_cert_chain->array)
463
0
  {
464
0
    for (UINT32 i = 0; i < x509_cert_chain->count; i++)
465
0
    {
466
0
      rdpCertBlob* element = &x509_cert_chain->array[i];
467
0
      cert_blob_free(element);
468
0
    }
469
0
  }
470
471
0
  free(x509_cert_chain->array);
472
0
}
473
474
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
475
static OSSL_PARAM* get_params(const BIGNUM* e, const BIGNUM* mod)
476
{
477
  WINPR_ASSERT(e);
478
  WINPR_ASSERT(mod);
479
480
  OSSL_PARAM* parameters = NULL;
481
  OSSL_PARAM_BLD* param = OSSL_PARAM_BLD_new();
482
  if (!param)
483
    return NULL;
484
485
  const int bits = BN_num_bits(e);
486
  if ((bits < 0) || (bits > 32))
487
    goto fail;
488
489
  UINT ie = 0;
490
  const int ne = BN_bn2nativepad(e, (BYTE*)&ie, sizeof(ie));
491
  if ((ne < 0) || (ne > 4))
492
    goto fail;
493
  if (OSSL_PARAM_BLD_push_BN(param, OSSL_PKEY_PARAM_RSA_N, mod) != 1)
494
    goto fail;
495
  if (OSSL_PARAM_BLD_push_uint(param, OSSL_PKEY_PARAM_RSA_E, ie) != 1)
496
    goto fail;
497
498
  parameters = OSSL_PARAM_BLD_to_param(param);
499
fail:
500
  OSSL_PARAM_BLD_free(param);
501
502
  return parameters;
503
}
504
#endif
505
506
static BOOL update_x509_from_info(rdpCertificate* cert)
507
0
{
508
0
  BOOL rc = FALSE;
509
510
0
  WINPR_ASSERT(cert);
511
512
0
  X509_free(cert->x509);
513
0
  cert->x509 = NULL;
514
515
0
  rdpCertInfo* info = &cert->cert_info;
516
517
0
  BIGNUM* e = BN_new();
518
0
  BIGNUM* mod = BN_new();
519
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
520
0
  RSA* rsa = RSA_new();
521
0
  if (!rsa)
522
0
    goto fail;
523
0
#endif
524
525
0
  if (!mod || !e)
526
0
    goto fail;
527
0
  if (!BN_bin2bn(info->Modulus, info->ModulusLength, mod))
528
0
    goto fail;
529
0
  if (!BN_bin2bn(info->exponent, sizeof(info->exponent), e))
530
0
    goto fail;
531
532
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
533
0
  const int rec = RSA_set0_key(rsa, mod, e, NULL);
534
0
  if (rec != 1)
535
0
    goto fail;
536
537
0
  cert->x509 = x509_from_rsa(rsa);
538
#else
539
  EVP_PKEY* pkey = NULL;
540
  EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
541
  if (!ctx)
542
    goto fail2;
543
  const int xx = EVP_PKEY_fromdata_init(ctx);
544
  if (xx != 1)
545
    goto fail2;
546
  OSSL_PARAM* parameters = get_params(e, mod);
547
  if (!parameters)
548
    goto fail2;
549
550
  const int rc2 = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, parameters);
551
  OSSL_PARAM_free(parameters);
552
  if (rc2 <= 0)
553
    goto fail2;
554
555
  cert->x509 = X509_new();
556
  if (!cert->x509)
557
    goto fail2;
558
  if (X509_set_pubkey(cert->x509, pkey) != 1)
559
  {
560
    X509_free(cert->x509);
561
    cert->x509 = NULL;
562
  }
563
fail2:
564
  EVP_PKEY_free(pkey);
565
  EVP_PKEY_CTX_free(ctx);
566
#endif
567
0
  if (!cert->x509)
568
0
    goto fail;
569
570
0
  rc = TRUE;
571
572
0
fail:
573
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
574
0
  if (rsa)
575
0
    RSA_free(rsa);
576
0
  else
577
0
#endif
578
0
  {
579
0
    BN_free(mod);
580
0
    BN_free(e);
581
0
  }
582
0
  return rc;
583
0
}
584
585
static BOOL certificate_process_server_public_key(rdpCertificate* cert, wStream* s, UINT32 length)
586
0
{
587
0
  char magic[sizeof(rsa_magic)] = { 0 };
588
0
  UINT32 keylen = 0;
589
0
  UINT32 bitlen = 0;
590
0
  UINT32 datalen = 0;
591
592
0
  WINPR_ASSERT(cert);
593
0
  WINPR_ASSERT(s);
594
595
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
596
0
    return FALSE;
597
598
0
  Stream_Read(s, magic, sizeof(magic));
599
600
0
  if (memcmp(magic, rsa_magic, sizeof(magic)) != 0)
601
0
  {
602
0
    WLog_ERR(TAG, "magic error");
603
0
    return FALSE;
604
0
  }
605
606
0
  rdpCertInfo* info = &cert->cert_info;
607
0
  cert_info_free(info);
608
609
0
  Stream_Read_UINT32(s, keylen);
610
0
  Stream_Read_UINT32(s, bitlen);
611
0
  Stream_Read_UINT32(s, datalen);
612
0
  Stream_Read(s, info->exponent, 4);
613
614
0
  if ((keylen <= 8) || (!Stream_CheckAndLogRequiredLength(TAG, s, keylen)))
615
0
    return FALSE;
616
617
0
  info->ModulusLength = keylen - 8;
618
0
  BYTE* tmp = realloc(info->Modulus, info->ModulusLength);
619
620
0
  if (!tmp)
621
0
    return FALSE;
622
0
  info->Modulus = tmp;
623
624
0
  Stream_Read(s, info->Modulus, info->ModulusLength);
625
0
  Stream_Seek(s, 8); /* 8 bytes of zero padding */
626
0
  return update_x509_from_info(cert);
627
0
}
628
629
static BOOL certificate_process_server_public_signature(rdpCertificate* certificate,
630
                                                        const BYTE* sigdata, size_t sigdatalen,
631
                                                        wStream* s, UINT32 siglen)
632
0
{
633
0
  WINPR_ASSERT(certificate);
634
#if defined(CERT_VALIDATE_PADDING) || defined(CERT_VALIDATE_RSA)
635
  size_t i, sum;
636
#endif
637
#if defined(CERT_VALIDATE_RSA)
638
  BYTE sig[TSSK_KEY_LENGTH];
639
#endif
640
0
  BYTE encsig[TSSK_KEY_LENGTH + 8];
641
#if defined(CERT_VALIDATE_MD5) && defined(CERT_VALIDATE_RSA)
642
  BYTE md5hash[WINPR_MD5_DIGEST_LENGTH];
643
#endif
644
0
#if !defined(CERT_VALIDATE_MD5) || !defined(CERT_VALIDATE_RSA)
645
0
  (void)sigdata;
646
0
  (void)sigdatalen;
647
0
#endif
648
0
  (void)certificate;
649
  /* Do not bother with validation of server proprietary certificate. The use of MD5 here is not
650
   * allowed under FIPS. Since the validation is not protecting against anything since the
651
   * private/public keys are well known and documented in MS-RDPBCGR section 5.3.3.1, we are not
652
   * gaining any security by using MD5 for signature comparison. Rather then use MD5
653
   * here we just dont do the validation to avoid its use. Historically, freerdp has been ignoring
654
   * a failed validation anyways. */
655
#if defined(CERT_VALIDATE_MD5)
656
657
  if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash, sizeof(md5hash)))
658
    return FALSE;
659
660
#endif
661
0
  Stream_Read(s, encsig, siglen);
662
663
0
  if (siglen < 8)
664
0
    return FALSE;
665
666
    /* Last 8 bytes shall be all zero. */
667
#if defined(CERT_VALIDATE_PADDING)
668
669
  for (sum = 0, i = sizeof(encsig) - 8; i < sizeof(encsig); i++)
670
    sum += encsig[i];
671
672
  if (sum != 0)
673
  {
674
    WLog_ERR(TAG, "invalid signature");
675
    return FALSE;
676
  }
677
678
#endif
679
#if defined(CERT_VALIDATE_RSA)
680
681
  if (crypto_rsa_public_decrypt(encsig, siglen - 8, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent,
682
                                sig) <= 0)
683
  {
684
    WLog_ERR(TAG, "invalid RSA decrypt");
685
    return FALSE;
686
  }
687
688
  /* Verify signature. */
689
  /* Do not bother with validation of server proprietary certificate as described above. */
690
#if defined(CERT_VALIDATE_MD5)
691
692
  if (memcmp(md5hash, sig, sizeof(md5hash)) != 0)
693
  {
694
    WLog_ERR(TAG, "invalid signature");
695
    return FALSE;
696
  }
697
698
#endif
699
  /*
700
   * Verify rest of decrypted data:
701
   * The 17th byte is 0x00.
702
   * The 18th through 62nd bytes are each 0xFF.
703
   * The 63rd byte is 0x01.
704
   */
705
706
  for (sum = 0, i = 17; i < 62; i++)
707
    sum += sig[i];
708
709
  if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01)
710
  {
711
    WLog_ERR(TAG, "invalid signature");
712
    return FALSE;
713
  }
714
715
#endif
716
0
  return TRUE;
717
0
}
718
719
static BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate, wStream* s)
720
0
{
721
0
  UINT32 dwSigAlgId = 0;
722
0
  UINT32 dwKeyAlgId = 0;
723
0
  UINT16 wPublicKeyBlobType = 0;
724
0
  UINT16 wPublicKeyBlobLen = 0;
725
0
  UINT16 wSignatureBlobType = 0;
726
0
  UINT16 wSignatureBlobLen = 0;
727
0
  size_t sigdatalen = 0;
728
729
0
  WINPR_ASSERT(certificate);
730
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
731
0
    return FALSE;
732
733
  /* -4, because we need to include dwVersion */
734
0
  const BYTE* sigdata = Stream_PointerAs(s, const BYTE) - 4;
735
0
  Stream_Read_UINT32(s, dwSigAlgId);
736
0
  Stream_Read_UINT32(s, dwKeyAlgId);
737
738
0
  if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
739
0
  {
740
0
    WLog_ERR(TAG,
741
0
             "unsupported signature or key algorithm, dwSigAlgId=%" PRIu32
742
0
             " dwKeyAlgId=%" PRIu32 "",
743
0
             dwSigAlgId, dwKeyAlgId);
744
0
    return FALSE;
745
0
  }
746
747
0
  Stream_Read_UINT16(s, wPublicKeyBlobType);
748
749
0
  if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
750
0
  {
751
0
    WLog_ERR(TAG, "unsupported public key blob type %" PRIu16 "", wPublicKeyBlobType);
752
0
    return FALSE;
753
0
  }
754
755
0
  Stream_Read_UINT16(s, wPublicKeyBlobLen);
756
757
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, wPublicKeyBlobLen))
758
0
    return FALSE;
759
760
0
  if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
761
0
    return FALSE;
762
763
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
764
0
    return FALSE;
765
766
0
  sigdatalen = Stream_PointerAs(s, const BYTE) - sigdata;
767
0
  Stream_Read_UINT16(s, wSignatureBlobType);
768
769
0
  if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
770
0
  {
771
0
    WLog_ERR(TAG, "unsupported blob signature %" PRIu16 "", wSignatureBlobType);
772
0
    return FALSE;
773
0
  }
774
775
0
  Stream_Read_UINT16(s, wSignatureBlobLen);
776
777
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, wSignatureBlobLen))
778
0
    return FALSE;
779
780
0
  if (wSignatureBlobLen != 72)
781
0
  {
782
0
    WLog_ERR(TAG, "invalid signature length (got %" PRIu16 ", expected 72)", wSignatureBlobLen);
783
0
    return FALSE;
784
0
  }
785
786
0
  if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s,
787
0
                                                   wSignatureBlobLen))
788
0
  {
789
0
    WLog_ERR(TAG, "unable to parse server public signature");
790
0
    return FALSE;
791
0
  }
792
0
  return TRUE;
793
0
}
794
795
/* [MS-RDPBCGR] 2.2.1.4.3.1.1.1 RSA Public Key (RSA_PUBLIC_KEY) */
796
static BOOL cert_write_rsa_public_key(wStream* s, const rdpCertificate* cert)
797
0
{
798
0
  WINPR_ASSERT(cert);
799
0
  WINPR_ASSERT(freerdp_certificate_is_rsa(cert));
800
801
0
  const rdpCertInfo* info = &cert->cert_info;
802
803
0
  const UINT32 keyLen = info->ModulusLength + 8;
804
0
  const UINT32 bitLen = info->ModulusLength * 8;
805
0
  const UINT32 dataLen = (bitLen / 8) - 1;
806
0
  const size_t pubExpLen = sizeof(info->exponent);
807
0
  const BYTE* pubExp = info->exponent;
808
0
  const BYTE* modulus = info->Modulus;
809
810
0
  const size_t wPublicKeyBlobLen = 16 + pubExpLen + keyLen;
811
0
  WINPR_ASSERT(wPublicKeyBlobLen <= UINT16_MAX);
812
0
  if (!Stream_EnsureRemainingCapacity(s, 2 + wPublicKeyBlobLen))
813
0
    return FALSE;
814
0
  Stream_Write_UINT16(s, (UINT16)wPublicKeyBlobLen);
815
0
  Stream_Write(s, rsa_magic, sizeof(rsa_magic));
816
0
  Stream_Write_UINT32(s, keyLen);
817
0
  Stream_Write_UINT32(s, bitLen);
818
0
  Stream_Write_UINT32(s, dataLen);
819
0
  Stream_Write(s, pubExp, pubExpLen);
820
0
  Stream_Write(s, modulus, info->ModulusLength);
821
0
  Stream_Zero(s, 8);
822
0
  return TRUE;
823
0
}
824
825
static BOOL cert_write_rsa_signature(wStream* s, const void* sigData, size_t sigDataLen)
826
0
{
827
0
  BYTE encryptedSignature[TSSK_KEY_LENGTH] = { 0 };
828
0
  BYTE signature[sizeof(initial_signature)] = { 0 };
829
830
0
  memcpy(signature, initial_signature, sizeof(initial_signature));
831
0
  if (!winpr_Digest(WINPR_MD_MD5, sigData, sigDataLen, signature, sizeof(signature)))
832
0
    return FALSE;
833
834
0
  crypto_rsa_private_encrypt(signature, sizeof(signature), priv_key_tssk, encryptedSignature,
835
0
                             sizeof(encryptedSignature));
836
837
0
  if (!Stream_EnsureRemainingCapacity(s, 2 * sizeof(UINT16) + sizeof(encryptedSignature) + 8))
838
0
    return FALSE;
839
0
  Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB);
840
0
  Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */
841
0
  Stream_Write(s, encryptedSignature, sizeof(encryptedSignature));
842
0
  Stream_Zero(s, 8);
843
0
  return TRUE;
844
0
}
845
846
/* [MS-RDPBCGR] 2.2.1.4.3.1.1 Server Proprietary Certificate (PROPRIETARYSERVERCERTIFICATE) */
847
static BOOL cert_write_server_certificate_v1(wStream* s, const rdpCertificate* certificate)
848
0
{
849
0
  const size_t start = Stream_GetPosition(s);
850
0
  const BYTE* sigData = Stream_PointerAs(s, const BYTE) - sizeof(UINT32);
851
852
0
  WINPR_ASSERT(start >= 4);
853
0
  if (!Stream_EnsureRemainingCapacity(s, 10))
854
0
    return FALSE;
855
0
  Stream_Write_UINT32(s, SIGNATURE_ALG_RSA);
856
0
  Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA);
857
0
  Stream_Write_UINT16(s, BB_RSA_KEY_BLOB);
858
0
  if (!cert_write_rsa_public_key(s, certificate))
859
0
    return FALSE;
860
861
0
  const size_t end = Stream_GetPosition(s);
862
0
  return cert_write_rsa_signature(s, sigData, end - start + sizeof(UINT32));
863
0
}
864
865
static BOOL cert_write_server_certificate_v2(wStream* s, const rdpCertificate* certificate)
866
0
{
867
0
  WINPR_ASSERT(certificate);
868
869
0
  const rdpX509CertChain* chain = &certificate->x509_cert_chain;
870
0
  const size_t padding = 8ull + 4ull * chain->count;
871
872
0
  if (!Stream_EnsureRemainingCapacity(s, sizeof(UINT32)))
873
0
    return FALSE;
874
875
0
  Stream_Write_UINT32(s, chain->count);
876
0
  for (UINT32 x = 0; x < chain->count; x++)
877
0
  {
878
0
    const rdpCertBlob* cert = &chain->array[x];
879
0
    if (!cert_blob_write(cert, s))
880
0
      return FALSE;
881
0
  }
882
883
0
  if (!Stream_EnsureRemainingCapacity(s, padding))
884
0
    return FALSE;
885
0
  Stream_Zero(s, padding);
886
0
  return TRUE;
887
0
}
888
889
SSIZE_T freerdp_certificate_write_server_cert(const rdpCertificate* certificate, UINT32 dwVersion,
890
                                              wStream* s)
891
0
{
892
0
  if (!certificate)
893
0
    return -1;
894
895
0
  const size_t start = Stream_GetPosition(s);
896
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
897
0
    return -1;
898
0
  Stream_Write_UINT32(s, dwVersion);
899
900
0
  switch (dwVersion & CERT_CHAIN_VERSION_MASK)
901
0
  {
902
0
    case CERT_CHAIN_VERSION_1:
903
0
      if (!cert_write_server_certificate_v1(s, certificate))
904
0
        return -1;
905
0
      break;
906
0
    case CERT_CHAIN_VERSION_2:
907
0
      if (!cert_write_server_certificate_v2(s, certificate))
908
0
        return -1;
909
0
      break;
910
0
    default:
911
0
      WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
912
0
               dwVersion & CERT_CHAIN_VERSION_MASK);
913
0
      return -1;
914
0
  }
915
916
0
  const size_t end = Stream_GetPosition(s);
917
0
  return end - start;
918
0
}
919
920
/**
921
 * Read an X.509 Certificate Chain.
922
 * @param certificate certificate module
923
 * @param s stream
924
 */
925
926
static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* cert, wStream* s)
927
0
{
928
0
  UINT32 numCertBlobs = 0;
929
0
  DEBUG_CERTIFICATE("Server X.509 Certificate Chain");
930
931
0
  WINPR_ASSERT(cert);
932
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
933
0
    return FALSE;
934
935
0
  Stream_Read_UINT32(s, numCertBlobs); /* numCertBlobs */
936
0
  certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
937
0
  cert->x509_cert_chain = certificate_new_x509_certificate_chain(numCertBlobs);
938
939
0
  for (UINT32 i = 0; i < cert->x509_cert_chain.count; i++)
940
0
  {
941
0
    rdpCertBlob* blob = &cert->x509_cert_chain.array[i];
942
0
    if (!cert_blob_read(blob, s))
943
0
      return FALSE;
944
945
0
    if (numCertBlobs - i == 1)
946
0
    {
947
0
      DEBUG_CERTIFICATE("Terminal Server Certificate");
948
949
0
      BOOL res = certificate_read_x509_certificate(blob, &cert->cert_info);
950
951
0
      if (res)
952
0
      {
953
0
        if (!update_x509_from_info(cert))
954
0
          res = FALSE;
955
0
      }
956
957
0
      if (!res)
958
0
      {
959
0
        return FALSE;
960
0
      }
961
962
0
      DEBUG_CERTIFICATE("modulus length:%" PRIu32 "", cert->cert_info.ModulusLength);
963
0
    }
964
0
  }
965
966
0
  return update_x509_from_info(cert);
967
0
}
968
969
static BOOL certificate_write_server_x509_certificate_chain(const rdpCertificate* certificate,
970
                                                            wStream* s)
971
0
{
972
0
  UINT32 numCertBlobs = 0;
973
0
974
0
  WINPR_ASSERT(certificate);
975
0
  WINPR_ASSERT(s);
976
0
977
0
  numCertBlobs = certificate->x509_cert_chain.count;
978
0
979
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
980
0
    return FALSE;
981
0
  Stream_Write_UINT32(s, numCertBlobs); /* numCertBlobs */
982
0
983
0
  for (UINT32 i = 0; i < numCertBlobs; i++)
984
0
  {
985
0
    const rdpCertBlob* cert = &certificate->x509_cert_chain.array[i];
986
0
    if (!cert_blob_write(cert, s))
987
0
      return FALSE;
988
0
  }
989
0
990
0
  return TRUE;
991
0
}
992
993
/**
994
 * Read a Server Certificate.
995
 * @param certificate certificate module
996
 * @param server_cert server certificate
997
 * @param length certificate length
998
 */
999
1000
BOOL freerdp_certificate_read_server_cert(rdpCertificate* certificate, const BYTE* server_cert,
1001
                                          size_t length)
1002
0
{
1003
0
  BOOL ret = FALSE;
1004
0
  wStream *s, sbuffer;
1005
0
  UINT32 dwVersion = 0;
1006
1007
0
  WINPR_ASSERT(certificate);
1008
0
  if (length < 4) /* NULL certificate is not an error see #1795 */
1009
0
    return TRUE;
1010
1011
0
  WINPR_ASSERT(server_cert);
1012
0
  s = Stream_StaticConstInit(&sbuffer, server_cert, length);
1013
1014
0
  if (!s)
1015
0
  {
1016
0
    WLog_ERR(TAG, "Stream_New failed!");
1017
0
    return FALSE;
1018
0
  }
1019
1020
0
  Stream_Read_UINT32(s, dwVersion); /* dwVersion (4 bytes) */
1021
1022
0
  switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1023
0
  {
1024
0
    case CERT_CHAIN_VERSION_1:
1025
0
      ret = certificate_read_server_proprietary_certificate(certificate, s);
1026
0
      break;
1027
1028
0
    case CERT_CHAIN_VERSION_2:
1029
0
      ret = certificate_read_server_x509_certificate_chain(certificate, s);
1030
0
      break;
1031
1032
0
    default:
1033
0
      WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
1034
0
               dwVersion & CERT_CHAIN_VERSION_MASK);
1035
0
      ret = FALSE;
1036
0
      break;
1037
0
  }
1038
1039
0
  return ret;
1040
0
}
1041
1042
static BOOL cert_blob_copy(rdpCertBlob* dst, const rdpCertBlob* src)
1043
0
{
1044
0
  WINPR_ASSERT(dst);
1045
0
  WINPR_ASSERT(src);
1046
1047
0
  cert_blob_free(dst);
1048
0
  if (src->length > 0)
1049
0
  {
1050
0
    dst->data = malloc(src->length);
1051
0
    if (!dst->data)
1052
0
      return FALSE;
1053
0
    dst->length = src->length;
1054
0
    memcpy(dst->data, src->data, src->length);
1055
0
  }
1056
1057
0
  return TRUE;
1058
0
}
1059
1060
static BOOL cert_x509_chain_copy(rdpX509CertChain* cert, const rdpX509CertChain* src)
1061
0
{
1062
0
  WINPR_ASSERT(cert);
1063
1064
0
  certificate_free_x509_certificate_chain(cert);
1065
0
  if (!src)
1066
0
    return TRUE;
1067
1068
0
  if (src->count > 0)
1069
0
  {
1070
0
    cert->array = calloc(src->count, sizeof(rdpCertBlob));
1071
0
    if (!cert->array)
1072
0
    {
1073
0
      return FALSE;
1074
0
    }
1075
0
    cert->count = src->count;
1076
1077
0
    for (UINT32 x = 0; x < cert->count; x++)
1078
0
    {
1079
0
      const rdpCertBlob* srcblob = &src->array[x];
1080
0
      rdpCertBlob* dstblob = &cert->array[x];
1081
1082
0
      if (!cert_blob_copy(dstblob, srcblob))
1083
0
      {
1084
0
        certificate_free_x509_certificate_chain(cert);
1085
0
        return FALSE;
1086
0
      }
1087
0
    }
1088
0
  }
1089
1090
0
  return TRUE;
1091
0
}
1092
1093
BOOL cert_clone_int(rdpCertificate* dst, const rdpCertificate* src)
1094
0
{
1095
0
  WINPR_ASSERT(dst);
1096
0
  WINPR_ASSERT(src);
1097
1098
0
  if (src->x509)
1099
0
  {
1100
0
    dst->x509 = X509_dup(src->x509);
1101
0
    if (!dst->x509)
1102
0
      return FALSE;
1103
0
  }
1104
1105
0
  if (!cert_info_clone(&dst->cert_info, &src->cert_info))
1106
0
    return FALSE;
1107
0
  return cert_x509_chain_copy(&dst->x509_cert_chain, &src->x509_cert_chain);
1108
0
}
1109
1110
rdpCertificate* freerdp_certificate_clone(const rdpCertificate* certificate)
1111
0
{
1112
0
  if (!certificate)
1113
0
    return NULL;
1114
1115
0
  rdpCertificate* _certificate = freerdp_certificate_new();
1116
1117
0
  if (!_certificate)
1118
0
    return NULL;
1119
1120
0
  if (!cert_clone_int(_certificate, certificate))
1121
0
    goto out_fail;
1122
1123
0
  return _certificate;
1124
0
out_fail:
1125
1126
0
  freerdp_certificate_free(_certificate);
1127
0
  return NULL;
1128
0
}
1129
1130
/**
1131
 * Instantiate new certificate module.
1132
 * @return new certificate module
1133
 */
1134
1135
rdpCertificate* freerdp_certificate_new(void)
1136
0
{
1137
0
  return (rdpCertificate*)calloc(1, sizeof(rdpCertificate));
1138
0
}
1139
1140
void certificate_free_int(rdpCertificate* cert)
1141
0
{
1142
0
  WINPR_ASSERT(cert);
1143
1144
0
  if (cert->x509)
1145
0
    X509_free(cert->x509);
1146
0
  if (cert->chain)
1147
0
    sk_X509_free(cert->chain);
1148
1149
0
  certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1150
0
  cert_info_free(&cert->cert_info);
1151
0
}
1152
1153
/**
1154
 * Free certificate module.
1155
 * @param certificate certificate module to be freed
1156
 */
1157
1158
void freerdp_certificate_free(rdpCertificate* cert)
1159
0
{
1160
0
  if (!cert)
1161
0
    return;
1162
1163
0
  certificate_free_int(cert);
1164
0
  free(cert);
1165
0
}
1166
1167
static BOOL freerdp_rsa_from_x509(rdpCertificate* cert)
1168
0
{
1169
0
  BOOL rc = FALSE;
1170
1171
0
  WINPR_ASSERT(cert);
1172
1173
0
  if (!freerdp_certificate_is_rsa(cert))
1174
0
    return TRUE;
1175
1176
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1177
0
  RSA* rsa = NULL;
1178
0
  const BIGNUM* rsa_n = NULL;
1179
0
  const BIGNUM* rsa_e = NULL;
1180
#else
1181
  BIGNUM* rsa_n = NULL;
1182
  BIGNUM* rsa_e = NULL;
1183
#endif
1184
0
  EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1185
0
  if (!pubkey)
1186
0
    goto fail;
1187
1188
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1189
0
  rsa = EVP_PKEY_get1_RSA(pubkey);
1190
1191
  /* If this is not a RSA key return success */
1192
0
  rc = TRUE;
1193
0
  if (!rsa)
1194
0
    goto fail;
1195
1196
  /* Now we return failure again if something is wrong. */
1197
0
  rc = FALSE;
1198
1199
0
  RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
1200
#else
1201
  if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &rsa_e))
1202
    goto fail;
1203
  if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &rsa_n))
1204
    goto fail;
1205
#endif
1206
0
  if (!rsa_n || !rsa_e)
1207
0
    goto fail;
1208
0
  if (!cert_info_create(&cert->cert_info, rsa_n, rsa_e))
1209
0
    goto fail;
1210
0
  rc = TRUE;
1211
0
fail:
1212
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1213
0
  RSA_free(rsa);
1214
#else
1215
  BN_free(rsa_n);
1216
  BN_free(rsa_e);
1217
#endif
1218
0
  return rc;
1219
0
}
1220
1221
rdpCertificate* freerdp_certificate_new_from_der(const BYTE* data, size_t length)
1222
0
{
1223
0
  rdpCertificate* cert = freerdp_certificate_new();
1224
1225
0
  if (!cert || !data || (length == 0))
1226
0
    goto fail;
1227
0
  const BYTE* ptr = data;
1228
0
  cert->x509 = d2i_X509(NULL, &ptr, length);
1229
0
  if (!cert->x509)
1230
0
    goto fail;
1231
0
  if (!freerdp_rsa_from_x509(cert))
1232
0
    goto fail;
1233
0
  return cert;
1234
0
fail:
1235
0
  freerdp_certificate_free(cert);
1236
0
  return NULL;
1237
0
}
1238
1239
rdpCertificate* freerdp_certificate_new_from_x509(const X509* xcert, const STACK_OF(X509) * chain)
1240
0
{
1241
0
  WINPR_ASSERT(xcert);
1242
1243
0
  rdpCertificate* cert = freerdp_certificate_new();
1244
0
  if (!cert)
1245
0
    return NULL;
1246
1247
0
  cert->x509 = X509_dup(xcert);
1248
0
  if (!cert->x509)
1249
0
    goto fail;
1250
1251
0
  if (!freerdp_rsa_from_x509(cert))
1252
0
    goto fail;
1253
1254
0
  if (chain)
1255
0
  {
1256
0
    cert->chain = sk_X509_dup(chain);
1257
0
  }
1258
0
  return cert;
1259
0
fail:
1260
0
  freerdp_certificate_free(cert);
1261
0
  return NULL;
1262
0
}
1263
1264
static rdpCertificate* freerdp_certificate_new_from(const char* file, BOOL isFile)
1265
0
{
1266
0
  X509* x509 = x509_utils_from_pem(file, strlen(file), isFile);
1267
0
  if (!x509)
1268
0
    return NULL;
1269
0
  rdpCertificate* cert = freerdp_certificate_new_from_x509(x509, NULL);
1270
0
  X509_free(x509);
1271
0
  return cert;
1272
0
}
1273
1274
rdpCertificate* freerdp_certificate_new_from_file(const char* file)
1275
0
{
1276
0
  return freerdp_certificate_new_from(file, TRUE);
1277
0
}
1278
1279
rdpCertificate* freerdp_certificate_new_from_pem(const char* pem)
1280
0
{
1281
0
  return freerdp_certificate_new_from(pem, FALSE);
1282
0
}
1283
1284
const rdpCertInfo* freerdp_certificate_get_info(const rdpCertificate* cert)
1285
0
{
1286
0
  WINPR_ASSERT(cert);
1287
0
  if (!freerdp_certificate_is_rsa(cert))
1288
0
    return NULL;
1289
0
  return &cert->cert_info;
1290
0
}
1291
1292
char* freerdp_certificate_get_fingerprint(const rdpCertificate* cert)
1293
0
{
1294
0
  return freerdp_certificate_get_fingerprint_by_hash(cert, "sha256");
1295
0
}
1296
1297
char* freerdp_certificate_get_fingerprint_by_hash(const rdpCertificate* cert, const char* hash)
1298
0
{
1299
0
  return freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, TRUE);
1300
0
}
1301
1302
char* freerdp_certificate_get_fingerprint_by_hash_ex(const rdpCertificate* cert, const char* hash,
1303
                                                     BOOL separator)
1304
0
{
1305
0
  size_t fp_len = 0;
1306
0
  size_t pos = 0;
1307
0
  size_t size = 0;
1308
0
  BYTE* fp = NULL;
1309
0
  char* fp_buffer = NULL;
1310
0
  if (!cert || !cert->x509)
1311
0
  {
1312
0
    WLog_ERR(TAG, "Invalid certificate [%p, %p]", cert, cert ? cert->x509 : NULL);
1313
0
    return NULL;
1314
0
  }
1315
0
  if (!hash)
1316
0
  {
1317
0
    WLog_ERR(TAG, "Invalid certificate hash %p", hash);
1318
0
    return NULL;
1319
0
  }
1320
0
  fp = x509_utils_get_hash(cert->x509, hash, &fp_len);
1321
0
  if (!fp)
1322
0
    return NULL;
1323
1324
0
  size = fp_len * 3 + 1;
1325
0
  fp_buffer = calloc(size, sizeof(char));
1326
0
  if (!fp_buffer)
1327
0
    goto fail;
1328
1329
0
  pos = 0;
1330
1331
0
  size_t i = 0;
1332
0
  for (i = 0; i < (fp_len - 1); i++)
1333
0
  {
1334
0
    int rc;
1335
0
    char* p = &fp_buffer[pos];
1336
0
    if (separator)
1337
0
      rc = sprintf_s(p, size - pos, "%02" PRIx8 ":", fp[i]);
1338
0
    else
1339
0
      rc = sprintf_s(p, size - pos, "%02" PRIx8, fp[i]);
1340
0
    if (rc <= 0)
1341
0
      goto fail;
1342
0
    pos += (size_t)rc;
1343
0
  }
1344
1345
0
  sprintf_s(&fp_buffer[pos], size - pos, "%02" PRIx8 "", fp[i]);
1346
1347
0
  free(fp);
1348
1349
0
  return fp_buffer;
1350
0
fail:
1351
0
  free(fp);
1352
0
  free(fp_buffer);
1353
0
  return NULL;
1354
0
}
1355
1356
static BOOL bio_read_pem(BIO* bio, char** ppem, size_t* plength)
1357
0
{
1358
0
  BOOL rc = FALSE;
1359
1360
0
  WINPR_ASSERT(bio);
1361
0
  WINPR_ASSERT(ppem);
1362
1363
0
  size_t offset = 0;
1364
0
  size_t length = 2048;
1365
0
  char* pem = NULL;
1366
0
  while (offset < length)
1367
0
  {
1368
0
    char* tmp = realloc(pem, length + 1);
1369
0
    if (!tmp)
1370
0
      goto fail;
1371
0
    pem = tmp;
1372
1373
0
    ERR_clear_error();
1374
1375
0
    const int status = BIO_read(bio, &pem[offset], length - offset);
1376
0
    if (status < 0)
1377
0
    {
1378
0
      WLog_ERR(TAG, "failed to read certificate");
1379
0
      goto fail;
1380
0
    }
1381
1382
0
    if (status == 0)
1383
0
      break;
1384
1385
0
    offset += (size_t)status;
1386
0
    if (length - offset > 0)
1387
0
      break;
1388
0
    length *= 2;
1389
0
  }
1390
0
  pem[offset] = '\0';
1391
0
  *ppem = pem;
1392
0
  if (plength)
1393
0
    *plength = offset;
1394
0
  rc = TRUE;
1395
0
fail:
1396
0
  return rc;
1397
0
}
1398
1399
char* freerdp_certificate_get_pem(const rdpCertificate* cert, size_t* pLength)
1400
0
{
1401
0
  char* pem = NULL;
1402
0
  WINPR_ASSERT(cert);
1403
1404
0
  if (!cert->x509)
1405
0
    return NULL;
1406
1407
0
  BIO* bio;
1408
0
  int status;
1409
1410
  /**
1411
   * Don't manage certificates internally, leave it up entirely to the external client
1412
   * implementation
1413
   */
1414
0
  bio = BIO_new(BIO_s_mem());
1415
1416
0
  if (!bio)
1417
0
  {
1418
0
    WLog_ERR(TAG, "BIO_new() failure");
1419
0
    return NULL;
1420
0
  }
1421
1422
0
  status = PEM_write_bio_X509(bio, cert->x509);
1423
1424
0
  if (status < 0)
1425
0
  {
1426
0
    WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
1427
0
    goto fail;
1428
0
  }
1429
1430
#if 0
1431
        if (chain)
1432
        {
1433
            count = sk_X509_num(chain);
1434
            for (x = 0; x < count; x++)
1435
            {
1436
                X509* c = sk_X509_value(chain, x);
1437
                status = PEM_write_bio_X509(bio, c);
1438
                if (status < 0)
1439
                {
1440
                    WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
1441
                    goto fail;
1442
                }
1443
            }
1444
        }
1445
#endif
1446
0
  if (!bio_read_pem(bio, &pem, pLength))
1447
0
    goto fail;
1448
0
fail:
1449
0
  BIO_free_all(bio);
1450
0
  return pem;
1451
0
}
1452
1453
char* freerdp_certificate_get_subject(const rdpCertificate* cert)
1454
0
{
1455
0
  WINPR_ASSERT(cert);
1456
0
  return x509_utils_get_subject(cert->x509);
1457
0
}
1458
1459
char* freerdp_certificate_get_issuer(const rdpCertificate* cert)
1460
0
{
1461
0
  WINPR_ASSERT(cert);
1462
0
  return x509_utils_get_issuer(cert->x509);
1463
0
}
1464
1465
char* freerdp_certificate_get_upn(const rdpCertificate* cert)
1466
0
{
1467
0
  WINPR_ASSERT(cert);
1468
0
  return x509_utils_get_upn(cert->x509);
1469
0
}
1470
1471
char* freerdp_certificate_get_email(const rdpCertificate* cert)
1472
0
{
1473
0
  WINPR_ASSERT(cert);
1474
0
  return x509_utils_get_email(cert->x509);
1475
0
}
1476
1477
BOOL freerdp_certificate_check_eku(const rdpCertificate* cert, int nid)
1478
0
{
1479
0
  WINPR_ASSERT(cert);
1480
0
  return x509_utils_check_eku(cert->x509, nid);
1481
0
}
1482
1483
BOOL freerdp_certificate_get_public_key(const rdpCertificate* cert, BYTE** PublicKey,
1484
                                        DWORD* PublicKeyLength)
1485
0
{
1486
0
  BYTE* ptr = NULL;
1487
0
  BYTE* optr = NULL;
1488
0
  int length;
1489
0
  BOOL status = FALSE;
1490
0
  EVP_PKEY* pkey = NULL;
1491
1492
0
  WINPR_ASSERT(cert);
1493
1494
0
  pkey = X509_get0_pubkey(cert->x509);
1495
1496
0
  if (!pkey)
1497
0
  {
1498
0
    WLog_ERR(TAG, "X509_get_pubkey() failed");
1499
0
    goto exit;
1500
0
  }
1501
1502
0
  length = i2d_PublicKey(pkey, NULL);
1503
1504
0
  if (length < 1)
1505
0
  {
1506
0
    WLog_ERR(TAG, "i2d_PublicKey() failed");
1507
0
    goto exit;
1508
0
  }
1509
1510
0
  *PublicKey = optr = ptr = (BYTE*)calloc(length, sizeof(BYTE));
1511
1512
0
  if (!ptr)
1513
0
    goto exit;
1514
1515
0
  const int length2 = i2d_PublicKey(pkey, &ptr);
1516
0
  if (length != length2)
1517
0
    goto exit;
1518
0
  *PublicKeyLength = (DWORD)length2;
1519
0
  status = TRUE;
1520
0
exit:
1521
1522
0
  if (!status)
1523
0
    free(optr);
1524
1525
0
  return status;
1526
0
}
1527
1528
BOOL freerdp_certificate_verify(const rdpCertificate* cert, const char* certificate_store_path)
1529
0
{
1530
0
  WINPR_ASSERT(cert);
1531
0
  return x509_utils_verify(cert->x509, cert->chain, certificate_store_path);
1532
0
}
1533
1534
char** freerdp_certificate_get_dns_names(const rdpCertificate* cert, size_t* pcount,
1535
                                         size_t** pplengths)
1536
0
{
1537
0
  WINPR_ASSERT(cert);
1538
0
  return x509_utils_get_dns_names(cert->x509, pcount, pplengths);
1539
0
}
1540
1541
char* freerdp_certificate_get_common_name(const rdpCertificate* cert, size_t* plength)
1542
0
{
1543
0
  WINPR_ASSERT(cert);
1544
0
  return x509_utils_get_common_name(cert->x509, plength);
1545
0
}
1546
1547
WINPR_MD_TYPE freerdp_certificate_get_signature_alg(const rdpCertificate* cert)
1548
0
{
1549
0
  WINPR_ASSERT(cert);
1550
0
  return x509_utils_get_signature_alg(cert->x509);
1551
0
}
1552
1553
void freerdp_certificate_free_dns_names(size_t count, size_t* lengths, char** names)
1554
0
{
1555
0
  x509_utils_dns_names_free(count, lengths, names);
1556
0
}
1557
1558
char* freerdp_certificate_get_hash(const rdpCertificate* cert, const char* hash, size_t* plength)
1559
0
{
1560
0
  WINPR_ASSERT(cert);
1561
0
  return (char*)x509_utils_get_hash(cert->x509, hash, plength);
1562
0
}
1563
1564
X509* freerdp_certificate_get_x509(rdpCertificate* cert)
1565
0
{
1566
0
  WINPR_ASSERT(cert);
1567
0
  return cert->x509;
1568
0
}
1569
1570
BOOL freerdp_certificate_publickey_encrypt(const rdpCertificate* cert, const BYTE* input,
1571
                                           size_t cbInput, BYTE** poutput, size_t* pcbOutput)
1572
0
{
1573
0
  WINPR_ASSERT(cert);
1574
0
  WINPR_ASSERT(input);
1575
0
  WINPR_ASSERT(poutput);
1576
0
  WINPR_ASSERT(pcbOutput);
1577
1578
0
  BOOL ret = FALSE;
1579
0
  BYTE* output = NULL;
1580
0
  EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1581
0
  if (!pkey)
1582
0
    return FALSE;
1583
1584
0
  EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
1585
0
  if (!ctx)
1586
0
    return FALSE;
1587
1588
0
  size_t outputSize = EVP_PKEY_size(pkey);
1589
0
  output = malloc(outputSize);
1590
0
  *pcbOutput = outputSize;
1591
1592
0
  if (EVP_PKEY_encrypt_init(ctx) != 1 ||
1593
0
      EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) != 1 ||
1594
0
      EVP_PKEY_encrypt(ctx, output, pcbOutput, input, cbInput) != 1)
1595
0
  {
1596
0
    WLog_ERR(TAG, "error when setting up public key");
1597
0
    goto out;
1598
0
  }
1599
1600
0
  *poutput = output;
1601
0
  output = NULL;
1602
0
  ret = TRUE;
1603
0
out:
1604
0
  EVP_PKEY_CTX_free(ctx);
1605
0
  free(output);
1606
0
  return ret;
1607
0
}
1608
1609
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1610
static RSA* freerdp_certificate_get_RSA(const rdpCertificate* cert)
1611
0
{
1612
0
  WINPR_ASSERT(cert);
1613
1614
0
  if (!freerdp_certificate_is_rsa(cert))
1615
0
    return NULL;
1616
1617
0
  EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1618
0
  if (!pubkey)
1619
0
    return NULL;
1620
1621
0
  return EVP_PKEY_get1_RSA(pubkey);
1622
0
}
1623
#endif
1624
1625
BYTE* freerdp_certificate_get_der(const rdpCertificate* cert, size_t* pLength)
1626
0
{
1627
0
  WINPR_ASSERT(cert);
1628
1629
0
  if (pLength)
1630
0
    *pLength = 0;
1631
1632
0
  const int rc = i2d_X509(cert->x509, NULL);
1633
0
  if (rc <= 0)
1634
0
    return NULL;
1635
1636
0
  BYTE* ptr = calloc(rc + 1, sizeof(BYTE));
1637
0
  if (!ptr)
1638
0
    return NULL;
1639
0
  BYTE* i2d_ptr = ptr;
1640
1641
0
  const int rc2 = i2d_X509(cert->x509, &i2d_ptr);
1642
0
  if (rc2 <= 0)
1643
0
  {
1644
0
    free(ptr);
1645
0
    return NULL;
1646
0
  }
1647
1648
0
  if (pLength)
1649
0
    *pLength = (size_t)rc2;
1650
0
  return ptr;
1651
0
}
1652
1653
BOOL freerdp_certificate_is_rsa(const rdpCertificate* cert)
1654
0
{
1655
0
  WINPR_ASSERT(cert);
1656
0
  return is_rsa_key(cert->x509);
1657
0
}
1658
1659
BOOL freerdp_certificate_is_rdp_security_compatible(const rdpCertificate* cert)
1660
0
{
1661
0
  const rdpCertInfo* info = freerdp_certificate_get_info(cert);
1662
0
  if (!freerdp_certificate_is_rsa(cert) || !info || (info->ModulusLength != 2048 / 8))
1663
0
  {
1664
0
    WLog_INFO(TAG, "certificate is not RSA 2048, RDP security not supported.");
1665
0
    return FALSE;
1666
0
  }
1667
0
  return TRUE;
1668
0
}
1669
1670
char* freerdp_certificate_get_param(const rdpCertificate* cert, enum FREERDP_CERT_PARAM what,
1671
                                    size_t* psize)
1672
0
{
1673
0
  WINPR_ASSERT(cert);
1674
0
  WINPR_ASSERT(psize);
1675
1676
0
  *psize = 0;
1677
1678
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1679
0
  const BIGNUM* bn = NULL;
1680
0
  RSA* rsa = freerdp_certificate_get_RSA(cert);
1681
0
  switch (what)
1682
0
  {
1683
0
    case FREERDP_CERT_RSA_E:
1684
0
      RSA_get0_key(rsa, NULL, &bn, NULL);
1685
0
      break;
1686
0
    case FREERDP_CERT_RSA_N:
1687
0
      RSA_get0_key(rsa, &bn, NULL, NULL);
1688
0
      break;
1689
0
    default:
1690
0
      RSA_free(rsa);
1691
0
      return NULL;
1692
0
  }
1693
0
  RSA_free(rsa);
1694
#else
1695
  EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1696
  if (!pkey)
1697
    return NULL;
1698
1699
  BIGNUM* bn = NULL;
1700
  switch (what)
1701
  {
1702
    case FREERDP_CERT_RSA_E:
1703
      if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn))
1704
        return NULL;
1705
      break;
1706
    case FREERDP_CERT_RSA_N:
1707
      if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn))
1708
        return NULL;
1709
      break;
1710
    default:
1711
      return NULL;
1712
  }
1713
#endif
1714
1715
0
  const size_t bnsize = BN_num_bytes(bn);
1716
0
  char* rc = calloc(bnsize + 1, sizeof(char));
1717
0
  if (!rc)
1718
0
    goto fail;
1719
0
  BN_bn2bin(bn, (BYTE*)rc);
1720
0
  *psize = bnsize;
1721
1722
0
fail:
1723
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR < 3)
1724
  BN_free(bn);
1725
#endif
1726
0
  return rc;
1727
0
}