Coverage Report

Created: 2024-09-08 06:20

/src/FreeRDP/winpr/libwinpr/crypto/hash.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
#ifdef WITH_OPENSSL
26
#include <openssl/md4.h>
27
#include <openssl/md5.h>
28
#include <openssl/sha.h>
29
#include <openssl/evp.h>
30
#include <openssl/hmac.h>
31
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
32
#include <openssl/core_names.h>
33
#endif
34
#endif
35
36
#ifdef WITH_MBEDTLS
37
#ifdef MBEDTLS_MD5_C
38
#include <mbedtls/md5.h>
39
#endif
40
#include <mbedtls/sha1.h>
41
#include <mbedtls/md.h>
42
#if MBEDTLS_VERSION_MAJOR < 3
43
#define mbedtls_md_info_from_ctx(_ctx) (_ctx->md_info)
44
#endif
45
#endif
46
47
#if defined(WITH_INTERNAL_MD4)
48
#include "md4.h"
49
#endif
50
51
#if defined(WITH_INTERNAL_MD5)
52
#include "md5.h"
53
#include "hmac_md5.h"
54
#endif
55
56
#include "../log.h"
57
#define TAG WINPR_TAG("crypto.hash")
58
59
/**
60
 * HMAC
61
 */
62
63
#ifdef WITH_OPENSSL
64
extern const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md);
65
#endif
66
67
#ifdef WITH_OPENSSL
68
const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md)
69
1.62k
{
70
1.62k
  const char* name = winpr_md_type_to_string(md);
71
1.62k
  if (!name)
72
0
    return NULL;
73
1.62k
  return EVP_get_digestbyname(name);
74
1.62k
}
75
#endif
76
77
#ifdef WITH_MBEDTLS
78
mbedtls_md_type_t winpr_mbedtls_get_md_type(int md)
79
{
80
  mbedtls_md_type_t type = MBEDTLS_MD_NONE;
81
82
  switch (md)
83
  {
84
    case WINPR_MD_MD5:
85
      type = MBEDTLS_MD_MD5;
86
      break;
87
88
    case WINPR_MD_SHA1:
89
      type = MBEDTLS_MD_SHA1;
90
      break;
91
92
    case WINPR_MD_SHA224:
93
      type = MBEDTLS_MD_SHA224;
94
      break;
95
96
    case WINPR_MD_SHA256:
97
      type = MBEDTLS_MD_SHA256;
98
      break;
99
100
    case WINPR_MD_SHA384:
101
      type = MBEDTLS_MD_SHA384;
102
      break;
103
104
    case WINPR_MD_SHA512:
105
      type = MBEDTLS_MD_SHA512;
106
      break;
107
  }
108
109
  return type;
110
}
111
#endif
112
113
struct hash_map
114
{
115
  const char* name;
116
  WINPR_MD_TYPE md;
117
};
118
static const struct hash_map hashes[] = { { "md2", WINPR_MD_MD2 },
119
                                        { "md4", WINPR_MD_MD4 },
120
                                        { "md5", WINPR_MD_MD5 },
121
                                        { "sha1", WINPR_MD_SHA1 },
122
                                        { "sha224", WINPR_MD_SHA224 },
123
                                        { "sha256", WINPR_MD_SHA256 },
124
                                        { "sha384", WINPR_MD_SHA384 },
125
                                        { "sha512", WINPR_MD_SHA512 },
126
                                        { "sha3_224", WINPR_MD_SHA3_224 },
127
                                        { "sha3_256", WINPR_MD_SHA3_256 },
128
                                        { "sha3_384", WINPR_MD_SHA3_384 },
129
                                        { "sha3_512", WINPR_MD_SHA3_512 },
130
                                        { "shake128", WINPR_MD_SHAKE128 },
131
                                        { "shake256", WINPR_MD_SHAKE256 },
132
                                        { NULL, WINPR_MD_NONE } };
133
134
WINPR_MD_TYPE winpr_md_type_from_string(const char* name)
135
0
{
136
0
  const struct hash_map* cur = hashes;
137
0
  while (cur->name)
138
0
  {
139
0
    if (_stricmp(cur->name, name) == 0)
140
0
      return cur->md;
141
0
    cur++;
142
0
  }
143
0
  return WINPR_MD_NONE;
144
0
}
145
146
const char* winpr_md_type_to_string(WINPR_MD_TYPE md)
147
1.62k
{
148
1.62k
  const struct hash_map* cur = hashes;
149
6.28k
  while (cur->name)
150
6.28k
  {
151
6.28k
    if (cur->md == md)
152
1.62k
      return cur->name;
153
4.65k
    cur++;
154
4.65k
  }
155
0
  return NULL;
156
1.62k
}
157
158
struct winpr_hmac_ctx_private_st
159
{
160
  WINPR_MD_TYPE md;
161
162
#if defined(WITH_INTERNAL_MD5)
163
  WINPR_HMAC_MD5_CTX hmac_md5;
164
#endif
165
#if defined(WITH_OPENSSL)
166
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
167
  EVP_MAC_CTX* xhmac;
168
#else
169
  HMAC_CTX* hmac;
170
#endif
171
#endif
172
#if defined(WITH_MBEDTLS)
173
  mbedtls_md_context_t hmac;
174
#endif
175
};
176
177
WINPR_HMAC_CTX* winpr_HMAC_New(void)
178
0
{
179
0
  WINPR_HMAC_CTX* ctx = (WINPR_HMAC_CTX*)calloc(1, sizeof(WINPR_HMAC_CTX));
180
0
  if (!ctx)
181
0
    return NULL;
182
0
#if defined(WITH_OPENSSL)
183
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
184
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
185
186
  if (!(ctx->hmac = (HMAC_CTX*)calloc(1, sizeof(HMAC_CTX))))
187
    goto fail;
188
189
  HMAC_CTX_init(ctx->hmac);
190
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
191
0
  if (!(ctx->hmac = HMAC_CTX_new()))
192
0
    goto fail;
193
#else
194
  EVP_MAC* emac = EVP_MAC_fetch(NULL, "HMAC", NULL);
195
  if (!emac)
196
    goto fail;
197
  ctx->xhmac = EVP_MAC_CTX_new(emac);
198
  EVP_MAC_free(emac);
199
  if (!ctx->xhmac)
200
    goto fail;
201
#endif
202
#elif defined(WITH_MBEDTLS)
203
  mbedtls_md_init(&ctx->hmac);
204
#endif
205
0
  return ctx;
206
207
0
fail:
208
0
  WINPR_PRAGMA_DIAG_PUSH
209
0
  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
210
0
  winpr_HMAC_Free(ctx);
211
0
  WINPR_PRAGMA_DIAG_POP
212
0
  return NULL;
213
0
}
214
215
BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const void* key, size_t keylen)
216
0
{
217
0
  WINPR_ASSERT(ctx);
218
219
0
  ctx->md = md;
220
0
  switch (ctx->md)
221
0
  {
222
#if defined(WITH_INTERNAL_MD5)
223
    case WINPR_MD_MD5:
224
      hmac_md5_init(&ctx->hmac_md5, key, keylen);
225
      return TRUE;
226
#endif
227
0
    default:
228
0
      break;
229
0
  }
230
231
0
#if defined(WITH_OPENSSL)
232
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
233
  char* hash = WINPR_CAST_CONST_PTR_AWAY(winpr_md_type_to_string(md), char*);
234
235
  if (!ctx->xhmac)
236
    return FALSE;
237
238
  const char* param_name = OSSL_MAC_PARAM_DIGEST;
239
  const OSSL_PARAM param[] = { OSSL_PARAM_construct_utf8_string(param_name, hash, 0),
240
                             OSSL_PARAM_construct_end() };
241
242
  if (EVP_MAC_init(ctx->xhmac, key, keylen, param) == 1)
243
    return TRUE;
244
#else
245
0
  HMAC_CTX* hmac = ctx->hmac;
246
0
  const EVP_MD* evp = winpr_openssl_get_evp_md(md);
247
248
0
  if (!evp || !hmac)
249
0
    return FALSE;
250
251
0
  if (keylen > INT_MAX)
252
0
    return FALSE;
253
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
254
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
255
  HMAC_Init_ex(hmac, key, (int)keylen, evp, NULL); /* no return value on OpenSSL 0.9.x */
256
  return TRUE;
257
#else
258
259
0
  if (HMAC_Init_ex(hmac, key, (int)keylen, evp, NULL) == 1)
260
0
    return TRUE;
261
262
0
#endif
263
0
#endif
264
#elif defined(WITH_MBEDTLS)
265
  mbedtls_md_context_t* hmac = &ctx->hmac;
266
  mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
267
  const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
268
269
  if (!md_info || !hmac)
270
    return FALSE;
271
272
  if (mbedtls_md_info_from_ctx(hmac) != md_info)
273
  {
274
    mbedtls_md_free(hmac); /* can be called at any time after mbedtls_md_init */
275
276
    if (mbedtls_md_setup(hmac, md_info, 1) != 0)
277
      return FALSE;
278
  }
279
280
  if (mbedtls_md_hmac_starts(hmac, key, keylen) == 0)
281
    return TRUE;
282
283
#endif
284
0
  return FALSE;
285
0
}
286
287
BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const void* input, size_t ilen)
288
0
{
289
0
  WINPR_ASSERT(ctx);
290
291
0
  switch (ctx->md)
292
0
  {
293
#if defined(WITH_INTERNAL_MD5)
294
    case WINPR_MD_MD5:
295
      hmac_md5_update(&ctx->hmac_md5, input, ilen);
296
      return TRUE;
297
#endif
298
0
    default:
299
0
      break;
300
0
  }
301
302
0
#if defined(WITH_OPENSSL)
303
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
304
  if (EVP_MAC_update(ctx->xhmac, input, ilen) == 1)
305
    return TRUE;
306
#else
307
0
  HMAC_CTX* hmac = ctx->hmac;
308
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
309
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
310
  HMAC_Update(hmac, input, ilen); /* no return value on OpenSSL 0.9.x */
311
  return TRUE;
312
#else
313
314
0
  if (HMAC_Update(hmac, input, ilen) == 1)
315
0
    return TRUE;
316
0
#endif
317
0
#endif
318
#elif defined(WITH_MBEDTLS)
319
  mbedtls_md_context_t* mdctx = &ctx->hmac;
320
321
  if (mbedtls_md_hmac_update(mdctx, input, ilen) == 0)
322
    return TRUE;
323
324
#endif
325
0
  return FALSE;
326
0
}
327
328
BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, void* output, size_t olen)
329
0
{
330
0
  WINPR_ASSERT(ctx);
331
332
0
  switch (ctx->md)
333
0
  {
334
#if defined(WITH_INTERNAL_MD5)
335
    case WINPR_MD_MD5:
336
      if (olen < WINPR_MD5_DIGEST_LENGTH)
337
        return FALSE;
338
      hmac_md5_finalize(&ctx->hmac_md5, output);
339
      return TRUE;
340
#endif
341
0
    default:
342
0
      break;
343
0
  }
344
345
0
#if defined(WITH_OPENSSL)
346
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
347
  const int rc = EVP_MAC_final(ctx->xhmac, output, NULL, olen);
348
  if (rc == 1)
349
    return TRUE;
350
#else
351
0
  HMAC_CTX* hmac = ctx->hmac;
352
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
353
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
354
  HMAC_Final(hmac, output, NULL); /* no return value on OpenSSL 0.9.x */
355
  return TRUE;
356
#else
357
358
0
  if (HMAC_Final(hmac, output, NULL) == 1)
359
0
    return TRUE;
360
361
0
#endif
362
0
#endif
363
#elif defined(WITH_MBEDTLS)
364
  mbedtls_md_context_t* mdctx = &ctx->hmac;
365
366
  if (mbedtls_md_hmac_finish(mdctx, output) == 0)
367
    return TRUE;
368
369
#endif
370
0
  return FALSE;
371
0
}
372
373
void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx)
374
0
{
375
0
  if (!ctx)
376
0
    return;
377
378
0
#if defined(WITH_OPENSSL)
379
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
380
  EVP_MAC_CTX_free(ctx->xhmac);
381
#else
382
0
  HMAC_CTX* hmac = ctx->hmac;
383
384
0
  if (hmac)
385
0
  {
386
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
387
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
388
    HMAC_CTX_cleanup(hmac);
389
    free(hmac);
390
#else
391
0
    HMAC_CTX_free(hmac);
392
0
#endif
393
0
  }
394
0
#endif
395
#elif defined(WITH_MBEDTLS)
396
  mbedtls_md_context_t* hmac = &ctx->hmac;
397
398
  if (hmac)
399
    mbedtls_md_free(hmac);
400
401
#endif
402
403
0
  free(ctx);
404
0
}
405
406
BOOL winpr_HMAC(WINPR_MD_TYPE md, const void* key, size_t keylen, const void* input, size_t ilen,
407
                void* output, size_t olen)
408
0
{
409
0
  BOOL result = FALSE;
410
0
  WINPR_HMAC_CTX* ctx = winpr_HMAC_New();
411
412
0
  if (!ctx)
413
0
    return FALSE;
414
415
0
  if (!winpr_HMAC_Init(ctx, md, key, keylen))
416
0
    goto out;
417
418
0
  if (!winpr_HMAC_Update(ctx, input, ilen))
419
0
    goto out;
420
421
0
  if (!winpr_HMAC_Final(ctx, output, olen))
422
0
    goto out;
423
424
0
  result = TRUE;
425
0
out:
426
0
  winpr_HMAC_Free(ctx);
427
0
  return result;
428
0
}
429
430
/**
431
 * Generic Digest API
432
 */
433
434
struct winpr_digest_ctx_private_st
435
{
436
  WINPR_MD_TYPE md;
437
438
#if defined(WITH_INTERNAL_MD4)
439
  WINPR_MD4_CTX md4;
440
#endif
441
#if defined(WITH_INTERNAL_MD5)
442
  WINPR_MD5_CTX md5;
443
#endif
444
#if defined(WITH_OPENSSL)
445
  EVP_MD_CTX* mdctx;
446
#endif
447
#if defined(WITH_MBEDTLS)
448
  mbedtls_md_context_t* mdctx;
449
#endif
450
};
451
452
WINPR_DIGEST_CTX* winpr_Digest_New(void)
453
1.62k
{
454
1.62k
  WINPR_DIGEST_CTX* ctx = calloc(1, sizeof(WINPR_DIGEST_CTX));
455
1.62k
  if (!ctx)
456
0
    return NULL;
457
458
1.62k
#if defined(WITH_OPENSSL)
459
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
460
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
461
  ctx->mdctx = EVP_MD_CTX_create();
462
#else
463
1.62k
  ctx->mdctx = EVP_MD_CTX_new();
464
1.62k
#endif
465
1.62k
  if (!ctx->mdctx)
466
0
    goto fail;
467
468
#elif defined(WITH_MBEDTLS)
469
  ctx->mdctx = (mbedtls_md_context_t*)calloc(1, sizeof(mbedtls_md_context_t));
470
471
  if (!ctx->mdctx)
472
    goto fail;
473
474
  mbedtls_md_init(ctx->mdctx);
475
#endif
476
1.62k
  return ctx;
477
478
0
fail:
479
0
  WINPR_PRAGMA_DIAG_PUSH
480
0
  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
481
0
  winpr_Digest_Free(ctx);
482
0
  WINPR_PRAGMA_DIAG_POP
483
0
  return NULL;
484
1.62k
}
485
486
#if defined(WITH_OPENSSL)
487
static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, const EVP_MD* evp)
488
1.62k
{
489
1.62k
  WINPR_ASSERT(ctx);
490
1.62k
  EVP_MD_CTX* mdctx = ctx->mdctx;
491
492
1.62k
  if (!mdctx || !evp)
493
0
    return FALSE;
494
495
1.62k
  if (EVP_DigestInit_ex(mdctx, evp, NULL) != 1)
496
0
  {
497
0
    WLog_ERR(TAG, "Failed to initialize digest %s", winpr_md_type_to_string(ctx->md));
498
0
    return FALSE;
499
0
  }
500
501
1.62k
  return TRUE;
502
1.62k
}
503
504
#elif defined(WITH_MBEDTLS)
505
static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
506
{
507
  WINPR_ASSERT(ctx);
508
  mbedtls_md_context_t* mdctx = ctx->mdctx;
509
  mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
510
  const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
511
512
  if (!md_info)
513
    return FALSE;
514
515
  if (mbedtls_md_info_from_ctx(mdctx) != md_info)
516
  {
517
    mbedtls_md_free(mdctx); /* can be called at any time after mbedtls_md_init */
518
519
    if (mbedtls_md_setup(mdctx, md_info, 0) != 0)
520
      return FALSE;
521
  }
522
523
  if (mbedtls_md_starts(mdctx) != 0)
524
    return FALSE;
525
526
  return TRUE;
527
}
528
#endif
529
530
BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
531
0
{
532
0
  WINPR_ASSERT(ctx);
533
534
0
  ctx->md = md;
535
0
  switch (md)
536
0
  {
537
0
    case WINPR_MD_MD5:
538
#if defined(WITH_INTERNAL_MD5)
539
      winpr_MD5_Init(&ctx->md5);
540
      return TRUE;
541
#endif
542
0
      break;
543
0
    default:
544
0
      WLog_ERR(TAG, "Invalid FIPS digest %s requested", winpr_md_type_to_string(md));
545
0
      return FALSE;
546
0
  }
547
548
0
#if defined(WITH_OPENSSL)
549
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
550
  if (md == WINPR_MD_MD5)
551
  {
552
    EVP_MD* md5 = EVP_MD_fetch(NULL, "MD5", "fips=no");
553
    BOOL rc = winpr_Digest_Init_Internal(ctx, md5);
554
    EVP_MD_free(md5);
555
    return rc;
556
  }
557
#endif
558
0
  const EVP_MD* evp = winpr_openssl_get_evp_md(md);
559
0
  EVP_MD_CTX_set_flags(ctx->mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
560
0
  return winpr_Digest_Init_Internal(ctx, evp);
561
#elif defined(WITH_MBEDTLS)
562
  return winpr_Digest_Init_Internal(ctx, md);
563
#endif
564
0
}
565
566
BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
567
1.62k
{
568
1.62k
  WINPR_ASSERT(ctx);
569
570
1.62k
  ctx->md = md;
571
1.62k
  switch (md)
572
1.62k
  {
573
#if defined(WITH_INTERNAL_MD4)
574
    case WINPR_MD_MD4:
575
      winpr_MD4_Init(&ctx->md4);
576
      return TRUE;
577
#endif
578
#if defined(WITH_INTERNAL_MD5)
579
    case WINPR_MD_MD5:
580
      winpr_MD5_Init(&ctx->md5);
581
      return TRUE;
582
#endif
583
1.62k
    default:
584
1.62k
      break;
585
1.62k
  }
586
587
1.62k
#if defined(WITH_OPENSSL)
588
1.62k
  const EVP_MD* evp = winpr_openssl_get_evp_md(md);
589
1.62k
  return winpr_Digest_Init_Internal(ctx, evp);
590
#else
591
  return winpr_Digest_Init_Internal(ctx, md);
592
#endif
593
1.62k
}
594
595
BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
596
1.62k
{
597
1.62k
  WINPR_ASSERT(ctx);
598
599
1.62k
  switch (ctx->md)
600
1.62k
  {
601
#if defined(WITH_INTERNAL_MD4)
602
    case WINPR_MD_MD4:
603
      winpr_MD4_Update(&ctx->md4, input, ilen);
604
      return TRUE;
605
#endif
606
#if defined(WITH_INTERNAL_MD5)
607
    case WINPR_MD_MD5:
608
      winpr_MD5_Update(&ctx->md5, input, ilen);
609
      return TRUE;
610
#endif
611
1.62k
    default:
612
1.62k
      break;
613
1.62k
  }
614
615
1.62k
#if defined(WITH_OPENSSL)
616
1.62k
  EVP_MD_CTX* mdctx = ctx->mdctx;
617
618
1.62k
  if (EVP_DigestUpdate(mdctx, input, ilen) != 1)
619
0
    return FALSE;
620
621
#elif defined(WITH_MBEDTLS)
622
  mbedtls_md_context_t* mdctx = ctx->mdctx;
623
624
  if (mbedtls_md_update(mdctx, input, ilen) != 0)
625
    return FALSE;
626
627
#endif
628
1.62k
  return TRUE;
629
1.62k
}
630
631
BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, void* output, size_t olen)
632
1.62k
{
633
1.62k
  WINPR_ASSERT(ctx);
634
635
1.62k
  switch (ctx->md)
636
1.62k
  {
637
#if defined(WITH_INTERNAL_MD4)
638
    case WINPR_MD_MD4:
639
      if (olen < WINPR_MD4_DIGEST_LENGTH)
640
        return FALSE;
641
      winpr_MD4_Final(output, &ctx->md4);
642
      return TRUE;
643
#endif
644
#if defined(WITH_INTERNAL_MD5)
645
    case WINPR_MD_MD5:
646
      if (olen < WINPR_MD5_DIGEST_LENGTH)
647
        return FALSE;
648
      winpr_MD5_Final(output, &ctx->md5);
649
      return TRUE;
650
#endif
651
652
1.62k
    default:
653
1.62k
      break;
654
1.62k
  }
655
656
1.62k
#if defined(WITH_OPENSSL)
657
1.62k
  EVP_MD_CTX* mdctx = ctx->mdctx;
658
659
1.62k
  if (EVP_DigestFinal_ex(mdctx, output, NULL) == 1)
660
1.62k
    return TRUE;
661
662
#elif defined(WITH_MBEDTLS)
663
  mbedtls_md_context_t* mdctx = ctx->mdctx;
664
665
  if (mbedtls_md_finish(mdctx, output) == 0)
666
    return TRUE;
667
668
#endif
669
0
  return FALSE;
670
1.62k
}
671
672
BOOL winpr_DigestSign_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE digest, void* key)
673
0
{
674
0
  WINPR_ASSERT(ctx);
675
676
0
#if defined(WITH_OPENSSL)
677
0
  const EVP_MD* evp = winpr_openssl_get_evp_md(digest);
678
0
  if (!evp)
679
0
    return FALSE;
680
681
0
  const int rdsi = EVP_DigestSignInit(ctx->mdctx, NULL, evp, NULL, key);
682
0
  if (rdsi <= 0)
683
0
    return FALSE;
684
0
  return TRUE;
685
#else
686
  return FALSE;
687
#endif
688
0
}
689
690
BOOL winpr_DigestSign_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
691
0
{
692
0
  WINPR_ASSERT(ctx);
693
694
0
#if defined(WITH_OPENSSL)
695
0
  EVP_MD_CTX* mdctx = ctx->mdctx;
696
697
0
  if (EVP_DigestSignUpdate(mdctx, input, ilen) != 1)
698
0
    return FALSE;
699
0
  return TRUE;
700
#else
701
  return FALSE;
702
#endif
703
0
}
704
705
BOOL winpr_DigestSign_Final(WINPR_DIGEST_CTX* ctx, void* output, size_t* piolen)
706
0
{
707
0
  WINPR_ASSERT(ctx);
708
709
0
#if defined(WITH_OPENSSL)
710
0
  EVP_MD_CTX* mdctx = ctx->mdctx;
711
712
0
  return EVP_DigestSignFinal(mdctx, output, piolen) == 1;
713
#else
714
  return FALSE;
715
#endif
716
0
}
717
718
void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx)
719
1.62k
{
720
1.62k
  if (!ctx)
721
0
    return;
722
1.62k
#if defined(WITH_OPENSSL)
723
1.62k
  if (ctx->mdctx)
724
1.62k
  {
725
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
726
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
727
    EVP_MD_CTX_destroy(ctx->mdctx);
728
#else
729
1.62k
    EVP_MD_CTX_free(ctx->mdctx);
730
1.62k
#endif
731
1.62k
  }
732
733
#elif defined(WITH_MBEDTLS)
734
  if (ctx->mdctx)
735
  {
736
    mbedtls_md_free(ctx->mdctx);
737
    free(ctx->mdctx);
738
  }
739
740
#endif
741
1.62k
  free(ctx);
742
1.62k
}
743
744
BOOL winpr_Digest_Allow_FIPS(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output,
745
                             size_t olen)
746
0
{
747
0
  BOOL result = FALSE;
748
0
  WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
749
750
0
  if (!ctx)
751
0
    return FALSE;
752
753
0
  if (!winpr_Digest_Init_Allow_FIPS(ctx, md))
754
0
    goto out;
755
756
0
  if (!winpr_Digest_Update(ctx, input, ilen))
757
0
    goto out;
758
759
0
  if (!winpr_Digest_Final(ctx, output, olen))
760
0
    goto out;
761
762
0
  result = TRUE;
763
0
out:
764
0
  winpr_Digest_Free(ctx);
765
0
  return result;
766
0
}
767
768
BOOL winpr_Digest(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output, size_t olen)
769
1.62k
{
770
1.62k
  BOOL result = FALSE;
771
1.62k
  WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
772
773
1.62k
  if (!ctx)
774
0
    return FALSE;
775
776
1.62k
  if (!winpr_Digest_Init(ctx, md))
777
0
    goto out;
778
779
1.62k
  if (!winpr_Digest_Update(ctx, input, ilen))
780
0
    goto out;
781
782
1.62k
  if (!winpr_Digest_Final(ctx, output, olen))
783
0
    goto out;
784
785
1.62k
  result = TRUE;
786
1.62k
out:
787
1.62k
  winpr_Digest_Free(ctx);
788
1.62k
  return result;
789
1.62k
}