Coverage Report

Created: 2024-09-08 06:20

/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
104
  do                         \
67
104
  {                          \
68
104
  } 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
92
{
231
92
  UINT32 certLength = 0;
232
92
  WINPR_ASSERT(blob);
233
92
  cert_blob_free(blob);
234
235
92
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
236
30
    goto fail;
237
238
62
  Stream_Read_UINT32(s, certLength);
239
240
62
  if (!Stream_CheckAndLogRequiredLength(TAG, s, certLength))
241
13
    goto fail;
242
243
49
  DEBUG_CERTIFICATE("X.509 Certificate length:%" PRIu32 "", certLength);
244
49
  blob->data = (BYTE*)malloc(certLength);
245
246
49
  if (!blob->data)
247
0
    goto fail;
248
249
49
  Stream_Read(s, blob->data, certLength);
250
49
  blob->length = certLength;
251
252
49
  return TRUE;
253
254
43
fail:
255
43
  cert_blob_free(blob);
256
43
  return FALSE;
257
49
}
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
554M
{
273
554M
  if (!blob)
274
0
    return;
275
554M
  free(blob->data);
276
554M
  blob->data = NULL;
277
554M
  blob->length = 0;
278
554M
}
279
280
/**
281
 * Read X.509 Certificate
282
 */
283
284
static BOOL is_rsa_key(const X509* x509)
285
36
{
286
36
  EVP_PKEY* evp = X509_get0_pubkey(x509);
287
36
  if (!evp)
288
4
    return FALSE;
289
290
32
  return (EVP_PKEY_id(evp) == EVP_PKEY_RSA);
291
36
}
292
293
static BOOL certificate_read_x509_certificate(const rdpCertBlob* cert, rdpCertInfo* info)
294
3
{
295
3
  wStream sbuffer = { 0 };
296
3
  wStream* s = NULL;
297
3
  size_t length = 0;
298
3
  BYTE padding = 0;
299
3
  UINT32 version = 0;
300
3
  size_t modulus_length = 0;
301
3
  size_t exponent_length = 0;
302
3
  int error = 0;
303
304
3
  WINPR_ASSERT(cert);
305
3
  WINPR_ASSERT(info);
306
307
3
  cert_info_free(info);
308
309
3
  s = Stream_StaticConstInit(&sbuffer, cert->data, cert->length);
310
311
3
  if (!s)
312
0
    return FALSE;
313
314
3
  if (!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */
315
3
    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
3
error:
429
3
  WLog_ERR(TAG, "error reading when reading certificate: part=%s error=%d",
430
3
           certificate_read_errors[error], error);
431
3
  cert_info_free(info);
432
3
  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
48
{
443
48
  rdpX509CertChain x509_cert_chain = { 0 };
444
445
48
  x509_cert_chain.array = (rdpCertBlob*)calloc(count, sizeof(rdpCertBlob));
446
447
48
  if (x509_cert_chain.array)
448
48
    x509_cert_chain.count = count;
449
450
48
  return x509_cert_chain;
451
48
}
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
92.9k
{
460
92.9k
  if (!x509_cert_chain)
461
0
    return;
462
463
92.9k
  if (x509_cert_chain->array)
464
48
  {
465
554M
    for (UINT32 i = 0; i < x509_cert_chain->count; i++)
466
554M
    {
467
554M
      rdpCertBlob* element = &x509_cert_chain->array[i];
468
554M
      cert_blob_free(element);
469
554M
    }
470
48
  }
471
472
92.9k
  free(x509_cert_chain->array);
473
92.9k
}
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
2
{
509
2
  BOOL rc = FALSE;
510
511
2
  WINPR_ASSERT(cert);
512
513
2
  X509_free(cert->x509);
514
2
  cert->x509 = NULL;
515
516
2
  rdpCertInfo* info = &cert->cert_info;
517
518
2
  BIGNUM* e = BN_new();
519
2
  BIGNUM* mod = BN_new();
520
2
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
521
2
  RSA* rsa = RSA_new();
522
2
  if (!rsa)
523
0
    goto fail;
524
2
#endif
525
526
2
  if (!mod || !e)
527
0
    goto fail;
528
2
  if (!BN_bin2bn(info->Modulus, info->ModulusLength, mod))
529
0
    goto fail;
530
2
  if (!BN_bin2bn(info->exponent, sizeof(info->exponent), e))
531
0
    goto fail;
532
533
2
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
534
2
  const int rec = RSA_set0_key(rsa, mod, e, NULL);
535
2
  if (rec != 1)
536
0
    goto fail;
537
538
2
  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
2
  if (!cert->x509)
569
0
    goto fail;
570
571
2
  rc = TRUE;
572
573
2
fail:
574
2
  if (!rc)
575
2
    WLog_ERR(TAG, "failed to update x509 from rdpCertInfo");
576
577
2
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
578
2
  if (rsa)
579
2
    RSA_free(rsa);
580
0
  else
581
0
#endif
582
0
  {
583
0
    BN_free(mod);
584
0
    BN_free(e);
585
0
  }
586
2
  return rc;
587
2
}
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
81
{
743
81
  UINT32 dwSigAlgId = 0;
744
81
  UINT32 dwKeyAlgId = 0;
745
81
  UINT16 wPublicKeyBlobType = 0;
746
81
  UINT16 wPublicKeyBlobLen = 0;
747
81
  UINT16 wSignatureBlobType = 0;
748
81
  UINT16 wSignatureBlobLen = 0;
749
81
  size_t sigdatalen = 0;
750
751
81
  WINPR_ASSERT(certificate);
752
81
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
753
2
    return FALSE;
754
755
  /* -4, because we need to include dwVersion */
756
79
  const BYTE* sigdata = Stream_PointerAs(s, const BYTE) - 4;
757
79
  Stream_Read_UINT32(s, dwSigAlgId);
758
79
  Stream_Read_UINT32(s, dwKeyAlgId);
759
760
79
  if (!((dwSigAlgId == SIGNATURE_ALG_RSA) && (dwKeyAlgId == KEY_EXCHANGE_ALG_RSA)))
761
76
  {
762
76
    WLog_ERR(TAG,
763
76
             "unsupported signature or key algorithm, dwSigAlgId=%" PRIu32
764
76
             " dwKeyAlgId=%" PRIu32 "",
765
76
             dwSigAlgId, dwKeyAlgId);
766
76
    return FALSE;
767
76
  }
768
769
3
  Stream_Read_UINT16(s, wPublicKeyBlobType);
770
771
3
  if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
772
3
  {
773
3
    WLog_ERR(TAG, "unsupported public key blob type %" PRIu16 "", wPublicKeyBlobType);
774
3
    return FALSE;
775
3
  }
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
52
{
951
52
  UINT32 numCertBlobs = 0;
952
52
  DEBUG_CERTIFICATE("Server X.509 Certificate Chain");
953
954
52
  WINPR_ASSERT(cert);
955
52
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
956
4
    return FALSE;
957
958
48
  Stream_Read_UINT32(s, numCertBlobs); /* numCertBlobs */
959
48
  certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
960
48
  cert->x509_cert_chain = certificate_new_x509_certificate_chain(numCertBlobs);
961
962
94
  for (UINT32 i = 0; i < cert->x509_cert_chain.count; i++)
963
92
  {
964
92
    rdpCertBlob* blob = &cert->x509_cert_chain.array[i];
965
92
    if (!cert_blob_read(blob, s))
966
43
      return FALSE;
967
968
49
    if (numCertBlobs - i == 1)
969
3
    {
970
3
      DEBUG_CERTIFICATE("Terminal Server Certificate");
971
972
3
      BOOL res = certificate_read_x509_certificate(blob, &cert->cert_info);
973
974
3
      if (res)
975
0
      {
976
0
        if (!update_x509_from_info(cert))
977
0
          res = FALSE;
978
0
      }
979
980
3
      if (!res)
981
3
      {
982
3
        WLog_ERR(TAG, "Failed to read x509 certificate");
983
3
        return FALSE;
984
3
      }
985
986
0
      DEBUG_CERTIFICATE("modulus length:%" PRIu32 "", cert->cert_info.ModulusLength);
987
0
    }
988
49
  }
989
990
2
  return update_x509_from_info(cert);
991
48
}
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
140
{
1027
140
  BOOL ret = FALSE;
1028
140
  wStream* s = NULL;
1029
140
  wStream sbuffer;
1030
140
  UINT32 dwVersion = 0;
1031
1032
140
  WINPR_ASSERT(certificate);
1033
140
  if (length < 4) /* NULL certificate is not an error see #1795 */
1034
3
  {
1035
3
    WLog_DBG(TAG, "Received empty certificate, ignoring...");
1036
3
    return TRUE;
1037
3
  }
1038
1039
137
  WINPR_ASSERT(server_cert);
1040
137
  s = Stream_StaticConstInit(&sbuffer, server_cert, length);
1041
1042
137
  if (!s)
1043
0
  {
1044
0
    WLog_ERR(TAG, "Stream_New failed!");
1045
0
    return FALSE;
1046
0
  }
1047
1048
137
  Stream_Read_UINT32(s, dwVersion); /* dwVersion (4 bytes) */
1049
1050
137
  switch (dwVersion & CERT_CHAIN_VERSION_MASK)
1051
137
  {
1052
81
    case CERT_CHAIN_VERSION_1:
1053
81
      ret = certificate_read_server_proprietary_certificate(certificate, s);
1054
81
      break;
1055
1056
52
    case CERT_CHAIN_VERSION_2:
1057
52
      ret = certificate_read_server_x509_certificate_chain(certificate, s);
1058
52
      break;
1059
1060
4
    default:
1061
4
      WLog_ERR(TAG, "invalid certificate chain version:%" PRIu32 "",
1062
4
               dwVersion & CERT_CHAIN_VERSION_MASK);
1063
4
      ret = FALSE;
1064
4
      break;
1065
137
  }
1066
1067
137
  return ret;
1068
137
}
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
13.2k
{
1090
13.2k
  WINPR_ASSERT(cert);
1091
1092
13.2k
  certificate_free_x509_certificate_chain(cert);
1093
13.2k
  if (!src)
1094
0
    return TRUE;
1095
1096
13.2k
  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
13.2k
  return TRUE;
1119
13.2k
}
1120
1121
BOOL cert_clone_int(rdpCertificate* dst, const rdpCertificate* src)
1122
13.2k
{
1123
13.2k
  WINPR_ASSERT(dst);
1124
13.2k
  WINPR_ASSERT(src);
1125
1126
13.2k
  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
13.2k
  if (!cert_info_clone(&dst->cert_info, &src->cert_info))
1134
0
    return FALSE;
1135
13.2k
  return cert_x509_chain_copy(&dst->x509_cert_chain, &src->x509_cert_chain);
1136
13.2k
}
1137
1138
rdpCertificate* freerdp_certificate_clone(const rdpCertificate* certificate)
1139
13.2k
{
1140
13.2k
  if (!certificate)
1141
0
    return NULL;
1142
1143
13.2k
  rdpCertificate* _certificate = freerdp_certificate_new();
1144
1145
13.2k
  if (!_certificate)
1146
0
    return NULL;
1147
1148
13.2k
  if (!cert_clone_int(_certificate, certificate))
1149
0
    goto out_fail;
1150
1151
13.2k
  return _certificate;
1152
0
out_fail:
1153
1154
0
  freerdp_certificate_free(_certificate);
1155
0
  return NULL;
1156
13.2k
}
1157
1158
/**
1159
 * Instantiate new certificate module.
1160
 * @return new certificate module
1161
 */
1162
1163
rdpCertificate* freerdp_certificate_new(void)
1164
79.6k
{
1165
79.6k
  return (rdpCertificate*)calloc(1, sizeof(rdpCertificate));
1166
79.6k
}
1167
1168
void certificate_free_int(rdpCertificate* cert)
1169
79.6k
{
1170
79.6k
  WINPR_ASSERT(cert);
1171
1172
79.6k
  if (cert->x509)
1173
38
    X509_free(cert->x509);
1174
79.6k
  if (cert->chain)
1175
0
    sk_X509_free(cert->chain);
1176
1177
79.6k
  certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1178
79.6k
  cert_info_free(&cert->cert_info);
1179
79.6k
}
1180
1181
/**
1182
 * Free certificate module.
1183
 * @param cert certificate module to be freed
1184
 */
1185
1186
void freerdp_certificate_free(rdpCertificate* cert)
1187
252k
{
1188
252k
  if (!cert)
1189
173k
    return;
1190
1191
79.6k
  certificate_free_int(cert);
1192
79.6k
  free(cert);
1193
79.6k
}
1194
1195
static BOOL freerdp_rsa_from_x509(rdpCertificate* cert)
1196
36
{
1197
36
  BOOL rc = FALSE;
1198
1199
36
  WINPR_ASSERT(cert);
1200
1201
36
  if (!freerdp_certificate_is_rsa(cert))
1202
5
    return TRUE;
1203
1204
31
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1205
31
  RSA* rsa = NULL;
1206
31
  const BIGNUM* rsa_n = NULL;
1207
31
  const BIGNUM* rsa_e = NULL;
1208
#else
1209
  BIGNUM* rsa_n = NULL;
1210
  BIGNUM* rsa_e = NULL;
1211
#endif
1212
31
  EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1213
31
  if (!pubkey)
1214
0
    goto fail;
1215
1216
31
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1217
31
  rsa = EVP_PKEY_get1_RSA(pubkey);
1218
1219
  /* If this is not a RSA key return success */
1220
31
  rc = TRUE;
1221
31
  if (!rsa)
1222
0
    goto fail;
1223
1224
  /* Now we return failure again if something is wrong. */
1225
31
  rc = FALSE;
1226
1227
31
  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
31
  if (!rsa_n || !rsa_e)
1235
0
    goto fail;
1236
31
  if (!cert_info_create(&cert->cert_info, rsa_n, rsa_e))
1237
12
    goto fail;
1238
19
  rc = TRUE;
1239
31
fail:
1240
31
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1241
31
  RSA_free(rsa);
1242
#else
1243
  BN_free(rsa_n);
1244
  BN_free(rsa_e);
1245
#endif
1246
31
  return rc;
1247
19
}
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
37
{
1269
37
  WINPR_ASSERT(xcert);
1270
1271
37
  rdpCertificate* cert = freerdp_certificate_new();
1272
37
  if (!cert)
1273
0
    return NULL;
1274
1275
37
  cert->x509 = X509_dup(xcert);
1276
37
  if (!cert->x509)
1277
1
    goto fail;
1278
1279
36
  if (!freerdp_rsa_from_x509(cert))
1280
12
    goto fail;
1281
1282
24
  if (chain)
1283
0
  {
1284
0
    cert->chain = sk_X509_dup(chain);
1285
0
  }
1286
24
  return cert;
1287
13
fail:
1288
13
  freerdp_certificate_free(cert);
1289
13
  return NULL;
1290
36
}
1291
1292
static rdpCertificate* freerdp_certificate_new_from(const char* file, BOOL isFile)
1293
767
{
1294
767
  X509* x509 = x509_utils_from_pem(file, strlen(file), isFile);
1295
767
  if (!x509)
1296
730
    return NULL;
1297
37
  rdpCertificate* cert = freerdp_certificate_new_from_x509(x509, NULL);
1298
37
  X509_free(x509);
1299
37
  return cert;
1300
767
}
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
767
{
1309
767
  return freerdp_certificate_new_from(pem, FALSE);
1310
767
}
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
24
{
1322
24
  return freerdp_certificate_get_fingerprint_by_hash(cert, "sha256");
1323
24
}
1324
1325
char* freerdp_certificate_get_fingerprint_by_hash(const rdpCertificate* cert, const char* hash)
1326
24
{
1327
24
  return freerdp_certificate_get_fingerprint_by_hash_ex(cert, hash, TRUE);
1328
24
}
1329
1330
char* freerdp_certificate_get_fingerprint_by_hash_ex(const rdpCertificate* cert, const char* hash,
1331
                                                     BOOL separator)
1332
24
{
1333
24
  size_t fp_len = 0;
1334
24
  size_t pos = 0;
1335
24
  size_t size = 0;
1336
24
  BYTE* fp = NULL;
1337
24
  char* fp_buffer = NULL;
1338
24
  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
24
  if (!hash)
1344
0
  {
1345
0
    WLog_ERR(TAG, "Invalid certificate hash %p", hash);
1346
0
    return NULL;
1347
0
  }
1348
24
  fp = x509_utils_get_hash(cert->x509, hash, &fp_len);
1349
24
  if (!fp)
1350
0
    return NULL;
1351
1352
24
  if (fp_len < 1)
1353
0
    goto fail;
1354
1355
24
  size = fp_len * 3 + 1;
1356
24
  fp_buffer = calloc(size, sizeof(char));
1357
24
  if (!fp_buffer)
1358
0
    goto fail;
1359
1360
24
  pos = 0;
1361
1362
24
  size_t i = 0;
1363
768
  for (; i < (fp_len - 1); i++)
1364
744
  {
1365
744
    int rc = 0;
1366
744
    char* p = &fp_buffer[pos];
1367
744
    if (separator)
1368
744
      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
744
    if (rc <= 0)
1372
0
      goto fail;
1373
744
    pos += (size_t)rc;
1374
744
  }
1375
1376
24
  (void)sprintf_s(&fp_buffer[pos], size - pos, "%02" PRIx8 "", fp[i]);
1377
1378
24
  free(fp);
1379
1380
24
  return fp_buffer;
1381
0
fail:
1382
0
  free(fp);
1383
0
  free(fp_buffer);
1384
0
  return NULL;
1385
24
}
1386
1387
static BOOL bio_read_pem(BIO* bio, char** ppem, size_t* plength)
1388
48
{
1389
48
  BOOL rc = FALSE;
1390
1391
48
  WINPR_ASSERT(bio);
1392
48
  WINPR_ASSERT(ppem);
1393
1394
48
  size_t offset = 0;
1395
48
  size_t length = 2048;
1396
48
  char* pem = NULL;
1397
48
  while (offset < length)
1398
48
  {
1399
48
    char* tmp = realloc(pem, length + 1);
1400
48
    if (!tmp)
1401
0
      goto fail;
1402
48
    pem = tmp;
1403
1404
48
    ERR_clear_error();
1405
1406
48
    const int status = BIO_read(bio, &pem[offset], length - offset);
1407
48
    if (status < 0)
1408
0
    {
1409
0
      WLog_ERR(TAG, "failed to read certificate");
1410
0
      goto fail;
1411
0
    }
1412
1413
48
    if (status == 0)
1414
0
      break;
1415
1416
48
    offset += (size_t)status;
1417
48
    if (length - offset > 0)
1418
48
      break;
1419
0
    length *= 2;
1420
0
  }
1421
48
  pem[offset] = '\0';
1422
48
  *ppem = pem;
1423
48
  if (plength)
1424
48
    *plength = offset;
1425
48
  rc = TRUE;
1426
48
fail:
1427
48
  return rc;
1428
48
}
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
48
{
1438
48
  char* pem = NULL;
1439
48
  WINPR_ASSERT(cert);
1440
1441
48
  if (!cert->x509)
1442
0
    return NULL;
1443
1444
48
  BIO* bio = NULL;
1445
48
  int status = 0;
1446
1447
  /**
1448
   * Don't manage certificates internally, leave it up entirely to the external client
1449
   * implementation
1450
   */
1451
48
  bio = BIO_new(BIO_s_mem());
1452
1453
48
  if (!bio)
1454
0
  {
1455
0
    WLog_ERR(TAG, "BIO_new() failure");
1456
0
    return NULL;
1457
0
  }
1458
1459
48
  status = PEM_write_bio_X509(bio, cert->x509);
1460
1461
48
  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
48
  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
48
  if (!bio_read_pem(bio, &pem, pLength))
1483
0
    goto fail;
1484
48
fail:
1485
48
  BIO_free_all(bio);
1486
48
  return pem;
1487
48
}
1488
1489
char* freerdp_certificate_get_subject(const rdpCertificate* cert)
1490
24
{
1491
24
  WINPR_ASSERT(cert);
1492
24
  return x509_utils_get_subject(cert->x509);
1493
24
}
1494
1495
char* freerdp_certificate_get_issuer(const rdpCertificate* cert)
1496
24
{
1497
24
  WINPR_ASSERT(cert);
1498
24
  return x509_utils_get_issuer(cert->x509);
1499
24
}
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
36
{
1699
36
  WINPR_ASSERT(cert);
1700
36
  return is_rsa_key(cert->x509);
1701
36
}
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
}