ntdll: Use close_handle instead of NtClose for internal memory management functions.
[wine.git] / dlls / bcrypt / bcrypt_main.c
blob43d4688a1e918244784055b0384574bc14e63b3b
1 /*
2 * Copyright 2009 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "config.h"
21 #include "wine/port.h"
23 #include <stdarg.h>
24 #ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
25 #include <CommonCrypto/CommonDigest.h>
26 #include <CommonCrypto/CommonHMAC.h>
27 #elif defined(SONAME_LIBGNUTLS)
28 #include <gnutls/gnutls.h>
29 #include <gnutls/crypto.h>
30 #endif
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "windef.h"
35 #include "winbase.h"
36 #include "ntsecapi.h"
37 #include "bcrypt.h"
39 #include "wine/debug.h"
40 #include "wine/library.h"
41 #include "wine/unicode.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
45 static HINSTANCE instance;
47 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
48 WINE_DECLARE_DEBUG_CHANNEL(winediag);
50 static void *libgnutls_handle;
51 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
52 MAKE_FUNCPTR(gnutls_global_deinit);
53 MAKE_FUNCPTR(gnutls_global_init);
54 MAKE_FUNCPTR(gnutls_global_set_log_function);
55 MAKE_FUNCPTR(gnutls_global_set_log_level);
56 MAKE_FUNCPTR(gnutls_hash);
57 MAKE_FUNCPTR(gnutls_hash_deinit);
58 MAKE_FUNCPTR(gnutls_hash_init);
59 MAKE_FUNCPTR(gnutls_hmac);
60 MAKE_FUNCPTR(gnutls_hmac_deinit);
61 MAKE_FUNCPTR(gnutls_hmac_init);
62 MAKE_FUNCPTR(gnutls_perror);
63 #undef MAKE_FUNCPTR
65 static void gnutls_log( int level, const char *msg )
67 TRACE( "<%d> %s", level, msg );
70 static BOOL gnutls_initialize(void)
72 int ret;
74 if (!(libgnutls_handle = wine_dlopen( SONAME_LIBGNUTLS, RTLD_NOW, NULL, 0 )))
76 ERR_(winediag)( "failed to load libgnutls, no support for crypto hashes\n" );
77 return FALSE;
80 #define LOAD_FUNCPTR(f) \
81 if (!(p##f = wine_dlsym( libgnutls_handle, #f, NULL, 0 ))) \
82 { \
83 ERR( "failed to load %s\n", #f ); \
84 goto fail; \
87 LOAD_FUNCPTR(gnutls_global_deinit)
88 LOAD_FUNCPTR(gnutls_global_init)
89 LOAD_FUNCPTR(gnutls_global_set_log_function)
90 LOAD_FUNCPTR(gnutls_global_set_log_level)
91 LOAD_FUNCPTR(gnutls_hash);
92 LOAD_FUNCPTR(gnutls_hash_deinit);
93 LOAD_FUNCPTR(gnutls_hash_init);
94 LOAD_FUNCPTR(gnutls_hmac);
95 LOAD_FUNCPTR(gnutls_hmac_deinit);
96 LOAD_FUNCPTR(gnutls_hmac_init);
97 LOAD_FUNCPTR(gnutls_perror)
98 #undef LOAD_FUNCPTR
100 if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS)
102 pgnutls_perror( ret );
103 goto fail;
106 if (TRACE_ON( bcrypt ))
108 pgnutls_global_set_log_level( 4 );
109 pgnutls_global_set_log_function( gnutls_log );
112 return TRUE;
114 fail:
115 wine_dlclose( libgnutls_handle, NULL, 0 );
116 libgnutls_handle = NULL;
117 return FALSE;
120 static void gnutls_uninitialize(void)
122 pgnutls_global_deinit();
123 wine_dlclose( libgnutls_handle, NULL, 0 );
124 libgnutls_handle = NULL;
126 #endif /* HAVE_GNUTLS_HASH && !HAVE_COMMONCRYPTO_COMMONDIGEST_H */
128 NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount,
129 BCRYPT_ALGORITHM_IDENTIFIER **ppAlgList, ULONG dwFlags)
131 FIXME("%08x, %p, %p, %08x - stub\n", dwAlgOperations, pAlgCount, ppAlgList, dwFlags);
133 *ppAlgList=NULL;
134 *pAlgCount=0;
136 return STATUS_NOT_IMPLEMENTED;
139 NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE algorithm, UCHAR *buffer, ULONG count, ULONG flags)
141 const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
142 TRACE("%p, %p, %u, %08x - semi-stub\n", algorithm, buffer, count, flags);
144 if (!algorithm)
146 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
147 * is set. In this case the preferred system RNG is used.
149 if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
150 return STATUS_INVALID_HANDLE;
152 if (!buffer)
153 return STATUS_INVALID_PARAMETER;
155 if (flags & ~supported_flags)
156 FIXME("unsupported flags %08x\n", flags & ~supported_flags);
158 if (algorithm)
159 FIXME("ignoring selected algorithm\n");
161 /* When zero bytes are requested the function returns success too. */
162 if (!count)
163 return STATUS_SUCCESS;
165 if (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG)
167 if (RtlGenRandom(buffer, count))
168 return STATUS_SUCCESS;
171 FIXME("called with unsupported parameters, returning error\n");
172 return STATUS_NOT_IMPLEMENTED;
175 #define MAGIC_ALG (('A' << 24) | ('L' << 16) | ('G' << 8) | '0')
176 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
177 struct object
179 ULONG magic;
182 enum alg_id
184 ALG_ID_MD5,
185 ALG_ID_SHA1,
186 ALG_ID_SHA256,
187 ALG_ID_SHA384,
188 ALG_ID_SHA512
191 static const struct {
192 ULONG hash_length;
193 const WCHAR *alg_name;
194 } alg_props[] = {
195 /* ALG_ID_MD5 */ { 16, BCRYPT_MD5_ALGORITHM },
196 /* ALG_ID_SHA1 */ { 20, BCRYPT_SHA1_ALGORITHM },
197 /* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM },
198 /* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM },
199 /* ALG_ID_SHA512 */ { 64, BCRYPT_SHA512_ALGORITHM }
202 struct algorithm
204 struct object hdr;
205 enum alg_id id;
206 BOOL hmac;
209 NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
211 struct algorithm *alg;
212 enum alg_id alg_id;
214 const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG;
216 TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags );
218 if (!handle || !id) return STATUS_INVALID_PARAMETER;
219 if (flags & ~supported_flags)
221 FIXME( "unsupported flags %08x\n", flags & ~supported_flags);
222 return STATUS_NOT_IMPLEMENTED;
225 if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1;
226 else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5;
227 else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256;
228 else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384;
229 else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512;
230 else
232 FIXME( "algorithm %s not supported\n", debugstr_w(id) );
233 return STATUS_NOT_IMPLEMENTED;
235 if (implementation && strcmpW( implementation, MS_PRIMITIVE_PROVIDER ))
237 FIXME( "implementation %s not supported\n", debugstr_w(implementation) );
238 return STATUS_NOT_IMPLEMENTED;
241 if (!(alg = HeapAlloc( GetProcessHeap(), 0, sizeof(*alg) ))) return STATUS_NO_MEMORY;
242 alg->hdr.magic = MAGIC_ALG;
243 alg->id = alg_id;
244 alg->hmac = flags & BCRYPT_ALG_HANDLE_HMAC_FLAG;
246 *handle = alg;
247 return STATUS_SUCCESS;
250 NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags )
252 struct algorithm *alg = handle;
254 TRACE( "%p, %08x\n", handle, flags );
256 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
257 HeapFree( GetProcessHeap(), 0, alg );
258 return STATUS_SUCCESS;
261 NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled)
263 FIXME("%p - semi-stub\n", enabled);
265 if (!enabled)
266 return STATUS_INVALID_PARAMETER;
268 *enabled = FALSE;
269 return STATUS_SUCCESS;
272 #ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
273 struct hash
275 struct object hdr;
276 enum alg_id alg_id;
277 BOOL hmac;
278 union
280 CC_MD5_CTX md5_ctx;
281 CC_SHA1_CTX sha1_ctx;
282 CC_SHA256_CTX sha256_ctx;
283 CC_SHA512_CTX sha512_ctx;
284 CCHmacContext hmac_ctx;
285 } u;
288 static NTSTATUS hash_init( struct hash *hash )
290 switch (hash->alg_id)
292 case ALG_ID_MD5:
293 CC_MD5_Init( &hash->u.md5_ctx );
294 break;
296 case ALG_ID_SHA1:
297 CC_SHA1_Init( &hash->u.sha1_ctx );
298 break;
300 case ALG_ID_SHA256:
301 CC_SHA256_Init( &hash->u.sha256_ctx );
302 break;
304 case ALG_ID_SHA384:
305 CC_SHA384_Init( &hash->u.sha512_ctx );
306 break;
308 case ALG_ID_SHA512:
309 CC_SHA512_Init( &hash->u.sha512_ctx );
310 break;
312 default:
313 ERR( "unhandled id %u\n", hash->alg_id );
314 return STATUS_NOT_IMPLEMENTED;
316 return STATUS_SUCCESS;
319 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
321 CCHmacAlgorithm cc_algorithm;
322 switch (hash->alg_id)
324 case ALG_ID_MD5:
325 cc_algorithm = kCCHmacAlgMD5;
326 break;
328 case ALG_ID_SHA1:
329 cc_algorithm = kCCHmacAlgSHA1;
330 break;
332 case ALG_ID_SHA256:
333 cc_algorithm = kCCHmacAlgSHA256;
334 break;
336 case ALG_ID_SHA384:
337 cc_algorithm = kCCHmacAlgSHA384;
338 break;
340 case ALG_ID_SHA512:
341 cc_algorithm = kCCHmacAlgSHA512;
342 break;
344 default:
345 ERR( "unhandled id %u\n", hash->alg_id );
346 return STATUS_NOT_IMPLEMENTED;
349 CCHmacInit( &hash->u.hmac_ctx, cc_algorithm, key, key_size );
350 return STATUS_SUCCESS;
354 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
356 switch (hash->alg_id)
358 case ALG_ID_MD5:
359 CC_MD5_Update( &hash->u.md5_ctx, input, size );
360 break;
362 case ALG_ID_SHA1:
363 CC_SHA1_Update( &hash->u.sha1_ctx, input, size );
364 break;
366 case ALG_ID_SHA256:
367 CC_SHA256_Update( &hash->u.sha256_ctx, input, size );
368 break;
370 case ALG_ID_SHA384:
371 CC_SHA384_Update( &hash->u.sha512_ctx, input, size );
372 break;
374 case ALG_ID_SHA512:
375 CC_SHA512_Update( &hash->u.sha512_ctx, input, size );
376 break;
378 default:
379 ERR( "unhandled id %u\n", hash->alg_id );
380 return STATUS_NOT_IMPLEMENTED;
382 return STATUS_SUCCESS;
385 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
387 CCHmacUpdate( &hash->u.hmac_ctx, input, size );
388 return STATUS_SUCCESS;
391 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
393 switch (hash->alg_id)
395 case ALG_ID_MD5:
396 CC_MD5_Final( output, &hash->u.md5_ctx );
397 break;
399 case ALG_ID_SHA1:
400 CC_SHA1_Final( output, &hash->u.sha1_ctx );
401 break;
403 case ALG_ID_SHA256:
404 CC_SHA256_Final( output, &hash->u.sha256_ctx );
405 break;
407 case ALG_ID_SHA384:
408 CC_SHA384_Final( output, &hash->u.sha512_ctx );
409 break;
411 case ALG_ID_SHA512:
412 CC_SHA512_Final( output, &hash->u.sha512_ctx );
413 break;
415 default:
416 ERR( "unhandled id %u\n", hash->alg_id );
417 break;
419 return STATUS_SUCCESS;
422 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
424 CCHmacFinal( &hash->u.hmac_ctx, output );
426 return STATUS_SUCCESS;
428 #elif defined(HAVE_GNUTLS_HASH)
429 struct hash
431 struct object hdr;
432 enum alg_id alg_id;
433 BOOL hmac;
434 union
436 gnutls_hash_hd_t hash_handle;
437 gnutls_hmac_hd_t hmac_handle;
438 } u;
441 static NTSTATUS hash_init( struct hash *hash )
443 gnutls_digest_algorithm_t alg;
445 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
447 switch (hash->alg_id)
449 case ALG_ID_MD5:
450 alg = GNUTLS_DIG_MD5;
451 break;
452 case ALG_ID_SHA1:
453 alg = GNUTLS_DIG_SHA1;
454 break;
456 case ALG_ID_SHA256:
457 alg = GNUTLS_DIG_SHA256;
458 break;
460 case ALG_ID_SHA384:
461 alg = GNUTLS_DIG_SHA384;
462 break;
464 case ALG_ID_SHA512:
465 alg = GNUTLS_DIG_SHA512;
466 break;
468 default:
469 ERR( "unhandled id %u\n", hash->alg_id );
470 return STATUS_NOT_IMPLEMENTED;
473 if (pgnutls_hash_init( &hash->u.hash_handle, alg )) return STATUS_INTERNAL_ERROR;
474 return STATUS_SUCCESS;
477 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
479 gnutls_mac_algorithm_t alg;
481 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
483 switch (hash->alg_id)
485 case ALG_ID_MD5:
486 alg = GNUTLS_MAC_MD5;
487 break;
488 case ALG_ID_SHA1:
489 alg = GNUTLS_MAC_SHA1;
490 break;
492 case ALG_ID_SHA256:
493 alg = GNUTLS_MAC_SHA256;
494 break;
496 case ALG_ID_SHA384:
497 alg = GNUTLS_MAC_SHA384;
498 break;
500 case ALG_ID_SHA512:
501 alg = GNUTLS_MAC_SHA512;
502 break;
504 default:
505 ERR( "unhandled id %u\n", hash->alg_id );
506 return STATUS_NOT_IMPLEMENTED;
509 if (pgnutls_hmac_init( &hash->u.hmac_handle, alg, key, key_size )) return STATUS_INTERNAL_ERROR;
510 return STATUS_SUCCESS;
513 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
515 if (pgnutls_hash( hash->u.hash_handle, input, size )) return STATUS_INTERNAL_ERROR;
516 return STATUS_SUCCESS;
519 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
521 if (pgnutls_hmac( hash->u.hmac_handle, input, size )) return STATUS_INTERNAL_ERROR;
522 return STATUS_SUCCESS;
525 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
527 pgnutls_hash_deinit( hash->u.hash_handle, output );
528 return STATUS_SUCCESS;
531 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
533 pgnutls_hmac_deinit( hash->u.hmac_handle, output );
534 return STATUS_SUCCESS;
536 #else
537 struct hash
539 struct object hdr;
540 BOOL hmac;
541 enum alg_id alg_id;
544 static NTSTATUS hash_init( struct hash *hash )
546 ERR( "support for hashes not available at build time\n" );
547 return STATUS_NOT_IMPLEMENTED;
550 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
552 ERR( "support for hashes not available at build time\n" );
553 return STATUS_NOT_IMPLEMENTED;
556 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
558 ERR( "support for hashes not available at build time\n" );
559 return STATUS_NOT_IMPLEMENTED;
562 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
564 ERR( "support for hashes not available at build time\n" );
565 return STATUS_NOT_IMPLEMENTED;
568 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
570 ERR( "support for hashes not available at build time\n" );
571 return STATUS_NOT_IMPLEMENTED;
574 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
576 ERR( "support for hashes not available at build time\n" );
577 return STATUS_NOT_IMPLEMENTED;
579 #endif
581 #define OBJECT_LENGTH_MD5 274
582 #define OBJECT_LENGTH_SHA1 278
583 #define OBJECT_LENGTH_SHA256 286
584 #define OBJECT_LENGTH_SHA384 382
585 #define OBJECT_LENGTH_SHA512 382
587 static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
589 if (!strcmpW( prop, BCRYPT_HASH_LENGTH ))
591 *ret_size = sizeof(ULONG);
592 if (size < sizeof(ULONG))
593 return STATUS_BUFFER_TOO_SMALL;
594 if(buf)
595 *(ULONG*)buf = alg_props[id].hash_length;
596 return STATUS_SUCCESS;
599 if (!strcmpW( prop, BCRYPT_ALGORITHM_NAME ))
601 *ret_size = (strlenW(alg_props[id].alg_name)+1)*sizeof(WCHAR);
602 if (size < *ret_size)
603 return STATUS_BUFFER_TOO_SMALL;
604 if(buf)
605 memcpy(buf, alg_props[id].alg_name, *ret_size);
606 return STATUS_SUCCESS;
609 return STATUS_NOT_IMPLEMENTED;
612 static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
614 NTSTATUS status;
615 ULONG value;
617 status = generic_alg_property( id, prop, buf, size, ret_size );
618 if (status != STATUS_NOT_IMPLEMENTED)
619 return status;
621 switch (id)
623 case ALG_ID_MD5:
624 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
626 value = OBJECT_LENGTH_MD5;
627 break;
629 FIXME( "unsupported md5 algorithm property %s\n", debugstr_w(prop) );
630 return STATUS_NOT_IMPLEMENTED;
631 case ALG_ID_SHA1:
632 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
634 value = OBJECT_LENGTH_SHA1;
635 break;
637 FIXME( "unsupported sha1 algorithm property %s\n", debugstr_w(prop) );
638 return STATUS_NOT_IMPLEMENTED;
640 case ALG_ID_SHA256:
641 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
643 value = OBJECT_LENGTH_SHA256;
644 break;
646 FIXME( "unsupported sha256 algorithm property %s\n", debugstr_w(prop) );
647 return STATUS_NOT_IMPLEMENTED;
649 case ALG_ID_SHA384:
650 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
652 value = OBJECT_LENGTH_SHA384;
653 break;
655 FIXME( "unsupported sha384 algorithm property %s\n", debugstr_w(prop) );
656 return STATUS_NOT_IMPLEMENTED;
658 case ALG_ID_SHA512:
659 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
661 value = OBJECT_LENGTH_SHA512;
662 break;
664 FIXME( "unsupported sha512 algorithm property %s\n", debugstr_w(prop) );
665 return STATUS_NOT_IMPLEMENTED;
667 default:
668 FIXME( "unsupported algorithm %u\n", id );
669 return STATUS_NOT_IMPLEMENTED;
672 if (size < sizeof(ULONG))
674 *ret_size = sizeof(ULONG);
675 return STATUS_BUFFER_TOO_SMALL;
677 if (buf) *(ULONG *)buf = value;
678 *ret_size = sizeof(ULONG);
680 return STATUS_SUCCESS;
683 static NTSTATUS get_hash_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
685 NTSTATUS status;
687 status = generic_alg_property( id, prop, buf, size, ret_size );
688 if (status == STATUS_NOT_IMPLEMENTED)
689 FIXME( "unsupported property %s\n", debugstr_w(prop) );
690 return status;
693 NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags )
695 struct object *object = handle;
697 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags );
699 if (!object) return STATUS_INVALID_HANDLE;
700 if (!prop || !res) return STATUS_INVALID_PARAMETER;
702 switch (object->magic)
704 case MAGIC_ALG:
706 const struct algorithm *alg = (const struct algorithm *)object;
707 return get_alg_property( alg->id, prop, buffer, count, res );
709 case MAGIC_HASH:
711 const struct hash *hash = (const struct hash *)object;
712 return get_hash_property( hash->alg_id, prop, buffer, count, res );
714 default:
715 WARN( "unknown magic %08x\n", object->magic );
716 return STATUS_INVALID_HANDLE;
720 NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen,
721 UCHAR *secret, ULONG secretlen, ULONG flags )
723 struct algorithm *alg = algorithm;
724 struct hash *hash;
725 NTSTATUS status;
727 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen,
728 secret, secretlen, flags );
729 if (flags)
731 FIXME( "unimplemented flags %08x\n", flags );
732 return STATUS_NOT_IMPLEMENTED;
735 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
736 if (object) FIXME( "ignoring object buffer\n" );
738 if (!(hash = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash) ))) return STATUS_NO_MEMORY;
739 hash->hdr.magic = MAGIC_HASH;
740 hash->alg_id = alg->id;
741 hash->hmac = alg->hmac;
743 if (hash->hmac)
745 status = hmac_init( hash, secret, secretlen );
747 else
749 status = hash_init( hash );
752 if (status != STATUS_SUCCESS)
754 HeapFree( GetProcessHeap(), 0, hash );
755 return status;
758 *handle = hash;
759 return STATUS_SUCCESS;
762 NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
764 struct hash *hash = handle;
766 TRACE( "%p\n", handle );
768 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
769 HeapFree( GetProcessHeap(), 0, hash );
770 return STATUS_SUCCESS;
773 NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG size, ULONG flags )
775 struct hash *hash = handle;
777 TRACE( "%p, %p, %u, %08x\n", handle, input, size, flags );
779 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
780 if (!input) return STATUS_SUCCESS;
782 if (hash->hmac)
784 return hmac_update( hash, input, size );
786 else
788 return hash_update( hash, input, size );
792 NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
794 struct hash *hash = handle;
796 TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags );
798 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
799 if (!output) return STATUS_INVALID_PARAMETER;
801 if (hash->hmac)
803 return hmac_finish( hash, output, size );
805 else
807 return hash_finish( hash, output, size );
811 NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen,
812 UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen )
814 NTSTATUS status;
815 BCRYPT_HASH_HANDLE handle;
817 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secretlen,
818 input, inputlen, output, outputlen );
820 status = BCryptCreateHash( algorithm, &handle, NULL, 0, secret, secretlen, 0);
821 if (status != STATUS_SUCCESS)
823 return status;
826 status = BCryptHashData( handle, input, inputlen, 0 );
827 if (status != STATUS_SUCCESS)
829 BCryptDestroyHash( handle );
830 return status;
833 status = BCryptFinishHash( handle, output, outputlen, 0 );
834 if (status != STATUS_SUCCESS)
836 BCryptDestroyHash( handle );
837 return status;
840 return BCryptDestroyHash( handle );
843 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
845 switch (reason)
847 case DLL_PROCESS_ATTACH:
848 instance = hinst;
849 DisableThreadLibraryCalls( hinst );
850 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
851 gnutls_initialize();
852 #endif
853 break;
855 case DLL_PROCESS_DETACH:
856 if (reserved) break;
857 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
858 gnutls_uninitialize();
859 #endif
860 break;
862 return TRUE;