Coverage Report

Created: 2024-05-20 06:11

/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
36
{
286
36
  EVP_PKEY* evp = X509_get0_pubkey(x509);
287
36
  if (!evp)
288
2
    return FALSE;
289
290
34
  return (EVP_PKEY_id(evp) == EVP_PKEY_RSA);
291
36
}
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
104k
{
460
104k
  if (!x509_cert_chain)
461
0
    return;
462
463
104k
  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
104k
  free(x509_cert_chain->array);
473
104k
}
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
14.9k
{
1090
14.9k
  WINPR_ASSERT(cert);
1091
1092
14.9k
  certificate_free_x509_certificate_chain(cert);
1093
14.9k
  if (!src)
1094
0
    return TRUE;
1095
1096
14.9k
  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
14.9k
  return TRUE;
1119
14.9k
}
1120
1121
BOOL cert_clone_int(rdpCertificate* dst, const rdpCertificate* src)
1122
14.9k
{
1123
14.9k
  WINPR_ASSERT(dst);
1124
14.9k
  WINPR_ASSERT(src);
1125
1126
14.9k
  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
14.9k
  if (!cert_info_clone(&dst->cert_info, &src->cert_info))
1134
0
    return FALSE;
1135
14.9k
  return cert_x509_chain_copy(&dst->x509_cert_chain, &src->x509_cert_chain);
1136
14.9k
}
1137
1138
rdpCertificate* freerdp_certificate_clone(const rdpCertificate* certificate)
1139
14.9k
{
1140
14.9k
  if (!certificate)
1141
0
    return NULL;
1142
1143
14.9k
  rdpCertificate* _certificate = freerdp_certificate_new();
1144
1145
14.9k
  if (!_certificate)
1146
0
    return NULL;
1147
1148
14.9k
  if (!cert_clone_int(_certificate, certificate))
1149
0
    goto out_fail;
1150
1151
14.9k
  return _certificate;
1152
0
out_fail:
1153
1154
0
  freerdp_certificate_free(_certificate);
1155
0
  return NULL;
1156
14.9k
}
1157
1158
/**
1159
 * Instantiate new certificate module.
1160
 * @return new certificate module
1161
 */
1162
1163
rdpCertificate* freerdp_certificate_new(void)
1164
89.8k
{
1165
89.8k
  return (rdpCertificate*)calloc(1, sizeof(rdpCertificate));
1166
89.8k
}
1167
1168
void certificate_free_int(rdpCertificate* cert)
1169
89.8k
{
1170
89.8k
  WINPR_ASSERT(cert);
1171
1172
89.8k
  if (cert->x509)
1173
36
    X509_free(cert->x509);
1174
89.8k
  if (cert->chain)
1175
0
    sk_X509_free(cert->chain);
1176
1177
89.8k
  certificate_free_x509_certificate_chain(&cert->x509_cert_chain);
1178
89.8k
  cert_info_free(&cert->cert_info);
1179
89.8k
}
1180
1181
/**
1182
 * Free certificate module.
1183
 * @param cert certificate module to be freed
1184
 */
1185
1186
void freerdp_certificate_free(rdpCertificate* cert)
1187
285k
{
1188
285k
  if (!cert)
1189
195k
    return;
1190
1191
89.8k
  certificate_free_int(cert);
1192
89.8k
  free(cert);
1193
89.8k
}
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
3
    return TRUE;
1203
1204
33
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1205
33
  RSA* rsa = NULL;
1206
33
  const BIGNUM* rsa_n = NULL;
1207
33
  const BIGNUM* rsa_e = NULL;
1208
#else
1209
  BIGNUM* rsa_n = NULL;
1210
  BIGNUM* rsa_e = NULL;
1211
#endif
1212
33
  EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1213
33
  if (!pubkey)
1214
0
    goto fail;
1215
1216
33
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1217
33
  rsa = EVP_PKEY_get1_RSA(pubkey);
1218
1219
  /* If this is not a RSA key return success */
1220
33
  rc = TRUE;
1221
33
  if (!rsa)
1222
0
    goto fail;
1223
1224
  /* Now we return failure again if something is wrong. */
1225
33
  rc = FALSE;
1226
1227
33
  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
33
  if (!rsa_n || !rsa_e)
1235
0
    goto fail;
1236
33
  if (!cert_info_create(&cert->cert_info, rsa_n, rsa_e))
1237
12
    goto fail;
1238
21
  rc = TRUE;
1239
33
fail:
1240
33
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1241
33
  RSA_free(rsa);
1242
#else
1243
  BN_free(rsa_n);
1244
  BN_free(rsa_e);
1245
#endif
1246
33
  return rc;
1247
21
}
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
776
{
1294
776
  X509* x509 = x509_utils_from_pem(file, strlen(file), isFile);
1295
776
  if (!x509)
1296
739
    return NULL;
1297
37
  rdpCertificate* cert = freerdp_certificate_new_from_x509(x509, NULL);
1298
37
  X509_free(x509);
1299
37
  return cert;
1300
776
}
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
776
{
1309
776
  return freerdp_certificate_new_from(pem, FALSE);
1310
776
}
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
  size = fp_len * 3 + 1;
1353
24
  fp_buffer = calloc(size, sizeof(char));
1354
24
  if (!fp_buffer)
1355
0
    goto fail;
1356
1357
24
  pos = 0;
1358
1359
24
  size_t i = 0;
1360
768
  for (; i < (fp_len - 1); i++)
1361
744
  {
1362
744
    int rc = 0;
1363
744
    char* p = &fp_buffer[pos];
1364
744
    if (separator)
1365
744
      rc = sprintf_s(p, size - pos, "%02" PRIx8 ":", fp[i]);
1366
0
    else
1367
0
      rc = sprintf_s(p, size - pos, "%02" PRIx8, fp[i]);
1368
744
    if (rc <= 0)
1369
0
      goto fail;
1370
744
    pos += (size_t)rc;
1371
744
  }
1372
1373
24
  sprintf_s(&fp_buffer[pos], size - pos, "%02" PRIx8 "", fp[i]);
1374
1375
24
  free(fp);
1376
1377
24
  return fp_buffer;
1378
0
fail:
1379
0
  free(fp);
1380
0
  free(fp_buffer);
1381
0
  return NULL;
1382
24
}
1383
1384
static BOOL bio_read_pem(BIO* bio, char** ppem, size_t* plength)
1385
24
{
1386
24
  BOOL rc = FALSE;
1387
1388
24
  WINPR_ASSERT(bio);
1389
24
  WINPR_ASSERT(ppem);
1390
1391
24
  size_t offset = 0;
1392
24
  size_t length = 2048;
1393
24
  char* pem = NULL;
1394
24
  while (offset < length)
1395
24
  {
1396
24
    char* tmp = realloc(pem, length + 1);
1397
24
    if (!tmp)
1398
0
      goto fail;
1399
24
    pem = tmp;
1400
1401
24
    ERR_clear_error();
1402
1403
24
    const int status = BIO_read(bio, &pem[offset], length - offset);
1404
24
    if (status < 0)
1405
0
    {
1406
0
      WLog_ERR(TAG, "failed to read certificate");
1407
0
      goto fail;
1408
0
    }
1409
1410
24
    if (status == 0)
1411
0
      break;
1412
1413
24
    offset += (size_t)status;
1414
24
    if (length - offset > 0)
1415
24
      break;
1416
0
    length *= 2;
1417
0
  }
1418
24
  pem[offset] = '\0';
1419
24
  *ppem = pem;
1420
24
  if (plength)
1421
24
    *plength = offset;
1422
24
  rc = TRUE;
1423
24
fail:
1424
24
  return rc;
1425
24
}
1426
1427
char* freerdp_certificate_get_pem(const rdpCertificate* cert, size_t* pLength)
1428
24
{
1429
24
  char* pem = NULL;
1430
24
  WINPR_ASSERT(cert);
1431
1432
24
  if (!cert->x509)
1433
0
    return NULL;
1434
1435
24
  BIO* bio = NULL;
1436
24
  int status = 0;
1437
1438
  /**
1439
   * Don't manage certificates internally, leave it up entirely to the external client
1440
   * implementation
1441
   */
1442
24
  bio = BIO_new(BIO_s_mem());
1443
1444
24
  if (!bio)
1445
0
  {
1446
0
    WLog_ERR(TAG, "BIO_new() failure");
1447
0
    return NULL;
1448
0
  }
1449
1450
24
  status = PEM_write_bio_X509(bio, cert->x509);
1451
1452
24
  if (status < 0)
1453
0
  {
1454
0
    WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
1455
0
    goto fail;
1456
0
  }
1457
1458
#if 0
1459
        if (chain)
1460
        {
1461
            int count = sk_X509_num(chain);
1462
            for (int x = 0; x < count; x++)
1463
            {
1464
                X509* c = sk_X509_value(chain, x);
1465
                status = PEM_write_bio_X509(bio, c);
1466
                if (status < 0)
1467
                {
1468
                    WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
1469
                    goto fail;
1470
                }
1471
            }
1472
        }
1473
#endif
1474
24
  if (!bio_read_pem(bio, &pem, pLength))
1475
0
    goto fail;
1476
24
fail:
1477
24
  BIO_free_all(bio);
1478
24
  return pem;
1479
24
}
1480
1481
char* freerdp_certificate_get_subject(const rdpCertificate* cert)
1482
24
{
1483
24
  WINPR_ASSERT(cert);
1484
24
  return x509_utils_get_subject(cert->x509);
1485
24
}
1486
1487
char* freerdp_certificate_get_issuer(const rdpCertificate* cert)
1488
24
{
1489
24
  WINPR_ASSERT(cert);
1490
24
  return x509_utils_get_issuer(cert->x509);
1491
24
}
1492
1493
char* freerdp_certificate_get_upn(const rdpCertificate* cert)
1494
0
{
1495
0
  WINPR_ASSERT(cert);
1496
0
  return x509_utils_get_upn(cert->x509);
1497
0
}
1498
1499
char* freerdp_certificate_get_email(const rdpCertificate* cert)
1500
0
{
1501
0
  WINPR_ASSERT(cert);
1502
0
  return x509_utils_get_email(cert->x509);
1503
0
}
1504
1505
BOOL freerdp_certificate_check_eku(const rdpCertificate* cert, int nid)
1506
0
{
1507
0
  WINPR_ASSERT(cert);
1508
0
  return x509_utils_check_eku(cert->x509, nid);
1509
0
}
1510
1511
BOOL freerdp_certificate_get_public_key(const rdpCertificate* cert, BYTE** PublicKey,
1512
                                        DWORD* PublicKeyLength)
1513
0
{
1514
0
  BYTE* ptr = NULL;
1515
0
  BYTE* optr = NULL;
1516
0
  int length = 0;
1517
0
  BOOL status = FALSE;
1518
0
  EVP_PKEY* pkey = NULL;
1519
1520
0
  WINPR_ASSERT(cert);
1521
1522
0
  pkey = X509_get0_pubkey(cert->x509);
1523
1524
0
  if (!pkey)
1525
0
  {
1526
0
    WLog_ERR(TAG, "X509_get_pubkey() failed");
1527
0
    goto exit;
1528
0
  }
1529
1530
0
  length = i2d_PublicKey(pkey, NULL);
1531
1532
0
  if (length < 1)
1533
0
  {
1534
0
    WLog_ERR(TAG, "i2d_PublicKey() failed");
1535
0
    goto exit;
1536
0
  }
1537
1538
0
  *PublicKey = optr = ptr = (BYTE*)calloc(length, sizeof(BYTE));
1539
1540
0
  if (!ptr)
1541
0
    goto exit;
1542
1543
0
  const int length2 = i2d_PublicKey(pkey, &ptr);
1544
0
  if (length != length2)
1545
0
    goto exit;
1546
0
  *PublicKeyLength = (DWORD)length2;
1547
0
  status = TRUE;
1548
0
exit:
1549
1550
0
  if (!status)
1551
0
    free(optr);
1552
1553
0
  return status;
1554
0
}
1555
1556
BOOL freerdp_certificate_verify(const rdpCertificate* cert, const char* certificate_store_path)
1557
0
{
1558
0
  WINPR_ASSERT(cert);
1559
0
  return x509_utils_verify(cert->x509, cert->chain, certificate_store_path);
1560
0
}
1561
1562
char** freerdp_certificate_get_dns_names(const rdpCertificate* cert, size_t* pcount,
1563
                                         size_t** pplengths)
1564
0
{
1565
0
  WINPR_ASSERT(cert);
1566
0
  return x509_utils_get_dns_names(cert->x509, pcount, pplengths);
1567
0
}
1568
1569
char* freerdp_certificate_get_common_name(const rdpCertificate* cert, size_t* plength)
1570
0
{
1571
0
  WINPR_ASSERT(cert);
1572
0
  return x509_utils_get_common_name(cert->x509, plength);
1573
0
}
1574
1575
WINPR_MD_TYPE freerdp_certificate_get_signature_alg(const rdpCertificate* cert)
1576
0
{
1577
0
  WINPR_ASSERT(cert);
1578
0
  return x509_utils_get_signature_alg(cert->x509);
1579
0
}
1580
1581
void freerdp_certificate_free_dns_names(size_t count, size_t* lengths, char** names)
1582
0
{
1583
0
  x509_utils_dns_names_free(count, lengths, names);
1584
0
}
1585
1586
char* freerdp_certificate_get_hash(const rdpCertificate* cert, const char* hash, size_t* plength)
1587
0
{
1588
0
  WINPR_ASSERT(cert);
1589
0
  return (char*)x509_utils_get_hash(cert->x509, hash, plength);
1590
0
}
1591
1592
X509* freerdp_certificate_get_x509(rdpCertificate* cert)
1593
0
{
1594
0
  WINPR_ASSERT(cert);
1595
0
  return cert->x509;
1596
0
}
1597
1598
BOOL freerdp_certificate_publickey_encrypt(const rdpCertificate* cert, const BYTE* input,
1599
                                           size_t cbInput, BYTE** poutput, size_t* pcbOutput)
1600
0
{
1601
0
  WINPR_ASSERT(cert);
1602
0
  WINPR_ASSERT(input);
1603
0
  WINPR_ASSERT(poutput);
1604
0
  WINPR_ASSERT(pcbOutput);
1605
1606
0
  BOOL ret = FALSE;
1607
0
  BYTE* output = NULL;
1608
0
  EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1609
0
  if (!pkey)
1610
0
    return FALSE;
1611
1612
0
  EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
1613
0
  if (!ctx)
1614
0
    return FALSE;
1615
1616
0
  size_t outputSize = EVP_PKEY_size(pkey);
1617
0
  output = malloc(outputSize);
1618
0
  if (output == NULL)
1619
0
    goto out;
1620
0
  *pcbOutput = outputSize;
1621
1622
0
  if (EVP_PKEY_encrypt_init(ctx) != 1 ||
1623
0
      EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) != 1 ||
1624
0
      EVP_PKEY_encrypt(ctx, output, pcbOutput, input, cbInput) != 1)
1625
0
  {
1626
0
    WLog_ERR(TAG, "error when setting up public key");
1627
0
    goto out;
1628
0
  }
1629
1630
0
  *poutput = output;
1631
0
  output = NULL;
1632
0
  ret = TRUE;
1633
0
out:
1634
0
  EVP_PKEY_CTX_free(ctx);
1635
0
  free(output);
1636
0
  return ret;
1637
0
}
1638
1639
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1640
static RSA* freerdp_certificate_get_RSA(const rdpCertificate* cert)
1641
0
{
1642
0
  WINPR_ASSERT(cert);
1643
1644
0
  if (!freerdp_certificate_is_rsa(cert))
1645
0
    return NULL;
1646
1647
0
  EVP_PKEY* pubkey = X509_get0_pubkey(cert->x509);
1648
0
  if (!pubkey)
1649
0
    return NULL;
1650
1651
0
  return EVP_PKEY_get1_RSA(pubkey);
1652
0
}
1653
#endif
1654
1655
BYTE* freerdp_certificate_get_der(const rdpCertificate* cert, size_t* pLength)
1656
0
{
1657
0
  WINPR_ASSERT(cert);
1658
1659
0
  if (pLength)
1660
0
    *pLength = 0;
1661
1662
0
  const int rc = i2d_X509(cert->x509, NULL);
1663
0
  if (rc <= 0)
1664
0
    return NULL;
1665
1666
0
  BYTE* ptr = calloc(rc + 1, sizeof(BYTE));
1667
0
  if (!ptr)
1668
0
    return NULL;
1669
0
  BYTE* i2d_ptr = ptr;
1670
1671
0
  const int rc2 = i2d_X509(cert->x509, &i2d_ptr);
1672
0
  if (rc2 <= 0)
1673
0
  {
1674
0
    free(ptr);
1675
0
    return NULL;
1676
0
  }
1677
1678
0
  if (pLength)
1679
0
    *pLength = (size_t)rc2;
1680
0
  return ptr;
1681
0
}
1682
1683
BOOL freerdp_certificate_is_rsa(const rdpCertificate* cert)
1684
36
{
1685
36
  WINPR_ASSERT(cert);
1686
36
  return is_rsa_key(cert->x509);
1687
36
}
1688
1689
BOOL freerdp_certificate_is_rdp_security_compatible(const rdpCertificate* cert)
1690
0
{
1691
0
  const rdpCertInfo* info = freerdp_certificate_get_info(cert);
1692
0
  if (!freerdp_certificate_is_rsa(cert) || !info || (info->ModulusLength != 2048 / 8))
1693
0
  {
1694
0
    WLog_INFO(TAG, "certificate is not RSA 2048, RDP security not supported.");
1695
0
    return FALSE;
1696
0
  }
1697
0
  return TRUE;
1698
0
}
1699
1700
char* freerdp_certificate_get_param(const rdpCertificate* cert, enum FREERDP_CERT_PARAM what,
1701
                                    size_t* psize)
1702
0
{
1703
0
  WINPR_ASSERT(cert);
1704
0
  WINPR_ASSERT(psize);
1705
1706
0
  *psize = 0;
1707
1708
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
1709
0
  const BIGNUM* bn = NULL;
1710
0
  RSA* rsa = freerdp_certificate_get_RSA(cert);
1711
0
  switch (what)
1712
0
  {
1713
0
    case FREERDP_CERT_RSA_E:
1714
0
      RSA_get0_key(rsa, NULL, &bn, NULL);
1715
0
      break;
1716
0
    case FREERDP_CERT_RSA_N:
1717
0
      RSA_get0_key(rsa, &bn, NULL, NULL);
1718
0
      break;
1719
0
    default:
1720
0
      RSA_free(rsa);
1721
0
      return NULL;
1722
0
  }
1723
0
  RSA_free(rsa);
1724
#else
1725
  EVP_PKEY* pkey = X509_get0_pubkey(cert->x509);
1726
  if (!pkey)
1727
    return NULL;
1728
1729
  BIGNUM* bn = NULL;
1730
  switch (what)
1731
  {
1732
    case FREERDP_CERT_RSA_E:
1733
      if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn))
1734
        return NULL;
1735
      break;
1736
    case FREERDP_CERT_RSA_N:
1737
      if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn))
1738
        return NULL;
1739
      break;
1740
    default:
1741
      return NULL;
1742
  }
1743
#endif
1744
1745
0
  const size_t bnsize = BN_num_bytes(bn);
1746
0
  char* rc = calloc(bnsize + 1, sizeof(char));
1747
0
  if (!rc)
1748
0
    goto fail;
1749
0
  BN_bn2bin(bn, (BYTE*)rc);
1750
0
  *psize = bnsize;
1751
1752
0
fail:
1753
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR < 3)
1754
  BN_free(bn);
1755
#endif
1756
0
  return rc;
1757
0
}