Coverage Report

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