Coverage Report

Created: 2024-05-20 06:11

/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.24k
  while (cur->name)
150
6.24k
  {
151
6.24k
    if (cur->md == md)
152
1.62k
      return cur->name;
153
4.62k
    cur++;
154
4.62k
  }
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
  const char* hash = winpr_md_type_to_string(md);
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
0
  const EVP_MD* evp = winpr_openssl_get_evp_md(md);
550
0
  EVP_MD_CTX_set_flags(ctx->mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
551
0
  return winpr_Digest_Init_Internal(ctx, evp);
552
#elif defined(WITH_MBEDTLS)
553
  return winpr_Digest_Init_Internal(ctx, md);
554
#endif
555
0
}
556
557
BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
558
1.62k
{
559
1.62k
  WINPR_ASSERT(ctx);
560
561
1.62k
  ctx->md = md;
562
1.62k
  switch (md)
563
1.62k
  {
564
#if defined(WITH_INTERNAL_MD4)
565
    case WINPR_MD_MD4:
566
      winpr_MD4_Init(&ctx->md4);
567
      return TRUE;
568
#endif
569
#if defined(WITH_INTERNAL_MD5)
570
    case WINPR_MD_MD5:
571
      winpr_MD5_Init(&ctx->md5);
572
      return TRUE;
573
#endif
574
1.62k
    default:
575
1.62k
      break;
576
1.62k
  }
577
578
1.62k
#if defined(WITH_OPENSSL)
579
1.62k
  const EVP_MD* evp = winpr_openssl_get_evp_md(md);
580
1.62k
  return winpr_Digest_Init_Internal(ctx, evp);
581
#else
582
  return winpr_Digest_Init_Internal(ctx, md);
583
#endif
584
1.62k
}
585
586
BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
587
1.62k
{
588
1.62k
  WINPR_ASSERT(ctx);
589
590
1.62k
  switch (ctx->md)
591
1.62k
  {
592
#if defined(WITH_INTERNAL_MD4)
593
    case WINPR_MD_MD4:
594
      winpr_MD4_Update(&ctx->md4, input, ilen);
595
      return TRUE;
596
#endif
597
#if defined(WITH_INTERNAL_MD5)
598
    case WINPR_MD_MD5:
599
      winpr_MD5_Update(&ctx->md5, input, ilen);
600
      return TRUE;
601
#endif
602
1.62k
    default:
603
1.62k
      break;
604
1.62k
  }
605
606
1.62k
#if defined(WITH_OPENSSL)
607
1.62k
  EVP_MD_CTX* mdctx = ctx->mdctx;
608
609
1.62k
  if (EVP_DigestUpdate(mdctx, input, ilen) != 1)
610
0
    return FALSE;
611
612
#elif defined(WITH_MBEDTLS)
613
  mbedtls_md_context_t* mdctx = ctx->mdctx;
614
615
  if (mbedtls_md_update(mdctx, input, ilen) != 0)
616
    return FALSE;
617
618
#endif
619
1.62k
  return TRUE;
620
1.62k
}
621
622
BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, void* output, size_t olen)
623
1.62k
{
624
1.62k
  WINPR_ASSERT(ctx);
625
626
1.62k
  switch (ctx->md)
627
1.62k
  {
628
#if defined(WITH_INTERNAL_MD4)
629
    case WINPR_MD_MD4:
630
      if (olen < WINPR_MD4_DIGEST_LENGTH)
631
        return FALSE;
632
      winpr_MD4_Final(output, &ctx->md4);
633
      return TRUE;
634
#endif
635
#if defined(WITH_INTERNAL_MD5)
636
    case WINPR_MD_MD5:
637
      if (olen < WINPR_MD5_DIGEST_LENGTH)
638
        return FALSE;
639
      winpr_MD5_Final(output, &ctx->md5);
640
      return TRUE;
641
#endif
642
643
1.62k
    default:
644
1.62k
      break;
645
1.62k
  }
646
647
1.62k
#if defined(WITH_OPENSSL)
648
1.62k
  EVP_MD_CTX* mdctx = ctx->mdctx;
649
650
1.62k
  if (EVP_DigestFinal_ex(mdctx, output, NULL) == 1)
651
1.62k
    return TRUE;
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.62k
}
662
663
BOOL winpr_DigestSign_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE digest, 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(digest);
669
0
  if (!evp)
670
0
    return FALSE;
671
672
0
  const int rdsi = EVP_DigestSignInit(ctx->mdctx, NULL, evp, NULL, key);
673
0
  if (rdsi <= 0)
674
0
    return FALSE;
675
0
  return TRUE;
676
#else
677
  return FALSE;
678
#endif
679
0
}
680
681
BOOL winpr_DigestSign_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
682
0
{
683
0
  WINPR_ASSERT(ctx);
684
685
0
#if defined(WITH_OPENSSL)
686
0
  EVP_MD_CTX* mdctx = ctx->mdctx;
687
688
0
  if (EVP_DigestSignUpdate(mdctx, input, ilen) != 1)
689
0
    return FALSE;
690
0
  return TRUE;
691
#else
692
  return FALSE;
693
#endif
694
0
}
695
696
BOOL winpr_DigestSign_Final(WINPR_DIGEST_CTX* ctx, void* output, size_t* piolen)
697
0
{
698
0
  WINPR_ASSERT(ctx);
699
700
0
#if defined(WITH_OPENSSL)
701
0
  EVP_MD_CTX* mdctx = ctx->mdctx;
702
703
0
  return EVP_DigestSignFinal(mdctx, output, piolen) == 1;
704
#else
705
  return FALSE;
706
#endif
707
0
}
708
709
void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx)
710
1.62k
{
711
1.62k
  if (!ctx)
712
0
    return;
713
1.62k
#if defined(WITH_OPENSSL)
714
1.62k
  if (ctx->mdctx)
715
1.62k
  {
716
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
717
    (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
718
    EVP_MD_CTX_destroy(ctx->mdctx);
719
#else
720
1.62k
    EVP_MD_CTX_free(ctx->mdctx);
721
1.62k
#endif
722
1.62k
  }
723
724
#elif defined(WITH_MBEDTLS)
725
  if (ctx->mdctx)
726
  {
727
    mbedtls_md_free(ctx->mdctx);
728
    free(ctx->mdctx);
729
  }
730
731
#endif
732
1.62k
  free(ctx);
733
1.62k
}
734
735
BOOL winpr_Digest_Allow_FIPS(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output,
736
                             size_t olen)
737
0
{
738
0
  BOOL result = FALSE;
739
0
  WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
740
741
0
  if (!ctx)
742
0
    return FALSE;
743
744
0
  if (!winpr_Digest_Init_Allow_FIPS(ctx, md))
745
0
    goto out;
746
747
0
  if (!winpr_Digest_Update(ctx, input, ilen))
748
0
    goto out;
749
750
0
  if (!winpr_Digest_Final(ctx, output, olen))
751
0
    goto out;
752
753
0
  result = TRUE;
754
0
out:
755
0
  winpr_Digest_Free(ctx);
756
0
  return result;
757
0
}
758
759
BOOL winpr_Digest(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output, size_t olen)
760
1.62k
{
761
1.62k
  BOOL result = FALSE;
762
1.62k
  WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
763
764
1.62k
  if (!ctx)
765
0
    return FALSE;
766
767
1.62k
  if (!winpr_Digest_Init(ctx, md))
768
0
    goto out;
769
770
1.62k
  if (!winpr_Digest_Update(ctx, input, ilen))
771
0
    goto out;
772
773
1.62k
  if (!winpr_Digest_Final(ctx, output, olen))
774
0
    goto out;
775
776
1.62k
  result = TRUE;
777
1.62k
out:
778
1.62k
  winpr_Digest_Free(ctx);
779
1.62k
  return result;
780
1.62k
}