FreeRDP
Loading...
Searching...
No Matches
libwinpr/crypto/hash.c
1
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
63#ifdef WITH_OPENSSL
64extern const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md);
65#endif
66
67#ifdef WITH_OPENSSL
68const EVP_MD* winpr_openssl_get_evp_md(WINPR_MD_TYPE md)
69{
70 const char* name = winpr_md_type_to_string(md);
71 if (!name)
72 return NULL;
73 return EVP_get_digestbyname(name);
74}
75#endif
76
77#ifdef WITH_MBEDTLS
78mbedtls_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
113struct hash_map
114{
115 const char* name;
116 WINPR_MD_TYPE md;
117};
118static 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
134WINPR_MD_TYPE winpr_md_type_from_string(const char* name)
135{
136 const struct hash_map* cur = hashes;
137 while (cur->name)
138 {
139 if (_stricmp(cur->name, name) == 0)
140 return cur->md;
141 cur++;
142 }
143 return WINPR_MD_NONE;
144}
145
146const char* winpr_md_type_to_string(WINPR_MD_TYPE md)
147{
148 const struct hash_map* cur = hashes;
149 while (cur->name)
150 {
151 if (cur->md == md)
152 return cur->name;
153 cur++;
154 }
155 return NULL;
156}
157
158struct 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
177WINPR_HMAC_CTX* winpr_HMAC_New(void)
178{
179 WINPR_HMAC_CTX* ctx = (WINPR_HMAC_CTX*)calloc(1, sizeof(WINPR_HMAC_CTX));
180 if (!ctx)
181 return NULL;
182#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 if (!(ctx->hmac = HMAC_CTX_new()))
192 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 return ctx;
206
207fail:
208 WINPR_PRAGMA_DIAG_PUSH
209 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
210 winpr_HMAC_Free(ctx);
211 WINPR_PRAGMA_DIAG_POP
212 return NULL;
213}
214
215BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const void* key, size_t keylen)
216{
217 WINPR_ASSERT(ctx);
218
219 ctx->md = md;
220 switch (ctx->md)
221 {
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 default:
228 break;
229 }
230
231#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 HMAC_CTX* hmac = ctx->hmac;
246 const EVP_MD* evp = winpr_openssl_get_evp_md(md);
247
248 if (!evp || !hmac)
249 return FALSE;
250
251 if (keylen > INT_MAX)
252 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 if (HMAC_Init_ex(hmac, key, (int)keylen, evp, NULL) == 1)
260 return TRUE;
261
262#endif
263#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 return FALSE;
285}
286
287BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const void* input, size_t ilen)
288{
289 WINPR_ASSERT(ctx);
290
291 switch (ctx->md)
292 {
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 default:
299 break;
300 }
301
302#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 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 if (HMAC_Update(hmac, input, ilen) == 1)
315 return TRUE;
316#endif
317#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 return FALSE;
326}
327
328BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, void* output, size_t olen)
329{
330 WINPR_ASSERT(ctx);
331
332 switch (ctx->md)
333 {
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 default:
342 break;
343 }
344
345#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 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 if (HMAC_Final(hmac, output, NULL) == 1)
359 return TRUE;
360
361#endif
362#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 return FALSE;
371}
372
373void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx)
374{
375 if (!ctx)
376 return;
377
378#if defined(WITH_OPENSSL)
379#if OPENSSL_VERSION_NUMBER >= 0x30000000L
380 EVP_MAC_CTX_free(ctx->xhmac);
381#else
382 HMAC_CTX* hmac = ctx->hmac;
383
384 if (hmac)
385 {
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 HMAC_CTX_free(hmac);
392#endif
393 }
394#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 free(ctx);
404}
405
406BOOL 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{
409 BOOL result = FALSE;
410 WINPR_HMAC_CTX* ctx = winpr_HMAC_New();
411
412 if (!ctx)
413 return FALSE;
414
415 if (!winpr_HMAC_Init(ctx, md, key, keylen))
416 goto out;
417
418 if (!winpr_HMAC_Update(ctx, input, ilen))
419 goto out;
420
421 if (!winpr_HMAC_Final(ctx, output, olen))
422 goto out;
423
424 result = TRUE;
425out:
426 winpr_HMAC_Free(ctx);
427 return result;
428}
429
434struct 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
452WINPR_DIGEST_CTX* winpr_Digest_New(void)
453{
454 WINPR_DIGEST_CTX* ctx = calloc(1, sizeof(WINPR_DIGEST_CTX));
455 if (!ctx)
456 return NULL;
457
458#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 ctx->mdctx = EVP_MD_CTX_new();
464#endif
465 if (!ctx->mdctx)
466 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 return ctx;
477
478fail:
479 WINPR_PRAGMA_DIAG_PUSH
480 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
481 winpr_Digest_Free(ctx);
482 WINPR_PRAGMA_DIAG_POP
483 return NULL;
484}
485
486#if defined(WITH_OPENSSL)
487static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, const EVP_MD* evp)
488{
489 WINPR_ASSERT(ctx);
490 EVP_MD_CTX* mdctx = ctx->mdctx;
491
492 if (!mdctx || !evp)
493 return FALSE;
494
495 if (EVP_DigestInit_ex(mdctx, evp, NULL) != 1)
496 {
497 WLog_ERR(TAG, "Failed to initialize digest %s", winpr_md_type_to_string(ctx->md));
498 return FALSE;
499 }
500
501 return TRUE;
502}
503
504#elif defined(WITH_MBEDTLS)
505static 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
530BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
531{
532 WINPR_ASSERT(ctx);
533
534 ctx->md = md;
535 switch (md)
536 {
537 case WINPR_MD_MD5:
538 {
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 const EVP_MD* evp = winpr_openssl_get_evp_md(md);
555 EVP_MD_CTX_set_flags(ctx->mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
556 return winpr_Digest_Init_Internal(ctx, evp);
557#elif defined(WITH_MBEDTLS)
558 return winpr_Digest_Init_Internal(ctx, md);
559#endif
560 }
561 default:
562 WLog_ERR(TAG, "Invalid FIPS digest %s requested", winpr_md_type_to_string(md));
563 return FALSE;
564 }
565}
566
567BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
568{
569 WINPR_ASSERT(ctx);
570
571 ctx->md = md;
572 switch (md)
573 {
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 default:
585 break;
586 }
587
588#if defined(WITH_OPENSSL)
589 const EVP_MD* evp = winpr_openssl_get_evp_md(md);
590 return winpr_Digest_Init_Internal(ctx, evp);
591#else
592 return winpr_Digest_Init_Internal(ctx, md);
593#endif
594}
595
596BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
597{
598 WINPR_ASSERT(ctx);
599
600 switch (ctx->md)
601 {
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 default:
613 break;
614 }
615
616#if defined(WITH_OPENSSL)
617 EVP_MD_CTX* mdctx = ctx->mdctx;
618
619 if (EVP_DigestUpdate(mdctx, input, ilen) != 1)
620 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 return TRUE;
630}
631
632BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, void* output, WINPR_ATTR_UNUSED size_t olen)
633{
634 WINPR_ASSERT(ctx);
635
636 switch (ctx->md)
637 {
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 default:
654 break;
655 }
656
657#if defined(WITH_OPENSSL)
658 EVP_MD_CTX* mdctx = ctx->mdctx;
659
660 if (EVP_DigestFinal_ex(mdctx, output, NULL) == 1)
661 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 return FALSE;
671}
672
673BOOL winpr_DigestSign_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md, void* key)
674{
675 WINPR_ASSERT(ctx);
676
677#if defined(WITH_OPENSSL)
678 const EVP_MD* evp = winpr_openssl_get_evp_md(md);
679 if (!evp)
680 return FALSE;
681
682 const int rdsi = EVP_DigestSignInit(ctx->mdctx, NULL, evp, NULL, key);
683 if (rdsi <= 0)
684 return FALSE;
685 return TRUE;
686#else
687 return FALSE;
688#endif
689}
690
691BOOL winpr_DigestSign_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
692{
693 WINPR_ASSERT(ctx);
694
695#if defined(WITH_OPENSSL)
696 EVP_MD_CTX* mdctx = ctx->mdctx;
697
698 if (EVP_DigestSignUpdate(mdctx, input, ilen) != 1)
699 return FALSE;
700 return TRUE;
701#else
702 return FALSE;
703#endif
704}
705
706BOOL winpr_DigestSign_Final(WINPR_DIGEST_CTX* ctx, void* output, size_t* piolen)
707{
708 WINPR_ASSERT(ctx);
709
710#if defined(WITH_OPENSSL)
711 EVP_MD_CTX* mdctx = ctx->mdctx;
712
713 return EVP_DigestSignFinal(mdctx, output, piolen) == 1;
714#else
715 return FALSE;
716#endif
717}
718
719void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx)
720{
721 if (!ctx)
722 return;
723#if defined(WITH_OPENSSL)
724 if (ctx->mdctx)
725 {
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 EVP_MD_CTX_free(ctx->mdctx);
731#endif
732 }
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 free(ctx);
743}
744
745BOOL winpr_Digest_Allow_FIPS(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output,
746 size_t olen)
747{
748 BOOL result = FALSE;
749 WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
750
751 if (!ctx)
752 return FALSE;
753
754 if (!winpr_Digest_Init_Allow_FIPS(ctx, md))
755 goto out;
756
757 if (!winpr_Digest_Update(ctx, input, ilen))
758 goto out;
759
760 if (!winpr_Digest_Final(ctx, output, olen))
761 goto out;
762
763 result = TRUE;
764out:
765 winpr_Digest_Free(ctx);
766 return result;
767}
768
769BOOL winpr_Digest(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output, size_t olen)
770{
771 BOOL result = FALSE;
772 WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
773
774 if (!ctx)
775 return FALSE;
776
777 if (!winpr_Digest_Init(ctx, md))
778 goto out;
779
780 if (!winpr_Digest_Update(ctx, input, ilen))
781 goto out;
782
783 if (!winpr_Digest_Final(ctx, output, olen))
784 goto out;
785
786 result = TRUE;
787out:
788 winpr_Digest_Free(ctx);
789 return result;
790}