5212af96391f0445c4b0d1bf3b223da7cf53eb6b
[reactos.git] / reactos / dll / win32 / bcrypt / bcrypt_main.c
1 /*
2 * Copyright 2009 Henri Verbeet for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 *
18 */
19
20 #include <wine/config.h>
21 #include <wine/port.h>
22
23 #include <ntstatus.h>
24 #define WIN32_NO_STATUS
25 #include <windef.h>
26 #include <winbase.h>
27 #include <ntsecapi.h>
28 #include <bcrypt.h>
29
30 #include <wine/debug.h>
31 #include <wine/unicode.h>
32 #include <wine/library.h>
33
34 #ifdef SONAME_LIBMBEDTLS
35 #include <mbedtls/sha1.h>
36 #include <mbedtls/sha256.h>
37 #include <mbedtls/sha512.h>
38 #endif
39
40 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
41
42 static HINSTANCE instance;
43
44 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
45 WINE_DECLARE_DEBUG_CHANNEL(winediag);
46
47 static void *libgnutls_handle;
48 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
49 MAKE_FUNCPTR(gnutls_global_deinit);
50 MAKE_FUNCPTR(gnutls_global_init);
51 MAKE_FUNCPTR(gnutls_global_set_log_function);
52 MAKE_FUNCPTR(gnutls_global_set_log_level);
53 MAKE_FUNCPTR(gnutls_hash);
54 MAKE_FUNCPTR(gnutls_hash_deinit);
55 MAKE_FUNCPTR(gnutls_hash_init);
56 MAKE_FUNCPTR(gnutls_perror);
57 #undef MAKE_FUNCPTR
58
59 static void gnutls_log( int level, const char *msg )
60 {
61 TRACE( "<%d> %s", level, msg );
62 }
63
64 static BOOL gnutls_initialize(void)
65 {
66 int ret;
67
68 if (!(libgnutls_handle = wine_dlopen( SONAME_LIBGNUTLS, RTLD_NOW, NULL, 0 )))
69 {
70 ERR_(winediag)( "failed to load libgnutls, no support for crypto hashes\n" );
71 return FALSE;
72 }
73
74 #define LOAD_FUNCPTR(f) \
75 if (!(p##f = wine_dlsym( libgnutls_handle, #f, NULL, 0 ))) \
76 { \
77 ERR( "failed to load %s\n", #f ); \
78 goto fail; \
79 }
80
81 LOAD_FUNCPTR(gnutls_global_deinit)
82 LOAD_FUNCPTR(gnutls_global_init)
83 LOAD_FUNCPTR(gnutls_global_set_log_function)
84 LOAD_FUNCPTR(gnutls_global_set_log_level)
85 LOAD_FUNCPTR(gnutls_hash);
86 LOAD_FUNCPTR(gnutls_hash_deinit);
87 LOAD_FUNCPTR(gnutls_hash_init);
88 LOAD_FUNCPTR(gnutls_perror)
89 #undef LOAD_FUNCPTR
90
91 if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS)
92 {
93 pgnutls_perror( ret );
94 goto fail;
95 }
96
97 if (TRACE_ON( bcrypt ))
98 {
99 pgnutls_global_set_log_level( 4 );
100 pgnutls_global_set_log_function( gnutls_log );
101 }
102
103 return TRUE;
104
105 fail:
106 wine_dlclose( libgnutls_handle, NULL, 0 );
107 libgnutls_handle = NULL;
108 return FALSE;
109 }
110
111 static void gnutls_uninitialize(void)
112 {
113 pgnutls_global_deinit();
114 wine_dlclose( libgnutls_handle, NULL, 0 );
115 libgnutls_handle = NULL;
116 }
117 #elif defined(SONAME_LIBMBEDTLS) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) && !defined(__REACTOS__)
118 WINE_DECLARE_DEBUG_CHANNEL(winediag);
119
120 void *libmbedtls_handle;
121
122 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
123 MAKE_FUNCPTR(mbedtls_sha1_init);
124 MAKE_FUNCPTR(mbedtls_sha1_starts);
125 MAKE_FUNCPTR(mbedtls_sha1_update);
126 MAKE_FUNCPTR(mbedtls_sha1_finish);
127 MAKE_FUNCPTR(mbedtls_sha1_free);
128 MAKE_FUNCPTR(mbedtls_sha256_init);
129 MAKE_FUNCPTR(mbedtls_sha256_starts);
130 MAKE_FUNCPTR(mbedtls_sha256_update);
131 MAKE_FUNCPTR(mbedtls_sha256_finish);
132 MAKE_FUNCPTR(mbedtls_sha256_free);
133 MAKE_FUNCPTR(mbedtls_sha512_init);
134 MAKE_FUNCPTR(mbedtls_sha512_starts);
135 MAKE_FUNCPTR(mbedtls_sha512_update);
136 MAKE_FUNCPTR(mbedtls_sha512_finish);
137 MAKE_FUNCPTR(mbedtls_sha512_free);
138 #undef MAKE_FUNCPTR
139
140 #define mbedtls_sha1_init pmbedtls_sha1_init
141 #define mbedtls_sha1_starts pmbedtls_sha1_starts
142 #define mbedtls_sha1_update pmbedtls_sha1_update
143 #define mbedtls_sha1_finish pmbedtls_sha1_finish
144 #define mbedtls_sha1_free pmbedtls_sha1_free
145 #define mbedtls_sha256_init pmbedtls_sha256_init
146 #define mbedtls_sha256_starts pmbedtls_sha256_starts
147 #define mbedtls_sha256_update pmbedtls_sha256_update
148 #define mbedtls_sha256_finish pmbedtls_sha256_finish
149 #define mbedtls_sha256_free pmbedtls_sha256_free
150 #define mbedtls_sha512_init pmbedtls_sha512_init
151 #define mbedtls_sha512_starts pmbedtls_sha512_starts
152 #define mbedtls_sha512_update pmbedtls_sha512_update
153 #define mbedtls_sha512_finish pmbedtls_sha512_finish
154 #define mbedtls_sha512_free pmbedtls_sha512_free
155
156 static BOOL mbedtls_initialize(void)
157 {
158 if (!(libmbedtls_handle = wine_dlopen( SONAME_LIBMBEDTLS, RTLD_NOW, NULL, 0 )))
159 {
160 ERR_(winediag)( "failed to load libmbedtls, no support for crypto hashes\n" );
161 return FALSE;
162 }
163
164 #define LOAD_FUNCPTR(f) \
165 if (!(p##f = wine_dlsym( libmbedtls_handle, #f, NULL, 0 ))) \
166 { \
167 ERR( "failed to load %s\n", #f ); \
168 goto fail; \
169 }
170
171 LOAD_FUNCPTR(mbedtls_sha1_init)
172 LOAD_FUNCPTR(mbedtls_sha1_starts)
173 LOAD_FUNCPTR(mbedtls_sha1_update)
174 LOAD_FUNCPTR(mbedtls_sha1_finish)
175 LOAD_FUNCPTR(mbedtls_sha1_free);
176 LOAD_FUNCPTR(mbedtls_sha256_init)
177 LOAD_FUNCPTR(mbedtls_sha256_starts)
178 LOAD_FUNCPTR(mbedtls_sha256_update)
179 LOAD_FUNCPTR(mbedtls_sha256_finish)
180 LOAD_FUNCPTR(mbedtls_sha256_free);
181 LOAD_FUNCPTR(mbedtls_sha512_init)
182 LOAD_FUNCPTR(mbedtls_sha512_starts)
183 LOAD_FUNCPTR(mbedtls_sha512_update)
184 LOAD_FUNCPTR(mbedtls_sha512_finish)
185 LOAD_FUNCPTR(mbedtls_sha512_free);
186 #undef LOAD_FUNCPTR
187
188 return TRUE;
189
190 fail:
191 wine_dlclose( libmbedtls_handle, NULL, 0 );
192 libmbedtls_handle = NULL;
193 return FALSE;
194 }
195
196 static void mbedtls_uninitialize(void)
197 {
198 wine_dlclose( libmbedtls_handle, NULL, 0 );
199 libmbedtls_handle = NULL;
200 }
201 #endif /* SONAME_LIBMBEDTLS && !HAVE_COMMONCRYPTO_COMMONDIGEST_H && !__REACTOS__ */
202
203 NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount,
204 BCRYPT_ALGORITHM_IDENTIFIER **ppAlgList, ULONG dwFlags)
205 {
206 FIXME("%08x, %p, %p, %08x - stub\n", dwAlgOperations, pAlgCount, ppAlgList, dwFlags);
207
208 *ppAlgList=NULL;
209 *pAlgCount=0;
210
211 return STATUS_NOT_IMPLEMENTED;
212 }
213
214 NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE algorithm, UCHAR *buffer, ULONG count, ULONG flags)
215 {
216 const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
217 TRACE("%p, %p, %u, %08x - semi-stub\n", algorithm, buffer, count, flags);
218
219 if (!algorithm)
220 {
221 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
222 * is set. In this case the preferred system RNG is used.
223 */
224 if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
225 return STATUS_INVALID_HANDLE;
226 }
227 if (!buffer)
228 return STATUS_INVALID_PARAMETER;
229
230 if (flags & ~supported_flags)
231 FIXME("unsupported flags %08x\n", flags & ~supported_flags);
232
233 if (algorithm)
234 FIXME("ignoring selected algorithm\n");
235
236 /* When zero bytes are requested the function returns success too. */
237 if (!count)
238 return STATUS_SUCCESS;
239
240 if (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG)
241 {
242 if (RtlGenRandom(buffer, count))
243 return STATUS_SUCCESS;
244 }
245
246 FIXME("called with unsupported parameters, returning error\n");
247 return STATUS_NOT_IMPLEMENTED;
248 }
249
250 #define MAGIC_ALG (('A' << 24) | ('L' << 16) | ('G' << 8) | '0')
251 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
252 struct object
253 {
254 ULONG magic;
255 };
256
257 enum alg_id
258 {
259 ALG_ID_SHA1,
260 ALG_ID_SHA256,
261 ALG_ID_SHA384,
262 ALG_ID_SHA512
263 };
264
265 static const struct {
266 ULONG hash_length;
267 const WCHAR *alg_name;
268 } alg_props[] = {
269 /* ALG_ID_SHA1 */ { 20, BCRYPT_SHA1_ALGORITHM },
270 /* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM },
271 /* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM },
272 /* ALG_ID_SHA512 */ { 64, BCRYPT_SHA512_ALGORITHM }
273 };
274
275 struct algorithm
276 {
277 struct object hdr;
278 enum alg_id id;
279 };
280
281 NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
282 {
283 struct algorithm *alg;
284 enum alg_id alg_id;
285
286 TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags );
287
288 if (!handle || !id) return STATUS_INVALID_PARAMETER;
289 if (flags)
290 {
291 FIXME( "unimplemented flags %08x\n", flags );
292 return STATUS_NOT_IMPLEMENTED;
293 }
294
295 if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1;
296 else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256;
297 else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384;
298 else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512;
299 else
300 {
301 FIXME( "algorithm %s not supported\n", debugstr_w(id) );
302 return STATUS_NOT_IMPLEMENTED;
303 }
304 if (implementation && strcmpW( implementation, MS_PRIMITIVE_PROVIDER ))
305 {
306 FIXME( "implementation %s not supported\n", debugstr_w(implementation) );
307 return STATUS_NOT_IMPLEMENTED;
308 }
309
310 if (!(alg = HeapAlloc( GetProcessHeap(), 0, sizeof(*alg) ))) return STATUS_NO_MEMORY;
311 alg->hdr.magic = MAGIC_ALG;
312 alg->id = alg_id;
313
314 *handle = alg;
315 return STATUS_SUCCESS;
316 }
317
318 NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags )
319 {
320 struct algorithm *alg = handle;
321
322 TRACE( "%p, %08x\n", handle, flags );
323
324 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
325 HeapFree( GetProcessHeap(), 0, alg );
326 return STATUS_SUCCESS;
327 }
328
329 NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled)
330 {
331 FIXME("%p - semi-stub\n", enabled);
332
333 if (!enabled)
334 return STATUS_INVALID_PARAMETER;
335
336 *enabled = FALSE;
337 return STATUS_SUCCESS;
338 }
339
340 #ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
341 struct hash
342 {
343 struct object hdr;
344 enum alg_id alg_id;
345 union
346 {
347 CC_SHA1_CTX sha1_ctx;
348 CC_SHA256_CTX sha256_ctx;
349 CC_SHA512_CTX sha512_ctx;
350 } u;
351 };
352
353 static NTSTATUS hash_init( struct hash *hash )
354 {
355 switch (hash->alg_id)
356 {
357 case ALG_ID_SHA1:
358 CC_SHA1_Init( &hash->u.sha1_ctx );
359 break;
360
361 case ALG_ID_SHA256:
362 CC_SHA256_Init( &hash->u.sha256_ctx );
363 break;
364
365 case ALG_ID_SHA384:
366 CC_SHA384_Init( &hash->u.sha512_ctx );
367 break;
368
369 case ALG_ID_SHA512:
370 CC_SHA512_Init( &hash->u.sha512_ctx );
371 break;
372
373 default:
374 ERR( "unhandled id %u\n", hash->alg_id );
375 return STATUS_NOT_IMPLEMENTED;
376 }
377 return STATUS_SUCCESS;
378 }
379
380 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
381 {
382 switch (hash->alg_id)
383 {
384 case ALG_ID_SHA1:
385 CC_SHA1_Update( &hash->u.sha1_ctx, input, size );
386 break;
387
388 case ALG_ID_SHA256:
389 CC_SHA256_Update( &hash->u.sha256_ctx, input, size );
390 break;
391
392 case ALG_ID_SHA384:
393 CC_SHA384_Update( &hash->u.sha512_ctx, input, size );
394 break;
395
396 case ALG_ID_SHA512:
397 CC_SHA512_Update( &hash->u.sha512_ctx, input, size );
398 break;
399
400 default:
401 ERR( "unhandled id %u\n", hash->alg_id );
402 return STATUS_NOT_IMPLEMENTED;
403 }
404 return STATUS_SUCCESS;
405 }
406
407 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
408 {
409 switch (hash->alg_id)
410 {
411 case ALG_ID_SHA1:
412 CC_SHA1_Final( output, &hash->u.sha1_ctx );
413 break;
414
415 case ALG_ID_SHA256:
416 CC_SHA256_Final( output, &hash->u.sha256_ctx );
417 break;
418
419 case ALG_ID_SHA384:
420 CC_SHA384_Final( output, &hash->u.sha512_ctx );
421 break;
422
423 case ALG_ID_SHA512:
424 CC_SHA512_Final( output, &hash->u.sha512_ctx );
425 break;
426
427 default:
428 ERR( "unhandled id %u\n", hash->alg_id );
429 break;
430 }
431 return STATUS_SUCCESS;
432 }
433 #elif defined(HAVE_GNUTLS_HASH)
434 struct hash
435 {
436 struct object hdr;
437 enum alg_id alg_id;
438 gnutls_hash_hd_t handle;
439 };
440
441 static NTSTATUS hash_init( struct hash *hash )
442 {
443 gnutls_digest_algorithm_t alg;
444
445 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
446
447 switch (hash->alg_id)
448 {
449 case ALG_ID_SHA1:
450 alg = GNUTLS_DIG_SHA1;
451 break;
452
453 case ALG_ID_SHA256:
454 alg = GNUTLS_DIG_SHA256;
455 break;
456
457 case ALG_ID_SHA384:
458 alg = GNUTLS_DIG_SHA384;
459 break;
460
461 case ALG_ID_SHA512:
462 alg = GNUTLS_DIG_SHA512;
463 break;
464
465 default:
466 ERR( "unhandled id %u\n", hash->alg_id );
467 return STATUS_NOT_IMPLEMENTED;
468 }
469
470 if (pgnutls_hash_init( &hash->handle, alg )) return STATUS_INTERNAL_ERROR;
471 return STATUS_SUCCESS;
472 }
473
474 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
475 {
476 if (pgnutls_hash( hash->handle, input, size )) return STATUS_INTERNAL_ERROR;
477 return STATUS_SUCCESS;
478 }
479
480 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
481 {
482 pgnutls_hash_deinit( hash->handle, output );
483 return STATUS_SUCCESS;
484 }
485 #elif defined(SONAME_LIBMBEDTLS)
486 struct hash
487 {
488 struct object hdr;
489 enum alg_id alg_id;
490 union
491 {
492 mbedtls_sha1_context sha1_ctx;
493 mbedtls_sha256_context sha256_ctx;
494 mbedtls_sha512_context sha512_ctx;
495 } u;
496 };
497
498 static NTSTATUS hash_init( struct hash *hash )
499 {
500 #ifndef __REACTOS__
501 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
502 #endif
503 switch (hash->alg_id)
504 {
505 case ALG_ID_SHA1:
506 mbedtls_sha1_init(&hash->u.sha1_ctx);
507 mbedtls_sha1_starts(&hash->u.sha1_ctx);
508 break;
509
510 case ALG_ID_SHA256:
511 mbedtls_sha256_init(&hash->u.sha256_ctx);
512 mbedtls_sha256_starts(&hash->u.sha256_ctx, FALSE);
513 break;
514
515 case ALG_ID_SHA384:
516 case ALG_ID_SHA512:
517 mbedtls_sha512_init(&hash->u.sha512_ctx);
518 mbedtls_sha512_starts(&hash->u.sha512_ctx, hash->alg_id==ALG_ID_SHA384);
519 break;
520
521 default:
522 ERR( "unhandled id %u\n", hash->alg_id );
523 return STATUS_NOT_IMPLEMENTED;
524 }
525
526 return STATUS_SUCCESS;
527 }
528
529 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
530 {
531 #ifndef __REACTOS__
532 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
533 #endif
534 switch (hash->alg_id)
535 {
536 case ALG_ID_SHA1:
537 mbedtls_sha1_update(&hash->u.sha1_ctx, input, size);
538 break;
539
540 case ALG_ID_SHA256:
541 mbedtls_sha256_update(&hash->u.sha256_ctx, input, size);
542 break;
543
544 case ALG_ID_SHA384:
545 case ALG_ID_SHA512:
546 mbedtls_sha512_update(&hash->u.sha512_ctx, input, size);
547 break;
548
549 default:
550 ERR( "unhandled id %u\n", hash->alg_id );
551 return STATUS_NOT_IMPLEMENTED;
552 }
553
554 return STATUS_SUCCESS;
555 }
556
557 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
558 {
559 #ifndef __REACTOS__
560 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
561 #endif
562 switch (hash->alg_id)
563 {
564 case ALG_ID_SHA1:
565 mbedtls_sha1_finish(&hash->u.sha1_ctx, output);
566 mbedtls_sha1_free(&hash->u.sha1_ctx);
567 break;
568
569 case ALG_ID_SHA256:
570 mbedtls_sha256_finish(&hash->u.sha256_ctx, output);
571 mbedtls_sha256_free(&hash->u.sha256_ctx);
572 break;
573
574 case ALG_ID_SHA384:
575 case ALG_ID_SHA512:
576 mbedtls_sha512_finish(&hash->u.sha512_ctx, output);
577 mbedtls_sha512_free(&hash->u.sha512_ctx);
578 break;
579
580 default:
581 ERR( "unhandled id %u\n", hash->alg_id );
582 return STATUS_NOT_IMPLEMENTED;
583 }
584
585 return STATUS_SUCCESS;
586 }
587 #else
588 struct hash
589 {
590 struct object hdr;
591 enum alg_id alg_id;
592 };
593
594 static NTSTATUS hash_init( struct hash *hash )
595 {
596 ERR( "support for hashes not available at build time\n" );
597 return STATUS_NOT_IMPLEMENTED;
598 }
599
600 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
601 {
602 ERR( "support for hashes not available at build time\n" );
603 return STATUS_NOT_IMPLEMENTED;
604 }
605
606 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
607 {
608 ERR( "support for hashes not available at build time\n" );
609 return STATUS_NOT_IMPLEMENTED;
610 }
611 #endif
612
613 #define OBJECT_LENGTH_SHA1 278
614 #define OBJECT_LENGTH_SHA256 286
615 #define OBJECT_LENGTH_SHA384 382
616 #define OBJECT_LENGTH_SHA512 382
617
618 static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
619 {
620 if (!strcmpW( prop, BCRYPT_HASH_LENGTH ))
621 {
622 *ret_size = sizeof(ULONG);
623 if (size < sizeof(ULONG))
624 return STATUS_BUFFER_TOO_SMALL;
625 if(buf)
626 *(ULONG*)buf = alg_props[id].hash_length;
627 return STATUS_SUCCESS;
628 }
629
630 if (!strcmpW( prop, BCRYPT_ALGORITHM_NAME ))
631 {
632 *ret_size = (strlenW(alg_props[id].alg_name)+1)*sizeof(WCHAR);
633 if (size < *ret_size)
634 return STATUS_BUFFER_TOO_SMALL;
635 if(buf)
636 memcpy(buf, alg_props[id].alg_name, *ret_size);
637 return STATUS_SUCCESS;
638 }
639
640 return STATUS_NOT_IMPLEMENTED;
641 }
642
643 static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
644 {
645 NTSTATUS status;
646 ULONG value;
647
648 status = generic_alg_property( id, prop, buf, size, ret_size );
649 if (status != STATUS_NOT_IMPLEMENTED)
650 return status;
651
652 switch (id)
653 {
654 case ALG_ID_SHA1:
655 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
656 {
657 value = OBJECT_LENGTH_SHA1;
658 break;
659 }
660 FIXME( "unsupported sha1 algorithm property %s\n", debugstr_w(prop) );
661 return STATUS_NOT_IMPLEMENTED;
662
663 case ALG_ID_SHA256:
664 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
665 {
666 value = OBJECT_LENGTH_SHA256;
667 break;
668 }
669 FIXME( "unsupported sha256 algorithm property %s\n", debugstr_w(prop) );
670 return STATUS_NOT_IMPLEMENTED;
671
672 case ALG_ID_SHA384:
673 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
674 {
675 value = OBJECT_LENGTH_SHA384;
676 break;
677 }
678 FIXME( "unsupported sha384 algorithm property %s\n", debugstr_w(prop) );
679 return STATUS_NOT_IMPLEMENTED;
680
681 case ALG_ID_SHA512:
682 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
683 {
684 value = OBJECT_LENGTH_SHA512;
685 break;
686 }
687 FIXME( "unsupported sha512 algorithm property %s\n", debugstr_w(prop) );
688 return STATUS_NOT_IMPLEMENTED;
689
690 default:
691 FIXME( "unsupported algorithm %u\n", id );
692 return STATUS_NOT_IMPLEMENTED;
693 }
694
695 if (size < sizeof(ULONG))
696 {
697 *ret_size = sizeof(ULONG);
698 return STATUS_BUFFER_TOO_SMALL;
699 }
700 if (buf) *(ULONG *)buf = value;
701 *ret_size = sizeof(ULONG);
702
703 return STATUS_SUCCESS;
704 }
705
706 static NTSTATUS get_hash_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
707 {
708 NTSTATUS status;
709
710 status = generic_alg_property( id, prop, buf, size, ret_size );
711 if (status == STATUS_NOT_IMPLEMENTED)
712 FIXME( "unsupported property %s\n", debugstr_w(prop) );
713 return status;
714 }
715
716 NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags )
717 {
718 struct object *object = handle;
719
720 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags );
721
722 if (!object) return STATUS_INVALID_HANDLE;
723 if (!prop || !res) return STATUS_INVALID_PARAMETER;
724
725 switch (object->magic)
726 {
727 case MAGIC_ALG:
728 {
729 const struct algorithm *alg = (const struct algorithm *)object;
730 return get_alg_property( alg->id, prop, buffer, count, res );
731 }
732 case MAGIC_HASH:
733 {
734 const struct hash *hash = (const struct hash *)object;
735 return get_hash_property( hash->alg_id, prop, buffer, count, res );
736 }
737 default:
738 WARN( "unknown magic %08x\n", object->magic );
739 return STATUS_INVALID_HANDLE;
740 }
741 }
742
743 NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen,
744 UCHAR *secret, ULONG secretlen, ULONG flags )
745 {
746 struct algorithm *alg = algorithm;
747 struct hash *hash;
748 NTSTATUS status;
749
750 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen,
751 secret, secretlen, flags );
752 if (flags)
753 {
754 FIXME( "unimplemented flags %08x\n", flags );
755 return STATUS_NOT_IMPLEMENTED;
756 }
757
758 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
759 if (object) FIXME( "ignoring object buffer\n" );
760
761 if (!(hash = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash) ))) return STATUS_NO_MEMORY;
762 hash->hdr.magic = MAGIC_HASH;
763 hash->alg_id = alg->id;
764 if ((status = hash_init( hash )) != STATUS_SUCCESS)
765 {
766 HeapFree( GetProcessHeap(), 0, hash );
767 return status;
768 }
769
770 *handle = hash;
771 return STATUS_SUCCESS;
772 }
773
774 NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
775 {
776 struct hash *hash = handle;
777
778 TRACE( "%p\n", handle );
779
780 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
781 HeapFree( GetProcessHeap(), 0, hash );
782 return STATUS_SUCCESS;
783 }
784
785 NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG size, ULONG flags )
786 {
787 struct hash *hash = handle;
788
789 TRACE( "%p, %p, %u, %08x\n", handle, input, size, flags );
790
791 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
792 if (!input) return STATUS_INVALID_PARAMETER;
793
794 return hash_update( hash, input, size );
795 }
796
797 NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
798 {
799 struct hash *hash = handle;
800
801 TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags );
802
803 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
804 if (!output) return STATUS_INVALID_PARAMETER;
805
806 return hash_finish( hash, output, size );
807 }
808
809 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
810 {
811 switch (reason)
812 {
813 case DLL_PROCESS_ATTACH:
814 instance = hinst;
815 DisableThreadLibraryCalls( hinst );
816 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
817 gnutls_initialize();
818 #elif defined(SONAME_LIBMBEDTLS) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) && !defined(__REACTOS__)
819 mbedtls_initialize();
820 #endif
821 break;
822
823 case DLL_PROCESS_DETACH:
824 if (reserved) break;
825 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
826 gnutls_uninitialize();
827 #elif defined(SONAME_LIBMBEDTLS) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) && !defined(__REACTOS__)
828 mbedtls_uninitialize();
829 #endif
830 break;
831 }
832 return TRUE;
833 }