Coverage Report

Created: 2023-11-19 06:16

/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
35
{
285
35
  EVP_PKEY* evp = X509_get0_pubkey(x509);
286
35
  if (!evp)
287
5
    return FALSE;
288
289
30
  return (EVP_PKEY_id(evp) == EVP_PKEY_RSA);
290
35
}
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
36
{
459
36
  if (!x509_cert_chain)
460
0
    return;
461
462
36
  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
36
  free(x509_cert_chain->array);
472
36
}
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 cert certificate module
923
 * @param s stream
924
 * @return \b TRUE for success, \b FALSE otherwise.
925
 */
926
927
static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* cert, wStream* s)
928
0
{
929
0
  UINT32 numCertBlobs = 0;
930
0
  DEBUG_CERTIFICATE("Server X.509 Certificate Chain");
931
932
0
  WINPR_ASSERT(cert);
933
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
934
0
    return FALSE;
935
936
0
  Stream_Read_UINT32(s, numCertBlobs); /* numCertBlobs */
937
0
  certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
938
0
  cert->x509_cert_chain = certificate_new_x509_certificate_chain(numCertBlobs);
939
940
0
  for (UINT32 i = 0; i < cert->x509_cert_chain.count; i++)
941
0
  {
942
0
    rdpCertBlob* blob = &cert->x509_cert_chain.array[i];
943
0
    if (!cert_blob_read(blob, s))
944
0
      return FALSE;
945
946
0
    if (numCertBlobs - i == 1)
947
0
    {
948
0
      DEBUG_CERTIFICATE("Terminal Server Certificate");
949
950
0
      BOOL res = certificate_read_x509_certificate(blob, &cert->cert_info);
951
952
0
      if (res)
953
0
      {
954
0
        if (!update_x509_from_info(cert))
955
0
          res = FALSE;
956
0
      }
957
958
0
      if (!res)
959
0
      {
960
0
        return FALSE;
961
0
      }
962
963
0
      DEBUG_CERTIFICATE("modulus length:%" PRIu32 "", cert->cert_info.ModulusLength);
964
0
    }
965
0
  }
966
967
0
  return update_x509_from_info(cert);
968
0
}
969
970
static BOOL certificate_write_server_x509_certificate_chain(const rdpCertificate* certificate,
971
                                                            wStream* s)
972
0
{
973
0
  UINT32 numCertBlobs = 0;
974
0
975
0
  WINPR_ASSERT(certificate);
976
0
  WINPR_ASSERT(s);
977
0
978
0
  numCertBlobs = certificate->x509_cert_chain.count;
979
0
980
0
  if (!Stream_EnsureRemainingCapacity(s, 4))
981
0
    return FALSE;
982
0
  Stream_Write_UINT32(s, numCertBlobs); /* numCertBlobs */
983
0
984
0
  for (UINT32 i = 0; i < numCertBlobs; i++)
985
0
  {
986
0
    const rdpCertBlob* cert = &certificate->x509_cert_chain.array[i];
987
0
    if (!cert_blob_write(cert, s))
988
0
      return FALSE;
989
0
  }
990
0
991
0
  return TRUE;
992
0
}
993
994
/**
995
 * Read a Server Certificate.
996
 * @param certificate certificate module
997
 * @param server_cert server certificate
998
 * @param length certificate length
999
 */
1000
1001
BOOL freerdp_certificate_read_server_cert(rdpCertificate* certificate, const BYTE* server_cert,
1002
                                          size_t length)
1003
0
{
1004
0
  BOOL ret = FALSE;
1005
0
  wStream *s, sbuffer;
1006
0
  UINT32 dwVersion = 0;
1007
1008
0
  WINPR_ASSERT(certificate);
1009
0
  if (length < 4) /* NULL certificate is not an error see #1795 */
1010
0
    return TRUE;
1011
1012
0
  WINPR_ASSERT(server_cert);
1013
0
  s = Stream_StaticConstInit(&sbuffer, server_cert, length);
1014
1015
0
  if (!s)
1016
0
  {
1017
0
    WLog_ERR(TAG, "Stream_New failed!");
1018
0
    return FALSE;
1019
0
  }
1020
1021
0
  Stream_Read_UINT32(s, dwVersion); /* dwVersion (4 bytes) */
1022
1023
0
  switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1024
0
  {
1025
0
    case CERT_CHAIN_VERSION_1:
1026
0
      ret = certificate_read_server_proprietary_certificate(certificate, s);
1027
0
      break;
1028
1029
0
    case CERT_CHAIN_VERSION_2:
1030
0
      ret = certificate_read_server_x509_certificate_chain(certificate, s);
1031
0
      break;
1032
1033
0
    default:
1034
0
      WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
1035
0
               dwVersion & CERT_CHAIN_VERSION_MASK);
1036
0
      ret = FALSE;
1037
0
      break;
1038
0
  }
1039
1040
0
  return ret;
1041
0
}
1042
1043
static BOOL cert_blob_copy(rdpCertBlob* dst, const rdpCertBlob* src)
1044
0
{
1045
0
  WINPR_ASSERT(dst);
1046
0
  WINPR_ASSERT(src);
1047
1048
0
  cert_blob_free(dst);
1049
0
  if (src->length > 0)
1050
0
  {
1051
0
    dst->data = malloc(src->length);
1052
0
    if (!dst->data)
1053
0
      return FALSE;
1054
0
    dst->length = src->length;
1055
0
    memcpy(dst->data, src->data, src->length);
1056
0
  }
1057
1058
0
  return TRUE;
1059
0
}
1060
1061
static BOOL cert_x509_chain_copy(rdpX509CertChain* cert, const rdpX509CertChain* src)
1062
0
{
1063
0
  WINPR_ASSERT(cert);
1064
1065
0
  certificate_free_x509_certificate_chain(cert);
1066
0
  if (!src)
1067
0
    return TRUE;
1068
1069
0
  if (src->count > 0)
1070
0
  {
1071
0
    cert->array = calloc(src->count, sizeof(rdpCertBlob));
1072
0
    if (!cert->array)
1073
0
    {
1074
0
      return FALSE;
1075
0
    }
1076
0
    cert->count = src->count;
1077
1078
0
    for (UINT32 x = 0; x < cert->count; x++)
1079
0
    {
1080
0
      const rdpCertBlob* srcblob = &src->array[x];
1081
0
      rdpCertBlob* dstblob = &cert->array[x];
1082
1083
0
      if (!cert_blob_copy(dstblob, srcblob))
1084
0
      {
1085
0
        certificate_free_x509_certificate_chain(cert);
1086
0
        return FALSE;
1087
0
      }
1088
0
    }
1089
0
  }
1090
1091
0
  return TRUE;
1092
0
}
1093
1094
BOOL cert_clone_int(rdpCertificate* dst, const rdpCertificate* src)
1095
0
{
1096
0
  WINPR_ASSERT(dst);
1097
0
  WINPR_ASSERT(src);
1098
1099
0
  if (src->x509)
1100
0
  {
1101
0
    dst->x509 = X509_dup(src->x509);
1102
0
    if (!dst->x509)
1103
0
      return FALSE;
1104
0
  }
1105
1106
0
  if (!cert_info_clone(&dst->cert_info, &src->cert_info))
1107
0
    return FALSE;
1108
0
  return cert_x509_chain_copy(&dst->x509_cert_chain, &src->x509_cert_chain);
1109
0
}
1110
1111
rdpCertificate* freerdp_certificate_clone(const rdpCertificate* certificate)
1112
0
{
1113
0
  if (!certificate)
1114
0
    return NULL;
1115
1116
0
  rdpCertificate* _certificate = freerdp_certificate_new();
1117
1118
0
  if (!_certificate)
1119
0
    return NULL;
1120
1121
0
  if (!cert_clone_int(_certificate, certificate))
1122
0
    goto out_fail;
1123
1124
0
  return _certificate;
1125
0
out_fail:
1126
1127
0
  freerdp_certificate_free(_certificate);
1128
0
  return NULL;
1129
0
}
1130
1131
/**
1132
 * Instantiate new certificate module.
1133
 * @return new certificate module
1134
 */
1135
1136
rdpCertificate* freerdp_certificate_new(void)
1137
36
{
1138
36
  return (rdpCertificate*)calloc(1, sizeof(rdpCertificate));
1139
36
}
1140
1141
void certificate_free_int(rdpCertificate* cert)
1142
36
{
1143
36
  WINPR_ASSERT(cert);
1144
1145
36
  if (cert->x509)
1146
35
    X509_free(cert->x509);
1147
36
  if (cert->chain)
1148
0
    sk_X509_free(cert->chain);
1149
1150
36
  certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1151
36
  cert_info_free(&cert->cert_info);
1152
36
}
1153
1154
/**
1155
 * Free certificate module.
1156
 * @param cert certificate module to be freed
1157
 */
1158
1159
void freerdp_certificate_free(rdpCertificate* cert)
1160
787
{
1161
787
  if (!cert)
1162
751
    return;
1163
1164
36
  certificate_free_int(cert);
1165
36
  free(cert);
1166
36
}
1167
1168
static BOOL freerdp_rsa_from_x509(rdpCertificate* cert)
1169
35
{
1170
35
  BOOL rc = FALSE;
1171
1172
35
  WINPR_ASSERT(cert);
1173
1174
35
  if (!freerdp_certificate_is_rsa(cert))
1175
6
    return TRUE;
1176
1177
29
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1178
29
  RSA* rsa = NULL;
1179
29
  const BIGNUM* rsa_n = NULL;
1180
29
  const BIGNUM* rsa_e = NULL;
1181
#else
1182
  BIGNUM* rsa_n = NULL;
1183
  BIGNUM* rsa_e = NULL;
1184
#endif
1185
29
  EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1186
29
  if (!pubkey)
1187
0
    goto fail;
1188
1189
29
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1190
29
  rsa = EVP_PKEY_get1_RSA(pubkey);
1191
1192
  /* If this is not a RSA key return success */
1193
29
  rc = TRUE;
1194
29
  if (!rsa)
1195
0
    goto fail;
1196
1197
  /* Now we return failure again if something is wrong. */
1198
29
  rc = FALSE;
1199
1200
29
  RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
1201
#else
1202
  if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &rsa_e))
1203
    goto fail;
1204
  if (!EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &rsa_n))
1205
    goto fail;
1206
#endif
1207
29
  if (!rsa_n || !rsa_e)
1208
0
    goto fail;
1209
29
  if (!cert_info_create(&cert->cert_info, rsa_n, rsa_e))
1210
13
    goto fail;
1211
16
  rc = TRUE;
1212
29
fail:
1213
29
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1214
29
  RSA_free(rsa);
1215
#else
1216
  BN_free(rsa_n);
1217
  BN_free(rsa_e);
1218
#endif
1219
29
  return rc;
1220
16
}
1221
1222
rdpCertificate* freerdp_certificate_new_from_der(const BYTE* data, size_t length)
1223
0
{
1224
0
  rdpCertificate* cert = freerdp_certificate_new();
1225
1226
0
  if (!cert || !data || (length == 0))
1227
0
    goto fail;
1228
0
  const BYTE* ptr = data;
1229
0
  cert->x509 = d2i_X509(NULL, &ptr, length);
1230
0
  if (!cert->x509)
1231
0
    goto fail;
1232
0
  if (!freerdp_rsa_from_x509(cert))
1233
0
    goto fail;
1234
0
  return cert;
1235
0
fail:
1236
0
  freerdp_certificate_free(cert);
1237
0
  return NULL;
1238
0
}
1239
1240
rdpCertificate* freerdp_certificate_new_from_x509(const X509* xcert, const STACK_OF(X509) * chain)
1241
36
{
1242
36
  WINPR_ASSERT(xcert);
1243
1244
36
  rdpCertificate* cert = freerdp_certificate_new();
1245
36
  if (!cert)
1246
0
    return NULL;
1247
1248
36
  cert->x509 = X509_dup(xcert);
1249
36
  if (!cert->x509)
1250
1
    goto fail;
1251
1252
35
  if (!freerdp_rsa_from_x509(cert))
1253
13
    goto fail;
1254
1255
22
  if (chain)
1256
0
  {
1257
0
    cert->chain = sk_X509_dup(chain);
1258
0
  }
1259
22
  return cert;
1260
14
fail:
1261
14
  freerdp_certificate_free(cert);
1262
14
  return NULL;
1263
35
}
1264
1265
static rdpCertificate* freerdp_certificate_new_from(const char* file, BOOL isFile)
1266
773
{
1267
773
  X509* x509 = x509_utils_from_pem(file, strlen(file), isFile);
1268
773
  if (!x509)
1269
737
    return NULL;
1270
36
  rdpCertificate* cert = freerdp_certificate_new_from_x509(x509, NULL);
1271
36
  X509_free(x509);
1272
36
  return cert;
1273
773
}
1274
1275
rdpCertificate* freerdp_certificate_new_from_file(const char* file)
1276
0
{
1277
0
  return freerdp_certificate_new_from(file, TRUE);
1278
0
}
1279
1280
rdpCertificate* freerdp_certificate_new_from_pem(const char* pem)
1281
773
{
1282
773
  return freerdp_certificate_new_from(pem, FALSE);
1283
773
}
1284
1285
const rdpCertInfo* freerdp_certificate_get_info(const rdpCertificate* cert)
1286
0
{
1287
0
  WINPR_ASSERT(cert);
1288
0
  if (!freerdp_certificate_is_rsa(cert))
1289
0
    return NULL;
1290
0
  return &cert->cert_info;
1291
0
}
1292
1293
char* freerdp_certificate_get_fingerprint(const rdpCertificate* cert)
1294
22
{
1295
22
  return freerdp_certificate_get_fingerprint_by_hash(cert, "sha256");
1296
22
}
1297
1298
char* freerdp_certificate_get_fingerprint_by_hash(const rdpCertificate* cert, const char* hash)
1299
22
{
1300
22
  return freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, TRUE);
1301
22
}
1302
1303
char* freerdp_certificate_get_fingerprint_by_hash_ex(const rdpCertificate* cert, const char* hash,
1304
                                                     BOOL separator)
1305
22
{
1306
22
  size_t fp_len = 0;
1307
22
  size_t pos = 0;
1308
22
  size_t size = 0;
1309
22
  BYTE* fp = NULL;
1310
22
  char* fp_buffer = NULL;
1311
22
  if (!cert || !cert->x509)
1312
0
  {
1313
0
    WLog_ERR(TAG, "Invalid certificate [%p, %p]", cert, cert ? cert->x509 : NULL);
1314
0
    return NULL;
1315
0
  }
1316
22
  if (!hash)
1317
0
  {
1318
0
    WLog_ERR(TAG, "Invalid certificate hash %p", hash);
1319
0
    return NULL;
1320
0
  }
1321
22
  fp = x509_utils_get_hash(cert->x509, hash, &fp_len);
1322
22
  if (!fp)
1323
0
    return NULL;
1324
1325
22
  size = fp_len * 3 + 1;
1326
22
  fp_buffer = calloc(size, sizeof(char));
1327
22
  if (!fp_buffer)
1328
0
    goto fail;
1329
1330
22
  pos = 0;
1331
1332
22
  size_t i = 0;
1333
704
  for (i = 0; i < (fp_len - 1); i++)
1334
682
  {
1335
682
    int rc;
1336
682
    char* p = &fp_buffer[pos];
1337
682
    if (separator)
1338
682
      rc = sprintf_s(p, size - pos, "%02" PRIx8 ":", fp[i]);
1339
0
    else
1340
0
      rc = sprintf_s(p, size - pos, "%02" PRIx8, fp[i]);
1341
682
    if (rc <= 0)
1342
0
      goto fail;
1343
682
    pos += (size_t)rc;
1344
682
  }
1345
1346
22
  sprintf_s(&fp_buffer[pos], size - pos, "%02" PRIx8 "", fp[i]);
1347
1348
22
  free(fp);
1349
1350
22
  return fp_buffer;
1351
0
fail:
1352
0
  free(fp);
1353
0
  free(fp_buffer);
1354
0
  return NULL;
1355
22
}
1356
1357
static BOOL bio_read_pem(BIO* bio, char** ppem, size_t* plength)
1358
22
{
1359
22
  BOOL rc = FALSE;
1360
1361
22
  WINPR_ASSERT(bio);
1362
22
  WINPR_ASSERT(ppem);
1363
1364
22
  size_t offset = 0;
1365
22
  size_t length = 2048;
1366
22
  char* pem = NULL;
1367
22
  while (offset < length)
1368
22
  {
1369
22
    char* tmp = realloc(pem, length + 1);
1370
22
    if (!tmp)
1371
0
      goto fail;
1372
22
    pem = tmp;
1373
1374
22
    ERR_clear_error();
1375
1376
22
    const int status = BIO_read(bio, &pem[offset], length - offset);
1377
22
    if (status < 0)
1378
0
    {
1379
0
      WLog_ERR(TAG, "failed to read certificate");
1380
0
      goto fail;
1381
0
    }
1382
1383
22
    if (status == 0)
1384
0
      break;
1385
1386
22
    offset += (size_t)status;
1387
22
    if (length - offset > 0)
1388
22
      break;
1389
0
    length *= 2;
1390
0
  }
1391
22
  pem[offset] = '\0';
1392
22
  *ppem = pem;
1393
22
  if (plength)
1394
22
    *plength = offset;
1395
22
  rc = TRUE;
1396
22
fail:
1397
22
  return rc;
1398
22
}
1399
1400
char* freerdp_certificate_get_pem(const rdpCertificate* cert, size_t* pLength)
1401
22
{
1402
22
  char* pem = NULL;
1403
22
  WINPR_ASSERT(cert);
1404
1405
22
  if (!cert->x509)
1406
0
    return NULL;
1407
1408
22
  BIO* bio;
1409
22
  int status;
1410
1411
  /**
1412
   * Don't manage certificates internally, leave it up entirely to the external client
1413
   * implementation
1414
   */
1415
22
  bio = BIO_new(BIO_s_mem());
1416
1417
22
  if (!bio)
1418
0
  {
1419
0
    WLog_ERR(TAG, "BIO_new() failure");
1420
0
    return NULL;
1421
0
  }
1422
1423
22
  status = PEM_write_bio_X509(bio, cert->x509);
1424
1425
22
  if (status < 0)
1426
0
  {
1427
0
    WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
1428
0
    goto fail;
1429
0
  }
1430
1431
#if 0
1432
        if (chain)
1433
        {
1434
            count = sk_X509_num(chain);
1435
            for (x = 0; x < count; x++)
1436
            {
1437
                X509* c = sk_X509_value(chain, x);
1438
                status = PEM_write_bio_X509(bio, c);
1439
                if (status < 0)
1440
                {
1441
                    WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
1442
                    goto fail;
1443
                }
1444
            }
1445
        }
1446
#endif
1447
22
  if (!bio_read_pem(bio, &pem, pLength))
1448
0
    goto fail;
1449
22
fail:
1450
22
  BIO_free_all(bio);
1451
22
  return pem;
1452
22
}
1453
1454
char* freerdp_certificate_get_subject(const rdpCertificate* cert)
1455
22
{
1456
22
  WINPR_ASSERT(cert);
1457
22
  return x509_utils_get_subject(cert->x509);
1458
22
}
1459
1460
char* freerdp_certificate_get_issuer(const rdpCertificate* cert)
1461
22
{
1462
22
  WINPR_ASSERT(cert);
1463
22
  return x509_utils_get_issuer(cert->x509);
1464
22
}
1465
1466
char* freerdp_certificate_get_upn(const rdpCertificate* cert)
1467
0
{
1468
0
  WINPR_ASSERT(cert);
1469
0
  return x509_utils_get_upn(cert->x509);
1470
0
}
1471
1472
char* freerdp_certificate_get_email(const rdpCertificate* cert)
1473
0
{
1474
0
  WINPR_ASSERT(cert);
1475
0
  return x509_utils_get_email(cert->x509);
1476
0
}
1477
1478
BOOL freerdp_certificate_check_eku(const rdpCertificate* cert, int nid)
1479
0
{
1480
0
  WINPR_ASSERT(cert);
1481
0
  return x509_utils_check_eku(cert->x509, nid);
1482
0
}
1483
1484
BOOL freerdp_certificate_get_public_key(const rdpCertificate* cert, BYTE** PublicKey,
1485
                                        DWORD* PublicKeyLength)
1486
0
{
1487
0
  BYTE* ptr = NULL;
1488
0
  BYTE* optr = NULL;
1489
0
  int length;
1490
0
  BOOL status = FALSE;
1491
0
  EVP_PKEY* pkey = NULL;
1492
1493
0
  WINPR_ASSERT(cert);
1494
1495
0
  pkey = X509_get0_pubkey(cert->x509);
1496
1497
0
  if (!pkey)
1498
0
  {
1499
0
    WLog_ERR(TAG, "X509_get_pubkey() failed");
1500
0
    goto exit;
1501
0
  }
1502
1503
0
  length = i2d_PublicKey(pkey, NULL);
1504
1505
0
  if (length < 1)
1506
0
  {
1507
0
    WLog_ERR(TAG, "i2d_PublicKey() failed");
1508
0
    goto exit;
1509
0
  }
1510
1511
0
  *PublicKey = optr = ptr = (BYTE*)calloc(length, sizeof(BYTE));
1512
1513
0
  if (!ptr)
1514
0
    goto exit;
1515
1516
0
  const int length2 = i2d_PublicKey(pkey, &ptr);
1517
0
  if (length != length2)
1518
0
    goto exit;
1519
0
  *PublicKeyLength = (DWORD)length2;
1520
0
  status = TRUE;
1521
0
exit:
1522
1523
0
  if (!status)
1524
0
    free(optr);
1525
1526
0
  return status;
1527
0
}
1528
1529
BOOL freerdp_certificate_verify(const rdpCertificate* cert, const char* certificate_store_path)
1530
0
{
1531
0
  WINPR_ASSERT(cert);
1532
0
  return x509_utils_verify(cert->x509, cert->chain, certificate_store_path);
1533
0
}
1534
1535
char** freerdp_certificate_get_dns_names(const rdpCertificate* cert, size_t* pcount,
1536
                                         size_t** pplengths)
1537
0
{
1538
0
  WINPR_ASSERT(cert);
1539
0
  return x509_utils_get_dns_names(cert->x509, pcount, pplengths);
1540
0
}
1541
1542
char* freerdp_certificate_get_common_name(const rdpCertificate* cert, size_t* plength)
1543
0
{
1544
0
  WINPR_ASSERT(cert);
1545
0
  return x509_utils_get_common_name(cert->x509, plength);
1546
0
}
1547
1548
WINPR_MD_TYPE freerdp_certificate_get_signature_alg(const rdpCertificate* cert)
1549
0
{
1550
0
  WINPR_ASSERT(cert);
1551
0
  return x509_utils_get_signature_alg(cert->x509);
1552
0
}
1553
1554
void freerdp_certificate_free_dns_names(size_t count, size_t* lengths, char** names)
1555
0
{
1556
0
  x509_utils_dns_names_free(count, lengths, names);
1557
0
}
1558
1559
char* freerdp_certificate_get_hash(const rdpCertificate* cert, const char* hash, size_t* plength)
1560
0
{
1561
0
  WINPR_ASSERT(cert);
1562
0
  return (char*)x509_utils_get_hash(cert->x509, hash, plength);
1563
0
}
1564
1565
X509* freerdp_certificate_get_x509(rdpCertificate* cert)
1566
0
{
1567
0
  WINPR_ASSERT(cert);
1568
0
  return cert->x509;
1569
0
}
1570
1571
BOOL freerdp_certificate_publickey_encrypt(const rdpCertificate* cert, const BYTE* input,
1572
                                           size_t cbInput, BYTE** poutput, size_t* pcbOutput)
1573
0
{
1574
0
  WINPR_ASSERT(cert);
1575
0
  WINPR_ASSERT(input);
1576
0
  WINPR_ASSERT(poutput);
1577
0
  WINPR_ASSERT(pcbOutput);
1578
1579
0
  BOOL ret = FALSE;
1580
0
  BYTE* output = NULL;
1581
0
  EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1582
0
  if (!pkey)
1583
0
    return FALSE;
1584
1585
0
  EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
1586
0
  if (!ctx)
1587
0
    return FALSE;
1588
1589
0
  size_t outputSize = EVP_PKEY_size(pkey);
1590
0
  output = malloc(outputSize);
1591
0
  *pcbOutput = outputSize;
1592
1593
0
  if (EVP_PKEY_encrypt_init(ctx) != 1 ||
1594
0
      EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) != 1 ||
1595
0
      EVP_PKEY_encrypt(ctx, output, pcbOutput, input, cbInput) != 1)
1596
0
  {
1597
0
    WLog_ERR(TAG, "error when setting up public key");
1598
0
    goto out;
1599
0
  }
1600
1601
0
  *poutput = output;
1602
0
  output = NULL;
1603
0
  ret = TRUE;
1604
0
out:
1605
0
  EVP_PKEY_CTX_free(ctx);
1606
0
  free(output);
1607
0
  return ret;
1608
0
}
1609
1610
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1611
static RSA* freerdp_certificate_get_RSA(const rdpCertificate* cert)
1612
0
{
1613
0
  WINPR_ASSERT(cert);
1614
1615
0
  if (!freerdp_certificate_is_rsa(cert))
1616
0
    return NULL;
1617
1618
0
  EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1619
0
  if (!pubkey)
1620
0
    return NULL;
1621
1622
0
  return EVP_PKEY_get1_RSA(pubkey);
1623
0
}
1624
#endif
1625
1626
BYTE* freerdp_certificate_get_der(const rdpCertificate* cert, size_t* pLength)
1627
0
{
1628
0
  WINPR_ASSERT(cert);
1629
1630
0
  if (pLength)
1631
0
    *pLength = 0;
1632
1633
0
  const int rc = i2d_X509(cert->x509, NULL);
1634
0
  if (rc <= 0)
1635
0
    return NULL;
1636
1637
0
  BYTE* ptr = calloc(rc + 1, sizeof(BYTE));
1638
0
  if (!ptr)
1639
0
    return NULL;
1640
0
  BYTE* i2d_ptr = ptr;
1641
1642
0
  const int rc2 = i2d_X509(cert->x509, &i2d_ptr);
1643
0
  if (rc2 <= 0)
1644
0
  {
1645
0
    free(ptr);
1646
0
    return NULL;
1647
0
  }
1648
1649
0
  if (pLength)
1650
0
    *pLength = (size_t)rc2;
1651
0
  return ptr;
1652
0
}
1653
1654
BOOL freerdp_certificate_is_rsa(const rdpCertificate* cert)
1655
35
{
1656
35
  WINPR_ASSERT(cert);
1657
35
  return is_rsa_key(cert->x509);
1658
35
}
1659
1660
BOOL freerdp_certificate_is_rdp_security_compatible(const rdpCertificate* cert)
1661
0
{
1662
0
  const rdpCertInfo* info = freerdp_certificate_get_info(cert);
1663
0
  if (!freerdp_certificate_is_rsa(cert) || !info || (info->ModulusLength != 2048 / 8))
1664
0
  {
1665
0
    WLog_INFO(TAG, "certificate is not RSA 2048, RDP security not supported.");
1666
0
    return FALSE;
1667
0
  }
1668
0
  return TRUE;
1669
0
}
1670
1671
char* freerdp_certificate_get_param(const rdpCertificate* cert, enum FREERDP_CERT_PARAM what,
1672
                                    size_t* psize)
1673
0
{
1674
0
  WINPR_ASSERT(cert);
1675
0
  WINPR_ASSERT(psize);
1676
1677
0
  *psize = 0;
1678
1679
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1680
0
  const BIGNUM* bn = NULL;
1681
0
  RSA* rsa = freerdp_certificate_get_RSA(cert);
1682
0
  switch (what)
1683
0
  {
1684
0
    case FREERDP_CERT_RSA_E:
1685
0
      RSA_get0_key(rsa, NULL, &bn, NULL);
1686
0
      break;
1687
0
    case FREERDP_CERT_RSA_N:
1688
0
      RSA_get0_key(rsa, &bn, NULL, NULL);
1689
0
      break;
1690
0
    default:
1691
0
      RSA_free(rsa);
1692
0
      return NULL;
1693
0
  }
1694
0
  RSA_free(rsa);
1695
#else
1696
  EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1697
  if (!pkey)
1698
    return NULL;
1699
1700
  BIGNUM* bn = NULL;
1701
  switch (what)
1702
  {
1703
    case FREERDP_CERT_RSA_E:
1704
      if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn))
1705
        return NULL;
1706
      break;
1707
    case FREERDP_CERT_RSA_N:
1708
      if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn))
1709
        return NULL;
1710
      break;
1711
    default:
1712
      return NULL;
1713
  }
1714
#endif
1715
1716
0
  const size_t bnsize = BN_num_bytes(bn);
1717
0
  char* rc = calloc(bnsize + 1, sizeof(char));
1718
0
  if (!rc)
1719
0
    goto fail;
1720
0
  BN_bn2bin(bn, (BYTE*)rc);
1721
0
  *psize = bnsize;
1722
1723
0
fail:
1724
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR < 3)
1725
  BN_free(bn);
1726
#endif
1727
0
  return rc;
1728
0
}