Coverage Report

Created: 2023-09-25 06:56

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