1 /* $NetBSD: evp-wincng.c,v 1.4 2023/06/19 21:41:43 christos Exp $ */
2
3 /*
4 * Copyright (c) 2015, Secure Endpoints Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * - Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /* Windows CNG provider */
34
35 #include <config.h>
36 #include <krb5/roken.h>
37 #include <assert.h>
38
39 #include <evp.h>
40 #include <evp-wincng.h>
41
42 #include <bcrypt.h>
43
44 /*
45 * CNG cipher provider
46 */
47
48 struct wincng_key {
49 BCRYPT_KEY_HANDLE hKey;
50 UCHAR rgbKeyObject[1];
51 };
52
53 #define WINCNG_KEY_OBJECT_SIZE(ctx) \
54 ((ctx)->cipher->ctx_size - sizeof(struct wincng_key) + 1)
55
56 static int
wincng_do_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,unsigned int size)57 wincng_do_cipher(EVP_CIPHER_CTX *ctx,
58 unsigned char *out,
59 const unsigned char *in,
60 unsigned int size)
61 {
62 struct wincng_key *cng = ctx->cipher_data;
63 NTSTATUS status;
64 ULONG cbResult;
65
66 assert(EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_STREAM_CIPHER ||
67 (size % ctx->cipher->block_size) == 0);
68
69 if (ctx->encrypt) {
70 status = BCryptEncrypt(cng->hKey,
71 (PUCHAR)in,
72 size,
73 NULL, /* pPaddingInfo */
74 ctx->cipher->iv_len ? ctx->iv : NULL,
75 ctx->cipher->iv_len,
76 out,
77 size,
78 &cbResult,
79 0);
80 } else {
81 status = BCryptDecrypt(cng->hKey,
82 (PUCHAR)in,
83 size,
84 NULL, /* pPaddingInfo */
85 ctx->cipher->iv_len ? ctx->iv : NULL,
86 ctx->cipher->iv_len,
87 out,
88 size,
89 &cbResult,
90 0);
91 }
92
93 return BCRYPT_SUCCESS(status) && cbResult == size;
94 }
95
96 static int
wincng_cleanup(EVP_CIPHER_CTX * ctx)97 wincng_cleanup(EVP_CIPHER_CTX *ctx)
98 {
99 struct wincng_key *cng = ctx->cipher_data;
100
101 if (cng->hKey)
102 BCryptDestroyKey(cng->hKey);
103 SecureZeroMemory(cng->rgbKeyObject, WINCNG_KEY_OBJECT_SIZE(ctx));
104
105 return 1;
106 }
107
108 static int
wincng_cipher_algorithm_init(EVP_CIPHER * cipher,LPWSTR pszAlgId)109 wincng_cipher_algorithm_init(EVP_CIPHER *cipher,
110 LPWSTR pszAlgId)
111 {
112 BCRYPT_ALG_HANDLE hAlgorithm = NULL;
113 NTSTATUS status;
114 LPCWSTR pszChainingMode;
115 ULONG cbKeyObject, cbChainingMode, cbData;
116
117 if (cipher->app_data)
118 return 1;
119
120 status = BCryptOpenAlgorithmProvider(&hAlgorithm,
121 pszAlgId,
122 NULL,
123 0);
124 if (!BCRYPT_SUCCESS(status))
125 return 0;
126
127 status = BCryptGetProperty(hAlgorithm,
128 BCRYPT_OBJECT_LENGTH,
129 (PUCHAR)&cbKeyObject,
130 sizeof(ULONG),
131 &cbData,
132 0);
133 if (!BCRYPT_SUCCESS(status)) {
134 BCryptCloseAlgorithmProvider(hAlgorithm, 0);
135 return 0;
136 }
137
138 cipher->ctx_size = sizeof(struct wincng_key) + cbKeyObject - 1;
139
140 switch (cipher->flags & EVP_CIPH_MODE) {
141 case EVP_CIPH_CBC_MODE:
142 pszChainingMode = BCRYPT_CHAIN_MODE_CBC;
143 cbChainingMode = sizeof(BCRYPT_CHAIN_MODE_CBC);
144 break;
145 case EVP_CIPH_CFB8_MODE:
146 pszChainingMode = BCRYPT_CHAIN_MODE_CFB;
147 cbChainingMode = sizeof(BCRYPT_CHAIN_MODE_CFB);
148 break;
149 default:
150 pszChainingMode = NULL;
151 cbChainingMode = 0;
152 break;
153 }
154
155 if (cbChainingMode) {
156 status = BCryptSetProperty(hAlgorithm,
157 BCRYPT_CHAINING_MODE,
158 (PUCHAR)pszChainingMode,
159 cbChainingMode,
160 0);
161 if (!BCRYPT_SUCCESS(status)) {
162 BCryptCloseAlgorithmProvider(hAlgorithm, 0);
163 return 0;
164 }
165 }
166
167 if (wcscmp(pszAlgId, BCRYPT_RC2_ALGORITHM) == 0) {
168 ULONG cbEffectiveKeyLength = EVP_CIPHER_key_length(cipher) * 8;
169
170 status = BCryptSetProperty(hAlgorithm,
171 BCRYPT_EFFECTIVE_KEY_LENGTH,
172 (PUCHAR)&cbEffectiveKeyLength,
173 sizeof(cbEffectiveKeyLength),
174 0);
175 if (!BCRYPT_SUCCESS(status)) {
176 BCryptCloseAlgorithmProvider(hAlgorithm, 0);
177 return 0;
178 }
179 }
180
181 InterlockedCompareExchangePointerRelease(&cipher->app_data,
182 hAlgorithm, NULL);
183 return 1;
184 }
185
186 static int
wincng_key_init(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int encp)187 wincng_key_init(EVP_CIPHER_CTX *ctx,
188 const unsigned char *key,
189 const unsigned char *iv,
190 int encp)
191 {
192 struct wincng_key *cng = ctx->cipher_data;
193 NTSTATUS status;
194
195 assert(cng != NULL);
196 assert(ctx->cipher != NULL);
197
198 if (ctx->cipher->app_data == NULL)
199 return 0;
200
201 if (cng->hKey) {
202 BCryptDestroyKey(cng->hKey); /* allow reinitialization */
203 cng->hKey = (BCRYPT_KEY_HANDLE)0;
204 }
205
206 /*
207 * Note: ctx->key_len not EVP_CIPHER_CTX_key_length() for
208 * variable length key support.
209 */
210 status = BCryptGenerateSymmetricKey(ctx->cipher->app_data,
211 &cng->hKey,
212 cng->rgbKeyObject,
213 WINCNG_KEY_OBJECT_SIZE(ctx),
214 (PUCHAR)key,
215 ctx->key_len,
216 0);
217
218 return BCRYPT_SUCCESS(status);
219 }
220
221 #define WINCNG_CIPHER_ALGORITHM(name, alg_id, block_size, key_len, \
222 iv_len, flags) \
223 \
224 static EVP_CIPHER \
225 wincng_##name = { \
226 0, \
227 block_size, \
228 key_len, \
229 iv_len, \
230 flags, \
231 wincng_key_init, \
232 wincng_do_cipher, \
233 wincng_cleanup, \
234 0, \
235 NULL, \
236 NULL, \
237 NULL, \
238 NULL \
239 }; \
240 \
241 const EVP_CIPHER * \
242 hc_EVP_wincng_##name(void) \
243 { \
244 wincng_cipher_algorithm_init(&wincng_##name, alg_id); \
245 return wincng_##name.app_data ? &wincng_##name : NULL; \
246 }
247
248 #define WINCNG_CIPHER_ALGORITHM_CLEANUP(name) do { \
249 if (wincng_##name.app_data) { \
250 BCryptCloseAlgorithmProvider(wincng_##name.app_data, 0); \
251 wincng_##name.app_data = NULL; \
252 } \
253 } while (0)
254
255 #define WINCNG_CIPHER_ALGORITHM_UNAVAILABLE(name) \
256 \
257 const EVP_CIPHER * \
258 hc_EVP_wincng_##name(void) \
259 { \
260 return NULL; \
261 }
262
263 /**
264 * The triple DES cipher type (Windows CNG provider)
265 *
266 * @return the DES-EDE3-CBC EVP_CIPHER pointer.
267 *
268 * @ingroup hcrypto_evp
269 */
270
271 WINCNG_CIPHER_ALGORITHM(des_ede3_cbc,
272 BCRYPT_3DES_ALGORITHM,
273 8,
274 24,
275 8,
276 EVP_CIPH_CBC_MODE);
277
278 /**
279 * The DES cipher type (Windows CNG provider)
280 *
281 * @return the DES-CBC EVP_CIPHER pointer.
282 *
283 * @ingroup hcrypto_evp
284 */
285
286 WINCNG_CIPHER_ALGORITHM(des_cbc,
287 BCRYPT_DES_ALGORITHM,
288 8,
289 8,
290 8,
291 EVP_CIPH_CBC_MODE);
292
293 /**
294 * The AES-128 cipher type (Windows CNG provider)
295 *
296 * @return the AES-128-CBC EVP_CIPHER pointer.
297 *
298 * @ingroup hcrypto_evp
299 */
300
301 WINCNG_CIPHER_ALGORITHM(aes_128_cbc,
302 BCRYPT_AES_ALGORITHM,
303 16,
304 16,
305 16,
306 EVP_CIPH_CBC_MODE);
307
308 /**
309 * The AES-192 cipher type (Windows CNG provider)
310 *
311 * @return the AES-192-CBC EVP_CIPHER pointer.
312 *
313 * @ingroup hcrypto_evp
314 */
315
316 WINCNG_CIPHER_ALGORITHM(aes_192_cbc,
317 BCRYPT_AES_ALGORITHM,
318 16,
319 24,
320 16,
321 EVP_CIPH_CBC_MODE);
322
323 /**
324 * The AES-256 cipher type (Windows CNG provider)
325 *
326 * @return the AES-256-CBC EVP_CIPHER pointer.
327 *
328 * @ingroup hcrypto_evp
329 */
330
331 WINCNG_CIPHER_ALGORITHM(aes_256_cbc,
332 BCRYPT_AES_ALGORITHM,
333 16,
334 32,
335 16,
336 EVP_CIPH_CBC_MODE);
337
338 /**
339 * The AES-128 CFB8 cipher type (Windows CNG provider)
340 *
341 * @return the AES-128-CFB8 EVP_CIPHER pointer.
342 *
343 * @ingroup hcrypto_evp
344 */
345
346 WINCNG_CIPHER_ALGORITHM(aes_128_cfb8,
347 BCRYPT_AES_ALGORITHM,
348 16,
349 16,
350 16,
351 EVP_CIPH_CFB8_MODE);
352
353 /**
354 * The AES-192 CFB8 cipher type (Windows CNG provider)
355 *
356 * @return the AES-192-CFB8 EVP_CIPHER pointer.
357 *
358 * @ingroup hcrypto_evp
359 */
360
361 WINCNG_CIPHER_ALGORITHM(aes_192_cfb8,
362 BCRYPT_AES_ALGORITHM,
363 16,
364 24,
365 16,
366 EVP_CIPH_CFB8_MODE);
367
368 /**
369 * The AES-256 CFB8 cipher type (Windows CNG provider)
370 *
371 * @return the AES-256-CFB8 EVP_CIPHER pointer.
372 *
373 * @ingroup hcrypto_evp
374 */
375
376 WINCNG_CIPHER_ALGORITHM(aes_256_cfb8,
377 BCRYPT_AES_ALGORITHM,
378 16,
379 32,
380 16,
381 EVP_CIPH_CFB8_MODE);
382
383 /**
384 * The RC2 cipher type - Windows CNG
385 *
386 * @return the RC2 EVP_CIPHER pointer.
387 *
388 * @ingroup hcrypto_evp
389 */
390
391 WINCNG_CIPHER_ALGORITHM(rc2_cbc,
392 BCRYPT_RC2_ALGORITHM,
393 8,
394 16,
395 8,
396 EVP_CIPH_CBC_MODE);
397
398 /**
399 * The RC2-40 cipher type - Windows CNG
400 *
401 * @return the RC2-40 EVP_CIPHER pointer.
402 *
403 * @ingroup hcrypto_evp
404 */
405
406 WINCNG_CIPHER_ALGORITHM(rc2_40_cbc,
407 BCRYPT_RC2_ALGORITHM,
408 8,
409 5,
410 8,
411 EVP_CIPH_CBC_MODE);
412
413 /**
414 * The RC2-64 cipher type - Windows CNG
415 *
416 * @return the RC2-64 EVP_CIPHER pointer.
417 *
418 * @ingroup hcrypto_evp
419 */
420
421 WINCNG_CIPHER_ALGORITHM(rc2_64_cbc,
422 BCRYPT_RC2_ALGORITHM,
423 8,
424 8,
425 8,
426 EVP_CIPH_CBC_MODE);
427
428 /**
429 * The Camellia-128 cipher type - CommonCrypto
430 *
431 * @return the Camellia-128 EVP_CIPHER pointer.
432 *
433 * @ingroup hcrypto_evp
434 */
435
436 WINCNG_CIPHER_ALGORITHM_UNAVAILABLE(camellia_128_cbc);
437
438 /**
439 * The Camellia-198 cipher type - CommonCrypto
440 *
441 * @return the Camellia-198 EVP_CIPHER pointer.
442 *
443 * @ingroup hcrypto_evp
444 */
445
446 WINCNG_CIPHER_ALGORITHM_UNAVAILABLE(camellia_192_cbc);
447
448 /**
449 * The Camellia-256 cipher type - CommonCrypto
450 *
451 * @return the Camellia-256 EVP_CIPHER pointer.
452 *
453 * @ingroup hcrypto_evp
454 */
455
456 WINCNG_CIPHER_ALGORITHM_UNAVAILABLE(camellia_256_cbc);
457
458 /**
459 * The RC4 cipher type (Windows CNG provider)
460 *
461 * @return the RC4 EVP_CIPHER pointer.
462 *
463 * @ingroup hcrypto_evp
464 */
465
466 WINCNG_CIPHER_ALGORITHM(rc4,
467 BCRYPT_RC4_ALGORITHM,
468 1,
469 16,
470 0,
471 EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH);
472
473 /**
474 * The RC4-40 cipher type (Windows CNG provider)
475 *
476 * @return the RC4 EVP_CIPHER pointer.
477 *
478 * @ingroup hcrypto_evp
479 */
480
481 WINCNG_CIPHER_ALGORITHM(rc4_40,
482 BCRYPT_RC4_ALGORITHM,
483 1,
484 5,
485 0,
486 EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH);
487
488 static void
wincng_cipher_algorithm_cleanup(void)489 wincng_cipher_algorithm_cleanup(void)
490 {
491 WINCNG_CIPHER_ALGORITHM_CLEANUP(des_ede3_cbc);
492 WINCNG_CIPHER_ALGORITHM_CLEANUP(des_cbc);
493 WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_128_cbc);
494 WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_192_cbc);
495 WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_256_cbc);
496 WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_128_cfb8);
497 WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_192_cfb8);
498 WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_256_cfb8);
499 WINCNG_CIPHER_ALGORITHM_CLEANUP(rc2_cbc);
500 WINCNG_CIPHER_ALGORITHM_CLEANUP(rc2_40_cbc);
501 WINCNG_CIPHER_ALGORITHM_CLEANUP(rc2_64_cbc);
502 WINCNG_CIPHER_ALGORITHM_CLEANUP(rc4);
503 WINCNG_CIPHER_ALGORITHM_CLEANUP(rc4_40);
504 }
505
506 /*
507 * CNG digest provider
508 */
509
510 struct wincng_md_ctx {
511 BCRYPT_HASH_HANDLE hHash;
512 ULONG cbHashObject;
513 UCHAR rgbHashObject[1];
514 };
515
516 static BCRYPT_ALG_HANDLE
wincng_md_algorithm_init(EVP_MD * md,LPCWSTR pszAlgId)517 wincng_md_algorithm_init(EVP_MD *md,
518 LPCWSTR pszAlgId)
519 {
520 BCRYPT_ALG_HANDLE hAlgorithm;
521 NTSTATUS status;
522 ULONG cbHashObject, cbData;
523 ULONG cbHash = 0, cbBlock = 0;
524
525 status = BCryptOpenAlgorithmProvider(&hAlgorithm,
526 pszAlgId,
527 NULL,
528 0);
529 if (!BCRYPT_SUCCESS(status))
530 return NULL;
531
532 status = BCryptGetProperty(hAlgorithm,
533 BCRYPT_HASH_LENGTH,
534 (PUCHAR)&cbHash,
535 sizeof(ULONG),
536 &cbData,
537 0);
538 if (!BCRYPT_SUCCESS(status)) {
539 BCryptCloseAlgorithmProvider(hAlgorithm, 0);
540 return NULL;
541 }
542
543 status = BCryptGetProperty(hAlgorithm,
544 BCRYPT_HASH_BLOCK_LENGTH,
545 (PUCHAR)&cbBlock,
546 sizeof(ULONG),
547 &cbData,
548 0);
549 if (!BCRYPT_SUCCESS(status)) {
550 BCryptCloseAlgorithmProvider(hAlgorithm, 0);
551 return NULL;
552 }
553
554 status = BCryptGetProperty(hAlgorithm,
555 BCRYPT_OBJECT_LENGTH,
556 (PUCHAR)&cbHashObject,
557 sizeof(ULONG),
558 &cbData,
559 0);
560 if (!BCRYPT_SUCCESS(status)) {
561 BCryptCloseAlgorithmProvider(hAlgorithm, 0);
562 return NULL;
563 }
564
565 md->hash_size = cbHash;
566 md->block_size = cbBlock;
567 md->ctx_size = sizeof(struct wincng_md_ctx) + cbHashObject - 1;
568
569 return hAlgorithm;
570 }
571
572 static int
wincng_md_hash_init(BCRYPT_ALG_HANDLE hAlgorithm,EVP_MD_CTX * ctx)573 wincng_md_hash_init(BCRYPT_ALG_HANDLE hAlgorithm,
574 EVP_MD_CTX *ctx)
575 {
576 struct wincng_md_ctx *cng = (struct wincng_md_ctx *)ctx;
577 NTSTATUS status;
578 ULONG cbData;
579
580 if (cng->hHash) {
581 BCryptDestroyHash(cng->hHash); /* allow reinitialization */
582 cng->hHash = (BCRYPT_HASH_HANDLE)0;
583 }
584
585 status = BCryptGetProperty(hAlgorithm,
586 BCRYPT_OBJECT_LENGTH,
587 (PUCHAR)&cng->cbHashObject,
588 sizeof(ULONG),
589 &cbData,
590 0);
591 if (!BCRYPT_SUCCESS(status))
592 return 0;
593
594 status = BCryptCreateHash(hAlgorithm,
595 &cng->hHash,
596 cng->rgbHashObject,
597 cng->cbHashObject,
598 NULL,
599 0,
600 0);
601
602 return BCRYPT_SUCCESS(status);
603 }
604
605 static int
wincng_md_update(EVP_MD_CTX * ctx,const void * data,size_t length)606 wincng_md_update(EVP_MD_CTX *ctx,
607 const void *data,
608 size_t length)
609 {
610 struct wincng_md_ctx *cng = (struct wincng_md_ctx *)ctx;
611 NTSTATUS status;
612
613 status = BCryptHashData(cng->hHash, (PUCHAR)data, length, 0);
614
615 return BCRYPT_SUCCESS(status);
616 }
617
618 static int
wincng_md_final(void * digest,EVP_MD_CTX * ctx)619 wincng_md_final(void *digest,
620 EVP_MD_CTX *ctx)
621 {
622 struct wincng_md_ctx *cng = (struct wincng_md_ctx *)ctx;
623 NTSTATUS status;
624 ULONG cbHash, cbData;
625
626 status = BCryptGetProperty(cng->hHash,
627 BCRYPT_HASH_LENGTH,
628 (PUCHAR)&cbHash,
629 sizeof(DWORD),
630 &cbData,
631 0);
632 if (!BCRYPT_SUCCESS(status))
633 return 0;
634
635 status = BCryptFinishHash(cng->hHash,
636 digest,
637 cbHash,
638 0);
639
640 return BCRYPT_SUCCESS(status);
641 }
642
643 static int
wincng_md_cleanup(EVP_MD_CTX * ctx)644 wincng_md_cleanup(EVP_MD_CTX *ctx)
645 {
646 struct wincng_md_ctx *cng = (struct wincng_md_ctx *)ctx;
647
648 if (cng->hHash)
649 BCryptDestroyHash(cng->hHash);
650 SecureZeroMemory(cng->rgbHashObject, cng->cbHashObject);
651
652 return 1;
653 }
654
655 #define WINCNG_MD_ALGORITHM(name, alg_id) \
656 \
657 static BCRYPT_ALG_HANDLE wincng_hAlgorithm_##name; \
658 \
659 static int wincng_##name##_init(EVP_MD_CTX *ctx) \
660 { \
661 return wincng_md_hash_init(wincng_hAlgorithm_##name, ctx); \
662 } \
663 \
664 const EVP_MD * \
665 hc_EVP_wincng_##name(void) \
666 { \
667 static struct hc_evp_md name = { \
668 0, \
669 0, \
670 0, \
671 wincng_##name##_init, \
672 wincng_md_update, \
673 wincng_md_final, \
674 wincng_md_cleanup \
675 }; \
676 \
677 if (wincng_hAlgorithm_##name == NULL) { \
678 BCRYPT_ALG_HANDLE hAlgorithm = \
679 wincng_md_algorithm_init(&name, alg_id); \
680 InterlockedCompareExchangePointerRelease( \
681 &wincng_hAlgorithm_##name, hAlgorithm, NULL); \
682 } \
683 return wincng_hAlgorithm_##name ? &name : NULL; \
684 }
685
686 #define WINCNG_MD_ALGORITHM_CLEANUP(name) do { \
687 if (wincng_hAlgorithm_##name) { \
688 BCryptCloseAlgorithmProvider(wincng_hAlgorithm_##name, 0); \
689 wincng_hAlgorithm_##name = NULL; \
690 } \
691 } while (0)
692
693 WINCNG_MD_ALGORITHM(md4, BCRYPT_MD4_ALGORITHM);
694 WINCNG_MD_ALGORITHM(md5, BCRYPT_MD5_ALGORITHM);
695 WINCNG_MD_ALGORITHM(sha1, BCRYPT_SHA1_ALGORITHM);
696 WINCNG_MD_ALGORITHM(sha256, BCRYPT_SHA256_ALGORITHM);
697 WINCNG_MD_ALGORITHM(sha384, BCRYPT_SHA384_ALGORITHM);
698 WINCNG_MD_ALGORITHM(sha512, BCRYPT_SHA512_ALGORITHM);
699
700 static void
wincng_md_algorithm_cleanup(void)701 wincng_md_algorithm_cleanup(void)
702 {
703 WINCNG_MD_ALGORITHM_CLEANUP(md4);
704 WINCNG_MD_ALGORITHM_CLEANUP(md5);
705 WINCNG_MD_ALGORITHM_CLEANUP(sha1);
706 WINCNG_MD_ALGORITHM_CLEANUP(sha256);
707 WINCNG_MD_ALGORITHM_CLEANUP(sha384);
708 WINCNG_MD_ALGORITHM_CLEANUP(sha512);
709 }
710
_hc_wincng_cleanup(void)711 void _hc_wincng_cleanup(void)
712 {
713 wincng_md_algorithm_cleanup();
714 wincng_cipher_algorithm_cleanup();
715 }
716