1 /*
2  * Unit test for bcrypt functions
3  *
4  * Copyright 2014 Bruno Jesus
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdio.h>
22 #include <ntstatus.h>
23 #define WIN32_NO_STATUS
24 #include <windows.h>
25 #include <bcrypt.h>
26 
27 #include "wine/test.h"
28 
29 static NTSTATUS (WINAPI *pBCryptHash)( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen,
30                                      UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen );
31 
32 static void test_BCryptGenRandom(void)
33 {
34     NTSTATUS ret;
35     UCHAR buffer[256];
36 
37     ret = BCryptGenRandom(NULL, NULL, 0, 0);
38     ok(ret == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got 0x%x\n", ret);
39     ret = BCryptGenRandom(NULL, buffer, 0, 0);
40     ok(ret == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got 0x%x\n", ret);
41     ret = BCryptGenRandom(NULL, buffer, sizeof(buffer), 0);
42     ok(ret == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got 0x%x\n", ret);
43     ret = BCryptGenRandom(NULL, buffer, sizeof(buffer), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
44     ok(ret == STATUS_SUCCESS, "Expected success, got 0x%x\n", ret);
45     ret = BCryptGenRandom(NULL, buffer, sizeof(buffer),
46           BCRYPT_USE_SYSTEM_PREFERRED_RNG|BCRYPT_RNG_USE_ENTROPY_IN_BUFFER);
47     ok(ret == STATUS_SUCCESS, "Expected success, got 0x%x\n", ret);
48     ret = BCryptGenRandom(NULL, NULL, sizeof(buffer), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
49     ok(ret == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got 0x%x\n", ret);
50 
51     /* Zero sized buffer should work too */
52     ret = BCryptGenRandom(NULL, buffer, 0, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
53     ok(ret == STATUS_SUCCESS, "Expected success, got 0x%x\n", ret);
54 
55     /* Test random number generation - It's impossible for a sane RNG to return 8 zeros */
56     memset(buffer, 0, 16);
57     ret = BCryptGenRandom(NULL, buffer, 8, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
58     ok(ret == STATUS_SUCCESS, "Expected success, got 0x%x\n", ret);
59     ok(memcmp(buffer, buffer + 8, 8), "Expected a random number, got 0\n");
60 }
61 
62 static void test_BCryptGetFipsAlgorithmMode(void)
63 {
64     static const WCHAR policyKeyVistaW[] = {
65         'S','y','s','t','e','m','\\',
66         'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
67         'C','o','n','t','r','o','l','\\',
68         'L','s','a','\\',
69         'F','I','P','S','A','l','g','o','r','i','t','h','m','P','o','l','i','c','y',0};
70     static const WCHAR policyValueVistaW[] = {'E','n','a','b','l','e','d',0};
71     static const WCHAR policyKeyXPW[] = {
72         'S','y','s','t','e','m','\\',
73         'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
74         'C','o','n','t','r','o','l','\\',
75         'L','s','a',0};
76     static const WCHAR policyValueXPW[] = {
77         'F','I','P','S','A','l','g','o','r','i','t','h','m','P','o','l','i','c','y',0};
78     BOOLEAN expected;
79     BOOLEAN enabled;
80     DWORD value, count[2] = {sizeof(value), sizeof(value)};
81     NTSTATUS ret;
82 
83     if (!RegGetValueW(HKEY_LOCAL_MACHINE, policyKeyVistaW, policyValueVistaW,
84         RRF_RT_REG_DWORD, NULL, &value, &count[0]))
85     {
86         expected = !!value;
87     }
88     else if (!RegGetValueW(HKEY_LOCAL_MACHINE, policyKeyXPW, policyValueXPW,
89              RRF_RT_REG_DWORD, NULL, &value, &count[1]))
90     {
91         expected = !!value;
92     }
93     else
94     {
95         expected = FALSE;
96 todo_wine
97         ok(0, "Neither XP or Vista key is present\n");
98     }
99 
100     ret = BCryptGetFipsAlgorithmMode(&enabled);
101     ok(ret == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%x\n", ret);
102     ok(enabled == expected, "expected result %d, got %d\n", expected, enabled);
103 
104     ret = BCryptGetFipsAlgorithmMode(NULL);
105     ok(ret == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got 0x%x\n", ret);
106 }
107 
108 static void format_hash(const UCHAR *bytes, ULONG size, char *buf)
109 {
110     ULONG i;
111     buf[0] = '\0';
112     for (i = 0; i < size; i++)
113     {
114         sprintf(buf + i * 2, "%02x", bytes[i]);
115     }
116     return;
117 }
118 
119 static int strcmp_wa(const WCHAR *strw, const char *stra)
120 {
121     WCHAR buf[512];
122     MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(buf[0]));
123     return lstrcmpW(strw, buf);
124 }
125 
126 #define test_hash_length(a,b) _test_hash_length(__LINE__,a,b)
127 static void _test_hash_length(unsigned line, void *handle, ULONG exlen)
128 {
129     ULONG len = 0xdeadbeef, size = 0xdeadbeef;
130     NTSTATUS status;
131 
132     status = BCryptGetProperty(handle, BCRYPT_HASH_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
133     ok_(__FILE__,line)(status == STATUS_SUCCESS, "BCryptGetProperty failed: %08x\n", status);
134     ok_(__FILE__,line)(size == sizeof(len), "got %u\n", size);
135     ok_(__FILE__,line)(len == exlen, "len = %u, expected %u\n", len, exlen);
136 }
137 
138 #define test_alg_name(a,b) _test_alg_name(__LINE__,a,b)
139 static void _test_alg_name(unsigned line, void *handle, const char *exname)
140 {
141     ULONG size = 0xdeadbeef;
142     UCHAR buf[256];
143     const WCHAR *name = (const WCHAR*)buf;
144     NTSTATUS status;
145 
146     status = BCryptGetProperty(handle, BCRYPT_ALGORITHM_NAME, buf, sizeof(buf), &size, 0);
147     ok_(__FILE__,line)(status == STATUS_SUCCESS, "BCryptGetProperty failed: %08x\n", status);
148     ok_(__FILE__,line)(size == (strlen(exname)+1)*sizeof(WCHAR), "got %u\n", size);
149     ok_(__FILE__,line)(!strcmp_wa(name, exname), "alg name = %s, expected %s\n", wine_dbgstr_w(name), exname);
150 }
151 
152 static void test_sha1(void)
153 {
154     static const char expected[] = "961fa64958818f767707072755d7018dcd278e94";
155     static const char expected_hmac[] = "2472cf65d0e090618d769d3e46f0d9446cf212da";
156     BCRYPT_ALG_HANDLE alg;
157     BCRYPT_HASH_HANDLE hash;
158     UCHAR buf[512], buf_hmac[1024], sha1[20], sha1_hmac[20];
159     ULONG size, len;
160     char str[41];
161     NTSTATUS ret;
162 
163     alg = NULL;
164     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
165     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
166     ok(alg != NULL, "alg not set\n");
167 
168     len = size = 0xdeadbeef;
169     ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
170     ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret);
171 
172     len = size = 0xdeadbeef;
173     ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0);
174     ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
175 
176     len = size = 0xdeadbeef;
177     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0);
178     ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
179 
180     len = size = 0xdeadbeef;
181     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0);
182     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
183     ok(size == sizeof(len), "got %u\n", size);
184 
185     len = size = 0xdeadbeef;
186     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0);
187     ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
188     ok(len == 0xdeadbeef, "got %u\n", len);
189     ok(size == sizeof(len), "got %u\n", size);
190 
191     len = size = 0xdeadbeef;
192     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0);
193     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
194     ok(len != 0xdeadbeef, "len not set\n");
195     ok(size == sizeof(len), "got %u\n", size);
196 
197     test_hash_length(alg, 20);
198     test_alg_name(alg, "SHA1");
199 
200     hash = NULL;
201     len = sizeof(buf);
202     ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0);
203     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
204     ok(hash != NULL, "hash not set\n");
205 
206     ret = BCryptHashData(hash, NULL, 0, 0);
207     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
208 
209     ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
210     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
211 
212     test_hash_length(hash, 20);
213     test_alg_name(hash, "SHA1");
214 
215     memset(sha1, 0, sizeof(sha1));
216     ret = BCryptFinishHash(hash, sha1, sizeof(sha1), 0);
217     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
218     format_hash( sha1, sizeof(sha1), str );
219     ok(!strcmp(str, expected), "got %s\n", str);
220 
221     ret = BCryptDestroyHash(hash);
222     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
223 
224     ret = BCryptCloseAlgorithmProvider(alg, 0);
225     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
226 
227     alg = NULL;
228     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
229     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
230     ok(alg != NULL, "alg not set\n");
231 
232     hash = NULL;
233     len = sizeof(buf_hmac);
234     ret = BCryptCreateHash(alg, &hash, buf_hmac, len, (UCHAR *)"key", sizeof("key"), 0);
235     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
236     ok(hash != NULL, "hash not set\n");
237 
238     ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
239     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
240 
241     test_hash_length(hash, 20);
242     test_alg_name(hash, "SHA1");
243 
244     memset(sha1_hmac, 0, sizeof(sha1_hmac));
245     ret = BCryptFinishHash(hash, sha1_hmac, sizeof(sha1_hmac), 0);
246     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
247     format_hash( sha1_hmac, sizeof(sha1_hmac), str );
248     ok(!strcmp(str, expected_hmac), "got %s\n", str);
249 
250     ret = BCryptDestroyHash(hash);
251     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
252 
253     ret = BCryptCloseAlgorithmProvider(alg, 0);
254     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
255 }
256 
257 static void test_sha256(void)
258 {
259     static const char expected[] =
260         "ceb73749c899693706ede1e30c9929b3fd5dd926163831c2fb8bd41e6efb1126";
261     static const char expected_hmac[] =
262         "34c1aa473a4468a91d06e7cdbc75bc4f93b830ccfc2a47ffd74e8e6ed29e4c72";
263     BCRYPT_ALG_HANDLE alg;
264     BCRYPT_HASH_HANDLE hash;
265     UCHAR buf[512], buf_hmac[1024], sha256[32], sha256_hmac[32];
266     ULONG size, len;
267     char str[65];
268     NTSTATUS ret;
269 
270     alg = NULL;
271     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA256_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
272     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
273     ok(alg != NULL, "alg not set\n");
274 
275     len = size = 0xdeadbeef;
276     ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
277     ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret);
278 
279     len = size = 0xdeadbeef;
280     ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0);
281     ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
282 
283     len = size = 0xdeadbeef;
284     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0);
285     ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
286 
287     len = size = 0xdeadbeef;
288     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0);
289     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
290     ok(size == sizeof(len), "got %u\n", size);
291 
292     len = size = 0xdeadbeef;
293     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0);
294     ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
295     ok(len == 0xdeadbeef, "got %u\n", len);
296     ok(size == sizeof(len), "got %u\n", size);
297 
298     len = size = 0xdeadbeef;
299     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0);
300     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
301     ok(len != 0xdeadbeef, "len not set\n");
302     ok(size == sizeof(len), "got %u\n", size);
303 
304     test_hash_length(alg, 32);
305     test_alg_name(alg, "SHA256");
306 
307     hash = NULL;
308     len = sizeof(buf);
309     ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0);
310     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
311     ok(hash != NULL, "hash not set\n");
312 
313     ret = BCryptHashData(hash, NULL, 0, 0);
314     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
315 
316     ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
317     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
318 
319     test_hash_length(hash, 32);
320     test_alg_name(hash, "SHA256");
321 
322     memset(sha256, 0, sizeof(sha256));
323     ret = BCryptFinishHash(hash, sha256, sizeof(sha256), 0);
324     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
325     format_hash( sha256, sizeof(sha256), str );
326     ok(!strcmp(str, expected), "got %s\n", str);
327 
328     ret = BCryptDestroyHash(hash);
329     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
330 
331     ret = BCryptCloseAlgorithmProvider(alg, 0);
332     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
333 
334     alg = NULL;
335     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA256_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
336     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
337     ok(alg != NULL, "alg not set\n");
338 
339     hash = NULL;
340     len = sizeof(buf_hmac);
341     ret = BCryptCreateHash(alg, &hash, buf_hmac, len, (UCHAR *)"key", sizeof("key"), 0);
342     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
343     ok(hash != NULL, "hash not set\n");
344 
345     ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
346     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
347 
348     test_hash_length(hash, 32);
349     test_alg_name(hash, "SHA256");
350 
351     memset(sha256_hmac, 0, sizeof(sha256_hmac));
352     ret = BCryptFinishHash(hash, sha256_hmac, sizeof(sha256_hmac), 0);
353     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
354     format_hash( sha256_hmac, sizeof(sha256_hmac), str );
355     ok(!strcmp(str, expected_hmac), "got %s\n", str);
356 
357     ret = BCryptDestroyHash(hash);
358     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
359 
360     ret = BCryptCloseAlgorithmProvider(alg, 0);
361     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
362 }
363 
364 static void test_sha384(void)
365 {
366     static const char expected[] =
367         "62b21e90c9022b101671ba1f808f8631a8149f0f12904055839a35c1ca78ae5363eed1e743a692d70e0504b0cfd12ef9";
368     static const char expected_hmac[] =
369         "4b3e6d6ff2da121790ab7e7b9247583e3a7eed2db5bd4dabc680303b1608f37dfdc836d96a704c03283bc05b4f6c5eb8";
370     BCRYPT_ALG_HANDLE alg;
371     BCRYPT_HASH_HANDLE hash;
372     UCHAR buf[512], buf_hmac[1024], sha384[48], sha384_hmac[48];
373     ULONG size, len;
374     char str[97];
375     NTSTATUS ret;
376 
377     alg = NULL;
378     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA384_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
379     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
380     ok(alg != NULL, "alg not set\n");
381 
382     len = size = 0xdeadbeef;
383     ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
384     ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret);
385 
386     len = size = 0xdeadbeef;
387     ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0);
388     ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
389 
390     len = size = 0xdeadbeef;
391     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0);
392     ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
393 
394     len = size = 0xdeadbeef;
395     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0);
396     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
397     ok(size == sizeof(len), "got %u\n", size);
398 
399     len = size = 0xdeadbeef;
400     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0);
401     ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
402     ok(len == 0xdeadbeef, "got %u\n", len);
403     ok(size == sizeof(len), "got %u\n", size);
404 
405     len = size = 0xdeadbeef;
406     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0);
407     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
408     ok(len != 0xdeadbeef, "len not set\n");
409     ok(size == sizeof(len), "got %u\n", size);
410 
411     test_hash_length(alg, 48);
412     test_alg_name(alg, "SHA384");
413 
414     hash = NULL;
415     len = sizeof(buf);
416     ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0);
417     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
418     ok(hash != NULL, "hash not set\n");
419 
420     ret = BCryptHashData(hash, NULL, 0, 0);
421     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
422 
423     ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
424     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
425 
426     test_hash_length(hash, 48);
427     test_alg_name(hash, "SHA384");
428 
429     memset(sha384, 0, sizeof(sha384));
430     ret = BCryptFinishHash(hash, sha384, sizeof(sha384), 0);
431     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
432     format_hash( sha384, sizeof(sha384), str );
433     ok(!strcmp(str, expected), "got %s\n", str);
434 
435     ret = BCryptDestroyHash(hash);
436     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
437 
438     ret = BCryptCloseAlgorithmProvider(alg, 0);
439     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
440 
441     alg = NULL;
442     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA384_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
443     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
444     ok(alg != NULL, "alg not set\n");
445 
446     hash = NULL;
447     len = sizeof(buf_hmac);
448     ret = BCryptCreateHash(alg, &hash, buf_hmac, len, (UCHAR *)"key", sizeof("key"), 0);
449     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
450     ok(hash != NULL, "hash not set\n");
451 
452     ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
453     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
454 
455     test_hash_length(hash, 48);
456     test_alg_name(hash, "SHA384");
457 
458     memset(sha384_hmac, 0, sizeof(sha384_hmac));
459     ret = BCryptFinishHash(hash, sha384_hmac, sizeof(sha384_hmac), 0);
460     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
461     format_hash( sha384_hmac, sizeof(sha384_hmac), str );
462     ok(!strcmp(str, expected_hmac), "got %s\n", str);
463 
464     ret = BCryptDestroyHash(hash);
465     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
466 
467     ret = BCryptCloseAlgorithmProvider(alg, 0);
468     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
469 }
470 
471 static void test_sha512(void)
472 {
473     static const char expected[] =
474         "d55ced17163bf5386f2cd9ff21d6fd7fe576a915065c24744d09cfae4ec84ee1e"
475         "f6ef11bfbc5acce3639bab725b50a1fe2c204f8c820d6d7db0df0ecbc49c5ca";
476     static const char expected_hmac[] =
477         "415fb6b10018ca03b38a1b1399c42ac0be5e8aceddb9a73103f5e543bf2d888f2"
478         "eecf91373941f9315dd730a77937fa92444450fbece86f409d9cb5ec48c6513";
479     BCRYPT_ALG_HANDLE alg;
480     BCRYPT_HASH_HANDLE hash;
481     UCHAR buf[512], buf_hmac[1024], sha512[64], sha512_hmac[64];
482     ULONG size, len;
483     char str[129];
484     NTSTATUS ret;
485 
486     alg = NULL;
487     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA512_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
488     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
489     ok(alg != NULL, "alg not set\n");
490 
491     len = size = 0xdeadbeef;
492     ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
493     ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret);
494 
495     len = size = 0xdeadbeef;
496     ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0);
497     ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
498 
499     len = size = 0xdeadbeef;
500     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0);
501     ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
502 
503     len = size = 0xdeadbeef;
504     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0);
505     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
506     ok(size == sizeof(len), "got %u\n", size);
507 
508     len = size = 0xdeadbeef;
509     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0);
510     ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
511     ok(len == 0xdeadbeef, "got %u\n", len);
512     ok(size == sizeof(len), "got %u\n", size);
513 
514     len = size = 0xdeadbeef;
515     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0);
516     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
517     ok(len != 0xdeadbeef, "len not set\n");
518     ok(size == sizeof(len), "got %u\n", size);
519 
520     test_hash_length(alg, 64);
521     test_alg_name(alg, "SHA512");
522 
523     hash = NULL;
524     len = sizeof(buf);
525     ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0);
526     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
527     ok(hash != NULL, "hash not set\n");
528 
529     ret = BCryptHashData(hash, NULL, 0, 0);
530     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
531 
532     ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
533     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
534 
535     test_hash_length(hash, 64);
536     test_alg_name(hash, "SHA512");
537 
538     memset(sha512, 0, sizeof(sha512));
539     ret = BCryptFinishHash(hash, sha512, sizeof(sha512), 0);
540     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
541     format_hash( sha512, sizeof(sha512), str );
542     ok(!strcmp(str, expected), "got %s\n", str);
543 
544     ret = BCryptDestroyHash(hash);
545     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
546 
547     ret = BCryptCloseAlgorithmProvider(alg, 0);
548     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
549 
550     alg = NULL;
551     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA512_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
552     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
553     ok(alg != NULL, "alg not set\n");
554 
555     hash = NULL;
556     len = sizeof(buf_hmac);
557     ret = BCryptCreateHash(alg, &hash, buf_hmac, len, (UCHAR *)"key", sizeof("key"), 0);
558     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
559     ok(hash != NULL, "hash not set\n");
560 
561     ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
562     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
563 
564     test_hash_length(hash, 64);
565     test_alg_name(hash, "SHA512");
566 
567     memset(sha512_hmac, 0, sizeof(sha512_hmac));
568     ret = BCryptFinishHash(hash, sha512_hmac, sizeof(sha512_hmac), 0);
569     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
570     format_hash( sha512_hmac, sizeof(sha512_hmac), str );
571     ok(!strcmp(str, expected_hmac), "got %s\n", str);
572 
573     ret = BCryptDestroyHash(hash);
574     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
575 
576     ret = BCryptCloseAlgorithmProvider(alg, 0);
577     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
578 
579 }
580 
581 static void test_md5(void)
582 {
583     static const char expected[] =
584         "e2a3e68d23ce348b8f68b3079de3d4c9";
585     static const char expected_hmac[] =
586         "7bda029b93fa8d817fcc9e13d6bdf092";
587     BCRYPT_ALG_HANDLE alg;
588     BCRYPT_HASH_HANDLE hash;
589     UCHAR buf[512], buf_hmac[1024], md5[16], md5_hmac[16];
590     ULONG size, len;
591     char str[65];
592     NTSTATUS ret;
593 
594     alg = NULL;
595     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_MD5_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
596     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
597     ok(alg != NULL, "alg not set\n");
598 
599     len = size = 0xdeadbeef;
600     ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
601     ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret);
602 
603     len = size = 0xdeadbeef;
604     ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0);
605     ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
606 
607     len = size = 0xdeadbeef;
608     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0);
609     ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
610 
611     len = size = 0xdeadbeef;
612     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0);
613     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
614     ok(size == sizeof(len), "got %u\n", size);
615 
616     len = size = 0xdeadbeef;
617     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0);
618     ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
619     ok(len == 0xdeadbeef, "got %u\n", len);
620     ok(size == sizeof(len), "got %u\n", size);
621 
622     len = size = 0xdeadbeef;
623     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0);
624     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
625     ok(len != 0xdeadbeef, "len not set\n");
626     ok(size == sizeof(len), "got %u\n", size);
627 
628     test_hash_length(alg, 16);
629     test_alg_name(alg, "MD5");
630 
631     hash = NULL;
632     len = sizeof(buf);
633     ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0);
634     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
635     ok(hash != NULL, "hash not set\n");
636 
637     ret = BCryptHashData(hash, NULL, 0, 0);
638     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
639 
640     ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
641     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
642 
643     test_hash_length(hash, 16);
644     test_alg_name(hash, "MD5");
645 
646     memset(md5, 0, sizeof(md5));
647     ret = BCryptFinishHash(hash, md5, sizeof(md5), 0);
648     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
649     format_hash( md5, sizeof(md5), str );
650     ok(!strcmp(str, expected), "got %s\n", str);
651 
652     ret = BCryptDestroyHash(hash);
653     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
654 
655     ret = BCryptCloseAlgorithmProvider(alg, 0);
656     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
657 
658     alg = NULL;
659     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_MD5_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
660     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
661     ok(alg != NULL, "alg not set\n");
662 
663     hash = NULL;
664     len = sizeof(buf_hmac);
665     ret = BCryptCreateHash(alg, &hash, buf_hmac, len, (UCHAR *)"key", sizeof("key"), 0);
666     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
667     ok(hash != NULL, "hash not set\n");
668 
669     ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0);
670     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
671 
672     test_hash_length(hash, 16);
673     test_alg_name(hash, "MD5");
674 
675     memset(md5_hmac, 0, sizeof(md5_hmac));
676     ret = BCryptFinishHash(hash, md5_hmac, sizeof(md5_hmac), 0);
677     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
678     format_hash( md5_hmac, sizeof(md5_hmac), str );
679     ok(!strcmp(str, expected_hmac), "got %s\n", str);
680 
681     ret = BCryptDestroyHash(hash);
682     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
683 
684     ret = BCryptCloseAlgorithmProvider(alg, 0);
685     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
686 }
687 
688 static void test_BcryptHash(void)
689 {
690     static const char expected[] =
691         "e2a3e68d23ce348b8f68b3079de3d4c9";
692     static const char expected_hmac[] =
693         "7bda029b93fa8d817fcc9e13d6bdf092";
694     BCRYPT_ALG_HANDLE alg;
695     UCHAR md5[16], md5_hmac[16];
696     char str[65];
697     NTSTATUS ret;
698 
699     alg = NULL;
700     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_MD5_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
701     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
702     ok(alg != NULL, "alg not set\n");
703 
704     test_hash_length(alg, 16);
705     test_alg_name(alg, "MD5");
706 
707     memset(md5, 0, sizeof(md5));
708     ret = pBCryptHash(alg, NULL, 0, (UCHAR *)"test", sizeof("test"), md5, sizeof(md5));
709     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
710     format_hash( md5, sizeof(md5), str );
711     ok(!strcmp(str, expected), "got %s\n", str);
712 
713     ret = BCryptCloseAlgorithmProvider(alg, 0);
714     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
715 
716     alg = NULL;
717     memset(md5_hmac, 0, sizeof(md5_hmac));
718     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_MD5_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
719     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
720     ok(alg != NULL, "alg not set\n");
721 
722     ret = pBCryptHash(alg, (UCHAR *)"key", sizeof("key"), (UCHAR *)"test", sizeof("test"), md5_hmac, sizeof(md5_hmac));
723     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
724     format_hash( md5_hmac, sizeof(md5_hmac), str );
725     ok(!strcmp(str, expected_hmac), "got %s\n", str);
726 
727     ret = BCryptCloseAlgorithmProvider(alg, 0);
728     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
729 }
730 
731 static void test_rng(void)
732 {
733     BCRYPT_ALG_HANDLE alg;
734     ULONG size, len;
735     UCHAR buf[16];
736     NTSTATUS ret;
737 
738     alg = NULL;
739     ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
740     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
741     ok(alg != NULL, "alg not set\n");
742 
743     len = size = 0xdeadbeef;
744     ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
745     ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret);
746 
747     test_alg_name(alg, "RNG");
748 
749     memset(buf, 0, 16);
750     ret = BCryptGenRandom(alg, buf, 8, 0);
751     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
752     ok(memcmp(buf, buf + 8, 8), "got zeroes\n");
753 
754     ret = BCryptCloseAlgorithmProvider(alg, 0);
755     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
756 }
757 
758 
759 START_TEST(bcrypt)
760 {
761     HMODULE module;
762 
763     module = GetModuleHandleA( "bcrypt.dll" );
764 
765     test_BCryptGenRandom();
766     test_BCryptGetFipsAlgorithmMode();
767     test_sha1();
768     test_sha256();
769     test_sha384();
770     test_sha512();
771     test_md5();
772     test_rng();
773 
774     pBCryptHash = (void *)GetProcAddress( module, "BCryptHash" );
775 
776     if (pBCryptHash)
777         test_BcryptHash();
778     else
779         win_skip("BCryptHash is not available\n");
780 }
781