Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/winpr/libwinpr/crypto/cipher.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * WinPR: Windows Portable Runtime
3
 *
4
 * Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.com>
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
#include <winpr/config.h>
20
21
#include <winpr/crt.h>
22
#include <winpr/assert.h>
23
#include <winpr/crypto.h>
24
25
#include "../log.h"
26
#define TAG WINPR_TAG("crypto.cipher")
27
28
#if defined(WITH_INTERNAL_RC4)
29
#include "rc4.h"
30
#endif
31
32
#ifdef WITH_OPENSSL
33
#include <openssl/aes.h>
34
#include <openssl/rc4.h>
35
#include <openssl/des.h>
36
#include <openssl/evp.h>
37
#endif
38
39
#ifdef WITH_MBEDTLS
40
#include <mbedtls/md.h>
41
#include <mbedtls/aes.h>
42
#include <mbedtls/des.h>
43
#include <mbedtls/cipher.h>
44
#if MBEDTLS_VERSION_MAJOR < 3
45
#define mbedtls_cipher_info_get_iv_size(_info) (_info->iv_size)
46
#define mbedtls_cipher_info_get_key_bitlen(_info) (_info->key_bitlen)
47
#endif
48
#endif
49
50
/**
51
 * RC4
52
 */
53
54
struct winpr_rc4_ctx_private_st
55
{
56
#if defined(WITH_INTERNAL_RC4)
57
  winpr_int_RC4_CTX* ictx;
58
#else
59
#if defined(WITH_OPENSSL)
60
  EVP_CIPHER_CTX* ctx;
61
#endif
62
#endif
63
};
64
65
static WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOOL override_fips)
66
0
{
67
0
  if (!key || (keylen == 0))
68
0
    return NULL;
69
70
0
  WINPR_RC4_CTX* ctx = (WINPR_RC4_CTX*)calloc(1, sizeof(WINPR_RC4_CTX));
71
0
  if (!ctx)
72
0
    return NULL;
73
74
#if defined(WITH_INTERNAL_RC4)
75
  WINPR_UNUSED(override_fips);
76
  ctx->ictx = winpr_int_rc4_new(key, keylen);
77
  if (!ctx->ictx)
78
    goto fail;
79
#elif defined(WITH_OPENSSL)
80
0
  const EVP_CIPHER* evp = NULL;
81
82
0
  if (keylen > INT_MAX)
83
0
    goto fail;
84
85
0
  ctx->ctx = EVP_CIPHER_CTX_new();
86
0
  if (!ctx->ctx)
87
0
    goto fail;
88
89
0
  evp = EVP_rc4();
90
91
0
  if (!evp)
92
0
    goto fail;
93
94
0
  EVP_CIPHER_CTX_reset(ctx->ctx);
95
0
  if (EVP_EncryptInit_ex(ctx->ctx, evp, NULL, NULL, NULL) != 1)
96
0
    goto fail;
97
98
    /* EVP_CIPH_FLAG_NON_FIPS_ALLOW does not exist before openssl 1.0.1 */
99
0
#if !(OPENSSL_VERSION_NUMBER < 0x10001000L)
100
101
0
  if (override_fips == TRUE)
102
0
    EVP_CIPHER_CTX_set_flags(ctx->ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW);
103
104
0
#endif
105
0
  EVP_CIPHER_CTX_set_key_length(ctx->ctx, (int)keylen);
106
0
  if (EVP_EncryptInit_ex(ctx->ctx, NULL, NULL, key, NULL) != 1)
107
0
    goto fail;
108
0
#endif
109
0
  return ctx;
110
111
0
fail:
112
0
  WINPR_PRAGMA_DIAG_PUSH
113
0
  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
114
115
0
  winpr_RC4_Free(ctx);
116
0
  WINPR_PRAGMA_DIAG_POP
117
0
  return NULL;
118
0
}
119
120
WINPR_RC4_CTX* winpr_RC4_New_Allow_FIPS(const void* key, size_t keylen)
121
0
{
122
0
  return winpr_RC4_New_Internal(key, keylen, TRUE);
123
0
}
124
125
WINPR_RC4_CTX* winpr_RC4_New(const void* key, size_t keylen)
126
0
{
127
0
  return winpr_RC4_New_Internal(key, keylen, FALSE);
128
0
}
129
130
BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const void* input, void* output)
131
0
{
132
0
  WINPR_ASSERT(ctx);
133
134
#if defined(WITH_INTERNAL_RC4)
135
  return winpr_int_rc4_update(ctx->ictx, length, input, output);
136
#elif defined(WITH_OPENSSL)
137
0
  WINPR_ASSERT(ctx->ctx);
138
0
  int outputLength = 0;
139
0
  if (length > INT_MAX)
140
0
    return FALSE;
141
142
0
  WINPR_ASSERT(ctx);
143
0
  if (EVP_CipherUpdate(ctx->ctx, output, &outputLength, input, (int)length) != 1)
144
0
    return FALSE;
145
0
  return TRUE;
146
0
#endif
147
0
  return FALSE;
148
0
}
149
150
void winpr_RC4_Free(WINPR_RC4_CTX* ctx)
151
29.9k
{
152
29.9k
  if (!ctx)
153
29.9k
    return;
154
155
#if defined(WITH_INTERNAL_RC4)
156
  winpr_int_rc4_free(ctx->ictx);
157
#elif defined(WITH_OPENSSL)
158
0
  EVP_CIPHER_CTX_free(ctx->ctx);
159
0
#endif
160
0
  free(ctx);
161
0
}
162
163
/**
164
 * Generic Cipher API
165
 */
166
167
#ifdef WITH_OPENSSL
168
extern const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md);
169
#endif
170
171
#ifdef WITH_MBEDTLS
172
extern mbedtls_md_type_t winpr_mbedtls_get_md_type(int md);
173
#endif
174
175
#if defined(WITH_OPENSSL)
176
static const EVP_CIPHER* winpr_openssl_get_evp_cipher(int cipher)
177
705
{
178
705
  const EVP_CIPHER* evp = NULL;
179
180
705
  switch (cipher)
181
705
  {
182
0
    case WINPR_CIPHER_NULL:
183
0
      evp = EVP_enc_null();
184
0
      break;
185
186
0
    case WINPR_CIPHER_AES_128_ECB:
187
0
      evp = EVP_get_cipherbyname("aes-128-ecb");
188
0
      break;
189
190
0
    case WINPR_CIPHER_AES_192_ECB:
191
0
      evp = EVP_get_cipherbyname("aes-192-ecb");
192
0
      break;
193
194
0
    case WINPR_CIPHER_AES_256_ECB:
195
0
      evp = EVP_get_cipherbyname("aes-256-ecb");
196
0
      break;
197
198
459
    case WINPR_CIPHER_AES_128_CBC:
199
459
      evp = EVP_get_cipherbyname("aes-128-cbc");
200
459
      break;
201
202
0
    case WINPR_CIPHER_AES_192_CBC:
203
0
      evp = EVP_get_cipherbyname("aes-192-cbc");
204
0
      break;
205
206
0
    case WINPR_CIPHER_AES_256_CBC:
207
0
      evp = EVP_get_cipherbyname("aes-256-cbc");
208
0
      break;
209
210
0
    case WINPR_CIPHER_AES_128_CFB128:
211
0
      evp = EVP_get_cipherbyname("aes-128-cfb128");
212
0
      break;
213
214
0
    case WINPR_CIPHER_AES_192_CFB128:
215
0
      evp = EVP_get_cipherbyname("aes-192-cfb128");
216
0
      break;
217
218
0
    case WINPR_CIPHER_AES_256_CFB128:
219
0
      evp = EVP_get_cipherbyname("aes-256-cfb128");
220
0
      break;
221
222
0
    case WINPR_CIPHER_AES_128_CTR:
223
0
      evp = EVP_get_cipherbyname("aes-128-ctr");
224
0
      break;
225
226
0
    case WINPR_CIPHER_AES_192_CTR:
227
0
      evp = EVP_get_cipherbyname("aes-192-ctr");
228
0
      break;
229
230
0
    case WINPR_CIPHER_AES_256_CTR:
231
0
      evp = EVP_get_cipherbyname("aes-256-ctr");
232
0
      break;
233
234
0
    case WINPR_CIPHER_AES_128_GCM:
235
0
      evp = EVP_get_cipherbyname("aes-128-gcm");
236
0
      break;
237
238
0
    case WINPR_CIPHER_AES_192_GCM:
239
0
      evp = EVP_get_cipherbyname("aes-192-gcm");
240
0
      break;
241
242
0
    case WINPR_CIPHER_AES_256_GCM:
243
0
      evp = EVP_get_cipherbyname("aes-256-gcm");
244
0
      break;
245
246
0
    case WINPR_CIPHER_AES_128_CCM:
247
0
      evp = EVP_get_cipherbyname("aes-128-ccm");
248
0
      break;
249
250
0
    case WINPR_CIPHER_AES_192_CCM:
251
0
      evp = EVP_get_cipherbyname("aes-192-ccm");
252
0
      break;
253
254
0
    case WINPR_CIPHER_AES_256_CCM:
255
0
      evp = EVP_get_cipherbyname("aes-256-ccm");
256
0
      break;
257
258
0
    case WINPR_CIPHER_CAMELLIA_128_ECB:
259
0
      evp = EVP_get_cipherbyname("camellia-128-ecb");
260
0
      break;
261
262
0
    case WINPR_CIPHER_CAMELLIA_192_ECB:
263
0
      evp = EVP_get_cipherbyname("camellia-192-ecb");
264
0
      break;
265
266
0
    case WINPR_CIPHER_CAMELLIA_256_ECB:
267
0
      evp = EVP_get_cipherbyname("camellia-256-ecb");
268
0
      break;
269
270
0
    case WINPR_CIPHER_CAMELLIA_128_CBC:
271
0
      evp = EVP_get_cipherbyname("camellia-128-cbc");
272
0
      break;
273
274
0
    case WINPR_CIPHER_CAMELLIA_192_CBC:
275
0
      evp = EVP_get_cipherbyname("camellia-192-cbc");
276
0
      break;
277
278
0
    case WINPR_CIPHER_CAMELLIA_256_CBC:
279
0
      evp = EVP_get_cipherbyname("camellia-256-cbc");
280
0
      break;
281
282
0
    case WINPR_CIPHER_CAMELLIA_128_CFB128:
283
0
      evp = EVP_get_cipherbyname("camellia-128-cfb128");
284
0
      break;
285
286
0
    case WINPR_CIPHER_CAMELLIA_192_CFB128:
287
0
      evp = EVP_get_cipherbyname("camellia-192-cfb128");
288
0
      break;
289
290
0
    case WINPR_CIPHER_CAMELLIA_256_CFB128:
291
0
      evp = EVP_get_cipherbyname("camellia-256-cfb128");
292
0
      break;
293
294
0
    case WINPR_CIPHER_CAMELLIA_128_CTR:
295
0
      evp = EVP_get_cipherbyname("camellia-128-ctr");
296
0
      break;
297
298
0
    case WINPR_CIPHER_CAMELLIA_192_CTR:
299
0
      evp = EVP_get_cipherbyname("camellia-192-ctr");
300
0
      break;
301
302
0
    case WINPR_CIPHER_CAMELLIA_256_CTR:
303
0
      evp = EVP_get_cipherbyname("camellia-256-ctr");
304
0
      break;
305
306
0
    case WINPR_CIPHER_CAMELLIA_128_GCM:
307
0
      evp = EVP_get_cipherbyname("camellia-128-gcm");
308
0
      break;
309
310
0
    case WINPR_CIPHER_CAMELLIA_192_GCM:
311
0
      evp = EVP_get_cipherbyname("camellia-192-gcm");
312
0
      break;
313
314
0
    case WINPR_CIPHER_CAMELLIA_256_GCM:
315
0
      evp = EVP_get_cipherbyname("camellia-256-gcm");
316
0
      break;
317
318
0
    case WINPR_CIPHER_CAMELLIA_128_CCM:
319
0
      evp = EVP_get_cipherbyname("camellia-128-ccm");
320
0
      break;
321
322
0
    case WINPR_CIPHER_CAMELLIA_192_CCM:
323
0
      evp = EVP_get_cipherbyname("camellia-192-gcm");
324
0
      break;
325
326
0
    case WINPR_CIPHER_CAMELLIA_256_CCM:
327
0
      evp = EVP_get_cipherbyname("camellia-256-gcm");
328
0
      break;
329
330
0
    case WINPR_CIPHER_DES_ECB:
331
0
      evp = EVP_get_cipherbyname("des-ecb");
332
0
      break;
333
334
0
    case WINPR_CIPHER_DES_CBC:
335
0
      evp = EVP_get_cipherbyname("des-cbc");
336
0
      break;
337
338
0
    case WINPR_CIPHER_DES_EDE_ECB:
339
0
      evp = EVP_get_cipherbyname("des-ede-ecb");
340
0
      break;
341
342
0
    case WINPR_CIPHER_DES_EDE_CBC:
343
0
      evp = EVP_get_cipherbyname("des-ede-cbc");
344
0
      break;
345
346
0
    case WINPR_CIPHER_DES_EDE3_ECB:
347
0
      evp = EVP_get_cipherbyname("des-ede3-ecb");
348
0
      break;
349
350
0
    case WINPR_CIPHER_DES_EDE3_CBC:
351
0
      evp = EVP_get_cipherbyname("des-ede3-cbc");
352
0
      break;
353
354
246
    case WINPR_CIPHER_ARC4_128:
355
246
      evp = EVP_get_cipherbyname("rc4");
356
246
      break;
357
358
0
    case WINPR_CIPHER_BLOWFISH_ECB:
359
0
      evp = EVP_get_cipherbyname("blowfish-ecb");
360
0
      break;
361
362
0
    case WINPR_CIPHER_BLOWFISH_CBC:
363
0
      evp = EVP_get_cipherbyname("blowfish-cbc");
364
0
      break;
365
366
0
    case WINPR_CIPHER_BLOWFISH_CFB64:
367
0
      evp = EVP_get_cipherbyname("blowfish-cfb64");
368
0
      break;
369
370
0
    case WINPR_CIPHER_BLOWFISH_CTR:
371
0
      evp = EVP_get_cipherbyname("blowfish-ctr");
372
0
      break;
373
705
  }
374
375
705
  return evp;
376
705
}
377
378
#elif defined(WITH_MBEDTLS)
379
mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher)
380
{
381
  mbedtls_cipher_type_t type = MBEDTLS_CIPHER_NONE;
382
383
  switch (cipher)
384
  {
385
    case WINPR_CIPHER_NONE:
386
      type = MBEDTLS_CIPHER_NONE;
387
      break;
388
389
    case WINPR_CIPHER_NULL:
390
      type = MBEDTLS_CIPHER_NULL;
391
      break;
392
393
    case WINPR_CIPHER_AES_128_ECB:
394
      type = MBEDTLS_CIPHER_AES_128_ECB;
395
      break;
396
397
    case WINPR_CIPHER_AES_192_ECB:
398
      type = MBEDTLS_CIPHER_AES_192_ECB;
399
      break;
400
401
    case WINPR_CIPHER_AES_256_ECB:
402
      type = MBEDTLS_CIPHER_AES_256_ECB;
403
      break;
404
405
    case WINPR_CIPHER_AES_128_CBC:
406
      type = MBEDTLS_CIPHER_AES_128_CBC;
407
      break;
408
409
    case WINPR_CIPHER_AES_192_CBC:
410
      type = MBEDTLS_CIPHER_AES_192_CBC;
411
      break;
412
413
    case WINPR_CIPHER_AES_256_CBC:
414
      type = MBEDTLS_CIPHER_AES_256_CBC;
415
      break;
416
417
    case WINPR_CIPHER_AES_128_CFB128:
418
      type = MBEDTLS_CIPHER_AES_128_CFB128;
419
      break;
420
421
    case WINPR_CIPHER_AES_192_CFB128:
422
      type = MBEDTLS_CIPHER_AES_192_CFB128;
423
      break;
424
425
    case WINPR_CIPHER_AES_256_CFB128:
426
      type = MBEDTLS_CIPHER_AES_256_CFB128;
427
      break;
428
429
    case WINPR_CIPHER_AES_128_CTR:
430
      type = MBEDTLS_CIPHER_AES_128_CTR;
431
      break;
432
433
    case WINPR_CIPHER_AES_192_CTR:
434
      type = MBEDTLS_CIPHER_AES_192_CTR;
435
      break;
436
437
    case WINPR_CIPHER_AES_256_CTR:
438
      type = MBEDTLS_CIPHER_AES_256_CTR;
439
      break;
440
441
    case WINPR_CIPHER_AES_128_GCM:
442
      type = MBEDTLS_CIPHER_AES_128_GCM;
443
      break;
444
445
    case WINPR_CIPHER_AES_192_GCM:
446
      type = MBEDTLS_CIPHER_AES_192_GCM;
447
      break;
448
449
    case WINPR_CIPHER_AES_256_GCM:
450
      type = MBEDTLS_CIPHER_AES_256_GCM;
451
      break;
452
453
    case WINPR_CIPHER_AES_128_CCM:
454
      type = MBEDTLS_CIPHER_AES_128_CCM;
455
      break;
456
457
    case WINPR_CIPHER_AES_192_CCM:
458
      type = MBEDTLS_CIPHER_AES_192_CCM;
459
      break;
460
461
    case WINPR_CIPHER_AES_256_CCM:
462
      type = MBEDTLS_CIPHER_AES_256_CCM;
463
      break;
464
  }
465
466
  return type;
467
}
468
#endif
469
470
WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const void* key, const void* iv)
471
705
{
472
705
  WINPR_CIPHER_CTX* ctx = NULL;
473
705
#if defined(WITH_OPENSSL)
474
705
  int operation = 0;
475
705
  const EVP_CIPHER* evp = NULL;
476
705
  EVP_CIPHER_CTX* octx = NULL;
477
478
705
  if (!(evp = winpr_openssl_get_evp_cipher(cipher)))
479
0
    return NULL;
480
481
705
  if (!(octx = EVP_CIPHER_CTX_new()))
482
0
    return NULL;
483
484
705
  operation = (op == WINPR_ENCRYPT) ? 1 : 0;
485
486
705
  if (EVP_CipherInit_ex(octx, evp, NULL, key, iv, operation) != 1)
487
0
  {
488
0
    EVP_CIPHER_CTX_free(octx);
489
0
    return NULL;
490
0
  }
491
492
705
  EVP_CIPHER_CTX_set_padding(octx, 0);
493
705
  ctx = (WINPR_CIPHER_CTX*)octx;
494
#elif defined(WITH_MBEDTLS)
495
  int key_bitlen;
496
  mbedtls_operation_t operation;
497
  mbedtls_cipher_context_t* mctx;
498
  mbedtls_cipher_type_t cipher_type = winpr_mbedtls_get_cipher_type(cipher);
499
  const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(cipher_type);
500
501
  if (!cipher_info)
502
    return NULL;
503
504
  if (!(mctx = (mbedtls_cipher_context_t*)calloc(1, sizeof(mbedtls_cipher_context_t))))
505
    return NULL;
506
507
  operation = (op == WINPR_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT;
508
  mbedtls_cipher_init(mctx);
509
510
  if (mbedtls_cipher_setup(mctx, cipher_info) != 0)
511
  {
512
    free(mctx);
513
    return NULL;
514
  }
515
516
  key_bitlen = mbedtls_cipher_get_key_bitlen(mctx);
517
518
  if (mbedtls_cipher_setkey(mctx, key, key_bitlen, operation) != 0)
519
  {
520
    mbedtls_cipher_free(mctx);
521
    free(mctx);
522
    return NULL;
523
  }
524
525
  if (mbedtls_cipher_set_padding_mode(mctx, MBEDTLS_PADDING_NONE) != 0)
526
  {
527
    mbedtls_cipher_free(mctx);
528
    free(mctx);
529
    return NULL;
530
  }
531
532
  ctx = (WINPR_CIPHER_CTX*)mctx;
533
#endif
534
705
  return ctx;
535
705
}
536
537
BOOL winpr_Cipher_SetPadding(WINPR_CIPHER_CTX* ctx, BOOL enabled)
538
0
{
539
0
  WINPR_ASSERT(ctx);
540
541
0
#if defined(WITH_OPENSSL)
542
0
  EVP_CIPHER_CTX_set_padding((EVP_CIPHER_CTX*)ctx, enabled);
543
#elif defined(WITH_MBEDTLS)
544
  mbedtls_cipher_padding_t option = enabled ? MBEDTLS_PADDING_PKCS7 : MBEDTLS_PADDING_NONE;
545
  if (mbedtls_cipher_set_padding_mode((mbedtls_cipher_context_t*)ctx, option) != 0)
546
    return FALSE;
547
#else
548
  return FALSE;
549
#endif
550
0
  return TRUE;
551
0
}
552
553
BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const void* input, size_t ilen, void* output,
554
                         size_t* olen)
555
705
{
556
705
#if defined(WITH_OPENSSL)
557
705
  int outl = (int)*olen;
558
559
705
  if (ilen > INT_MAX)
560
0
  {
561
0
    WLog_ERR(TAG, "input length %" PRIuz " > %d, abort", ilen, INT_MAX);
562
0
    return FALSE;
563
0
  }
564
565
705
  WINPR_ASSERT(ctx);
566
705
  if (EVP_CipherUpdate((EVP_CIPHER_CTX*)ctx, output, &outl, input, (int)ilen) == 1)
567
705
  {
568
705
    *olen = (size_t)outl;
569
705
    return TRUE;
570
705
  }
571
572
#elif defined(WITH_MBEDTLS)
573
574
  if (mbedtls_cipher_update((mbedtls_cipher_context_t*)ctx, input, ilen, output, olen) == 0)
575
    return TRUE;
576
577
#endif
578
579
0
  WLog_ERR(TAG, "Failed to update the data");
580
0
  return FALSE;
581
705
}
582
583
BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, void* output, size_t* olen)
584
705
{
585
705
#if defined(WITH_OPENSSL)
586
705
  int outl = (int)*olen;
587
588
705
  if (EVP_CipherFinal_ex((EVP_CIPHER_CTX*)ctx, output, &outl) == 1)
589
512
  {
590
512
    *olen = (size_t)outl;
591
512
    return TRUE;
592
512
  }
593
594
#elif defined(WITH_MBEDTLS)
595
596
  if (mbedtls_cipher_finish((mbedtls_cipher_context_t*)ctx, output, olen) == 0)
597
    return TRUE;
598
599
#endif
600
193
  return FALSE;
601
705
}
602
603
void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx)
604
30.7k
{
605
30.7k
  if (!ctx)
606
30.0k
    return;
607
608
705
#if defined(WITH_OPENSSL)
609
705
  EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*)ctx);
610
#elif defined(WITH_MBEDTLS)
611
  mbedtls_cipher_free((mbedtls_cipher_context_t*)ctx);
612
  free(ctx);
613
#endif
614
705
}
615
616
/**
617
 * Key Generation
618
 */
619
620
int winpr_Cipher_BytesToKey(int cipher, WINPR_MD_TYPE md, const void* salt, const void* data,
621
                            size_t datal, size_t count, void* key, void* iv)
622
0
{
623
  /**
624
   * Key and IV generation compatible with OpenSSL EVP_BytesToKey():
625
   * https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html
626
   */
627
0
#if defined(WITH_OPENSSL)
628
0
  const EVP_MD* evp_md = NULL;
629
0
  const EVP_CIPHER* evp_cipher = NULL;
630
0
  evp_md = winpr_openssl_get_evp_md((WINPR_MD_TYPE)md);
631
0
  evp_cipher = winpr_openssl_get_evp_cipher(cipher);
632
0
  return EVP_BytesToKey(evp_cipher, evp_md, salt, data, datal, count, key, iv);
633
#elif defined(WITH_MBEDTLS)
634
  int rv = 0;
635
  BYTE md_buf[64];
636
  int niv, nkey, addmd = 0;
637
  unsigned int mds = 0;
638
  mbedtls_md_context_t ctx;
639
  const mbedtls_md_info_t* md_info;
640
  mbedtls_cipher_type_t cipher_type;
641
  const mbedtls_cipher_info_t* cipher_info;
642
  mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
643
  md_info = mbedtls_md_info_from_type(md_type);
644
  cipher_type = winpr_mbedtls_get_cipher_type(cipher);
645
  cipher_info = mbedtls_cipher_info_from_type(cipher_type);
646
  nkey = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
647
  niv = mbedtls_cipher_info_get_iv_size(cipher_info);
648
649
  if ((nkey > 64) || (niv > 64))
650
    return 0;
651
652
  if (!data)
653
    return nkey;
654
655
  mbedtls_md_init(&ctx);
656
657
  if (mbedtls_md_setup(&ctx, md_info, 0) != 0)
658
    goto err;
659
660
  while (1)
661
  {
662
    if (mbedtls_md_starts(&ctx) != 0)
663
      goto err;
664
665
    if (addmd++)
666
    {
667
      if (mbedtls_md_update(&ctx, md_buf, mds) != 0)
668
        goto err;
669
    }
670
671
    if (mbedtls_md_update(&ctx, data, datal) != 0)
672
      goto err;
673
674
    if (salt)
675
    {
676
      if (mbedtls_md_update(&ctx, salt, 8) != 0)
677
        goto err;
678
    }
679
680
    if (mbedtls_md_finish(&ctx, md_buf) != 0)
681
      goto err;
682
683
    mds = mbedtls_md_get_size(md_info);
684
685
    for (unsigned int i = 1; i < (unsigned int)count; i++)
686
    {
687
      if (mbedtls_md_starts(&ctx) != 0)
688
        goto err;
689
690
      if (mbedtls_md_update(&ctx, md_buf, mds) != 0)
691
        goto err;
692
693
      if (mbedtls_md_finish(&ctx, md_buf) != 0)
694
        goto err;
695
    }
696
697
    i = 0;
698
699
    if (nkey)
700
    {
701
      while (1)
702
      {
703
        if (nkey == 0)
704
          break;
705
706
        if (i == mds)
707
          break;
708
709
        if (key)
710
          *(BYTE*)(key++) = md_buf[i];
711
712
        nkey--;
713
        i++;
714
      }
715
    }
716
717
    if (niv && (i != mds))
718
    {
719
      while (1)
720
      {
721
        if (niv == 0)
722
          break;
723
724
        if (i == mds)
725
          break;
726
727
        if (iv)
728
          *(BYTE*)(iv++) = md_buf[i];
729
730
        niv--;
731
        i++;
732
      }
733
    }
734
735
    if ((nkey == 0) && (niv == 0))
736
      break;
737
  }
738
739
  rv = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
740
err:
741
  mbedtls_md_free(&ctx);
742
  SecureZeroMemory(md_buf, 64);
743
  return rv;
744
#else
745
  return 0;
746
#endif
747
0
}