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