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/md.h>
36 #include <mbedtls/md5.h>
37 #include <mbedtls/sha1.h>
38 #include <mbedtls/sha256.h>
39 #include <mbedtls/sha512.h>
40 #endif
41
42 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt);
43
44 static HINSTANCE instance;
45
46 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
47 WINE_DECLARE_DEBUG_CHANNEL(winediag);
48
49 static void *libgnutls_handle;
50 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
51 MAKE_FUNCPTR(gnutls_global_deinit);
52 MAKE_FUNCPTR(gnutls_global_init);
53 MAKE_FUNCPTR(gnutls_global_set_log_function);
54 MAKE_FUNCPTR(gnutls_global_set_log_level);
55 MAKE_FUNCPTR(gnutls_hash);
56 MAKE_FUNCPTR(gnutls_hash_deinit);
57 MAKE_FUNCPTR(gnutls_hash_init);
58 MAKE_FUNCPTR(gnutls_hmac);
59 MAKE_FUNCPTR(gnutls_hmac_deinit);
60 MAKE_FUNCPTR(gnutls_hmac_init);
61 MAKE_FUNCPTR(gnutls_perror);
62 #undef MAKE_FUNCPTR
63
gnutls_log(int level,const char * msg)64 static void gnutls_log( int level, const char *msg )
65 {
66 TRACE( "<%d> %s", level, msg );
67 }
68
gnutls_initialize(void)69 static BOOL gnutls_initialize(void)
70 {
71 int ret;
72
73 if (!(libgnutls_handle = wine_dlopen( SONAME_LIBGNUTLS, RTLD_NOW, NULL, 0 )))
74 {
75 ERR_(winediag)( "failed to load libgnutls, no support for crypto hashes\n" );
76 return FALSE;
77 }
78
79 #define LOAD_FUNCPTR(f) \
80 if (!(p##f = wine_dlsym( libgnutls_handle, #f, NULL, 0 ))) \
81 { \
82 ERR( "failed to load %s\n", #f ); \
83 goto fail; \
84 }
85
86 LOAD_FUNCPTR(gnutls_global_deinit)
87 LOAD_FUNCPTR(gnutls_global_init)
88 LOAD_FUNCPTR(gnutls_global_set_log_function)
89 LOAD_FUNCPTR(gnutls_global_set_log_level)
90 LOAD_FUNCPTR(gnutls_hash);
91 LOAD_FUNCPTR(gnutls_hash_deinit);
92 LOAD_FUNCPTR(gnutls_hash_init);
93 LOAD_FUNCPTR(gnutls_hmac);
94 LOAD_FUNCPTR(gnutls_hmac_deinit);
95 LOAD_FUNCPTR(gnutls_hmac_init);
96 LOAD_FUNCPTR(gnutls_perror)
97 #undef LOAD_FUNCPTR
98
99 if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS)
100 {
101 pgnutls_perror( ret );
102 goto fail;
103 }
104
105 if (TRACE_ON( bcrypt ))
106 {
107 pgnutls_global_set_log_level( 4 );
108 pgnutls_global_set_log_function( gnutls_log );
109 }
110
111 return TRUE;
112
113 fail:
114 wine_dlclose( libgnutls_handle, NULL, 0 );
115 libgnutls_handle = NULL;
116 return FALSE;
117 }
118
gnutls_uninitialize(void)119 static void gnutls_uninitialize(void)
120 {
121 pgnutls_global_deinit();
122 wine_dlclose( libgnutls_handle, NULL, 0 );
123 libgnutls_handle = NULL;
124 }
125 #elif defined(SONAME_LIBMBEDTLS) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) && !defined(__REACTOS__)
126 WINE_DECLARE_DEBUG_CHANNEL(winediag);
127
128 void *libmbedtls_handle;
129
130 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
131 MAKE_FUNCPTR(mbedtls_md_init);
132 MAKE_FUNCPTR(mbedtls_md_setup);
133 MAKE_FUNCPTR(mbedtls_md_update);
134 MAKE_FUNCPTR(mbedtls_md_hmac_starts);
135 MAKE_FUNCPTR(mbedtls_md_hmac_finish);
136 MAKE_FUNCPTR(mbedtls_md_free);
137 MAKE_FUNCPTR(mbedtls_md5_init);
138 MAKE_FUNCPTR(mbedtls_md5_starts);
139 MAKE_FUNCPTR(mbedtls_md5_update);
140 MAKE_FUNCPTR(mbedtls_md5_finish);
141 MAKE_FUNCPTR(mbedtls_md5_free);
142 MAKE_FUNCPTR(mbedtls_sha1_init);
143 MAKE_FUNCPTR(mbedtls_sha1_starts);
144 MAKE_FUNCPTR(mbedtls_sha1_update);
145 MAKE_FUNCPTR(mbedtls_sha1_finish);
146 MAKE_FUNCPTR(mbedtls_sha1_free);
147 MAKE_FUNCPTR(mbedtls_sha256_init);
148 MAKE_FUNCPTR(mbedtls_sha256_starts);
149 MAKE_FUNCPTR(mbedtls_sha256_update);
150 MAKE_FUNCPTR(mbedtls_sha256_finish);
151 MAKE_FUNCPTR(mbedtls_sha256_free);
152 MAKE_FUNCPTR(mbedtls_sha512_init);
153 MAKE_FUNCPTR(mbedtls_sha512_starts);
154 MAKE_FUNCPTR(mbedtls_sha512_update);
155 MAKE_FUNCPTR(mbedtls_sha512_finish);
156 MAKE_FUNCPTR(mbedtls_sha512_free);
157 #undef MAKE_FUNCPTR
158
159 #define mbedtls_md_init pmbedtls_md_init
160 #define mbedtls_md_setup pmbedtls_md_setup
161 #define mbedtls_md_update pmbedtls_md_update
162 #define mbedtls_md_hmac_starts pmbedtls_md_hmac_starts
163 #define mbedtls_md_hmac_finish pmbedtls_md_hmac_finish
164 #define mbedtls_md_free pmbedtls_md_free
165 #define mbedtls_md5_init pmbedtls_md5_init
166 #define mbedtls_md5_starts pmbedtls_md5_starts
167 #define mbedtls_md5_update pmbedtls_md5_update
168 #define mbedtls_md5_finish pmbedtls_md5_finish
169 #define mbedtls_md5_free pmbedtls_md5_free
170 #define mbedtls_sha1_init pmbedtls_sha1_init
171 #define mbedtls_sha1_starts pmbedtls_sha1_starts
172 #define mbedtls_sha1_update pmbedtls_sha1_update
173 #define mbedtls_sha1_finish pmbedtls_sha1_finish
174 #define mbedtls_sha1_free pmbedtls_sha1_free
175 #define mbedtls_sha256_init pmbedtls_sha256_init
176 #define mbedtls_sha256_starts pmbedtls_sha256_starts
177 #define mbedtls_sha256_update pmbedtls_sha256_update
178 #define mbedtls_sha256_finish pmbedtls_sha256_finish
179 #define mbedtls_sha256_free pmbedtls_sha256_free
180 #define mbedtls_sha512_init pmbedtls_sha512_init
181 #define mbedtls_sha512_starts pmbedtls_sha512_starts
182 #define mbedtls_sha512_update pmbedtls_sha512_update
183 #define mbedtls_sha512_finish pmbedtls_sha512_finish
184 #define mbedtls_sha512_free pmbedtls_sha512_free
185
mbedtls_initialize(void)186 static BOOL mbedtls_initialize(void)
187 {
188 if (!(libmbedtls_handle = wine_dlopen( SONAME_LIBMBEDTLS, RTLD_NOW, NULL, 0 )))
189 {
190 ERR_(winediag)( "failed to load libmbedtls, no support for crypto hashes\n" );
191 return FALSE;
192 }
193
194 #define LOAD_FUNCPTR(f) \
195 if (!(p##f = wine_dlsym( libmbedtls_handle, #f, NULL, 0 ))) \
196 { \
197 ERR( "failed to load %s\n", #f ); \
198 goto fail; \
199 }
200
201 LOAD_FUNCPTR(mbedtls_md_init)
202 LOAD_FUNCPTR(mbedtls_md_setup)
203 LOAD_FUNCPTR(mbedtls_md_update)
204 LOAD_FUNCPTR(mbedtls_md_hmac_starts)
205 LOAD_FUNCPTR(mbedtls_md_hmac_finish)
206 LOAD_FUNCPTR(mbedtls_md_free);
207 LOAD_FUNCPTR(mbedtls_md5_init)
208 LOAD_FUNCPTR(mbedtls_md5_starts)
209 LOAD_FUNCPTR(mbedtls_md5_update)
210 LOAD_FUNCPTR(mbedtls_md5_finish)
211 LOAD_FUNCPTR(mbedtls_md5_free);
212 LOAD_FUNCPTR(mbedtls_sha1_init)
213 LOAD_FUNCPTR(mbedtls_sha1_starts)
214 LOAD_FUNCPTR(mbedtls_sha1_update)
215 LOAD_FUNCPTR(mbedtls_sha1_finish)
216 LOAD_FUNCPTR(mbedtls_sha1_free);
217 LOAD_FUNCPTR(mbedtls_sha256_init)
218 LOAD_FUNCPTR(mbedtls_sha256_starts)
219 LOAD_FUNCPTR(mbedtls_sha256_update)
220 LOAD_FUNCPTR(mbedtls_sha256_finish)
221 LOAD_FUNCPTR(mbedtls_sha256_free);
222 LOAD_FUNCPTR(mbedtls_sha512_init)
223 LOAD_FUNCPTR(mbedtls_sha512_starts)
224 LOAD_FUNCPTR(mbedtls_sha512_update)
225 LOAD_FUNCPTR(mbedtls_sha512_finish)
226 LOAD_FUNCPTR(mbedtls_sha512_free);
227 #undef LOAD_FUNCPTR
228
229 return TRUE;
230
231 fail:
232 wine_dlclose( libmbedtls_handle, NULL, 0 );
233 libmbedtls_handle = NULL;
234 return FALSE;
235 }
236
mbedtls_uninitialize(void)237 static void mbedtls_uninitialize(void)
238 {
239 wine_dlclose( libmbedtls_handle, NULL, 0 );
240 libmbedtls_handle = NULL;
241 }
242 #endif /* SONAME_LIBMBEDTLS && !HAVE_COMMONCRYPTO_COMMONDIGEST_H && !__REACTOS__ */
243
BCryptEnumAlgorithms(ULONG dwAlgOperations,ULONG * pAlgCount,BCRYPT_ALGORITHM_IDENTIFIER ** ppAlgList,ULONG dwFlags)244 NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG dwAlgOperations, ULONG *pAlgCount,
245 BCRYPT_ALGORITHM_IDENTIFIER **ppAlgList, ULONG dwFlags)
246 {
247 FIXME("%08x, %p, %p, %08x - stub\n", dwAlgOperations, pAlgCount, ppAlgList, dwFlags);
248
249 *ppAlgList=NULL;
250 *pAlgCount=0;
251
252 return STATUS_NOT_IMPLEMENTED;
253 }
254
255 #define MAGIC_ALG (('A' << 24) | ('L' << 16) | ('G' << 8) | '0')
256 #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H')
257 struct object
258 {
259 ULONG magic;
260 };
261
262 enum alg_id
263 {
264 ALG_ID_MD5,
265 ALG_ID_RNG,
266 ALG_ID_SHA1,
267 ALG_ID_SHA256,
268 ALG_ID_SHA384,
269 ALG_ID_SHA512,
270 ALG_ID_ECDSA_P256,
271 ALG_ID_ECDSA_P384,
272 };
273
274 static const struct {
275 ULONG hash_length;
276 const WCHAR *alg_name;
277 } alg_props[] = {
278 /* ALG_ID_MD5 */ { 16, BCRYPT_MD5_ALGORITHM },
279 /* ALG_ID_RNG */ { 0, BCRYPT_RNG_ALGORITHM },
280 /* ALG_ID_SHA1 */ { 20, BCRYPT_SHA1_ALGORITHM },
281 /* ALG_ID_SHA256 */ { 32, BCRYPT_SHA256_ALGORITHM },
282 /* ALG_ID_SHA384 */ { 48, BCRYPT_SHA384_ALGORITHM },
283 /* ALG_ID_SHA512 */ { 64, BCRYPT_SHA512_ALGORITHM },
284 /* ALG_ID_ECDSA_P256 */ { 0, BCRYPT_ECDSA_P256_ALGORITHM },
285 /* ALG_ID_ECDSA_P384 */ { 0, BCRYPT_ECDSA_P384_ALGORITHM },
286 };
287
288 struct algorithm
289 {
290 struct object hdr;
291 enum alg_id id;
292 BOOL hmac;
293 };
294
BCryptGenRandom(BCRYPT_ALG_HANDLE handle,UCHAR * buffer,ULONG count,ULONG flags)295 NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags)
296 {
297 const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
298 struct algorithm *algorithm = handle;
299
300 TRACE("%p, %p, %u, %08x - semi-stub\n", handle, buffer, count, flags);
301
302 if (!algorithm)
303 {
304 /* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
305 * is set. In this case the preferred system RNG is used.
306 */
307 if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
308 return STATUS_INVALID_HANDLE;
309 }
310 else if (algorithm->hdr.magic != MAGIC_ALG || algorithm->id != ALG_ID_RNG)
311 return STATUS_INVALID_HANDLE;
312
313 if (!buffer)
314 return STATUS_INVALID_PARAMETER;
315
316 if (flags & ~supported_flags)
317 FIXME("unsupported flags %08x\n", flags & ~supported_flags);
318
319 if (algorithm)
320 FIXME("ignoring selected algorithm\n");
321
322 /* When zero bytes are requested the function returns success too. */
323 if (!count)
324 return STATUS_SUCCESS;
325
326 if (algorithm || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
327 {
328 if (RtlGenRandom(buffer, count))
329 return STATUS_SUCCESS;
330 }
331
332 FIXME("called with unsupported parameters, returning error\n");
333 return STATUS_NOT_IMPLEMENTED;
334 }
335
BCryptOpenAlgorithmProvider(BCRYPT_ALG_HANDLE * handle,LPCWSTR id,LPCWSTR implementation,DWORD flags)336 NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
337 {
338 struct algorithm *alg;
339 enum alg_id alg_id;
340
341 const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG;
342
343 TRACE( "%p, %s, %s, %08x\n", handle, wine_dbgstr_w(id), wine_dbgstr_w(implementation), flags );
344
345 if (!handle || !id) return STATUS_INVALID_PARAMETER;
346 if (flags & ~supported_flags)
347 {
348 FIXME( "unsupported flags %08x\n", flags & ~supported_flags);
349 return STATUS_NOT_IMPLEMENTED;
350 }
351
352 if (!strcmpW( id, BCRYPT_SHA1_ALGORITHM )) alg_id = ALG_ID_SHA1;
353 else if (!strcmpW( id, BCRYPT_MD5_ALGORITHM )) alg_id = ALG_ID_MD5;
354 else if (!strcmpW( id, BCRYPT_RNG_ALGORITHM )) alg_id = ALG_ID_RNG;
355 else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256;
356 else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384;
357 else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512;
358 else if (!strcmpW( id, BCRYPT_ECDSA_P256_ALGORITHM )) alg_id = ALG_ID_ECDSA_P256;
359 else if (!strcmpW( id, BCRYPT_ECDSA_P384_ALGORITHM )) alg_id = ALG_ID_ECDSA_P384;
360 else
361 {
362 FIXME( "algorithm %s not supported\n", debugstr_w(id) );
363 return STATUS_NOT_IMPLEMENTED;
364 }
365 if (implementation && strcmpW( implementation, MS_PRIMITIVE_PROVIDER ))
366 {
367 FIXME( "implementation %s not supported\n", debugstr_w(implementation) );
368 return STATUS_NOT_IMPLEMENTED;
369 }
370
371 if (!(alg = HeapAlloc( GetProcessHeap(), 0, sizeof(*alg) ))) return STATUS_NO_MEMORY;
372 alg->hdr.magic = MAGIC_ALG;
373 alg->id = alg_id;
374 alg->hmac = flags & BCRYPT_ALG_HANDLE_HMAC_FLAG;
375
376 *handle = alg;
377 return STATUS_SUCCESS;
378 }
379
BCryptCloseAlgorithmProvider(BCRYPT_ALG_HANDLE handle,DWORD flags)380 NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags )
381 {
382 struct algorithm *alg = handle;
383
384 TRACE( "%p, %08x\n", handle, flags );
385
386 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
387 HeapFree( GetProcessHeap(), 0, alg );
388 return STATUS_SUCCESS;
389 }
390
BCryptGetFipsAlgorithmMode(BOOLEAN * enabled)391 NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *enabled)
392 {
393 FIXME("%p - semi-stub\n", enabled);
394
395 if (!enabled)
396 return STATUS_INVALID_PARAMETER;
397
398 *enabled = FALSE;
399 return STATUS_SUCCESS;
400 }
401
402 #ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
403 struct hash
404 {
405 struct object hdr;
406 enum alg_id alg_id;
407 BOOL hmac;
408 union
409 {
410 CC_MD5_CTX md5_ctx;
411 CC_SHA1_CTX sha1_ctx;
412 CC_SHA256_CTX sha256_ctx;
413 CC_SHA512_CTX sha512_ctx;
414 CCHmacContext hmac_ctx;
415 } u;
416 };
417
hash_init(struct hash * hash)418 static NTSTATUS hash_init( struct hash *hash )
419 {
420 switch (hash->alg_id)
421 {
422 case ALG_ID_MD5:
423 CC_MD5_Init( &hash->u.md5_ctx );
424 break;
425
426 case ALG_ID_SHA1:
427 CC_SHA1_Init( &hash->u.sha1_ctx );
428 break;
429
430 case ALG_ID_SHA256:
431 CC_SHA256_Init( &hash->u.sha256_ctx );
432 break;
433
434 case ALG_ID_SHA384:
435 CC_SHA384_Init( &hash->u.sha512_ctx );
436 break;
437
438 case ALG_ID_SHA512:
439 CC_SHA512_Init( &hash->u.sha512_ctx );
440 break;
441
442 default:
443 ERR( "unhandled id %u\n", hash->alg_id );
444 return STATUS_NOT_IMPLEMENTED;
445 }
446 return STATUS_SUCCESS;
447 }
448
hmac_init(struct hash * hash,UCHAR * key,ULONG key_size)449 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
450 {
451 CCHmacAlgorithm cc_algorithm;
452 switch (hash->alg_id)
453 {
454 case ALG_ID_MD5:
455 cc_algorithm = kCCHmacAlgMD5;
456 break;
457
458 case ALG_ID_SHA1:
459 cc_algorithm = kCCHmacAlgSHA1;
460 break;
461
462 case ALG_ID_SHA256:
463 cc_algorithm = kCCHmacAlgSHA256;
464 break;
465
466 case ALG_ID_SHA384:
467 cc_algorithm = kCCHmacAlgSHA384;
468 break;
469
470 case ALG_ID_SHA512:
471 cc_algorithm = kCCHmacAlgSHA512;
472 break;
473
474 default:
475 ERR( "unhandled id %u\n", hash->alg_id );
476 return STATUS_NOT_IMPLEMENTED;
477 }
478
479 CCHmacInit( &hash->u.hmac_ctx, cc_algorithm, key, key_size );
480 return STATUS_SUCCESS;
481 }
482
483
hash_update(struct hash * hash,UCHAR * input,ULONG size)484 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
485 {
486 switch (hash->alg_id)
487 {
488 case ALG_ID_MD5:
489 CC_MD5_Update( &hash->u.md5_ctx, input, size );
490 break;
491
492 case ALG_ID_SHA1:
493 CC_SHA1_Update( &hash->u.sha1_ctx, input, size );
494 break;
495
496 case ALG_ID_SHA256:
497 CC_SHA256_Update( &hash->u.sha256_ctx, input, size );
498 break;
499
500 case ALG_ID_SHA384:
501 CC_SHA384_Update( &hash->u.sha512_ctx, input, size );
502 break;
503
504 case ALG_ID_SHA512:
505 CC_SHA512_Update( &hash->u.sha512_ctx, input, size );
506 break;
507
508 default:
509 ERR( "unhandled id %u\n", hash->alg_id );
510 return STATUS_NOT_IMPLEMENTED;
511 }
512 return STATUS_SUCCESS;
513 }
514
hmac_update(struct hash * hash,UCHAR * input,ULONG size)515 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
516 {
517 CCHmacUpdate( &hash->u.hmac_ctx, input, size );
518 return STATUS_SUCCESS;
519 }
520
hash_finish(struct hash * hash,UCHAR * output,ULONG size)521 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
522 {
523 switch (hash->alg_id)
524 {
525 case ALG_ID_MD5:
526 CC_MD5_Final( output, &hash->u.md5_ctx );
527 break;
528
529 case ALG_ID_SHA1:
530 CC_SHA1_Final( output, &hash->u.sha1_ctx );
531 break;
532
533 case ALG_ID_SHA256:
534 CC_SHA256_Final( output, &hash->u.sha256_ctx );
535 break;
536
537 case ALG_ID_SHA384:
538 CC_SHA384_Final( output, &hash->u.sha512_ctx );
539 break;
540
541 case ALG_ID_SHA512:
542 CC_SHA512_Final( output, &hash->u.sha512_ctx );
543 break;
544
545 default:
546 ERR( "unhandled id %u\n", hash->alg_id );
547 break;
548 }
549 return STATUS_SUCCESS;
550 }
551
hmac_finish(struct hash * hash,UCHAR * output,ULONG size)552 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
553 {
554 CCHmacFinal( &hash->u.hmac_ctx, output );
555
556 return STATUS_SUCCESS;
557 }
558 #elif defined(HAVE_GNUTLS_HASH)
559 struct hash
560 {
561 struct object hdr;
562 enum alg_id alg_id;
563 BOOL hmac;
564 union
565 {
566 gnutls_hash_hd_t hash_handle;
567 gnutls_hmac_hd_t hmac_handle;
568 } u;
569 };
570
hash_init(struct hash * hash)571 static NTSTATUS hash_init( struct hash *hash )
572 {
573 gnutls_digest_algorithm_t alg;
574
575 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
576
577 switch (hash->alg_id)
578 {
579 case ALG_ID_MD5:
580 alg = GNUTLS_DIG_MD5;
581 break;
582 case ALG_ID_SHA1:
583 alg = GNUTLS_DIG_SHA1;
584 break;
585
586 case ALG_ID_SHA256:
587 alg = GNUTLS_DIG_SHA256;
588 break;
589
590 case ALG_ID_SHA384:
591 alg = GNUTLS_DIG_SHA384;
592 break;
593
594 case ALG_ID_SHA512:
595 alg = GNUTLS_DIG_SHA512;
596 break;
597
598 default:
599 ERR( "unhandled id %u\n", hash->alg_id );
600 return STATUS_NOT_IMPLEMENTED;
601 }
602
603 if (pgnutls_hash_init( &hash->u.hash_handle, alg )) return STATUS_INTERNAL_ERROR;
604 return STATUS_SUCCESS;
605 }
606
hmac_init(struct hash * hash,UCHAR * key,ULONG key_size)607 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
608 {
609 gnutls_mac_algorithm_t alg;
610
611 if (!libgnutls_handle) return STATUS_INTERNAL_ERROR;
612
613 switch (hash->alg_id)
614 {
615 case ALG_ID_MD5:
616 alg = GNUTLS_MAC_MD5;
617 break;
618 case ALG_ID_SHA1:
619 alg = GNUTLS_MAC_SHA1;
620 break;
621
622 case ALG_ID_SHA256:
623 alg = GNUTLS_MAC_SHA256;
624 break;
625
626 case ALG_ID_SHA384:
627 alg = GNUTLS_MAC_SHA384;
628 break;
629
630 case ALG_ID_SHA512:
631 alg = GNUTLS_MAC_SHA512;
632 break;
633
634 default:
635 ERR( "unhandled id %u\n", hash->alg_id );
636 return STATUS_NOT_IMPLEMENTED;
637 }
638
639 if (pgnutls_hmac_init( &hash->u.hmac_handle, alg, key, key_size )) return STATUS_INTERNAL_ERROR;
640 return STATUS_SUCCESS;
641 }
642
hash_update(struct hash * hash,UCHAR * input,ULONG size)643 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
644 {
645 if (pgnutls_hash( hash->u.hash_handle, input, size )) return STATUS_INTERNAL_ERROR;
646 return STATUS_SUCCESS;
647 }
648
hmac_update(struct hash * hash,UCHAR * input,ULONG size)649 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
650 {
651 if (pgnutls_hmac( hash->u.hmac_handle, input, size )) return STATUS_INTERNAL_ERROR;
652 return STATUS_SUCCESS;
653 }
654
hash_finish(struct hash * hash,UCHAR * output,ULONG size)655 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
656 {
657 pgnutls_hash_deinit( hash->u.hash_handle, output );
658 return STATUS_SUCCESS;
659 }
660
hmac_finish(struct hash * hash,UCHAR * output,ULONG size)661 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
662 {
663 pgnutls_hmac_deinit( hash->u.hmac_handle, output );
664 return STATUS_SUCCESS;
665 }
666 #elif defined(SONAME_LIBMBEDTLS)
667 struct hash
668 {
669 struct object hdr;
670 BOOL hmac;
671 enum alg_id alg_id;
672 union
673 {
674 mbedtls_md5_context md5_ctx;
675 mbedtls_sha1_context sha1_ctx;
676 mbedtls_sha256_context sha256_ctx;
677 mbedtls_sha512_context sha512_ctx;
678 mbedtls_md_context_t hmac_ctx;
679 } u;
680 };
681
hash_init(struct hash * hash)682 static NTSTATUS hash_init( struct hash *hash )
683 {
684 #ifndef __REACTOS__
685 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
686 #endif
687 switch (hash->alg_id)
688 {
689 case ALG_ID_MD5:
690 mbedtls_md5_init(&hash->u.md5_ctx);
691 mbedtls_md5_starts(&hash->u.md5_ctx);
692 break;
693
694 case ALG_ID_SHA1:
695 mbedtls_sha1_init(&hash->u.sha1_ctx);
696 mbedtls_sha1_starts(&hash->u.sha1_ctx);
697 break;
698
699 case ALG_ID_SHA256:
700 mbedtls_sha256_init(&hash->u.sha256_ctx);
701 mbedtls_sha256_starts(&hash->u.sha256_ctx, FALSE);
702 break;
703
704 case ALG_ID_SHA384:
705 case ALG_ID_SHA512:
706 mbedtls_sha512_init(&hash->u.sha512_ctx);
707 mbedtls_sha512_starts(&hash->u.sha512_ctx, hash->alg_id==ALG_ID_SHA384);
708 break;
709
710 default:
711 ERR( "unhandled id %u\n", hash->alg_id );
712 return STATUS_NOT_IMPLEMENTED;
713 }
714
715 return STATUS_SUCCESS;
716 }
717
hmac_init(struct hash * hash,UCHAR * key,ULONG key_size)718 static NTSTATUS hmac_init( struct hash *hash, UCHAR *key, ULONG key_size )
719 {
720 const mbedtls_md_info_t *md_info;
721 mbedtls_md_type_t md_type;
722 int ret;
723 #ifndef __REACTOS__
724 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
725 #endif
726 mbedtls_md_init(&hash->u.hmac_ctx);
727 switch (hash->alg_id)
728 {
729 case ALG_ID_MD5:
730 md_type = MBEDTLS_MD_MD5;
731 break;
732
733 case ALG_ID_SHA1:
734 md_type = MBEDTLS_MD_SHA1;
735 break;
736
737 case ALG_ID_SHA256:
738 md_type = MBEDTLS_MD_SHA256;
739 break;
740
741 case ALG_ID_SHA384:
742 md_type = MBEDTLS_MD_SHA384;
743 break;
744
745 case ALG_ID_SHA512:
746 md_type = MBEDTLS_MD_SHA512;
747 break;
748
749 default:
750 ERR("unhandled id %u\n", hash->alg_id);
751 return STATUS_NOT_IMPLEMENTED;
752 }
753 if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL)
754 {
755 mbedtls_md_free(&hash->u.hmac_ctx);
756 return STATUS_INTERNAL_ERROR;
757 }
758
759 if ((ret = mbedtls_md_setup(&hash->u.hmac_ctx, md_info, 1)) != 0)
760 {
761 mbedtls_md_free(&hash->u.hmac_ctx);
762 return STATUS_INTERNAL_ERROR;
763 }
764
765 mbedtls_md_hmac_starts(&hash->u.hmac_ctx, key, key_size);
766
767 return STATUS_SUCCESS;
768 }
769
hash_update(struct hash * hash,UCHAR * input,ULONG size)770 static NTSTATUS hash_update( struct hash *hash, UCHAR *input, ULONG size )
771 {
772 #ifndef __REACTOS__
773 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
774 #endif
775 switch (hash->alg_id)
776 {
777 case ALG_ID_MD5:
778 mbedtls_md5_update(&hash->u.md5_ctx, input, size);
779 break;
780
781 case ALG_ID_SHA1:
782 mbedtls_sha1_update(&hash->u.sha1_ctx, input, size);
783 break;
784
785 case ALG_ID_SHA256:
786 mbedtls_sha256_update(&hash->u.sha256_ctx, input, size);
787 break;
788
789 case ALG_ID_SHA384:
790 case ALG_ID_SHA512:
791 mbedtls_sha512_update(&hash->u.sha512_ctx, input, size);
792 break;
793
794 default:
795 ERR( "unhandled id %u\n", hash->alg_id );
796 return STATUS_NOT_IMPLEMENTED;
797 }
798
799 return STATUS_SUCCESS;
800 }
801
hmac_update(struct hash * hash,UCHAR * input,ULONG size)802 static NTSTATUS hmac_update( struct hash *hash, UCHAR *input, ULONG size )
803 {
804 #ifndef __REACTOS__
805 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
806 #endif
807 mbedtls_md_update(&hash->u.hmac_ctx, input, size);
808
809 return STATUS_SUCCESS;
810 }
811
hash_finish(struct hash * hash,UCHAR * output,ULONG size)812 static NTSTATUS hash_finish( struct hash *hash, UCHAR *output, ULONG size )
813 {
814 #ifndef __REACTOS__
815 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
816 #endif
817 switch (hash->alg_id)
818 {
819 case ALG_ID_MD5:
820 mbedtls_md5_finish(&hash->u.md5_ctx, output);
821 mbedtls_md5_free(&hash->u.md5_ctx);
822 break;
823
824 case ALG_ID_SHA1:
825 mbedtls_sha1_finish(&hash->u.sha1_ctx, output);
826 mbedtls_sha1_free(&hash->u.sha1_ctx);
827 break;
828
829 case ALG_ID_SHA256:
830 mbedtls_sha256_finish(&hash->u.sha256_ctx, output);
831 mbedtls_sha256_free(&hash->u.sha256_ctx);
832 break;
833
834 case ALG_ID_SHA384:
835 case ALG_ID_SHA512:
836 mbedtls_sha512_finish(&hash->u.sha512_ctx, output);
837 mbedtls_sha512_free(&hash->u.sha512_ctx);
838 break;
839
840 default:
841 ERR( "unhandled id %u\n", hash->alg_id );
842 return STATUS_NOT_IMPLEMENTED;
843 }
844
845 return STATUS_SUCCESS;
846 }
847
hmac_finish(struct hash * hash,UCHAR * output,ULONG size)848 static NTSTATUS hmac_finish( struct hash *hash, UCHAR *output, ULONG size )
849 {
850 #ifndef __REACTOS__
851 if (!libmbedtls_handle) return STATUS_INTERNAL_ERROR;
852 #endif
853 mbedtls_md_hmac_finish(&hash->u.hmac_ctx, output);
854 mbedtls_md_free(&hash->u.hmac_ctx);
855
856 return STATUS_SUCCESS;
857 }
858 #endif
859
860 #define OBJECT_LENGTH_MD5 274
861 #define OBJECT_LENGTH_SHA1 278
862 #define OBJECT_LENGTH_SHA256 286
863 #define OBJECT_LENGTH_SHA384 382
864 #define OBJECT_LENGTH_SHA512 382
865
generic_alg_property(enum alg_id id,const WCHAR * prop,UCHAR * buf,ULONG size,ULONG * ret_size)866 static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
867 {
868 if (!strcmpW( prop, BCRYPT_HASH_LENGTH ))
869 {
870 *ret_size = sizeof(ULONG);
871 if (size < sizeof(ULONG))
872 return STATUS_BUFFER_TOO_SMALL;
873 if(buf)
874 *(ULONG*)buf = alg_props[id].hash_length;
875 return STATUS_SUCCESS;
876 }
877
878 if (!strcmpW( prop, BCRYPT_ALGORITHM_NAME ))
879 {
880 *ret_size = (strlenW(alg_props[id].alg_name)+1)*sizeof(WCHAR);
881 if (size < *ret_size)
882 return STATUS_BUFFER_TOO_SMALL;
883 if(buf)
884 memcpy(buf, alg_props[id].alg_name, *ret_size);
885 return STATUS_SUCCESS;
886 }
887
888 return STATUS_NOT_IMPLEMENTED;
889 }
890
get_alg_property(enum alg_id id,const WCHAR * prop,UCHAR * buf,ULONG size,ULONG * ret_size)891 static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
892 {
893 NTSTATUS status;
894 ULONG value;
895
896 status = generic_alg_property( id, prop, buf, size, ret_size );
897 if (status != STATUS_NOT_IMPLEMENTED)
898 return status;
899
900 switch (id)
901 {
902 case ALG_ID_MD5:
903 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
904 {
905 value = OBJECT_LENGTH_MD5;
906 break;
907 }
908 FIXME( "unsupported md5 algorithm property %s\n", debugstr_w(prop) );
909 return STATUS_NOT_IMPLEMENTED;
910
911 case ALG_ID_RNG:
912 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH )) return STATUS_NOT_SUPPORTED;
913 FIXME( "unsupported rng algorithm property %s\n", debugstr_w(prop) );
914 return STATUS_NOT_IMPLEMENTED;
915
916 case ALG_ID_SHA1:
917 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
918 {
919 value = OBJECT_LENGTH_SHA1;
920 break;
921 }
922 FIXME( "unsupported sha1 algorithm property %s\n", debugstr_w(prop) );
923 return STATUS_NOT_IMPLEMENTED;
924
925 case ALG_ID_SHA256:
926 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
927 {
928 value = OBJECT_LENGTH_SHA256;
929 break;
930 }
931 FIXME( "unsupported sha256 algorithm property %s\n", debugstr_w(prop) );
932 return STATUS_NOT_IMPLEMENTED;
933
934 case ALG_ID_SHA384:
935 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
936 {
937 value = OBJECT_LENGTH_SHA384;
938 break;
939 }
940 FIXME( "unsupported sha384 algorithm property %s\n", debugstr_w(prop) );
941 return STATUS_NOT_IMPLEMENTED;
942
943 case ALG_ID_SHA512:
944 if (!strcmpW( prop, BCRYPT_OBJECT_LENGTH ))
945 {
946 value = OBJECT_LENGTH_SHA512;
947 break;
948 }
949 FIXME( "unsupported sha512 algorithm property %s\n", debugstr_w(prop) );
950 return STATUS_NOT_IMPLEMENTED;
951
952 default:
953 FIXME( "unsupported algorithm %u\n", id );
954 return STATUS_NOT_IMPLEMENTED;
955 }
956
957 if (size < sizeof(ULONG))
958 {
959 *ret_size = sizeof(ULONG);
960 return STATUS_BUFFER_TOO_SMALL;
961 }
962 if (buf) *(ULONG *)buf = value;
963 *ret_size = sizeof(ULONG);
964
965 return STATUS_SUCCESS;
966 }
967
get_hash_property(enum alg_id id,const WCHAR * prop,UCHAR * buf,ULONG size,ULONG * ret_size)968 static NTSTATUS get_hash_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
969 {
970 NTSTATUS status;
971
972 status = generic_alg_property( id, prop, buf, size, ret_size );
973 if (status == STATUS_NOT_IMPLEMENTED)
974 FIXME( "unsupported property %s\n", debugstr_w(prop) );
975 return status;
976 }
977
BCryptGetProperty(BCRYPT_HANDLE handle,LPCWSTR prop,UCHAR * buffer,ULONG count,ULONG * res,ULONG flags)978 NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags )
979 {
980 struct object *object = handle;
981
982 TRACE( "%p, %s, %p, %u, %p, %08x\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags );
983
984 if (!object) return STATUS_INVALID_HANDLE;
985 if (!prop || !res) return STATUS_INVALID_PARAMETER;
986
987 switch (object->magic)
988 {
989 case MAGIC_ALG:
990 {
991 const struct algorithm *alg = (const struct algorithm *)object;
992 return get_alg_property( alg->id, prop, buffer, count, res );
993 }
994 case MAGIC_HASH:
995 {
996 const struct hash *hash = (const struct hash *)object;
997 return get_hash_property( hash->alg_id, prop, buffer, count, res );
998 }
999 default:
1000 WARN( "unknown magic %08x\n", object->magic );
1001 return STATUS_INVALID_HANDLE;
1002 }
1003 }
1004
BCryptCreateHash(BCRYPT_ALG_HANDLE algorithm,BCRYPT_HASH_HANDLE * handle,UCHAR * object,ULONG objectlen,UCHAR * secret,ULONG secretlen,ULONG flags)1005 NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen,
1006 UCHAR *secret, ULONG secretlen, ULONG flags )
1007 {
1008 struct algorithm *alg = algorithm;
1009 struct hash *hash;
1010 NTSTATUS status;
1011
1012 TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen,
1013 secret, secretlen, flags );
1014 if (flags)
1015 {
1016 FIXME( "unimplemented flags %08x\n", flags );
1017 return STATUS_NOT_IMPLEMENTED;
1018 }
1019
1020 if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
1021 if (object) FIXME( "ignoring object buffer\n" );
1022
1023 if (!(hash = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash) ))) return STATUS_NO_MEMORY;
1024 hash->hdr.magic = MAGIC_HASH;
1025 hash->alg_id = alg->id;
1026 hash->hmac = alg->hmac;
1027
1028 if (hash->hmac)
1029 {
1030 status = hmac_init( hash, secret, secretlen );
1031 }
1032 else
1033 {
1034 status = hash_init( hash );
1035 }
1036
1037 if (status != STATUS_SUCCESS)
1038 {
1039 HeapFree( GetProcessHeap(), 0, hash );
1040 return status;
1041 }
1042
1043 *handle = hash;
1044 return STATUS_SUCCESS;
1045 }
1046
BCryptDestroyHash(BCRYPT_HASH_HANDLE handle)1047 NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
1048 {
1049 struct hash *hash = handle;
1050
1051 TRACE( "%p\n", handle );
1052
1053 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
1054 HeapFree( GetProcessHeap(), 0, hash );
1055 return STATUS_SUCCESS;
1056 }
1057
BCryptHashData(BCRYPT_HASH_HANDLE handle,UCHAR * input,ULONG size,ULONG flags)1058 NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG size, ULONG flags )
1059 {
1060 struct hash *hash = handle;
1061
1062 TRACE( "%p, %p, %u, %08x\n", handle, input, size, flags );
1063
1064 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
1065 if (!input) return STATUS_SUCCESS;
1066
1067 if (hash->hmac)
1068 {
1069 return hmac_update( hash, input, size );
1070 }
1071 else
1072 {
1073 return hash_update( hash, input, size );
1074 }
1075 }
1076
BCryptFinishHash(BCRYPT_HASH_HANDLE handle,UCHAR * output,ULONG size,ULONG flags)1077 NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
1078 {
1079 struct hash *hash = handle;
1080
1081 TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags );
1082
1083 if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
1084 if (!output) return STATUS_INVALID_PARAMETER;
1085
1086 if (hash->hmac)
1087 {
1088 return hmac_finish( hash, output, size );
1089 }
1090 else
1091 {
1092 return hash_finish( hash, output, size );
1093 }
1094 }
1095
BCryptHash(BCRYPT_ALG_HANDLE algorithm,UCHAR * secret,ULONG secretlen,UCHAR * input,ULONG inputlen,UCHAR * output,ULONG outputlen)1096 NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen,
1097 UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen )
1098 {
1099 NTSTATUS status;
1100 BCRYPT_HASH_HANDLE handle;
1101
1102 TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secretlen,
1103 input, inputlen, output, outputlen );
1104
1105 status = BCryptCreateHash( algorithm, &handle, NULL, 0, secret, secretlen, 0);
1106 if (status != STATUS_SUCCESS)
1107 {
1108 return status;
1109 }
1110
1111 status = BCryptHashData( handle, input, inputlen, 0 );
1112 if (status != STATUS_SUCCESS)
1113 {
1114 BCryptDestroyHash( handle );
1115 return status;
1116 }
1117
1118 status = BCryptFinishHash( handle, output, outputlen, 0 );
1119 if (status != STATUS_SUCCESS)
1120 {
1121 BCryptDestroyHash( handle );
1122 return status;
1123 }
1124
1125 return BCryptDestroyHash( handle );
1126 }
1127
DllMain(HINSTANCE hinst,DWORD reason,LPVOID reserved)1128 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
1129 {
1130 switch (reason)
1131 {
1132 case DLL_PROCESS_ATTACH:
1133 instance = hinst;
1134 DisableThreadLibraryCalls( hinst );
1135 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
1136 gnutls_initialize();
1137 #elif defined(SONAME_LIBMBEDTLS) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) && !defined(__REACTOS__)
1138 mbedtls_initialize();
1139 #endif
1140 break;
1141
1142 case DLL_PROCESS_DETACH:
1143 if (reserved) break;
1144 #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
1145 gnutls_uninitialize();
1146 #elif defined(SONAME_LIBMBEDTLS) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) && !defined(__REACTOS__)
1147 mbedtls_uninitialize();
1148 #endif
1149 break;
1150 }
1151 return TRUE;
1152 }
1153