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 nullptr;
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[] = {
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
129WINPR_MD_TYPE winpr_md_type_from_string(const char* name)
130{
131 const struct hash_map* cur = hashes;
132 while (cur->name)
133 {
134 if (_stricmp(cur->name, name) == 0)
135 return cur->md;
136 cur++;
137 }
138 return WINPR_MD_NONE;
139}
140
141const char* winpr_md_type_to_string(WINPR_MD_TYPE md)
142{
143 const struct hash_map* cur = hashes;
144 while (cur->name)
145 {
146 if (cur->md == md)
147 return cur->name;
148 cur++;
149 }
150 return nullptr;
151}
152
153struct 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
172WINPR_HMAC_CTX* winpr_HMAC_New(void)
173{
174 WINPR_HMAC_CTX* ctx = (WINPR_HMAC_CTX*)calloc(1, sizeof(WINPR_HMAC_CTX));
175 if (!ctx)
176 return nullptr;
177#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 if (!(ctx->hmac = HMAC_CTX_new()))
187 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 return ctx;
201
202fail:
203 WINPR_PRAGMA_DIAG_PUSH
204 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
205 winpr_HMAC_Free(ctx);
206 WINPR_PRAGMA_DIAG_POP
207 return nullptr;
208}
209
210BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const void* key, size_t keylen)
211{
212 WINPR_ASSERT(ctx);
213
214 ctx->md = md;
215 switch (ctx->md)
216 {
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 default:
223 break;
224 }
225
226#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 HMAC_CTX* hmac = ctx->hmac;
240 const EVP_MD* evp = winpr_openssl_get_evp_md(md);
241
242 if (!evp || !hmac)
243 return FALSE;
244
245 if (keylen > INT_MAX)
246 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 if (HMAC_Init_ex(hmac, key, (int)keylen, evp, nullptr) == 1)
254 return TRUE;
255
256#endif
257#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 return FALSE;
279}
280
281BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const void* input, size_t ilen)
282{
283 WINPR_ASSERT(ctx);
284
285 switch (ctx->md)
286 {
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 default:
293 break;
294 }
295
296#if defined(WITH_OPENSSL)
297#if OPENSSL_VERSION_NUMBER >= 0x30000000L
298 return EVP_MAC_update(ctx->xhmac, input, ilen) == 1;
299#else
300 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 if (HMAC_Update(hmac, input, ilen) == 1)
308 return TRUE;
309#endif
310#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 return FALSE;
319}
320
321BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, void* output, size_t olen)
322{
323 WINPR_ASSERT(ctx);
324
325 switch (ctx->md)
326 {
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 default:
335 break;
336 }
337
338#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 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 if (HMAC_Final(hmac, output, nullptr) == 1)
351 return TRUE;
352
353#endif
354#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 return FALSE;
363}
364
365void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx)
366{
367 if (!ctx)
368 return;
369
370#if defined(WITH_OPENSSL)
371#if OPENSSL_VERSION_NUMBER >= 0x30000000L
372 EVP_MAC_CTX_free(ctx->xhmac);
373#else
374 HMAC_CTX* hmac = ctx->hmac;
375
376 if (hmac)
377 {
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 HMAC_CTX_free(hmac);
384#endif
385 }
386#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 free(ctx);
396}
397
398BOOL 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{
401 BOOL result = FALSE;
402 WINPR_HMAC_CTX* ctx = winpr_HMAC_New();
403
404 if (!ctx)
405 return FALSE;
406
407 if (!winpr_HMAC_Init(ctx, md, key, keylen))
408 goto out;
409
410 if (!winpr_HMAC_Update(ctx, input, ilen))
411 goto out;
412
413 if (!winpr_HMAC_Final(ctx, output, olen))
414 goto out;
415
416 result = TRUE;
417out:
418 winpr_HMAC_Free(ctx);
419 return result;
420}
421
426struct 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
444WINPR_DIGEST_CTX* winpr_Digest_New(void)
445{
446 WINPR_DIGEST_CTX* ctx = calloc(1, sizeof(WINPR_DIGEST_CTX));
447 if (!ctx)
448 return nullptr;
449
450#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 ctx->mdctx = EVP_MD_CTX_new();
456#endif
457 if (!ctx->mdctx)
458 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 return ctx;
469
470fail:
471 WINPR_PRAGMA_DIAG_PUSH
472 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
473 winpr_Digest_Free(ctx);
474 WINPR_PRAGMA_DIAG_POP
475 return nullptr;
476}
477
478#if defined(WITH_OPENSSL)
479static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, const EVP_MD* evp)
480{
481 WINPR_ASSERT(ctx);
482 EVP_MD_CTX* mdctx = ctx->mdctx;
483
484 if (!mdctx || !evp)
485 return FALSE;
486
487 if (EVP_DigestInit_ex(mdctx, evp, nullptr) != 1)
488 {
489 WLog_ERR(TAG, "Failed to initialize digest %s", winpr_md_type_to_string(ctx->md));
490 return FALSE;
491 }
492
493 return TRUE;
494}
495
496#elif defined(WITH_MBEDTLS)
497static 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
522BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
523{
524 WINPR_ASSERT(ctx);
525
526 ctx->md = md;
527 switch (md)
528 {
529 case WINPR_MD_MD5:
530 {
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 const EVP_MD* evp = winpr_openssl_get_evp_md(md);
547 EVP_MD_CTX_set_flags(ctx->mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
548 return winpr_Digest_Init_Internal(ctx, evp);
549#elif defined(WITH_MBEDTLS)
550 return winpr_Digest_Init_Internal(ctx, md);
551#endif
552 }
553 default:
554 WLog_ERR(TAG, "Invalid FIPS digest %s requested", winpr_md_type_to_string(md));
555 return FALSE;
556 }
557}
558
559BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
560{
561 WINPR_ASSERT(ctx);
562
563 ctx->md = md;
564 switch (md)
565 {
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 default:
577 break;
578 }
579
580#if defined(WITH_OPENSSL)
581 const EVP_MD* evp = winpr_openssl_get_evp_md(md);
582 return winpr_Digest_Init_Internal(ctx, evp);
583#else
584 return winpr_Digest_Init_Internal(ctx, md);
585#endif
586}
587
588BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
589{
590 WINPR_ASSERT(ctx);
591
592 switch (ctx->md)
593 {
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 default:
605 break;
606 }
607
608#if defined(WITH_OPENSSL)
609 EVP_MD_CTX* mdctx = ctx->mdctx;
610
611 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 return TRUE;
621}
622
623BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, void* output, WINPR_ATTR_UNUSED size_t olen)
624{
625 WINPR_ASSERT(ctx);
626
627 switch (ctx->md)
628 {
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 default:
645 break;
646 }
647
648#if defined(WITH_OPENSSL)
649 EVP_MD_CTX* mdctx = ctx->mdctx;
650
651 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 return FALSE;
661}
662
663BOOL winpr_DigestSign_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md, void* key)
664{
665 WINPR_ASSERT(ctx);
666
667#if defined(WITH_OPENSSL)
668 const EVP_MD* evp = winpr_openssl_get_evp_md(md);
669 if (!evp)
670 return FALSE;
671
672 const int rdsi = EVP_DigestSignInit(ctx->mdctx, nullptr, evp, nullptr, key);
673 return (rdsi > 0);
674#else
675 return FALSE;
676#endif
677}
678
679BOOL winpr_DigestSign_Update(WINPR_DIGEST_CTX* ctx, const void* input, size_t ilen)
680{
681 WINPR_ASSERT(ctx);
682
683#if defined(WITH_OPENSSL)
684 EVP_MD_CTX* mdctx = ctx->mdctx;
685
686 return (EVP_DigestSignUpdate(mdctx, input, ilen) == 1);
687#else
688 return FALSE;
689#endif
690}
691
692BOOL winpr_DigestSign_Final(WINPR_DIGEST_CTX* ctx, void* output, size_t* piolen)
693{
694 WINPR_ASSERT(ctx);
695
696#if defined(WITH_OPENSSL)
697 EVP_MD_CTX* mdctx = ctx->mdctx;
698
699 return EVP_DigestSignFinal(mdctx, output, piolen) == 1;
700#else
701 return FALSE;
702#endif
703}
704
705void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx)
706{
707 if (!ctx)
708 return;
709#if defined(WITH_OPENSSL)
710 if (ctx->mdctx)
711 {
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 EVP_MD_CTX_free(ctx->mdctx);
717#endif
718 }
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 free(ctx);
729}
730
731BOOL winpr_Digest_Allow_FIPS(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output,
732 size_t olen)
733{
734 BOOL result = FALSE;
735 WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
736
737 if (!ctx)
738 return FALSE;
739
740 if (!winpr_Digest_Init_Allow_FIPS(ctx, md))
741 goto out;
742
743 if (!winpr_Digest_Update(ctx, input, ilen))
744 goto out;
745
746 if (!winpr_Digest_Final(ctx, output, olen))
747 goto out;
748
749 result = TRUE;
750out:
751 winpr_Digest_Free(ctx);
752 return result;
753}
754
755BOOL winpr_Digest(WINPR_MD_TYPE md, const void* input, size_t ilen, void* output, size_t olen)
756{
757 BOOL result = FALSE;
758 WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
759
760 if (!ctx)
761 return FALSE;
762
763 if (!winpr_Digest_Init(ctx, md))
764 goto out;
765
766 if (!winpr_Digest_Update(ctx, input, ilen))
767 goto out;
768
769 if (!winpr_Digest_Final(ctx, output, olen))
770 goto out;
771
772 result = TRUE;
773out:
774 winpr_Digest_Free(ctx);
775 return result;
776}