msctf: Fix spelling of a private struct's field name.
[wine.git] / dlls / bcrypt / bcrypt_main.c
blob6023c942e4911b007cbed18388fb2e6af96e03b0
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 #define MAGIC_ALG (('A' << 24) | ('L' << 16) | ('G' << 8) | '0')
140 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
141 struct object
143 ULONG magic;
146 enum alg_id
148 ALG_ID_MD5,
149 ALG_ID_RNG,
150 ALG_ID_SHA1,
151 ALG_ID_SHA256,
152 ALG_ID_SHA384,
153 ALG_ID_SHA512
156 static const struct {
157 ULONG hash_length;
158 const WCHAR *alg_name;
159 } alg_props[] = {
160 /* ALG_ID_MD5 */ { 16, BCRYPT_MD5_ALGORITHM },
161 /* ALG_ID_RNG */ { 0, BCRYPT_RNG_ALGORITHM },
162 /* ALG_ID_SHA1 */ { 20, BCRYPT_SHA1_ALGORITHM },
163 /* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM },
164 /* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM },
165 /* ALG_ID_SHA512 */ { 64, BCRYPT_SHA512_ALGORITHM }
168 struct algorithm
170 struct object hdr;
171 enum alg_id id;
172 BOOL hmac;
175 NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags)
177 const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
178 struct algorithm *algorithm = handle;
180 TRACE("%p, %p, %u, %08x - semi-stub\n", handle, buffer, count, flags);
182 if (!algorithm)
184 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
185 * is set. In this case the preferred system RNG is used.
187 if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
188 return STATUS_INVALID_HANDLE;
190 else if (algorithm->hdr.magic != MAGIC_ALG || algorithm->id != ALG_ID_RNG)
191 return STATUS_INVALID_HANDLE;
193 if (!buffer)
194 return STATUS_INVALID_PARAMETER;
196 if (flags & ~supported_flags)
197 FIXME("unsupported flags %08x\n", flags & ~supported_flags);
199 if (algorithm)
200 FIXME("ignoring selected algorithm\n");
202 /* When zero bytes are requested the function returns success too. */
203 if (!count)
204 return STATUS_SUCCESS;
206 if (algorithm || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
208 if (RtlGenRandom(buffer, count))
209 return STATUS_SUCCESS;
212 FIXME("called with unsupported parameters, returning error\n");
213 return STATUS_NOT_IMPLEMENTED;
216 NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
218 struct algorithm *alg;
219 enum alg_id alg_id;
221 const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG;
223 TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags );
225 if (!handle || !id) return STATUS_INVALID_PARAMETER;
226 if (flags & ~supported_flags)
228 FIXME( "unsupported flags %08x\n", flags & ~supported_flags);
229 return STATUS_NOT_IMPLEMENTED;
232 if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1;
233 else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5;
234 else if (!strcmpW( id, BCRYPT_RNG_ALGORITHM )) alg_id = ALG_ID_RNG;
235 else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256;
236 else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384;
237 else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512;
238 else
240 FIXME( "algorithm %s not supported\n", debugstr_w(id) );
241 return STATUS_NOT_IMPLEMENTED;
243 if (implementation && strcmpW( implementation, MS_PRIMITIVE_PROVIDER ))
245 FIXME( "implementation %s not supported\n", debugstr_w(implementation) );
246 return STATUS_NOT_IMPLEMENTED;
249 if (!(alg = HeapAlloc( GetProcessHeap(), 0, sizeof(*alg) ))) return STATUS_NO_MEMORY;
250 alg->hdr.magic = MAGIC_ALG;
251 alg->id = alg_id;
252 alg->hmac = flags & BCRYPT_ALG_HANDLE_HMAC_FLAG;
254 *handle = alg;
255 return STATUS_SUCCESS;
258 NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags )
260 struct algorithm *alg = handle;
262 TRACE( "%p, %08x\n", handle, flags );
264 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
265 HeapFree( GetProcessHeap(), 0, alg );
266 return STATUS_SUCCESS;
269 NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled)
271 FIXME("%p - semi-stub\n", enabled);
273 if (!enabled)
274 return STATUS_INVALID_PARAMETER;
276 *enabled = FALSE;
277 return STATUS_SUCCESS;
280 #ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
281 struct hash
283 struct object hdr;
284 enum alg_id alg_id;
285 BOOL hmac;
286 union
288 CC_MD5_CTX md5_ctx;
289 CC_SHA1_CTX sha1_ctx;
290 CC_SHA256_CTX sha256_ctx;
291 CC_SHA512_CTX sha512_ctx;
292 CCHmacContext hmac_ctx;
293 } u;
296 static NTSTATUS hash_init( struct hash *hash )
298 switch (hash->alg_id)
300 case ALG_ID_MD5:
301 CC_MD5_Init( &hash->u.md5_ctx );
302 break;
304 case ALG_ID_SHA1:
305 CC_SHA1_Init( &hash->u.sha1_ctx );
306 break;
308 case ALG_ID_SHA256:
309 CC_SHA256_Init( &hash->u.sha256_ctx );
310 break;
312 case ALG_ID_SHA384:
313 CC_SHA384_Init( &hash->u.sha512_ctx );
314 break;
316 case ALG_ID_SHA512:
317 CC_SHA512_Init( &hash->u.sha512_ctx );
318 break;
320 default:
321 ERR( "unhandled id %u\n", hash->alg_id );
322 return STATUS_NOT_IMPLEMENTED;
324 return STATUS_SUCCESS;
327 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
329 CCHmacAlgorithm cc_algorithm;
330 switch (hash->alg_id)
332 case ALG_ID_MD5:
333 cc_algorithm = kCCHmacAlgMD5;
334 break;
336 case ALG_ID_SHA1:
337 cc_algorithm = kCCHmacAlgSHA1;
338 break;
340 case ALG_ID_SHA256:
341 cc_algorithm = kCCHmacAlgSHA256;
342 break;
344 case ALG_ID_SHA384:
345 cc_algorithm = kCCHmacAlgSHA384;
346 break;
348 case ALG_ID_SHA512:
349 cc_algorithm = kCCHmacAlgSHA512;
350 break;
352 default:
353 ERR( "unhandled id %u\n", hash->alg_id );
354 return STATUS_NOT_IMPLEMENTED;
357 CCHmacInit( &hash->u.hmac_ctx, cc_algorithm, key, key_size );
358 return STATUS_SUCCESS;
362 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
364 switch (hash->alg_id)
366 case ALG_ID_MD5:
367 CC_MD5_Update( &hash->u.md5_ctx, input, size );
368 break;
370 case ALG_ID_SHA1:
371 CC_SHA1_Update( &hash->u.sha1_ctx, input, size );
372 break;
374 case ALG_ID_SHA256:
375 CC_SHA256_Update( &hash->u.sha256_ctx, input, size );
376 break;
378 case ALG_ID_SHA384:
379 CC_SHA384_Update( &hash->u.sha512_ctx, input, size );
380 break;
382 case ALG_ID_SHA512:
383 CC_SHA512_Update( &hash->u.sha512_ctx, input, size );
384 break;
386 default:
387 ERR( "unhandled id %u\n", hash->alg_id );
388 return STATUS_NOT_IMPLEMENTED;
390 return STATUS_SUCCESS;
393 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
395 CCHmacUpdate( &hash->u.hmac_ctx, input, size );
396 return STATUS_SUCCESS;
399 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
401 switch (hash->alg_id)
403 case ALG_ID_MD5:
404 CC_MD5_Final( output, &hash->u.md5_ctx );
405 break;
407 case ALG_ID_SHA1:
408 CC_SHA1_Final( output, &hash->u.sha1_ctx );
409 break;
411 case ALG_ID_SHA256:
412 CC_SHA256_Final( output, &hash->u.sha256_ctx );
413 break;
415 case ALG_ID_SHA384:
416 CC_SHA384_Final( output, &hash->u.sha512_ctx );
417 break;
419 case ALG_ID_SHA512:
420 CC_SHA512_Final( output, &hash->u.sha512_ctx );
421 break;
423 default:
424 ERR( "unhandled id %u\n", hash->alg_id );
425 break;
427 return STATUS_SUCCESS;
430 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
432 CCHmacFinal( &hash->u.hmac_ctx, output );
434 return STATUS_SUCCESS;
436 #elif defined(HAVE_GNUTLS_HASH)
437 struct hash
439 struct object hdr;
440 enum alg_id alg_id;
441 BOOL hmac;
442 union
444 gnutls_hash_hd_t hash_handle;
445 gnutls_hmac_hd_t hmac_handle;
446 } u;
449 static NTSTATUS hash_init( struct hash *hash )
451 gnutls_digest_algorithm_t alg;
453 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
455 switch (hash->alg_id)
457 case ALG_ID_MD5:
458 alg = GNUTLS_DIG_MD5;
459 break;
460 case ALG_ID_SHA1:
461 alg = GNUTLS_DIG_SHA1;
462 break;
464 case ALG_ID_SHA256:
465 alg = GNUTLS_DIG_SHA256;
466 break;
468 case ALG_ID_SHA384:
469 alg = GNUTLS_DIG_SHA384;
470 break;
472 case ALG_ID_SHA512:
473 alg = GNUTLS_DIG_SHA512;
474 break;
476 default:
477 ERR( "unhandled id %u\n", hash->alg_id );
478 return STATUS_NOT_IMPLEMENTED;
481 if (pgnutls_hash_init( &hash->u.hash_handle, alg )) return STATUS_INTERNAL_ERROR;
482 return STATUS_SUCCESS;
485 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
487 gnutls_mac_algorithm_t alg;
489 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
491 switch (hash->alg_id)
493 case ALG_ID_MD5:
494 alg = GNUTLS_MAC_MD5;
495 break;
496 case ALG_ID_SHA1:
497 alg = GNUTLS_MAC_SHA1;
498 break;
500 case ALG_ID_SHA256:
501 alg = GNUTLS_MAC_SHA256;
502 break;
504 case ALG_ID_SHA384:
505 alg = GNUTLS_MAC_SHA384;
506 break;
508 case ALG_ID_SHA512:
509 alg = GNUTLS_MAC_SHA512;
510 break;
512 default:
513 ERR( "unhandled id %u\n", hash->alg_id );
514 return STATUS_NOT_IMPLEMENTED;
517 if (pgnutls_hmac_init( &hash->u.hmac_handle, alg, key, key_size )) return STATUS_INTERNAL_ERROR;
518 return STATUS_SUCCESS;
521 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
523 if (pgnutls_hash( hash->u.hash_handle, input, size )) return STATUS_INTERNAL_ERROR;
524 return STATUS_SUCCESS;
527 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
529 if (pgnutls_hmac( hash->u.hmac_handle, input, size )) return STATUS_INTERNAL_ERROR;
530 return STATUS_SUCCESS;
533 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
535 pgnutls_hash_deinit( hash->u.hash_handle, output );
536 return STATUS_SUCCESS;
539 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
541 pgnutls_hmac_deinit( hash->u.hmac_handle, output );
542 return STATUS_SUCCESS;
544 #else
545 struct hash
547 struct object hdr;
548 BOOL hmac;
549 enum alg_id alg_id;
552 static NTSTATUS hash_init( struct hash *hash )
554 ERR( "support for hashes not available at build time\n" );
555 return STATUS_NOT_IMPLEMENTED;
558 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
560 ERR( "support for hashes not available at build time\n" );
561 return STATUS_NOT_IMPLEMENTED;
564 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
566 ERR( "support for hashes not available at build time\n" );
567 return STATUS_NOT_IMPLEMENTED;
570 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
572 ERR( "support for hashes not available at build time\n" );
573 return STATUS_NOT_IMPLEMENTED;
576 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
578 ERR( "support for hashes not available at build time\n" );
579 return STATUS_NOT_IMPLEMENTED;
582 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
584 ERR( "support for hashes not available at build time\n" );
585 return STATUS_NOT_IMPLEMENTED;
587 #endif
589 #define OBJECT_LENGTH_MD5 274
590 #define OBJECT_LENGTH_SHA1 278
591 #define OBJECT_LENGTH_SHA256 286
592 #define OBJECT_LENGTH_SHA384 382
593 #define OBJECT_LENGTH_SHA512 382
595 static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
597 if (!strcmpW( prop, BCRYPT_HASH_LENGTH ))
599 *ret_size = sizeof(ULONG);
600 if (size < sizeof(ULONG))
601 return STATUS_BUFFER_TOO_SMALL;
602 if(buf)
603 *(ULONG*)buf = alg_props[id].hash_length;
604 return STATUS_SUCCESS;
607 if (!strcmpW( prop, BCRYPT_ALGORITHM_NAME ))
609 *ret_size = (strlenW(alg_props[id].alg_name)+1)*sizeof(WCHAR);
610 if (size < *ret_size)
611 return STATUS_BUFFER_TOO_SMALL;
612 if(buf)
613 memcpy(buf, alg_props[id].alg_name, *ret_size);
614 return STATUS_SUCCESS;
617 return STATUS_NOT_IMPLEMENTED;
620 static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
622 NTSTATUS status;
623 ULONG value;
625 status = generic_alg_property( id, prop, buf, size, ret_size );
626 if (status != STATUS_NOT_IMPLEMENTED)
627 return status;
629 switch (id)
631 case ALG_ID_MD5:
632 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
634 value = OBJECT_LENGTH_MD5;
635 break;
637 FIXME( "unsupported md5 algorithm property %s\n", debugstr_w(prop) );
638 return STATUS_NOT_IMPLEMENTED;
640 case ALG_ID_RNG:
641 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) return STATUS_NOT_SUPPORTED;
642 FIXME( "unsupported rng algorithm property %s\n", debugstr_w(prop) );
643 return STATUS_NOT_IMPLEMENTED;
645 case ALG_ID_SHA1:
646 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
648 value = OBJECT_LENGTH_SHA1;
649 break;
651 FIXME( "unsupported sha1 algorithm property %s\n", debugstr_w(prop) );
652 return STATUS_NOT_IMPLEMENTED;
654 case ALG_ID_SHA256:
655 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
657 value = OBJECT_LENGTH_SHA256;
658 break;
660 FIXME( "unsupported sha256 algorithm property %s\n", debugstr_w(prop) );
661 return STATUS_NOT_IMPLEMENTED;
663 case ALG_ID_SHA384:
664 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
666 value = OBJECT_LENGTH_SHA384;
667 break;
669 FIXME( "unsupported sha384 algorithm property %s\n", debugstr_w(prop) );
670 return STATUS_NOT_IMPLEMENTED;
672 case ALG_ID_SHA512:
673 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
675 value = OBJECT_LENGTH_SHA512;
676 break;
678 FIXME( "unsupported sha512 algorithm property %s\n", debugstr_w(prop) );
679 return STATUS_NOT_IMPLEMENTED;
681 default:
682 FIXME( "unsupported algorithm %u\n", id );
683 return STATUS_NOT_IMPLEMENTED;
686 if (size < sizeof(ULONG))
688 *ret_size = sizeof(ULONG);
689 return STATUS_BUFFER_TOO_SMALL;
691 if (buf) *(ULONG *)buf = value;
692 *ret_size = sizeof(ULONG);
694 return STATUS_SUCCESS;
697 static NTSTATUS get_hash_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
699 NTSTATUS status;
701 status = generic_alg_property( id, prop, buf, size, ret_size );
702 if (status == STATUS_NOT_IMPLEMENTED)
703 FIXME( "unsupported property %s\n", debugstr_w(prop) );
704 return status;
707 NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags )
709 struct object *object = handle;
711 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags );
713 if (!object) return STATUS_INVALID_HANDLE;
714 if (!prop || !res) return STATUS_INVALID_PARAMETER;
716 switch (object->magic)
718 case MAGIC_ALG:
720 const struct algorithm *alg = (const struct algorithm *)object;
721 return get_alg_property( alg->id, prop, buffer, count, res );
723 case MAGIC_HASH:
725 const struct hash *hash = (const struct hash *)object;
726 return get_hash_property( hash->alg_id, prop, buffer, count, res );
728 default:
729 WARN( "unknown magic %08x\n", object->magic );
730 return STATUS_INVALID_HANDLE;
734 NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen,
735 UCHAR *secret, ULONG secretlen, ULONG flags )
737 struct algorithm *alg = algorithm;
738 struct hash *hash;
739 NTSTATUS status;
741 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen,
742 secret, secretlen, flags );
743 if (flags)
745 FIXME( "unimplemented flags %08x\n", flags );
746 return STATUS_NOT_IMPLEMENTED;
749 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
750 if (object) FIXME( "ignoring object buffer\n" );
752 if (!(hash = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash) ))) return STATUS_NO_MEMORY;
753 hash->hdr.magic = MAGIC_HASH;
754 hash->alg_id = alg->id;
755 hash->hmac = alg->hmac;
757 if (hash->hmac)
759 status = hmac_init( hash, secret, secretlen );
761 else
763 status = hash_init( hash );
766 if (status != STATUS_SUCCESS)
768 HeapFree( GetProcessHeap(), 0, hash );
769 return status;
772 *handle = hash;
773 return STATUS_SUCCESS;
776 NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
778 struct hash *hash = handle;
780 TRACE( "%p\n", handle );
782 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
783 HeapFree( GetProcessHeap(), 0, hash );
784 return STATUS_SUCCESS;
787 NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG size, ULONG flags )
789 struct hash *hash = handle;
791 TRACE( "%p, %p, %u, %08x\n", handle, input, size, flags );
793 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
794 if (!input) return STATUS_SUCCESS;
796 if (hash->hmac)
798 return hmac_update( hash, input, size );
800 else
802 return hash_update( hash, input, size );
806 NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
808 struct hash *hash = handle;
810 TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags );
812 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
813 if (!output) return STATUS_INVALID_PARAMETER;
815 if (hash->hmac)
817 return hmac_finish( hash, output, size );
819 else
821 return hash_finish( hash, output, size );
825 NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen,
826 UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen )
828 NTSTATUS status;
829 BCRYPT_HASH_HANDLE handle;
831 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secretlen,
832 input, inputlen, output, outputlen );
834 status = BCryptCreateHash( algorithm, &handle, NULL, 0, secret, secretlen, 0);
835 if (status != STATUS_SUCCESS)
837 return status;
840 status = BCryptHashData( handle, input, inputlen, 0 );
841 if (status != STATUS_SUCCESS)
843 BCryptDestroyHash( handle );
844 return status;
847 status = BCryptFinishHash( handle, output, outputlen, 0 );
848 if (status != STATUS_SUCCESS)
850 BCryptDestroyHash( handle );
851 return status;
854 return BCryptDestroyHash( handle );
857 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
859 switch (reason)
861 case DLL_PROCESS_ATTACH:
862 instance = hinst;
863 DisableThreadLibraryCalls( hinst );
864 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
865 gnutls_initialize();
866 #endif
867 break;
869 case DLL_PROCESS_DETACH:
870 if (reserved) break;
871 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
872 gnutls_uninitialize();
873 #endif
874 break;
876 return TRUE;