Coverage Report

Created: 2023-09-25 06:56

/src/FreeRDP/libfreerdp/crypto/privatekey.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Private key 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/crypto.h>
36
37
#include <openssl/pem.h>
38
#include <openssl/rsa.h>
39
40
#include "privatekey.h"
41
#include "cert_common.h"
42
43
#include <freerdp/crypto/privatekey.h>
44
45
#include <openssl/evp.h>
46
47
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
48
#include <openssl/core_names.h>
49
#endif
50
51
#include "x509_utils.h"
52
#include "crypto.h"
53
#include "opensslcompat.h"
54
55
#define TAG FREERDP_TAG("crypto")
56
57
struct rdp_private_key
58
{
59
  EVP_PKEY* evp;
60
61
  rdpCertInfo cert;
62
  BYTE* PrivateExponent;
63
  DWORD PrivateExponentLength;
64
};
65
66
/*
67
 * Terminal Services Signing Keys.
68
 * Yes, Terminal Services Private Key is publicly available.
69
 */
70
71
static BYTE tssk_modulus[] = { 0x3d, 0x3a, 0x5e, 0xbd, 0x72, 0x43, 0x3e, 0xc9, 0x4d, 0xbb, 0xc1,
72
                             0x1e, 0x4a, 0xba, 0x5f, 0xcb, 0x3e, 0x88, 0x20, 0x87, 0xef, 0xf5,
73
                             0xc1, 0xe2, 0xd7, 0xb7, 0x6b, 0x9a, 0xf2, 0x52, 0x45, 0x95, 0xce,
74
                             0x63, 0x65, 0x6b, 0x58, 0x3a, 0xfe, 0xef, 0x7c, 0xe7, 0xbf, 0xfe,
75
                             0x3d, 0xf6, 0x5c, 0x7d, 0x6c, 0x5e, 0x06, 0x09, 0x1a, 0xf5, 0x61,
76
                             0xbb, 0x20, 0x93, 0x09, 0x5f, 0x05, 0x6d, 0xea, 0x87 };
77
78
static BYTE tssk_privateExponent[] = {
79
  0x87, 0xa7, 0x19, 0x32, 0xda, 0x11, 0x87, 0x55, 0x58, 0x00, 0x16, 0x16, 0x25, 0x65, 0x68, 0xf8,
80
  0x24, 0x3e, 0xe6, 0xfa, 0xe9, 0x67, 0x49, 0x94, 0xcf, 0x92, 0xcc, 0x33, 0x99, 0xe8, 0x08, 0x60,
81
  0x17, 0x9a, 0x12, 0x9f, 0x24, 0xdd, 0xb1, 0x24, 0x99, 0xc7, 0x3a, 0xb8, 0x0a, 0x7b, 0x0d, 0xdd,
82
  0x35, 0x07, 0x79, 0x17, 0x0b, 0x51, 0x9b, 0xb3, 0xc7, 0x10, 0x01, 0x13, 0xe7, 0x3f, 0xf3, 0x5f
83
};
84
85
static const rdpPrivateKey tssk = { .PrivateExponent = tssk_privateExponent,
86
                                  .PrivateExponentLength = sizeof(tssk_privateExponent),
87
                                  .cert = { .Modulus = tssk_modulus,
88
                                            .ModulusLength = sizeof(tssk_modulus) } };
89
const rdpPrivateKey* priv_key_tssk = &tssk;
90
91
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
92
static RSA* evp_pkey_to_rsa(const rdpPrivateKey* key)
93
0
{
94
0
  if (!freerdp_key_is_rsa(key))
95
0
  {
96
0
    WLog_WARN(TAG, "Key is no RSA key");
97
0
    return NULL;
98
0
  }
99
100
0
  RSA* rsa = NULL;
101
0
  BIO* bio = BIO_new(BIO_s_secmem());
102
0
  if (!bio)
103
0
    return NULL;
104
0
  const int rc = PEM_write_bio_PrivateKey(bio, key->evp, NULL, NULL, 0, NULL, NULL);
105
0
  if (rc != 1)
106
0
    goto fail;
107
0
  rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
108
0
fail:
109
0
  BIO_free_all(bio);
110
0
  return rsa;
111
0
}
112
#endif
113
114
static EVP_PKEY* evp_pkey_utils_from_pem(const char* data, size_t len, BOOL fromFile)
115
0
{
116
0
  EVP_PKEY* evp = NULL;
117
0
  BIO* bio;
118
0
  if (fromFile)
119
0
    bio = BIO_new_file(data, "rb");
120
0
  else
121
0
    bio = BIO_new_mem_buf(data, len);
122
123
0
  if (!bio)
124
0
  {
125
0
    WLog_ERR(TAG, "BIO_new failed for private key");
126
0
    return NULL;
127
0
  }
128
129
0
  evp = PEM_read_bio_PrivateKey(bio, NULL, NULL, 0);
130
0
  BIO_free_all(bio);
131
0
  if (!evp)
132
0
    WLog_ERR(TAG, "PEM_read_bio_PrivateKey returned NULL [input length %" PRIuz "]", len);
133
134
0
  return evp;
135
0
}
136
137
static BOOL key_read_private(rdpPrivateKey* key)
138
0
{
139
0
  BOOL rc = FALSE;
140
141
0
  WINPR_ASSERT(key);
142
0
  WINPR_ASSERT(key->evp);
143
144
  /* The key is not an RSA key, that means we just return success. */
145
0
  if (!freerdp_key_is_rsa(key))
146
0
    return TRUE;
147
148
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
149
0
  RSA* rsa = evp_pkey_to_rsa(key);
150
0
  if (!rsa)
151
0
  {
152
0
    WLog_ERR(TAG, "unable to load RSA key: %s.", strerror(errno));
153
0
    goto fail;
154
0
  }
155
156
0
  switch (RSA_check_key(rsa))
157
0
  {
158
0
    case 0:
159
0
      WLog_ERR(TAG, "invalid RSA key");
160
0
      goto fail;
161
162
0
    case 1:
163
      /* Valid key. */
164
0
      break;
165
166
0
    default:
167
0
      WLog_ERR(TAG, "unexpected error when checking RSA key: %s.", strerror(errno));
168
0
      goto fail;
169
0
  }
170
171
0
  const BIGNUM* rsa_e = NULL;
172
0
  const BIGNUM* rsa_n = NULL;
173
0
  const BIGNUM* rsa_d = NULL;
174
175
0
  RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
176
#else
177
  BIGNUM* rsa_e = NULL;
178
  BIGNUM* rsa_n = NULL;
179
  BIGNUM* rsa_d = NULL;
180
181
  if (!EVP_PKEY_get_bn_param(key->evp, OSSL_PKEY_PARAM_RSA_N, &rsa_n))
182
    goto fail;
183
  if (!EVP_PKEY_get_bn_param(key->evp, OSSL_PKEY_PARAM_RSA_E, &rsa_e))
184
    goto fail;
185
  if (!EVP_PKEY_get_bn_param(key->evp, OSSL_PKEY_PARAM_RSA_D, &rsa_d))
186
    goto fail;
187
#endif
188
0
  if (BN_num_bytes(rsa_e) > 4)
189
0
  {
190
0
    WLog_ERR(TAG, "RSA public exponent too large");
191
0
    goto fail;
192
0
  }
193
194
0
  if (!read_bignum(&key->PrivateExponent, &key->PrivateExponentLength, rsa_d, TRUE))
195
0
    goto fail;
196
197
0
  if (!cert_info_create(&key->cert, rsa_n, rsa_e))
198
0
    goto fail;
199
0
  rc = TRUE;
200
0
fail:
201
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
202
0
  RSA_free(rsa);
203
#else
204
  BN_free(rsa_d);
205
  BN_free(rsa_e);
206
  BN_free(rsa_n);
207
#endif
208
0
  return rc;
209
0
}
210
211
rdpPrivateKey* freerdp_key_new_from_pem(const char* pem)
212
0
{
213
0
  rdpPrivateKey* key = freerdp_key_new();
214
0
  if (!key || !pem)
215
0
    goto fail;
216
0
  key->evp = evp_pkey_utils_from_pem(pem, strlen(pem), FALSE);
217
0
  if (!key->evp)
218
0
    goto fail;
219
0
  if (!key_read_private(key))
220
0
    goto fail;
221
0
  return key;
222
0
fail:
223
0
  freerdp_key_free(key);
224
0
  return NULL;
225
0
}
226
227
rdpPrivateKey* freerdp_key_new_from_file(const char* keyfile)
228
0
{
229
230
0
  rdpPrivateKey* key = freerdp_key_new();
231
0
  if (!key || !keyfile)
232
0
    goto fail;
233
234
0
  key->evp = evp_pkey_utils_from_pem(keyfile, strlen(keyfile), TRUE);
235
0
  if (!key->evp)
236
0
    goto fail;
237
0
  if (!key_read_private(key))
238
0
    goto fail;
239
0
  return key;
240
0
fail:
241
0
  freerdp_key_free(key);
242
0
  return NULL;
243
0
}
244
245
rdpPrivateKey* freerdp_key_new(void)
246
0
{
247
0
  return calloc(1, sizeof(rdpPrivateKey));
248
0
}
249
250
rdpPrivateKey* freerdp_key_clone(const rdpPrivateKey* key)
251
0
{
252
0
  if (!key)
253
0
    return NULL;
254
255
0
  rdpPrivateKey* _key = (rdpPrivateKey*)calloc(1, sizeof(rdpPrivateKey));
256
257
0
  if (!_key)
258
0
    return NULL;
259
260
0
  if (key->evp)
261
0
  {
262
0
    _key->evp = key->evp;
263
0
    if (!_key->evp)
264
0
      goto out_fail;
265
0
    EVP_PKEY_up_ref(_key->evp);
266
0
  }
267
268
0
  if (key->PrivateExponent)
269
0
  {
270
0
    _key->PrivateExponent = (BYTE*)malloc(key->PrivateExponentLength);
271
272
0
    if (!_key->PrivateExponent)
273
0
      goto out_fail;
274
275
0
    CopyMemory(_key->PrivateExponent, key->PrivateExponent, key->PrivateExponentLength);
276
0
    _key->PrivateExponentLength = key->PrivateExponentLength;
277
0
  }
278
279
0
  if (!cert_info_clone(&_key->cert, &key->cert))
280
0
    goto out_fail;
281
282
0
  return _key;
283
0
out_fail:
284
0
  freerdp_key_free(_key);
285
0
  return NULL;
286
0
}
287
288
void freerdp_key_free(rdpPrivateKey* key)
289
0
{
290
0
  if (!key)
291
0
    return;
292
293
0
  EVP_PKEY_free(key->evp);
294
0
  if (key->PrivateExponent)
295
0
    memset(key->PrivateExponent, 0, key->PrivateExponentLength);
296
0
  free(key->PrivateExponent);
297
0
  cert_info_free(&key->cert);
298
0
  free(key);
299
0
}
300
301
const rdpCertInfo* freerdp_key_get_info(const rdpPrivateKey* key)
302
0
{
303
0
  WINPR_ASSERT(key);
304
0
  if (!freerdp_key_is_rsa(key))
305
0
    return NULL;
306
0
  return &key->cert;
307
0
}
308
309
const BYTE* freerdp_key_get_exponent(const rdpPrivateKey* key, size_t* plength)
310
0
{
311
0
  WINPR_ASSERT(key);
312
0
  if (!freerdp_key_is_rsa(key))
313
0
  {
314
0
    if (plength)
315
0
      *plength = 0;
316
0
    return NULL;
317
0
  }
318
319
0
  if (plength)
320
0
    *plength = key->PrivateExponentLength;
321
0
  return key->PrivateExponent;
322
0
}
323
324
EVP_PKEY* freerdp_key_get_evp_pkey(const rdpPrivateKey* key)
325
0
{
326
0
  WINPR_ASSERT(key);
327
328
0
  EVP_PKEY* evp = key->evp;
329
0
  WINPR_ASSERT(evp);
330
0
  EVP_PKEY_up_ref(evp);
331
0
  return evp;
332
0
}
333
334
BOOL freerdp_key_is_rsa(const rdpPrivateKey* key)
335
0
{
336
0
  WINPR_ASSERT(key);
337
0
  if (key == priv_key_tssk)
338
0
    return TRUE;
339
340
0
  WINPR_ASSERT(key->evp);
341
0
  return (EVP_PKEY_id(key->evp) == EVP_PKEY_RSA);
342
0
}
343
344
size_t freerdp_key_get_bits(const rdpPrivateKey* key)
345
0
{
346
0
  int rc = -1;
347
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
348
0
  RSA* rsa = evp_pkey_to_rsa(key);
349
0
  if (rsa)
350
0
  {
351
0
    rc = RSA_bits(rsa);
352
0
    RSA_free(rsa);
353
0
  }
354
#else
355
  rc = EVP_PKEY_get_bits(key->evp);
356
#endif
357
358
0
  return rc;
359
0
}
360
361
BOOL freerdp_key_generate(rdpPrivateKey* key, size_t key_length)
362
0
{
363
0
  BOOL rc = FALSE;
364
365
0
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
366
0
  RSA* rsa = NULL;
367
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
368
  rsa = RSA_generate_key(key_length, RSA_F4, NULL, NULL);
369
#else
370
0
  {
371
0
    BIGNUM* bn = BN_secure_new();
372
373
0
    if (!bn)
374
0
      return FALSE;
375
376
0
    rsa = RSA_new();
377
378
0
    if (!rsa)
379
0
    {
380
0
      BN_clear_free(bn);
381
0
      return FALSE;
382
0
    }
383
384
0
    BN_set_word(bn, RSA_F4);
385
0
    const int res = RSA_generate_key_ex(rsa, key_length, bn, NULL);
386
0
    BN_clear_free(bn);
387
388
0
    if (res != 1)
389
0
      return FALSE;
390
0
  }
391
0
#endif
392
393
0
  EVP_PKEY_free(key->evp);
394
0
  key->evp = EVP_PKEY_new();
395
396
0
  if (!EVP_PKEY_assign_RSA(key->evp, rsa))
397
0
  {
398
0
    EVP_PKEY_free(key->evp);
399
0
    key->evp = NULL;
400
0
    RSA_free(rsa);
401
0
    return FALSE;
402
0
  }
403
404
0
  rc = TRUE;
405
#else
406
  EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
407
  if (!pctx)
408
    return FALSE;
409
410
  if (EVP_PKEY_keygen_init(pctx) != 1)
411
    goto fail;
412
413
  if (EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, key_length) != 1)
414
    goto fail;
415
416
  EVP_PKEY_free(key->evp);
417
  key->evp = NULL;
418
419
  if (EVP_PKEY_generate(pctx, &key->evp) != 1)
420
    goto fail;
421
422
  rc = TRUE;
423
fail:
424
  EVP_PKEY_CTX_free(pctx);
425
#endif
426
0
  return rc;
427
0
}
428
429
char* freerdp_key_get_param(const rdpPrivateKey* key, enum FREERDP_KEY_PARAM param, size_t* plength)
430
0
{
431
0
  BYTE* buf = NULL;
432
433
0
  WINPR_ASSERT(key);
434
0
  WINPR_ASSERT(plength);
435
436
0
  *plength = 0;
437
438
0
  BIGNUM* bn = NULL;
439
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
440
441
  const char* pk = NULL;
442
  switch (param)
443
  {
444
    case FREERDP_KEY_PARAM_RSA_D:
445
      pk = OSSL_PKEY_PARAM_RSA_D;
446
      break;
447
    case FREERDP_KEY_PARAM_RSA_E:
448
      pk = OSSL_PKEY_PARAM_RSA_E;
449
      break;
450
    case FREERDP_KEY_PARAM_RSA_N:
451
      pk = OSSL_PKEY_PARAM_RSA_N;
452
      break;
453
    default:
454
      return NULL;
455
  }
456
457
  if (!EVP_PKEY_get_bn_param(key->evp, pk, &bn))
458
    return NULL;
459
#else
460
0
  {
461
0
    const RSA* rsa = EVP_PKEY_get0_RSA(key->evp);
462
0
    if (!rsa)
463
0
      return NULL;
464
465
0
    const BIGNUM* cbn = NULL;
466
0
    switch (param)
467
0
    {
468
0
      case FREERDP_KEY_PARAM_RSA_D:
469
0
        cbn = RSA_get0_d(rsa);
470
0
        break;
471
0
      case FREERDP_KEY_PARAM_RSA_E:
472
0
        cbn = RSA_get0_e(rsa);
473
0
        break;
474
0
      case FREERDP_KEY_PARAM_RSA_N:
475
0
        cbn = RSA_get0_n(rsa);
476
0
        break;
477
0
      default:
478
0
        return NULL;
479
0
    }
480
0
    if (!cbn)
481
0
      return NULL;
482
0
    bn = BN_dup(cbn);
483
0
    if (!bn)
484
0
      return NULL;
485
0
  }
486
0
#endif
487
488
0
  const int length = BN_num_bytes(bn);
489
0
  if (length < 0)
490
0
    goto fail;
491
492
0
  const size_t alloc_size = (size_t)length + 1ull;
493
0
  buf = calloc(alloc_size, sizeof(BYTE));
494
0
  if (!buf)
495
0
    goto fail;
496
497
0
  const int bnlen = BN_bn2bin(bn, buf);
498
0
  if (bnlen != length)
499
0
  {
500
0
    free(buf);
501
0
    buf = NULL;
502
0
  }
503
0
  else
504
0
    *plength = length;
505
506
0
fail:
507
0
  BN_free(bn);
508
0
  return (char*)buf;
509
0
}
510
511
WINPR_DIGEST_CTX* freerdp_key_digest_sign(rdpPrivateKey* key, WINPR_MD_TYPE digest)
512
0
{
513
0
  WINPR_DIGEST_CTX* md_ctx = winpr_Digest_New();
514
0
  if (!md_ctx)
515
0
    return NULL;
516
517
0
  if (!winpr_DigestSign_Init(md_ctx, digest, key->evp))
518
0
  {
519
0
    winpr_Digest_Free(md_ctx);
520
0
    return NULL;
521
0
  }
522
0
  return md_ctx;
523
0
}