Coverage Report

Created: 2026-03-04 06:13

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