Coverage Report

Created: 2025-07-01 06:46

/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
0
{
70
0
  const char* name = winpr_md_type_to_string(md);
71
0
  if (!name)
72
0
    return NULL;
73
0
  return EVP_get_digestbyname(name);
74
0
}
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
0
{
148
0
  const struct hash_map* cur = hashes;
149
0
  while (cur->name)
150
0
  {
151
0
    if (cur->md == md)
152
0
      return cur->name;
153
0
    cur++;
154
0
  }
155
0
  return NULL;
156
0
}
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
0
{
454
0
  WINPR_DIGEST_CTX* ctx = calloc(1, sizeof(WINPR_DIGEST_CTX));
455
0
  if (!ctx)
456
0
    return NULL;
457
458
0
#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
0
  ctx->mdctx = EVP_MD_CTX_new();
464
0
#endif
465
0
  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
0
  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
0
}
485
486
#if defined(WITH_OPENSSL)
487
static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, const EVP_MD* evp)
488
0
{
489
0
  WINPR_ASSERT(ctx);
490
0
  EVP_MD_CTX* mdctx = ctx->mdctx;
491
492
0
  if (!mdctx || !evp)
493
0
    return FALSE;
494
495
0
  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
0
  return TRUE;
502
0
}
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
0
    {
539
#if defined(WITH_INTERNAL_MD5)
540
      winpr_MD5_Init(&ctx->md5);
541
      return TRUE;
542
#elif defined(WITH_OPENSSL)
543
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
544
#if !defined(WITH_INTERNAL_MD5)
545
      if (md == WINPR_MD_MD5)
546
      {
547
        EVP_MD* md5 = EVP_MD_fetch(NULL, "MD5", "fips=no");
548
        BOOL rc = winpr_Digest_Init_Internal(ctx, md5);
549
        EVP_MD_free(md5);
550
        return rc;
551
      }
552
#endif
553
#endif
554
0
      const EVP_MD* evp = winpr_openssl_get_evp_md(md);
555
0
      EVP_MD_CTX_set_flags(ctx->mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
556
0
      return winpr_Digest_Init_Internal(ctx, evp);
557
#elif defined(WITH_MBEDTLS)
558
      return winpr_Digest_Init_Internal(ctx, md);
559
#endif
560
0
    }
561
0
    default:
562
0
      WLog_ERR(TAG, "Invalid FIPS digest %s requested", winpr_md_type_to_string(md));
563
0
      return FALSE;
564
0
  }
565
0
}
566
567
BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
568
0
{
569
0
  WINPR_ASSERT(ctx);
570
571
0
  ctx->md = md;
572
0
  switch (md)
573
0
  {
574
#if defined(WITH_INTERNAL_MD4)
575
    case WINPR_MD_MD4:
576
      winpr_MD4_Init(&ctx->md4);
577
      return TRUE;
578
#endif
579
#if defined(WITH_INTERNAL_MD5)
580
    case WINPR_MD_MD5:
581
      winpr_MD5_Init(&ctx->md5);
582
      return TRUE;
583
#endif
584
0
    default:
585
0
      break;
586
0
  }
587
588
0
#if defined(WITH_OPENSSL)
589
0
  const EVP_MD* evp = winpr_openssl_get_evp_md(md);
590
0
  return winpr_Digest_Init_Internal(ctx, evp);
591
#else
592
  return winpr_Digest_Init_Internal(ctx, md);
593
#endif
594
0
}
595
596
BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
597
0
{
598
0
  WINPR_ASSERT(ctx);
599
600
0
  switch (ctx->md)
601
0
  {
602
#if defined(WITH_INTERNAL_MD4)
603
    case WINPR_MD_MD4:
604
      winpr_MD4_Update(&ctx->md4, input, ilen);
605
      return TRUE;
606
#endif
607
#if defined(WITH_INTERNAL_MD5)
608
    case WINPR_MD_MD5:
609
      winpr_MD5_Update(&ctx->md5, input, ilen);
610
      return TRUE;
611
#endif
612
0
    default:
613
0
      break;
614
0
  }
615
616
0
#if defined(WITH_OPENSSL)
617
0
  EVP_MD_CTX* mdctx = ctx->mdctx;
618
619
0
  if (EVP_DigestUpdate(mdctx, input, ilen) != 1)
620
0
    return FALSE;
621
622
#elif defined(WITH_MBEDTLS)
623
  mbedtls_md_context_t* mdctx = ctx->mdctx;
624
625
  if (mbedtls_md_update(mdctx, input, ilen) != 0)
626
    return FALSE;
627
628
#endif
629
0
  return TRUE;
630
0
}
631
632
BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, void* output, WINPR_ATTR_UNUSED size_t olen)
633
0
{
634
0
  WINPR_ASSERT(ctx);
635
636
0
  switch (ctx->md)
637
0
  {
638
#if defined(WITH_INTERNAL_MD4)
639
    case WINPR_MD_MD4:
640
      if (olen < WINPR_MD4_DIGEST_LENGTH)
641
        return FALSE;
642
      winpr_MD4_Final(output, &ctx->md4);
643
      return TRUE;
644
#endif
645
#if defined(WITH_INTERNAL_MD5)
646
    case WINPR_MD_MD5:
647
      if (olen < WINPR_MD5_DIGEST_LENGTH)
648
        return FALSE;
649
      winpr_MD5_Final(output, &ctx->md5);
650
      return TRUE;
651
#endif
652
653
0
    default:
654
0
      break;
655
0
  }
656
657
0
#if defined(WITH_OPENSSL)
658
0
  EVP_MD_CTX* mdctx = ctx->mdctx;
659
660
0
  if (EVP_DigestFinal_ex(mdctx, output, NULL) == 1)
661
0
    return TRUE;
662
663
#elif defined(WITH_MBEDTLS)
664
  mbedtls_md_context_t* mdctx = ctx->mdctx;
665
666
  if (mbedtls_md_finish(mdctx, output) == 0)
667
    return TRUE;
668
669
#endif
670
0
  return FALSE;
671
0
}
672
673
BOOL winpr_DigestSign_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md, void* key)
674
0
{
675
0
  WINPR_ASSERT(ctx);
676
677
0
#if defined(WITH_OPENSSL)
678
0
  const EVP_MD* evp = winpr_openssl_get_evp_md(md);
679
0
  if (!evp)
680
0
    return FALSE;
681
682
0
  const int rdsi = EVP_DigestSignInit(ctx->mdctx, NULL, evp, NULL, key);
683
0
  if (rdsi <= 0)
684
0
    return FALSE;
685
0
  return TRUE;
686
#else
687
  return FALSE;
688
#endif
689
0
}
690
691
BOOL winpr_DigestSign_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
692
0
{
693
0
  WINPR_ASSERT(ctx);
694
695
0
#if defined(WITH_OPENSSL)
696
0
  EVP_MD_CTX* mdctx = ctx->mdctx;
697
698
0
  if (EVP_DigestSignUpdate(mdctx, input, ilen) != 1)
699
0
    return FALSE;
700
0
  return TRUE;
701
#else
702
  return FALSE;
703
#endif
704
0
}
705
706
BOOL winpr_DigestSign_Final(WINPR_DIGEST_CTX* ctx, void* output, size_t* piolen)
707
0
{
708
0
  WINPR_ASSERT(ctx);
709
710
0
#if defined(WITH_OPENSSL)
711
0
  EVP_MD_CTX* mdctx = ctx->mdctx;
712
713
0
  return EVP_DigestSignFinal(mdctx, output, piolen) == 1;
714
#else
715
  return FALSE;
716
#endif
717
0
}
718
719
void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx)
720
0
{
721
0
  if (!ctx)
722
0
    return;
723
0
#if defined(WITH_OPENSSL)
724
0
  if (ctx->mdctx)
725
0
  {
726
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
727
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
728
    EVP_MD_CTX_destroy(ctx->mdctx);
729
#else
730
0
    EVP_MD_CTX_free(ctx->mdctx);
731
0
#endif
732
0
  }
733
734
#elif defined(WITH_MBEDTLS)
735
  if (ctx->mdctx)
736
  {
737
    mbedtls_md_free(ctx->mdctx);
738
    free(ctx->mdctx);
739
  }
740
741
#endif
742
0
  free(ctx);
743
0
}
744
745
BOOL winpr_Digest_Allow_FIPS(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output,
746
                             size_t olen)
747
0
{
748
0
  BOOL result = FALSE;
749
0
  WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
750
751
0
  if (!ctx)
752
0
    return FALSE;
753
754
0
  if (!winpr_Digest_Init_Allow_FIPS(ctx, md))
755
0
    goto out;
756
757
0
  if (!winpr_Digest_Update(ctx, input, ilen))
758
0
    goto out;
759
760
0
  if (!winpr_Digest_Final(ctx, output, olen))
761
0
    goto out;
762
763
0
  result = TRUE;
764
0
out:
765
0
  winpr_Digest_Free(ctx);
766
0
  return result;
767
0
}
768
769
BOOL winpr_Digest(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output, size_t olen)
770
0
{
771
0
  BOOL result = FALSE;
772
0
  WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
773
774
0
  if (!ctx)
775
0
    return FALSE;
776
777
0
  if (!winpr_Digest_Init(ctx, md))
778
0
    goto out;
779
780
0
  if (!winpr_Digest_Update(ctx, input, ilen))
781
0
    goto out;
782
783
0
  if (!winpr_Digest_Final(ctx, output, olen))
784
0
    goto out;
785
786
0
  result = TRUE;
787
0
out:
788
0
  winpr_Digest_Free(ctx);
789
0
  return result;
790
0
}