rsaenh: Add simple tests for SHA-256, SHA-384, and SHA-512.
[wine/hacks.git] / dlls / rsaenh / tests / rsaenh.c
blobce907f54d68089bbfd7405d19dde5ecf67f71ee2
1 /*
2 * Unit tests for rsaenh functions
4 * Copyright (c) 2004 Michael Jung
5 * Copyright (c) 2006 Juan Lang
6 * Copyright (c) 2007 Vijay Kiran Kamuju
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <string.h>
24 #include <stdio.h>
25 #include "wine/test.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "wincrypt.h"
30 #include "winreg.h"
32 static HCRYPTPROV hProv;
33 static const char szContainer[] = "winetest";
34 static const char szProvider[] = MS_ENHANCED_PROV_A;
36 typedef struct _ctdatatype {
37 unsigned char origstr[32];
38 unsigned char decstr[32];
39 int strlen;
40 int enclen;
41 int buflen;
42 } cryptdata;
44 static const cryptdata cTestData[4] = {
45 {"abcdefghijkl",
46 {'a','b','c','d','e','f','g','h',0x2,0x2,'k','l',0},
47 12,8,16},
48 {"abcdefghij",
49 {'a','b','c','d','e','f','g','h',0x2,0x2,0},
50 10,8,16},
51 {"abcdefgh",
52 {'a','b','c','d','e','f','g','h',0},
53 8,8,16},
54 {"abcdefghijkl",
55 {'a','b','c','d','e','f','g','h','i','j','k','l',0},
56 12,12,16}
60 * 1. Take the MD5 Hash of the container name (with an extra null byte)
61 * 2. Turn the hash into a 4 DWORD hex value
62 * 3. Append a '_'
63 * 4. Add the MachineGuid
66 static void uniquecontainer(char *unique)
68 /* MD5 hash of "winetest\0" in 4 DWORD hex */
69 static const char szContainer_md5[] = "9d20fd8d05ed2b8455d125d0bf6d6a70";
70 static const char szCryptography[] = "Software\\Microsoft\\Cryptography";
71 static const char szMachineGuid[] = "MachineGuid";
72 HKEY hkey;
73 char guid[MAX_PATH];
74 DWORD size = MAX_PATH;
75 HRESULT ret;
77 /* Get the MachineGUID */
78 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, szCryptography, 0, KEY_READ | KEY_WOW64_64KEY, &hkey);
79 if (ret == ERROR_ACCESS_DENIED)
81 /* Windows 2000 can't handle KEY_WOW64_64KEY */
82 RegOpenKeyA(HKEY_LOCAL_MACHINE, szCryptography, &hkey);
84 RegQueryValueExA(hkey, szMachineGuid, NULL, NULL, (LPBYTE)guid, &size);
85 RegCloseKey(hkey);
87 lstrcpy(unique, szContainer_md5);
88 lstrcat(unique, "_");
89 lstrcat(unique, guid);
92 static void printBytes(const char *heading, const BYTE *pb, size_t cb)
94 size_t i;
95 printf("%s: ",heading);
96 for(i=0;i<cb;i++)
97 printf("0x%02x,",pb[i]);
98 putchar('\n');
101 static BOOL (WINAPI *pCryptDuplicateHash) (HCRYPTHASH, DWORD*, DWORD, HCRYPTHASH*);
104 static void trace_hex(BYTE *pbData, DWORD dwLen) {
105 char szTemp[256];
106 DWORD i, j;
108 for (i = 0; i < dwLen-7; i+=8) {
109 sprintf(szTemp, "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
110 pbData[i], pbData[i+1], pbData[i+2], pbData[i+3], pbData[i+4], pbData[i+5],
111 pbData[i+6], pbData[i+7]);
112 trace(szTemp);
114 for (j=0; i<dwLen; j++,i++) {
115 sprintf(szTemp+6*j, "0x%02x,\n", pbData[i]);
117 trace(szTemp);
121 static int init_base_environment(DWORD dwKeyFlags)
123 HCRYPTKEY hKey;
124 BOOL result;
126 pCryptDuplicateHash = (void *)GetProcAddress(GetModuleHandleA("advapi32.dll"), "CryptDuplicateHash");
128 hProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
130 result = CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
131 ok(!result && (GetLastError()==NTE_BAD_FLAGS ||
132 broken(GetLastError() == NTE_KEYSET_NOT_DEF /* Win9x/NT4 */)),
133 "%d, %08x\n", result, GetLastError());
135 if (!CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, 0))
137 ok(GetLastError()==NTE_BAD_KEYSET ||
138 broken(GetLastError() == NTE_KEYSET_NOT_DEF /* Win9x/NT4 */),
139 "%08x\n", GetLastError());
140 if (GetLastError()!=NTE_BAD_KEYSET)
142 win_skip("RSA full provider not available\n");
143 return 0;
145 result = CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL,
146 CRYPT_NEWKEYSET);
147 ok(result, "%08x\n", GetLastError());
148 if (!result)
150 win_skip("Couldn't create crypto provider\n");
151 return 0;
153 result = CryptGenKey(hProv, AT_KEYEXCHANGE, dwKeyFlags, &hKey);
154 ok(result, "%08x\n", GetLastError());
155 if (result) CryptDestroyKey(hKey);
156 result = CryptGenKey(hProv, AT_SIGNATURE, dwKeyFlags, &hKey);
157 ok(result, "%08x\n", GetLastError());
158 if (result) CryptDestroyKey(hKey);
160 return 1;
163 static void clean_up_base_environment(void)
165 BOOL result;
167 SetLastError(0xdeadbeef);
168 result = CryptReleaseContext(hProv, 1);
169 ok(!result || broken(result) /* Win98 */, "Expected failure\n");
170 ok(GetLastError()==NTE_BAD_FLAGS, "Expected NTE_BAD_FLAGS, got %08x\n", GetLastError());
172 /* Just to prove that Win98 also released the CSP */
173 SetLastError(0xdeadbeef);
174 result = CryptReleaseContext(hProv, 0);
175 ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%08x\n", GetLastError());
177 CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
180 static int init_aes_environment(void)
182 HCRYPTKEY hKey;
183 BOOL result;
185 pCryptDuplicateHash = (void *)GetProcAddress(GetModuleHandleA("advapi32.dll"), "CryptDuplicateHash");
187 hProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
189 /* we are using NULL as provider name for RSA_AES provider as the provider
190 * names are different in Windows XP and Vista. Its different as to what
191 * its defined in the SDK on Windows XP.
192 * This provider is available on Windows XP, Windows 2003 and Vista. */
194 result = CryptAcquireContext(&hProv, szContainer, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
195 if (!result && GetLastError() == NTE_PROV_TYPE_NOT_DEF)
197 win_skip("RSA_AES provider not supported\n");
198 return 0;
200 ok(!result && GetLastError()==NTE_BAD_FLAGS, "%d, %08x\n", result, GetLastError());
202 if (!CryptAcquireContext(&hProv, szContainer, NULL, PROV_RSA_AES, 0))
204 ok(GetLastError()==NTE_BAD_KEYSET, "%08x\n", GetLastError());
205 if (GetLastError()!=NTE_BAD_KEYSET) return 0;
206 result = CryptAcquireContext(&hProv, szContainer, NULL, PROV_RSA_AES,
207 CRYPT_NEWKEYSET);
208 ok(result, "%08x\n", GetLastError());
209 if (!result) return 0;
210 result = CryptGenKey(hProv, AT_KEYEXCHANGE, 0, &hKey);
211 ok(result, "%08x\n", GetLastError());
212 if (result) CryptDestroyKey(hKey);
213 result = CryptGenKey(hProv, AT_SIGNATURE, 0, &hKey);
214 ok(result, "%08x\n", GetLastError());
215 if (result) CryptDestroyKey(hKey);
217 return 1;
220 static void clean_up_aes_environment(void)
222 BOOL result;
224 result = CryptReleaseContext(hProv, 1);
225 ok(!result && GetLastError()==NTE_BAD_FLAGS, "%08x\n", GetLastError());
227 CryptAcquireContext(&hProv, szContainer, NULL, PROV_RSA_AES, CRYPT_DELETEKEYSET);
230 static void test_prov(void)
232 BOOL result;
233 DWORD dwLen, dwInc;
235 dwLen = (DWORD)sizeof(DWORD);
236 SetLastError(0xdeadbeef);
237 result = CryptGetProvParam(hProv, PP_SIG_KEYSIZE_INC, (BYTE*)&dwInc, &dwLen, 0);
238 if (!result && GetLastError() == NTE_BAD_TYPE)
239 skip("PP_SIG_KEYSIZE_INC is not supported (win9x or NT)\n");
240 else
241 ok(result && dwInc==8, "%08x, %d\n", GetLastError(), dwInc);
243 dwLen = (DWORD)sizeof(DWORD);
244 SetLastError(0xdeadbeef);
245 result = CryptGetProvParam(hProv, PP_KEYX_KEYSIZE_INC, (BYTE*)&dwInc, &dwLen, 0);
246 if (!result && GetLastError() == NTE_BAD_TYPE)
247 skip("PP_KEYX_KEYSIZE_INC is not supported (win9x or NT)\n");
248 else
249 ok(result && dwInc==8, "%08x, %d\n", GetLastError(), dwInc);
252 static void test_gen_random(void)
254 BOOL result;
255 BYTE rnd1[16], rnd2[16];
257 memset(rnd1, 0, sizeof(rnd1));
258 memset(rnd2, 0, sizeof(rnd2));
260 result = CryptGenRandom(hProv, sizeof(rnd1), rnd1);
261 if (!result && GetLastError() == NTE_FAIL) {
262 /* rsaenh compiled without OpenSSL */
263 return;
266 ok(result, "%08x\n", GetLastError());
268 result = CryptGenRandom(hProv, sizeof(rnd2), rnd2);
269 ok(result, "%08x\n", GetLastError());
271 ok(memcmp(rnd1, rnd2, sizeof(rnd1)), "CryptGenRandom generates non random data\n");
274 static BOOL derive_key(ALG_ID aiAlgid, HCRYPTKEY *phKey, DWORD len)
276 HCRYPTHASH hHash;
277 BOOL result;
278 unsigned char pbData[2000];
279 int i;
281 *phKey = 0;
282 for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
283 result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
284 if (!result) {
285 /* rsaenh compiled without OpenSSL */
286 ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
287 return FALSE;
289 ok(result, "%08x\n", GetLastError());
290 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
291 ok(result, "%08x\n", GetLastError());
292 if (!result) return FALSE;
293 result = CryptDeriveKey(hProv, aiAlgid, hHash, (len << 16) | CRYPT_EXPORTABLE, phKey);
294 ok(result, "%08x\n", GetLastError());
295 if (!result) return FALSE;
296 len = 2000;
297 result = CryptGetHashParam(hHash, HP_HASHVAL, pbData, &len, 0);
298 ok(result, "%08x\n", GetLastError());
299 CryptDestroyHash(hHash);
300 return TRUE;
303 static void test_hashes(void)
305 static const unsigned char md2hash[16] = {
306 0x12, 0xcb, 0x1b, 0x08, 0xc8, 0x48, 0xa4, 0xa9,
307 0xaa, 0xf3, 0xf1, 0x9f, 0xfc, 0x29, 0x28, 0x68 };
308 static const unsigned char md4hash[16] = {
309 0x8e, 0x2a, 0x58, 0xbf, 0xf2, 0xf5, 0x26, 0x23,
310 0x79, 0xd2, 0x92, 0x36, 0x1b, 0x23, 0xe3, 0x81 };
311 static const unsigned char empty_md5hash[16] = {
312 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
313 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e };
314 static const unsigned char md5hash[16] = {
315 0x15, 0x76, 0xa9, 0x4d, 0x6c, 0xb3, 0x34, 0xdd,
316 0x12, 0x6c, 0xb1, 0xc2, 0x7f, 0x19, 0xe0, 0xf2 };
317 static const unsigned char sha1hash[20] = {
318 0xf1, 0x0c, 0xcf, 0xde, 0x60, 0xc1, 0x7d, 0xb2, 0x6e, 0x7d,
319 0x85, 0xd3, 0x56, 0x65, 0xc7, 0x66, 0x1d, 0xbb, 0xeb, 0x2c };
320 unsigned char pbData[2048];
321 BOOL result;
322 HCRYPTHASH hHash, hHashClone;
323 BYTE pbHashValue[36];
324 DWORD hashlen, len;
325 int i;
327 for (i=0; i<2048; i++) pbData[i] = (unsigned char)i;
329 /* MD2 Hashing */
330 result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
331 if (!result) {
332 /* rsaenh compiled without OpenSSL */
333 ok(GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
334 } else {
335 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
336 ok(result, "%08x\n", GetLastError());
338 len = sizeof(DWORD);
339 result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
340 ok(result && (hashlen == 16), "%08x, hashlen: %d\n", GetLastError(), hashlen);
342 len = 16;
343 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
344 ok(result, "%08x\n", GetLastError());
346 ok(!memcmp(pbHashValue, md2hash, 16), "Wrong MD2 hash!\n");
348 result = CryptDestroyHash(hHash);
349 ok(result, "%08x\n", GetLastError());
352 /* MD4 Hashing */
353 result = CryptCreateHash(hProv, CALG_MD4, 0, 0, &hHash);
354 ok(result, "%08x\n", GetLastError());
356 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
357 ok(result, "%08x\n", GetLastError());
359 len = sizeof(DWORD);
360 result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
361 ok(result && (hashlen == 16), "%08x, hashlen: %d\n", GetLastError(), hashlen);
363 len = 16;
364 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
365 ok(result, "%08x\n", GetLastError());
367 ok(!memcmp(pbHashValue, md4hash, 16), "Wrong MD4 hash!\n");
369 result = CryptDestroyHash(hHash);
370 ok(result, "%08x\n", GetLastError());
372 /* MD5 Hashing */
373 result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
374 ok(result, "%08x\n", GetLastError());
376 len = sizeof(DWORD);
377 result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
378 ok(result && (hashlen == 16), "%08x, hashlen: %d\n", GetLastError(), hashlen);
380 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
381 ok(result, "%08x\n", GetLastError());
383 len = 16;
384 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
385 ok(result, "%08x\n", GetLastError());
387 ok(!memcmp(pbHashValue, md5hash, 16), "Wrong MD5 hash!\n");
389 result = CryptDestroyHash(hHash);
390 ok(result, "%08x\n", GetLastError());
392 result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
393 ok(result, "%08x\n", GetLastError());
395 /* The hash is available even if CryptHashData hasn't been called */
396 len = 16;
397 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
398 ok(result, "%08x\n", GetLastError());
400 ok(!memcmp(pbHashValue, empty_md5hash, 16), "Wrong MD5 hash!\n");
402 /* It's also stable: getting it twice results in the same value */
403 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
404 ok(result, "%08x\n", GetLastError());
406 ok(!memcmp(pbHashValue, empty_md5hash, 16), "Wrong MD5 hash!\n");
408 /* Can't add data after the hash been retrieved */
409 SetLastError(0xdeadbeef);
410 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
411 ok(!result, "Expected failure\n");
412 ok(GetLastError() == NTE_BAD_HASH_STATE ||
413 GetLastError() == NTE_BAD_ALGID, /* Win9x, WinMe, NT4 */
414 "Expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID, got %08x\n", GetLastError());
416 /* You can still retrieve the hash, its value just hasn't changed */
417 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
418 ok(result, "%08x\n", GetLastError());
420 ok(!memcmp(pbHashValue, empty_md5hash, 16), "Wrong MD5 hash!\n");
422 result = CryptDestroyHash(hHash);
423 ok(result, "%08x\n", GetLastError());
425 /* SHA1 Hashing */
426 result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
427 ok(result, "%08x\n", GetLastError());
429 result = CryptHashData(hHash, pbData, 5, 0);
430 ok(result, "%08x\n", GetLastError());
432 if(pCryptDuplicateHash) {
433 result = pCryptDuplicateHash(hHash, 0, 0, &hHashClone);
434 ok(result, "%08x\n", GetLastError());
436 result = CryptHashData(hHashClone, (BYTE*)pbData+5, sizeof(pbData)-5, 0);
437 ok(result, "%08x\n", GetLastError());
439 len = sizeof(DWORD);
440 result = CryptGetHashParam(hHashClone, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
441 ok(result && (hashlen == 20), "%08x, hashlen: %d\n", GetLastError(), hashlen);
443 len = 20;
444 result = CryptGetHashParam(hHashClone, HP_HASHVAL, pbHashValue, &len, 0);
445 ok(result, "%08x\n", GetLastError());
447 ok(!memcmp(pbHashValue, sha1hash, 20), "Wrong SHA1 hash!\n");
449 result = CryptDestroyHash(hHashClone);
450 ok(result, "%08x\n", GetLastError());
453 result = CryptDestroyHash(hHash);
454 ok(result, "%08x\n", GetLastError());
456 /* The SHA-2 variants aren't supported in the RSA full provider */
457 result = CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash);
458 ok(!result && GetLastError() == NTE_BAD_ALGID,
459 "expected NTE_BAD_ALGID, got %08x\n", GetLastError());
460 result = CryptCreateHash(hProv, CALG_SHA_384, 0, 0, &hHash);
461 ok(!result && GetLastError() == NTE_BAD_ALGID,
462 "expected NTE_BAD_ALGID, got %08x\n", GetLastError());
463 result = CryptCreateHash(hProv, CALG_SHA_512, 0, 0, &hHash);
464 ok(!result && GetLastError() == NTE_BAD_ALGID,
465 "expected NTE_BAD_ALGID, got %08x\n", GetLastError());
468 static void test_block_cipher_modes(void)
470 static const BYTE plain[23] = {
471 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
472 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
473 static const BYTE ecb[24] = {
474 0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11, 0xf2, 0xb2, 0x5d, 0x5f,
475 0x08, 0xff, 0x49, 0xa4, 0x45, 0x3a, 0x68, 0x14, 0xca, 0x18, 0xe5, 0xf4 };
476 static const BYTE cbc[24] = {
477 0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11, 0x10, 0xf5, 0xda, 0x61,
478 0x4e, 0x3d, 0xab, 0xc0, 0x97, 0x85, 0x01, 0x12, 0x97, 0xa4, 0xf7, 0xd3 };
479 static const BYTE cfb[24] = {
480 0x29, 0xb5, 0x67, 0x85, 0x0b, 0x1b, 0xec, 0x07, 0x67, 0x2d, 0xa1, 0xa4,
481 0x1a, 0x47, 0x24, 0x6a, 0x54, 0xe1, 0xe0, 0x92, 0xf9, 0x0e, 0xf6, 0xeb };
482 HCRYPTKEY hKey;
483 BOOL result;
484 BYTE abData[24];
485 DWORD dwMode, dwLen;
487 result = derive_key(CALG_RC2, &hKey, 40);
488 if (!result) return;
490 memcpy(abData, plain, sizeof(plain));
492 dwMode = CRYPT_MODE_ECB;
493 result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
494 ok(result, "%08x\n", GetLastError());
496 dwLen = 23;
497 result = CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwLen, 24);
498 ok(result, "CryptEncrypt failed: %08x\n", GetLastError());
499 ok(dwLen == 24, "Unexpected length %d\n", dwLen);
501 SetLastError(ERROR_SUCCESS);
502 dwLen = 23;
503 result = CryptEncrypt(hKey, 0, TRUE, 0, abData, &dwLen, 24);
504 ok(result && dwLen == 24 && !memcmp(ecb, abData, sizeof(ecb)),
505 "%08x, dwLen: %d\n", GetLastError(), dwLen);
507 result = CryptDecrypt(hKey, 0, TRUE, 0, abData, &dwLen);
508 ok(result && dwLen == 23 && !memcmp(plain, abData, sizeof(plain)),
509 "%08x, dwLen: %d\n", GetLastError(), dwLen);
511 dwMode = CRYPT_MODE_CBC;
512 result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
513 ok(result, "%08x\n", GetLastError());
515 dwLen = 23;
516 result = CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwLen, 24);
517 ok(result, "CryptEncrypt failed: %08x\n", GetLastError());
518 ok(dwLen == 24, "Unexpected length %d\n", dwLen);
520 dwLen = 23;
521 result = CryptEncrypt(hKey, 0, TRUE, 0, abData, &dwLen, 24);
522 ok(result && dwLen == 24 && !memcmp(cbc, abData, sizeof(cbc)),
523 "%08x, dwLen: %d\n", GetLastError(), dwLen);
525 result = CryptDecrypt(hKey, 0, TRUE, 0, abData, &dwLen);
526 ok(result && dwLen == 23 && !memcmp(plain, abData, sizeof(plain)),
527 "%08x, dwLen: %d\n", GetLastError(), dwLen);
529 dwMode = CRYPT_MODE_CFB;
530 result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
531 ok(result, "%08x\n", GetLastError());
533 dwLen = 16;
534 result = CryptEncrypt(hKey, 0, FALSE, 0, abData, &dwLen, 24);
535 ok(result && dwLen == 16, "%08x, dwLen: %d\n", GetLastError(), dwLen);
537 dwLen = 7;
538 result = CryptEncrypt(hKey, 0, TRUE, 0, abData+16, &dwLen, 8);
539 ok(result && dwLen == 8 && !memcmp(cfb, abData, sizeof(cfb)),
540 "%08x, dwLen: %d\n", GetLastError(), dwLen);
542 dwLen = 8;
543 result = CryptDecrypt(hKey, 0, FALSE, 0, abData, &dwLen);
544 ok(result && dwLen == 8, "%08x, dwLen: %d\n", GetLastError(), dwLen);
546 dwLen = 16;
547 result = CryptDecrypt(hKey, 0, TRUE, 0, abData+8, &dwLen);
548 ok(result && dwLen == 15 && !memcmp(plain, abData, sizeof(plain)),
549 "%08x, dwLen: %d\n", GetLastError(), dwLen);
551 dwMode = CRYPT_MODE_OFB;
552 result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
553 ok(result, "%08x\n", GetLastError());
555 dwLen = 23;
556 result = CryptEncrypt(hKey, 0, TRUE, 0, abData, &dwLen, 24);
557 ok(!result && GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
559 CryptDestroyKey(hKey);
562 static void test_3des112(void)
564 HCRYPTKEY hKey;
565 BOOL result;
566 DWORD dwLen;
567 unsigned char pbData[16];
568 int i;
570 result = derive_key(CALG_3DES_112, &hKey, 0);
571 if (!result) {
572 /* rsaenh compiled without OpenSSL */
573 ok(GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
574 return;
577 for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
579 dwLen = 13;
580 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
581 ok(result, "%08x\n", GetLastError());
583 result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
584 ok(result, "%08x\n", GetLastError());
586 for (i=0; i<4; i++)
588 memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);
590 dwLen = cTestData[i].enclen;
591 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
592 ok(result, "%08x\n", GetLastError());
593 ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
595 result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
596 ok(result, "%08x\n", GetLastError());
597 ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
598 ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
599 if((dwLen != cTestData[i].enclen) ||
600 memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
602 printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
603 printBytes("got",pbData,dwLen);
606 result = CryptDestroyKey(hKey);
607 ok(result, "%08x\n", GetLastError());
610 static void test_des(void)
612 HCRYPTKEY hKey;
613 BOOL result;
614 DWORD dwLen, dwMode;
615 unsigned char pbData[16];
616 int i;
618 result = derive_key(CALG_DES, &hKey, 56);
619 if (!result) {
620 /* rsaenh compiled without OpenSSL */
621 ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
622 return;
625 dwMode = CRYPT_MODE_ECB;
626 result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
627 ok(result, "%08x\n", GetLastError());
629 dwLen = sizeof(DWORD);
630 result = CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
631 ok(result, "%08x\n", GetLastError());
633 for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
635 dwLen = 13;
636 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
637 ok(result, "%08x\n", GetLastError());
639 result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
640 ok(result, "%08x\n", GetLastError());
642 for (i=0; i<4; i++)
644 memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);
646 dwLen = cTestData[i].enclen;
647 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
648 ok(result, "%08x\n", GetLastError());
649 ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
651 result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
652 ok(result, "%08x\n", GetLastError());
653 ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
654 ok(memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen)==0,"decryption incorrect %d\n",i);
655 if((dwLen != cTestData[i].enclen) ||
656 memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
658 printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
659 printBytes("got",pbData,dwLen);
663 result = CryptDestroyKey(hKey);
664 ok(result, "%08x\n", GetLastError());
667 static void test_3des(void)
669 HCRYPTKEY hKey;
670 BOOL result;
671 DWORD dwLen;
672 unsigned char pbData[16];
673 static const BYTE des3[16] = {
674 0x7b, 0xba, 0xdd, 0xa2, 0x39, 0xd3, 0x7b, 0xb3,
675 0xc7, 0x51, 0x81, 0x41, 0x53, 0xe8, 0xcf, 0xeb };
676 int i;
678 result = derive_key(CALG_3DES, &hKey, 0);
679 if (!result) return;
681 for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
683 dwLen = 13;
684 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
685 ok(result, "%08x\n", GetLastError());
687 ok(!memcmp(pbData, des3, sizeof(des3)), "3DES encryption failed!\n");
689 result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
690 ok(result, "%08x\n", GetLastError());
692 for (i=0; i<4; i++)
694 memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);
696 dwLen = cTestData[i].enclen;
697 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
698 ok(result, "%08x\n", GetLastError());
699 ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
701 result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
702 ok(result, "%08x\n", GetLastError());
703 ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
704 ok(memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen)==0,"decryption incorrect %d\n",i);
705 if((dwLen != cTestData[i].enclen) ||
706 memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
708 printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
709 printBytes("got",pbData,dwLen);
712 result = CryptDestroyKey(hKey);
713 ok(result, "%08x\n", GetLastError());
716 static void test_aes(int keylen)
718 HCRYPTKEY hKey;
719 BOOL result;
720 DWORD dwLen;
721 unsigned char pbData[16];
722 int i;
724 switch (keylen)
726 case 256:
727 result = derive_key(CALG_AES_256, &hKey, 0);
728 break;
729 case 192:
730 result = derive_key(CALG_AES_192, &hKey, 0);
731 break;
732 default:
733 case 128:
734 result = derive_key(CALG_AES_128, &hKey, 0);
735 break;
737 if (!result) return;
739 for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
741 dwLen = 13;
742 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
743 ok(result, "%08x\n", GetLastError());
745 result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
746 ok(result, "%08x\n", GetLastError());
748 for (i=0; i<4; i++)
750 memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);
752 dwLen = cTestData[i].enclen;
753 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
754 ok(result, "%08x\n", GetLastError());
755 ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
757 result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
758 ok(result, "%08x\n", GetLastError());
759 ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
760 ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
761 if((dwLen != cTestData[i].enclen) ||
762 memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
764 printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
765 printBytes("got",pbData,dwLen);
768 result = CryptDestroyKey(hKey);
769 ok(result, "%08x\n", GetLastError());
772 static void test_sha2(void)
774 static const unsigned char sha256hash[32] = {
775 0x10, 0xfc, 0x3c, 0x51, 0xa1, 0x52, 0xe9, 0x0e, 0x5b, 0x90,
776 0x31, 0x9b, 0x60, 0x1d, 0x92, 0xcc, 0xf3, 0x72, 0x90, 0xef,
777 0x53, 0xc3, 0x5f, 0xf9, 0x25, 0x07, 0x68, 0x7d, 0x8a, 0x91,
778 0x1a, 0x08
780 static const unsigned char sha384hash[48] = {
781 0x98, 0xd3, 0x3f, 0x89, 0x0b, 0x23, 0x33, 0x44, 0x61, 0x32,
782 0x5a, 0x7c, 0xa3, 0x03, 0x89, 0xb5, 0x11, 0xd7, 0x41, 0xc8,
783 0x54, 0x6b, 0x12, 0x0c, 0x40, 0x15, 0xb6, 0x2a, 0x03, 0x43,
784 0xe5, 0x64, 0x7f, 0x10, 0x1e, 0xae, 0x47, 0xa9, 0x39, 0x05,
785 0x6f, 0x40, 0x60, 0x94, 0xd6, 0xad, 0x80, 0x55
787 static const unsigned char sha512hash[64] = {
788 0x37, 0x86, 0x0e, 0x7d, 0x25, 0xd9, 0xf9, 0x84, 0x3e, 0x3d,
789 0xc7, 0x13, 0x95, 0x73, 0x42, 0x04, 0xfd, 0x13, 0xad, 0x23,
790 0x39, 0x16, 0x32, 0x5f, 0x99, 0x3e, 0x3c, 0xee, 0x3f, 0x11,
791 0x36, 0xf9, 0xc9, 0x66, 0x08, 0x70, 0xcc, 0x49, 0xd8, 0xe0,
792 0x7d, 0xa1, 0x57, 0x62, 0x71, 0xa6, 0xc9, 0xa4, 0x24, 0x60,
793 0xfc, 0xde, 0x9d, 0xb2, 0xf1, 0xd2, 0xc2, 0xfb, 0x2d, 0xbf,
794 0xb7, 0xf4, 0x81, 0xd4
796 unsigned char pbData[2048];
797 BOOL result;
798 HCRYPTHASH hHash;
799 BYTE pbHashValue[64];
800 DWORD hashlen, len;
801 int i;
803 for (i=0; i<2048; i++) pbData[i] = (unsigned char)i;
805 /* SHA-256 hash */
806 result = CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash);
807 todo_wine
808 ok(result, "%08x\n", GetLastError());
809 if (result) {
810 len = sizeof(DWORD);
811 result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
812 ok(result && (hashlen == 32), "%08x, hashlen: %d\n", GetLastError(), hashlen);
814 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
815 ok(result, "%08x\n", GetLastError());
817 len = 32;
818 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
819 ok(result, "%08x\n", GetLastError());
821 ok(!memcmp(pbHashValue, sha256hash, 32), "Wrong SHA-256 hash!\n");
823 result = CryptDestroyHash(hHash);
824 ok(result, "%08x\n", GetLastError());
827 /* SHA-384 hash */
828 result = CryptCreateHash(hProv, CALG_SHA_384, 0, 0, &hHash);
829 todo_wine
830 ok(result, "%08x\n", GetLastError());
831 if (result) {
832 len = sizeof(DWORD);
833 result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
834 ok(result && (hashlen == 48), "%08x, hashlen: %d\n", GetLastError(), hashlen);
836 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
837 ok(result, "%08x\n", GetLastError());
839 len = 48;
840 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
841 ok(result, "%08x\n", GetLastError());
843 ok(!memcmp(pbHashValue, sha384hash, 48), "Wrong SHA-384 hash!\n");
845 result = CryptDestroyHash(hHash);
846 ok(result, "%08x\n", GetLastError());
849 /* SHA-512 hash */
850 result = CryptCreateHash(hProv, CALG_SHA_512, 0, 0, &hHash);
851 todo_wine
852 ok(result, "%08x\n", GetLastError());
853 if (result) {
854 len = sizeof(DWORD);
855 result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
856 ok(result && (hashlen == 64), "%08x, hashlen: %d\n", GetLastError(), hashlen);
858 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
859 ok(result, "%08x\n", GetLastError());
861 len = 64;
862 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
863 ok(result, "%08x\n", GetLastError());
865 ok(!memcmp(pbHashValue, sha512hash, 64), "Wrong SHA-512 hash!\n");
867 result = CryptDestroyHash(hHash);
868 ok(result, "%08x\n", GetLastError());
872 static void test_rc2(void)
874 static const BYTE rc2_40_encrypted[16] = {
875 0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11,
876 0xfb, 0x18, 0x87, 0xce, 0x0c, 0x75, 0x07, 0xb1 };
877 static const BYTE rc2_128_encrypted[] = {
878 0x82,0x81,0xf7,0xff,0xdd,0xd7,0x88,0x8c,0x2a,0x2a,0xc0,0xce,0x4c,0x89,
879 0xb6,0x66 };
880 HCRYPTHASH hHash;
881 HCRYPTKEY hKey;
882 BOOL result;
883 DWORD dwLen, dwKeyLen, dwDataLen, dwMode, dwModeBits;
884 BYTE *pbTemp;
885 unsigned char pbData[2000], pbHashValue[16];
886 int i;
888 for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
890 /* MD2 Hashing */
891 result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
892 if (!result) {
893 ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
894 } else {
895 CRYPT_INTEGER_BLOB salt;
897 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
898 ok(result, "%08x\n", GetLastError());
900 dwLen = 16;
901 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &dwLen, 0);
902 ok(result, "%08x\n", GetLastError());
904 result = CryptDeriveKey(hProv, CALG_RC2, hHash, 40 << 16, &hKey);
905 ok(result, "%08x\n", GetLastError());
907 dwLen = sizeof(DWORD);
908 result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
909 ok(result, "%08x\n", GetLastError());
911 dwMode = CRYPT_MODE_CBC;
912 result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
913 ok(result, "%08x\n", GetLastError());
915 dwLen = sizeof(DWORD);
916 result = CryptGetKeyParam(hKey, KP_MODE_BITS, (BYTE*)&dwModeBits, &dwLen, 0);
917 ok(result, "%08x\n", GetLastError());
919 dwModeBits = 0xdeadbeef;
920 dwLen = sizeof(DWORD);
921 result = CryptGetKeyParam(hKey, KP_PERMISSIONS, (BYTE*)&dwModeBits, &dwLen, 0);
922 ok(result, "%08x\n", GetLastError());
923 ok(dwModeBits ==
924 (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
925 broken(dwModeBits == 0xffffffff), /* Win9x/NT4 */
926 "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
927 " got %08x\n", dwModeBits);
929 dwLen = sizeof(DWORD);
930 result = CryptGetKeyParam(hKey, KP_PERMISSIONS, (BYTE*)&dwModeBits, &dwLen, 0);
931 ok(result, "%08x\n", GetLastError());
933 dwLen = sizeof(DWORD);
934 result = CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&dwModeBits, &dwLen, 0);
935 ok(result, "%08x\n", GetLastError());
937 result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
938 ok(result, "%08x\n", GetLastError());
939 pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
940 CryptGetKeyParam(hKey, KP_IV, pbTemp, &dwLen, 0);
941 HeapFree(GetProcessHeap(), 0, pbTemp);
943 result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
944 ok(result, "%08x\n", GetLastError());
945 pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
946 CryptGetKeyParam(hKey, KP_SALT, pbTemp, &dwLen, 0);
947 HeapFree(GetProcessHeap(), 0, pbTemp);
949 dwLen = sizeof(DWORD);
950 CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
952 result = CryptDestroyHash(hHash);
953 ok(result, "%08x\n", GetLastError());
955 dwDataLen = 13;
956 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
957 ok(result, "%08x\n", GetLastError());
959 ok(!memcmp(pbData, rc2_40_encrypted, 16), "RC2 encryption failed!\n");
961 result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
962 ok(result, "%08x\n", GetLastError());
963 pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
964 CryptGetKeyParam(hKey, KP_IV, pbTemp, &dwLen, 0);
965 HeapFree(GetProcessHeap(), 0, pbTemp);
967 result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen);
968 ok(result, "%08x\n", GetLastError());
970 /* What sizes salt can I set? */
971 salt.pbData = pbData;
972 for (i=0; i<24; i++)
974 salt.cbData = i;
975 result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
976 ok(result, "setting salt failed for size %d: %08x\n", i, GetLastError());
978 salt.cbData = 25;
979 SetLastError(0xdeadbeef);
980 result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
981 ok(!result ||
982 broken(result), /* Win9x, WinMe, NT4, W2K */
983 "%08x\n", GetLastError());
985 result = CryptDestroyKey(hKey);
986 ok(result, "%08x\n", GetLastError());
989 /* Again, but test setting the effective key len */
990 for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
992 result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
993 if (!result) {
994 ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
995 } else {
996 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
997 ok(result, "%08x\n", GetLastError());
999 dwLen = 16;
1000 result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &dwLen, 0);
1001 ok(result, "%08x\n", GetLastError());
1003 result = CryptDeriveKey(hProv, CALG_RC2, hHash, 56 << 16, &hKey);
1004 ok(result, "%08x\n", GetLastError());
1006 SetLastError(0xdeadbeef);
1007 result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, NULL, 0);
1008 ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%08x\n", GetLastError());
1009 dwKeyLen = 0;
1010 SetLastError(0xdeadbeef);
1011 result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
1012 ok(!result && GetLastError()==NTE_BAD_DATA, "%08x\n", GetLastError());
1013 dwKeyLen = 1025;
1014 SetLastError(0xdeadbeef);
1015 result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
1017 dwLen = sizeof(dwKeyLen);
1018 CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1019 ok(dwKeyLen == 56, "%d (%08x)\n", dwKeyLen, GetLastError());
1020 CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1021 ok(dwKeyLen == 56 || broken(dwKeyLen == 40), "%d (%08x)\n", dwKeyLen, GetLastError());
1023 dwKeyLen = 128;
1024 result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
1025 ok(result, "%d\n", GetLastError());
1027 dwLen = sizeof(dwKeyLen);
1028 CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1029 ok(dwKeyLen == 56, "%d (%08x)\n", dwKeyLen, GetLastError());
1030 CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1031 ok(dwKeyLen == 128, "%d (%08x)\n", dwKeyLen, GetLastError());
1033 result = CryptDestroyHash(hHash);
1034 ok(result, "%08x\n", GetLastError());
1036 dwDataLen = 13;
1037 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
1038 ok(result, "%08x\n", GetLastError());
1040 ok(!memcmp(pbData, rc2_128_encrypted, sizeof(rc2_128_encrypted)),
1041 "RC2 encryption failed!\n");
1043 /* Oddly enough this succeeds, though it should have no effect */
1044 dwKeyLen = 40;
1045 result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
1046 ok(result, "%d\n", GetLastError());
1048 result = CryptDestroyKey(hKey);
1049 ok(result, "%08x\n", GetLastError());
1053 static void test_rc4(void)
1055 static const BYTE rc4[16] = {
1056 0x17, 0x0c, 0x44, 0x8e, 0xae, 0x90, 0xcd, 0xb0,
1057 0x7f, 0x87, 0xf5, 0x7a, 0xec, 0xb2, 0x2e, 0x35 };
1058 BOOL result;
1059 HCRYPTHASH hHash;
1060 HCRYPTKEY hKey;
1061 DWORD dwDataLen = 5, dwKeyLen, dwLen = sizeof(DWORD), dwMode;
1062 unsigned char pbData[2000], *pbTemp;
1063 unsigned char pszBuffer[256];
1064 int i;
1066 for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
1068 /* MD2 Hashing */
1069 result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
1070 if (!result) {
1071 /* rsaenh compiled without OpenSSL */
1072 ok(GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
1073 } else {
1074 CRYPT_INTEGER_BLOB salt;
1076 result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
1077 ok(result, "%08x\n", GetLastError());
1079 dwLen = 16;
1080 result = CryptGetHashParam(hHash, HP_HASHVAL, pszBuffer, &dwLen, 0);
1081 ok(result, "%08x\n", GetLastError());
1083 result = CryptDeriveKey(hProv, CALG_RC4, hHash, 56 << 16, &hKey);
1084 ok(result, "%08x\n", GetLastError());
1086 dwLen = sizeof(DWORD);
1087 result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
1088 ok(result, "%08x\n", GetLastError());
1090 dwLen = sizeof(DWORD);
1091 result = CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
1092 ok(result, "%08x\n", GetLastError());
1094 result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
1095 ok(result, "%08x\n", GetLastError());
1096 pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
1097 CryptGetKeyParam(hKey, KP_IV, pbTemp, &dwLen, 0);
1098 HeapFree(GetProcessHeap(), 0, pbTemp);
1100 result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
1101 ok(result, "%08x\n", GetLastError());
1102 pbTemp = HeapAlloc(GetProcessHeap(), 0, dwLen);
1103 CryptGetKeyParam(hKey, KP_SALT, pbTemp, &dwLen, 0);
1104 HeapFree(GetProcessHeap(), 0, pbTemp);
1106 dwLen = sizeof(DWORD);
1107 CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
1109 result = CryptDestroyHash(hHash);
1110 ok(result, "%08x\n", GetLastError());
1112 dwDataLen = 16;
1113 result = CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwDataLen, 24);
1114 ok(result, "%08x\n", GetLastError());
1115 dwDataLen = 16;
1116 result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
1117 ok(result, "%08x\n", GetLastError());
1119 ok(!memcmp(pbData, rc4, dwDataLen), "RC4 encryption failed!\n");
1121 result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen);
1122 ok(result, "%08x\n", GetLastError());
1124 /* What sizes salt can I set? */
1125 salt.pbData = pbData;
1126 for (i=0; i<24; i++)
1128 salt.cbData = i;
1129 result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
1130 ok(result, "setting salt failed for size %d: %08x\n", i, GetLastError());
1132 salt.cbData = 25;
1133 SetLastError(0xdeadbeef);
1134 result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
1135 ok(!result ||
1136 broken(result), /* Win9x, WinMe, NT4, W2K */
1137 "%08x\n", GetLastError());
1139 result = CryptDestroyKey(hKey);
1140 ok(result, "%08x\n", GetLastError());
1144 static void test_hmac(void) {
1145 HCRYPTKEY hKey;
1146 HCRYPTHASH hHash;
1147 BOOL result;
1148 /* Using CALG_MD2 here fails on Windows 2003, why ? */
1149 HMAC_INFO hmacInfo = { CALG_MD5, NULL, 0, NULL, 0 };
1150 DWORD dwLen;
1151 BYTE abData[256];
1152 static const BYTE hmac[16] = {
1153 0x1a, 0x7d, 0x49, 0xc5, 0x9b, 0x2d, 0x0b, 0x9c,
1154 0xcf, 0x10, 0x6b, 0xb6, 0x7d, 0x0f, 0x13, 0x32 };
1155 int i;
1157 for (i=0; i<sizeof(abData)/sizeof(BYTE); i++) abData[i] = (BYTE)i;
1159 if (!derive_key(CALG_RC2, &hKey, 56)) return;
1161 result = CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHash);
1162 ok(result, "%08x\n", GetLastError());
1163 if (!result) return;
1165 result = CryptSetHashParam(hHash, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0);
1166 ok(result, "%08x\n", GetLastError());
1168 result = CryptHashData(hHash, abData, sizeof(abData), 0);
1169 ok(result, "%08x\n", GetLastError());
1171 dwLen = sizeof(abData)/sizeof(BYTE);
1172 result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
1173 ok(result, "%08x\n", GetLastError());
1175 ok(!memcmp(abData, hmac, sizeof(hmac)), "HMAC failed!\n");
1177 result = CryptDestroyHash(hHash);
1178 ok(result, "%08x\n", GetLastError());
1180 result = CryptDestroyKey(hKey);
1181 ok(result, "%08x\n", GetLastError());
1183 /* Provoke errors */
1184 result = CryptCreateHash(hProv, CALG_HMAC, 0, 0, &hHash);
1185 ok(!result && GetLastError() == NTE_BAD_KEY, "%08x\n", GetLastError());
1188 static void test_mac(void) {
1189 HCRYPTKEY hKey;
1190 HCRYPTHASH hHash;
1191 BOOL result;
1192 DWORD dwLen;
1193 BYTE abData[256], abEnc[264];
1194 static const BYTE mac_40[8] = { 0xb7, 0xa2, 0x46, 0xe9, 0x11, 0x31, 0xe0, 0xad};
1195 int i;
1197 for (i=0; i<sizeof(abData)/sizeof(BYTE); i++) abData[i] = (BYTE)i;
1198 for (i=0; i<sizeof(abData)/sizeof(BYTE); i++) abEnc[i] = (BYTE)i;
1200 if (!derive_key(CALG_RC2, &hKey, 40)) return;
1202 dwLen = 256;
1203 result = CryptEncrypt(hKey, 0, TRUE, 0, abEnc, &dwLen, 264);
1204 ok (result && dwLen == 264, "%08x, dwLen: %d\n", GetLastError(), dwLen);
1206 result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
1207 ok(result, "%08x\n", GetLastError());
1208 if (!result) return;
1210 result = CryptHashData(hHash, abData, sizeof(abData), 0);
1211 ok(result, "%08x\n", GetLastError());
1213 dwLen = sizeof(abData)/sizeof(BYTE);
1214 result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
1215 ok(result && dwLen == 8, "%08x, dwLen: %d\n", GetLastError(), dwLen);
1217 ok(!memcmp(abData, mac_40, sizeof(mac_40)), "MAC failed!\n");
1219 result = CryptDestroyHash(hHash);
1220 ok(result, "%08x\n", GetLastError());
1222 result = CryptDestroyKey(hKey);
1223 ok(result, "%08x\n", GetLastError());
1225 /* Provoke errors */
1226 if (!derive_key(CALG_RC4, &hKey, 56)) return;
1228 SetLastError(0xdeadbeef);
1229 result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
1230 ok((!result && GetLastError() == NTE_BAD_KEY) ||
1231 broken(result), /* Win9x, WinMe, NT4, W2K */
1232 "%08x\n", GetLastError());
1234 result = CryptDestroyKey(hKey);
1235 ok(result, "%08x\n", GetLastError());
1238 static BYTE abPlainPrivateKey[596] = {
1239 0x07, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
1240 0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
1241 0x01, 0x00, 0x01, 0x00, 0x9b, 0x64, 0xef, 0xce,
1242 0x31, 0x7c, 0xad, 0x56, 0xe2, 0x1e, 0x9b, 0x96,
1243 0xb3, 0xf0, 0x29, 0x88, 0x6e, 0xa8, 0xc2, 0x11,
1244 0x33, 0xd6, 0xcc, 0x8c, 0x69, 0xb2, 0x1a, 0xfd,
1245 0xfc, 0x23, 0x21, 0x30, 0x4d, 0x29, 0x45, 0xb6,
1246 0x3a, 0x67, 0x11, 0x80, 0x1a, 0x91, 0xf2, 0x9f,
1247 0x01, 0xac, 0xc0, 0x11, 0x50, 0x5f, 0xcd, 0xb9,
1248 0xad, 0x76, 0x9f, 0x6e, 0x91, 0x55, 0x71, 0xda,
1249 0x97, 0x96, 0x96, 0x22, 0x75, 0xb4, 0x83, 0x44,
1250 0x89, 0x9e, 0xf8, 0x44, 0x40, 0x7c, 0xd6, 0xcd,
1251 0x9d, 0x88, 0xd6, 0x88, 0xbc, 0x56, 0xb7, 0x64,
1252 0xe9, 0x2c, 0x24, 0x2f, 0x0d, 0x78, 0x55, 0x1c,
1253 0xb2, 0x67, 0xb1, 0x5e, 0xbc, 0x0c, 0xcf, 0x1c,
1254 0xe9, 0xd3, 0x9e, 0xa2, 0x15, 0x24, 0x73, 0xd6,
1255 0xdb, 0x6f, 0x83, 0xb2, 0xf8, 0xbc, 0xe7, 0x47,
1256 0x3b, 0x01, 0xef, 0x49, 0x08, 0x98, 0xd6, 0xa3,
1257 0xf9, 0x25, 0x57, 0xe9, 0x39, 0x3c, 0x53, 0x30,
1258 0x1b, 0xf2, 0xc9, 0x62, 0x31, 0x43, 0x5d, 0x84,
1259 0x24, 0x30, 0x21, 0x9a, 0xad, 0xdb, 0x62, 0x91,
1260 0xc8, 0x07, 0xd9, 0x2f, 0xd6, 0xb5, 0x37, 0x6f,
1261 0xfe, 0x7a, 0x12, 0xbc, 0xd9, 0xd2, 0x2b, 0xbf,
1262 0xd7, 0xb1, 0xfa, 0x7d, 0xc0, 0x48, 0xdd, 0x74,
1263 0xdd, 0x55, 0x04, 0xa1, 0x8b, 0xc1, 0x0a, 0xc4,
1264 0xa5, 0x57, 0x62, 0xee, 0x08, 0x8b, 0xf9, 0x19,
1265 0x6c, 0x52, 0x06, 0xf8, 0x73, 0x0f, 0x24, 0xc9,
1266 0x71, 0x9f, 0xc5, 0x45, 0x17, 0x3e, 0xae, 0x06,
1267 0x81, 0xa2, 0x96, 0x40, 0x06, 0xbf, 0xeb, 0x9e,
1268 0x80, 0x2b, 0x27, 0x20, 0x8f, 0x38, 0xcf, 0xeb,
1269 0xff, 0x3b, 0x38, 0x41, 0x35, 0x69, 0x66, 0x13,
1270 0x1d, 0x3c, 0x01, 0x3b, 0xf6, 0x37, 0xca, 0x9c,
1271 0x61, 0x74, 0x98, 0xcf, 0xc9, 0x6e, 0xe8, 0x90,
1272 0xc7, 0xb7, 0x33, 0xc0, 0x07, 0x3c, 0xf8, 0xc8,
1273 0xf6, 0xf2, 0xd7, 0xf0, 0x21, 0x62, 0x58, 0x8a,
1274 0x55, 0xbf, 0xa1, 0x2d, 0x3d, 0xa6, 0x69, 0xc5,
1275 0x02, 0x19, 0x31, 0xf0, 0x94, 0x0f, 0x45, 0x5c,
1276 0x95, 0x1b, 0x53, 0xbc, 0xf5, 0xb0, 0x1a, 0x8f,
1277 0xbf, 0x40, 0xe0, 0xc7, 0x73, 0xe7, 0x72, 0x6e,
1278 0xeb, 0xb1, 0x0f, 0x38, 0xc5, 0xf8, 0xee, 0x04,
1279 0xed, 0x34, 0x1a, 0x10, 0xf9, 0x53, 0x34, 0xf3,
1280 0x3e, 0xe6, 0x5c, 0xd1, 0x47, 0x65, 0xcd, 0xbd,
1281 0xf1, 0x06, 0xcb, 0xb4, 0xb1, 0x26, 0x39, 0x9f,
1282 0x71, 0xfe, 0x3d, 0xf8, 0x62, 0xab, 0x22, 0x8b,
1283 0x0e, 0xdc, 0xb9, 0xe8, 0x74, 0x06, 0xfc, 0x8c,
1284 0x25, 0xa1, 0xa9, 0xcf, 0x07, 0xf9, 0xac, 0x21,
1285 0x01, 0x7b, 0x1c, 0xdc, 0x94, 0xbd, 0x47, 0xe1,
1286 0xa0, 0x86, 0x59, 0x35, 0x6a, 0x6f, 0xb9, 0x70,
1287 0x26, 0x7c, 0x3c, 0xfd, 0xbd, 0x81, 0x39, 0x36,
1288 0x42, 0xc2, 0xbd, 0xbe, 0x84, 0x27, 0x9a, 0x69,
1289 0x81, 0xda, 0x99, 0x27, 0xc2, 0x4f, 0x62, 0x33,
1290 0xf4, 0x79, 0x30, 0xc5, 0x63, 0x54, 0x71, 0xf1,
1291 0x47, 0x22, 0x25, 0x9b, 0x6c, 0x00, 0x2f, 0x1c,
1292 0xf4, 0x1f, 0x85, 0xbc, 0xf6, 0x67, 0x6a, 0xe3,
1293 0xf6, 0x55, 0x8a, 0xef, 0xd0, 0x0b, 0xd3, 0xa2,
1294 0xc5, 0x51, 0x70, 0x15, 0x0a, 0xf0, 0x98, 0x4c,
1295 0xb7, 0x19, 0x62, 0x0e, 0x2d, 0x2a, 0x4a, 0x7d,
1296 0x7a, 0x0a, 0xc4, 0x17, 0xe3, 0x5d, 0x20, 0x52,
1297 0xa9, 0x98, 0xc3, 0xaa, 0x11, 0xf6, 0xbf, 0x4c,
1298 0x94, 0x99, 0x81, 0x89, 0xf0, 0x7f, 0x66, 0xaa,
1299 0xc8, 0x88, 0xd7, 0x31, 0x84, 0x71, 0xb6, 0x64,
1300 0x09, 0x76, 0x0b, 0x7f, 0x1a, 0x1f, 0x2e, 0xfe,
1301 0xcd, 0x59, 0x2a, 0x54, 0x11, 0x84, 0xd4, 0x6a,
1302 0x61, 0xdf, 0xaa, 0x76, 0x66, 0x9d, 0x82, 0x11,
1303 0x56, 0x3d, 0xd2, 0x52, 0xe6, 0x42, 0x5a, 0x77,
1304 0x92, 0x98, 0x34, 0xf3, 0x56, 0x6c, 0x96, 0x10,
1305 0x40, 0x59, 0x16, 0xcb, 0x77, 0x61, 0xe3, 0xbf,
1306 0x4b, 0xd4, 0x39, 0xfb, 0xb1, 0x4e, 0xc1, 0x74,
1307 0xec, 0x7a, 0xea, 0x3d, 0x68, 0xbb, 0x0b, 0xe6,
1308 0xc6, 0x06, 0xbf, 0xdd, 0x7f, 0x94, 0x42, 0xc0,
1309 0x0f, 0xe4, 0x92, 0x33, 0x6c, 0x6e, 0x1b, 0xba,
1310 0x73, 0xf9, 0x79, 0x84, 0xdf, 0x45, 0x00, 0xe4,
1311 0x94, 0x88, 0x9d, 0x08, 0x89, 0xcf, 0xf2, 0xa4,
1312 0xc5, 0x47, 0x45, 0x85, 0x86, 0xa5, 0xcc, 0xa8,
1313 0xf2, 0x5d, 0x58, 0x07
1316 static void test_import_private(void)
1318 DWORD dwLen, dwVal;
1319 HCRYPTKEY hKeyExchangeKey, hSessionKey;
1320 BOOL result;
1321 static BYTE abSessionKey[148] = {
1322 0x01, 0x02, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00,
1323 0x00, 0xa4, 0x00, 0x00, 0xb8, 0xa4, 0xdf, 0x5e,
1324 0x9e, 0xb1, 0xbf, 0x85, 0x3d, 0x24, 0x2d, 0x1e,
1325 0x69, 0xb7, 0x67, 0x13, 0x8e, 0x78, 0xf2, 0xdf,
1326 0xc6, 0x69, 0xce, 0x46, 0x7e, 0xf2, 0xf2, 0x33,
1327 0x20, 0x6f, 0xa1, 0xa5, 0x59, 0x83, 0x25, 0xcb,
1328 0x3a, 0xb1, 0x8a, 0x12, 0x63, 0x02, 0x3c, 0xfb,
1329 0x4a, 0xfa, 0xef, 0x8e, 0xf7, 0x29, 0x57, 0xb1,
1330 0x9e, 0xa7, 0xf3, 0x02, 0xfd, 0xca, 0xdf, 0x5a,
1331 0x1f, 0x71, 0xb6, 0x26, 0x09, 0x24, 0x39, 0xda,
1332 0xc0, 0xde, 0x2a, 0x0e, 0xcd, 0x1f, 0xe5, 0xb6,
1333 0x4f, 0x82, 0xa0, 0xa9, 0x90, 0xd3, 0xd9, 0x6a,
1334 0x43, 0x14, 0x2a, 0xf7, 0xac, 0xd5, 0xa0, 0x54,
1335 0x93, 0xc4, 0xb9, 0xe7, 0x24, 0x84, 0x4d, 0x69,
1336 0x5e, 0xcc, 0x2a, 0x32, 0xb5, 0xfb, 0xe4, 0xb4,
1337 0x08, 0xd5, 0x36, 0x58, 0x59, 0x40, 0xfb, 0x29,
1338 0x7f, 0xa7, 0x17, 0x25, 0xc4, 0x0d, 0x78, 0x37,
1339 0x04, 0x8c, 0x49, 0x92
1341 static BYTE abEncryptedMessage[12] = {
1342 0x40, 0x64, 0x28, 0xe8, 0x8a, 0xe7, 0xa4, 0xd4,
1343 0x1c, 0xfd, 0xde, 0x71
1346 dwLen = (DWORD)sizeof(abPlainPrivateKey);
1347 result = CryptImportKey(hProv, abPlainPrivateKey, dwLen, 0, 0, &hKeyExchangeKey);
1348 if (!result) {
1349 /* rsaenh compiled without OpenSSL */
1350 ok(GetLastError() == NTE_FAIL, "%08x\n", GetLastError());
1351 return;
1354 dwLen = (DWORD)sizeof(abSessionKey);
1355 result = CryptImportKey(hProv, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
1356 ok(result, "%08x\n", GetLastError());
1357 if (!result) return;
1359 dwVal = 0xdeadbeef;
1360 dwLen = sizeof(DWORD);
1361 result = CryptGetKeyParam(hSessionKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
1362 ok(result, "%08x\n", GetLastError());
1363 ok(dwVal ==
1364 (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
1365 broken(dwVal == 0xffffffff), /* Win9x/NT4 */
1366 "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
1367 " got %08x\n", dwVal);
1369 dwLen = (DWORD)sizeof(abEncryptedMessage);
1370 result = CryptDecrypt(hSessionKey, 0, TRUE, 0, abEncryptedMessage, &dwLen);
1371 ok(result && dwLen == 12 && !memcmp(abEncryptedMessage, "Wine rocks!",12),
1372 "%08x, len: %d\n", GetLastError(), dwLen);
1373 CryptDestroyKey(hSessionKey);
1375 if (!derive_key(CALG_RC4, &hSessionKey, 56)) return;
1377 dwLen = (DWORD)sizeof(abSessionKey);
1378 result = CryptExportKey(hSessionKey, hKeyExchangeKey, SIMPLEBLOB, 0, abSessionKey, &dwLen);
1379 ok(result, "%08x\n", GetLastError());
1380 CryptDestroyKey(hSessionKey);
1381 if (!result) return;
1383 dwLen = (DWORD)sizeof(abSessionKey);
1384 result = CryptImportKey(hProv, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
1385 ok(result, "%08x\n", GetLastError());
1386 if (!result) return;
1388 CryptDestroyKey(hSessionKey);
1389 CryptDestroyKey(hKeyExchangeKey);
1392 static void test_verify_signature(void) {
1393 HCRYPTHASH hHash;
1394 HCRYPTKEY hPubSignKey;
1395 BYTE abData[] = "Wine rocks!";
1396 BOOL result;
1397 BYTE abPubKey[148] = {
1398 0x06, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
1399 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00,
1400 0x01, 0x00, 0x01, 0x00, 0x71, 0x64, 0x9f, 0x19,
1401 0x89, 0x1c, 0x21, 0xcc, 0x36, 0xa3, 0xc9, 0x27,
1402 0x08, 0x8a, 0x09, 0xc6, 0xbe, 0xeb, 0xd3, 0xf8,
1403 0x19, 0xa9, 0x92, 0x57, 0xe4, 0xb9, 0x5d, 0xda,
1404 0x88, 0x93, 0xe4, 0x6b, 0x38, 0x77, 0x14, 0x8a,
1405 0x96, 0xc0, 0xb6, 0x4e, 0x42, 0xf5, 0x01, 0xdc,
1406 0xf0, 0xeb, 0x3c, 0xc7, 0x7b, 0xc4, 0xfd, 0x7c,
1407 0xde, 0x93, 0x34, 0x0a, 0x92, 0xe5, 0x97, 0x9c,
1408 0x3e, 0x65, 0xb8, 0x91, 0x2f, 0xe3, 0xf3, 0x89,
1409 0xcd, 0x6c, 0x26, 0xa4, 0x6c, 0xc7, 0x6d, 0x0b,
1410 0x2c, 0xa2, 0x0b, 0x29, 0xe2, 0xfc, 0x30, 0xfa,
1411 0x20, 0xdb, 0x4c, 0xb8, 0x91, 0xb8, 0x69, 0x63,
1412 0x96, 0x41, 0xc2, 0xb4, 0x60, 0xeb, 0xcd, 0xff,
1413 0x3a, 0x1f, 0x94, 0xb1, 0x23, 0xcf, 0x0f, 0x49,
1414 0xad, 0xd5, 0x33, 0x85, 0x71, 0xaf, 0x12, 0x87,
1415 0x84, 0xef, 0xa0, 0xea, 0xe1, 0xc1, 0xd4, 0xc7,
1416 0xe1, 0x21, 0x50, 0xac
1418 /* md2 with hash oid */
1419 BYTE abSignatureMD2[128] = {
1420 0x4a, 0x4e, 0xb7, 0x5e, 0x32, 0xda, 0xdb, 0x67,
1421 0x9f, 0x77, 0x84, 0x32, 0x00, 0xba, 0x5f, 0x6b,
1422 0x0d, 0xcf, 0xd9, 0x99, 0xbd, 0x96, 0x31, 0xda,
1423 0x23, 0x4c, 0xd9, 0x4a, 0x90, 0x84, 0x20, 0x59,
1424 0x51, 0xdc, 0xd4, 0x93, 0x3a, 0xae, 0x0a, 0x0a,
1425 0xa1, 0x76, 0xfa, 0xb5, 0x68, 0xee, 0xc7, 0x34,
1426 0x41, 0xd3, 0xe7, 0x5a, 0x0e, 0x22, 0x61, 0x40,
1427 0xea, 0x24, 0x56, 0xf1, 0x91, 0x5a, 0xf7, 0xa7,
1428 0x5b, 0xf4, 0x98, 0x6b, 0xc3, 0xef, 0xad, 0xc0,
1429 0x5e, 0x6b, 0x87, 0x76, 0xcb, 0x1f, 0x62, 0x06,
1430 0x7c, 0xf6, 0x48, 0x97, 0x81, 0x8d, 0xef, 0x51,
1431 0x51, 0xdc, 0x21, 0x91, 0x57, 0x1e, 0x79, 0x6f,
1432 0x49, 0xb5, 0xde, 0x31, 0x07, 0x45, 0x99, 0x46,
1433 0xc3, 0x4f, 0xca, 0x2d, 0x0e, 0x4c, 0x10, 0x25,
1434 0xcb, 0x1a, 0x98, 0x63, 0x41, 0x93, 0x47, 0xc0,
1435 0xb2, 0xbc, 0x10, 0x3c, 0xe7, 0xd4, 0x3c, 0x1e
1437 /* md2 without hash oid */
1438 BYTE abSignatureMD2NoOID[128] = {
1439 0x0c, 0x21, 0x3e, 0x60, 0xf9, 0xd0, 0x36, 0x2d,
1440 0xe1, 0x10, 0x45, 0x45, 0x85, 0x03, 0x29, 0x19,
1441 0xef, 0x19, 0xd9, 0xa6, 0x7e, 0x9c, 0x0d, 0xbd,
1442 0x03, 0x0e, 0xb9, 0x51, 0x9e, 0x74, 0x79, 0xc4,
1443 0xde, 0x25, 0xf2, 0x35, 0x74, 0x55, 0xbc, 0x65,
1444 0x7e, 0x33, 0x28, 0xa8, 0x1e, 0x72, 0xaa, 0x99,
1445 0xdd, 0xf5, 0x26, 0x20, 0x29, 0xf8, 0xa6, 0xdf,
1446 0x28, 0x4b, 0x1c, 0xdb, 0xa1, 0x41, 0x56, 0xbc,
1447 0xf9, 0x9c, 0x66, 0xc0, 0x37, 0x41, 0x55, 0xa0,
1448 0xe2, 0xec, 0xbf, 0x71, 0xf0, 0x5d, 0x25, 0x01,
1449 0x75, 0x91, 0xe2, 0x81, 0xb2, 0x9f, 0x57, 0xa7,
1450 0x5c, 0xd2, 0xfa, 0x66, 0xdb, 0x71, 0x2b, 0x1f,
1451 0xad, 0x30, 0xde, 0xea, 0x49, 0x73, 0x30, 0x6a,
1452 0x22, 0x54, 0x49, 0x4e, 0xae, 0xf6, 0x88, 0xc9,
1453 0xff, 0x71, 0xba, 0xbf, 0x27, 0xc5, 0xfa, 0x06,
1454 0xe2, 0x91, 0x71, 0x8a, 0x7e, 0x0c, 0xc2, 0x07
1456 /* md4 with hash oid */
1457 BYTE abSignatureMD4[128] = {
1458 0x1c, 0x78, 0xaa, 0xea, 0x74, 0xf4, 0x83, 0x51,
1459 0xae, 0x66, 0xe3, 0xa9, 0x1c, 0x03, 0x39, 0x1b,
1460 0xac, 0x7e, 0x4e, 0x85, 0x7e, 0x1c, 0x38, 0xd2,
1461 0x82, 0x43, 0xb3, 0x6f, 0x6f, 0x46, 0x45, 0x8e,
1462 0x17, 0x74, 0x58, 0x29, 0xca, 0xe1, 0x03, 0x13,
1463 0x45, 0x79, 0x34, 0xdf, 0x5c, 0xd6, 0xc3, 0xf9,
1464 0x7a, 0x1c, 0x9d, 0xff, 0x6f, 0x03, 0x7d, 0x0f,
1465 0x59, 0x1a, 0x2d, 0x0e, 0x94, 0xb4, 0x75, 0x96,
1466 0xd1, 0x48, 0x63, 0x6e, 0xb2, 0xc4, 0x5c, 0xd9,
1467 0xab, 0x49, 0xb4, 0x90, 0xd9, 0x57, 0x04, 0x6e,
1468 0x4c, 0xb6, 0xea, 0x00, 0x94, 0x4a, 0x34, 0xa0,
1469 0xd9, 0x63, 0xef, 0x2c, 0xde, 0x5b, 0xb9, 0xbe,
1470 0x35, 0xc8, 0xc1, 0x31, 0xb5, 0x31, 0x15, 0x18,
1471 0x90, 0x39, 0xf5, 0x2a, 0x34, 0x6d, 0xb4, 0xab,
1472 0x09, 0x34, 0x69, 0x54, 0x4d, 0x11, 0x2f, 0xf3,
1473 0xa2, 0x36, 0x0e, 0xa8, 0x45, 0xe7, 0x36, 0xac
1475 /* md4 without hash oid */
1476 BYTE abSignatureMD4NoOID[128] = {
1477 0xd3, 0x60, 0xb2, 0xb0, 0x22, 0x0a, 0x99, 0xda,
1478 0x04, 0x85, 0x64, 0xc6, 0xc6, 0xdb, 0x11, 0x24,
1479 0xe9, 0x68, 0x2d, 0xf7, 0x09, 0xef, 0xb6, 0xa0,
1480 0xa2, 0xfe, 0x45, 0xee, 0x85, 0x49, 0xcd, 0x36,
1481 0xf7, 0xc7, 0x9d, 0x2b, 0x4c, 0x68, 0xda, 0x85,
1482 0x8c, 0x50, 0xcc, 0x4f, 0x4b, 0xe1, 0x82, 0xc3,
1483 0xbe, 0xa3, 0xf1, 0x78, 0x6b, 0x60, 0x42, 0x3f,
1484 0x67, 0x22, 0x14, 0xe4, 0xe1, 0xa4, 0x6e, 0xa9,
1485 0x4e, 0xf1, 0xd4, 0xb0, 0xce, 0x82, 0xac, 0x06,
1486 0xba, 0x2c, 0xbc, 0xf7, 0xcb, 0xf6, 0x0c, 0x3f,
1487 0xf6, 0x79, 0xfe, 0xb3, 0xd8, 0x5a, 0xbc, 0xdb,
1488 0x05, 0x41, 0xa4, 0x07, 0x57, 0x9e, 0xa2, 0x96,
1489 0xfc, 0x60, 0x4b, 0xf7, 0x6f, 0x86, 0x26, 0x1f,
1490 0xc2, 0x2c, 0x67, 0x08, 0xcd, 0x7f, 0x91, 0xe9,
1491 0x16, 0xb5, 0x0e, 0xd9, 0xc4, 0xc4, 0x97, 0xeb,
1492 0x91, 0x3f, 0x20, 0x6c, 0xf0, 0x68, 0x86, 0x7f
1494 /* md5 with hash oid */
1495 BYTE abSignatureMD5[128] = {
1496 0x4f, 0xe0, 0x8c, 0x9b, 0x43, 0xdd, 0x02, 0xe5,
1497 0xf4, 0xa1, 0xdd, 0x88, 0x4c, 0x9c, 0x40, 0x0f,
1498 0x6c, 0x43, 0x86, 0x64, 0x00, 0xe6, 0xac, 0xf7,
1499 0xd0, 0x92, 0xaa, 0xc4, 0x62, 0x9a, 0x48, 0x98,
1500 0x1a, 0x56, 0x6d, 0x75, 0xec, 0x04, 0x89, 0xec,
1501 0x69, 0x93, 0xd6, 0x61, 0x37, 0xb2, 0x36, 0xb5,
1502 0xb2, 0xba, 0xf2, 0xf5, 0x21, 0x0c, 0xf1, 0x04,
1503 0xc8, 0x2d, 0xf5, 0xa0, 0x8d, 0x6d, 0x10, 0x0b,
1504 0x68, 0x63, 0xf2, 0x08, 0x68, 0xdc, 0xbd, 0x95,
1505 0x25, 0x7d, 0xee, 0x63, 0x5c, 0x3b, 0x98, 0x4c,
1506 0xea, 0x41, 0xdc, 0x6a, 0x8b, 0x6c, 0xbb, 0x29,
1507 0x2b, 0x1c, 0x5c, 0x8b, 0x7d, 0x94, 0x24, 0xa9,
1508 0x7a, 0x62, 0x94, 0xf3, 0x3a, 0x6a, 0xb2, 0x4c,
1509 0x33, 0x59, 0x00, 0xcd, 0x7d, 0x37, 0x79, 0x90,
1510 0x31, 0xd1, 0xd9, 0x84, 0x12, 0xe5, 0x08, 0x5e,
1511 0xb3, 0x60, 0x61, 0x27, 0x78, 0x37, 0x63, 0x01
1513 /* md5 without hash oid */
1514 BYTE abSignatureMD5NoOID[128] = {
1515 0xc6, 0xad, 0x5c, 0x2b, 0x9b, 0xe0, 0x99, 0x2f,
1516 0x5e, 0x55, 0x04, 0x32, 0x65, 0xe0, 0xb5, 0x75,
1517 0x01, 0x9a, 0x11, 0x4d, 0x0e, 0x9a, 0xe1, 0x9f,
1518 0xc7, 0xbf, 0x77, 0x6d, 0xa9, 0xfd, 0xcc, 0x9d,
1519 0x8b, 0xd1, 0x31, 0xed, 0x5a, 0xd2, 0xe5, 0x5f,
1520 0x42, 0x3b, 0xb5, 0x3c, 0x32, 0x30, 0x88, 0x49,
1521 0xcb, 0x67, 0xb8, 0x2e, 0xc9, 0xf5, 0x2b, 0xc8,
1522 0x35, 0x71, 0xb5, 0x1b, 0x32, 0x3f, 0x44, 0x4c,
1523 0x66, 0x93, 0xcb, 0xe8, 0x48, 0x7c, 0x14, 0x23,
1524 0xfb, 0x12, 0xa5, 0xb7, 0x86, 0x94, 0x6b, 0x19,
1525 0x17, 0x20, 0xc6, 0xb8, 0x09, 0xe8, 0xbb, 0xdb,
1526 0x00, 0x2b, 0x96, 0x4a, 0x93, 0x00, 0x26, 0xd3,
1527 0x07, 0xa0, 0x06, 0xce, 0x5a, 0x13, 0x69, 0x6b,
1528 0x62, 0x5a, 0x56, 0x61, 0x6a, 0xd8, 0x11, 0x3b,
1529 0xd5, 0x67, 0xc7, 0x4d, 0xf6, 0x66, 0x63, 0xc5,
1530 0xe3, 0x8f, 0x7c, 0x7c, 0xb1, 0x3e, 0x55, 0x43
1532 /* sha with hash oid */
1533 BYTE abSignatureSHA[128] = {
1534 0x5a, 0x4c, 0x66, 0xc9, 0x30, 0x67, 0xcb, 0x91,
1535 0x3c, 0x4d, 0xd5, 0x8d, 0xea, 0x4e, 0x85, 0xcd,
1536 0xd9, 0x68, 0x3a, 0xf3, 0x24, 0x3c, 0x99, 0x24,
1537 0x25, 0x32, 0x93, 0x3d, 0xd6, 0x2f, 0x86, 0x94,
1538 0x23, 0x09, 0xee, 0x02, 0xd4, 0x15, 0xdc, 0x5f,
1539 0x0e, 0x44, 0x45, 0x13, 0x5f, 0x18, 0x5d, 0x1a,
1540 0xd7, 0x0b, 0xd1, 0x23, 0xd6, 0x35, 0x98, 0x52,
1541 0x57, 0x45, 0x74, 0x92, 0xe3, 0x50, 0xb4, 0x20,
1542 0x28, 0x2a, 0x11, 0xbf, 0x49, 0xb4, 0x2c, 0xc5,
1543 0xd4, 0x1a, 0x27, 0x4e, 0xdf, 0xa0, 0xb5, 0x7a,
1544 0xc8, 0x14, 0xdd, 0x9b, 0xb6, 0xca, 0xd6, 0xff,
1545 0xb2, 0x6b, 0xd8, 0x98, 0x67, 0x80, 0xab, 0x53,
1546 0x52, 0xbb, 0xe1, 0x2a, 0xce, 0x79, 0x2f, 0x00,
1547 0x53, 0x26, 0xd8, 0xa7, 0x43, 0xca, 0x72, 0x0e,
1548 0x68, 0x97, 0x37, 0x71, 0x87, 0xc2, 0x6a, 0x98,
1549 0xbb, 0x6c, 0xa0, 0x01, 0xff, 0x04, 0x9d, 0xa6
1551 /* sha without hash oid */
1552 BYTE abSignatureSHANoOID[128] = {
1553 0x86, 0xa6, 0x2b, 0x9a, 0x04, 0xda, 0x47, 0xc6,
1554 0x4f, 0x97, 0x8a, 0x8a, 0xf4, 0xfa, 0x63, 0x1a,
1555 0x32, 0x89, 0x56, 0x41, 0x37, 0x91, 0x15, 0x2f,
1556 0x2d, 0x1c, 0x8f, 0xdc, 0x88, 0x40, 0xbb, 0x37,
1557 0x3e, 0x06, 0x33, 0x1b, 0xde, 0xda, 0x7c, 0x65,
1558 0x91, 0x35, 0xca, 0x45, 0x17, 0x0e, 0x24, 0xbe,
1559 0x9e, 0xf6, 0x4e, 0x8a, 0xa4, 0x3e, 0xca, 0xe6,
1560 0x11, 0x36, 0xb8, 0x3a, 0xf0, 0xde, 0x71, 0xfe,
1561 0xdd, 0xb3, 0xcb, 0x6c, 0x39, 0xe0, 0x5f, 0x0c,
1562 0x9e, 0xa8, 0x40, 0x26, 0x9c, 0x81, 0xe9, 0xc4,
1563 0x15, 0x90, 0xbf, 0x4f, 0xd2, 0xc1, 0xa1, 0x80,
1564 0x52, 0xfd, 0xf6, 0x3d, 0x99, 0x1b, 0x9c, 0x8a,
1565 0x27, 0x1b, 0x0c, 0x9a, 0xf3, 0xf9, 0xa2, 0x00,
1566 0x3e, 0x5b, 0xdf, 0xc2, 0xb4, 0x71, 0xa5, 0xbd,
1567 0xf8, 0xae, 0x63, 0xbb, 0x4a, 0xc9, 0xdd, 0x67,
1568 0xc1, 0x3e, 0x93, 0xee, 0xf1, 0x1f, 0x24, 0x5b
1571 result = CryptImportKey(hProv, abPubKey, 148, 0, 0, &hPubSignKey);
1572 ok(result, "%08x\n", GetLastError());
1573 if (!result) return;
1575 result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
1576 ok(result, "%08x\n", GetLastError());
1577 if (!result) return;
1579 result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
1580 ok(result, "%08x\n", GetLastError());
1581 if (!result) return;
1583 /*check that a NULL pointer signature is correctly handled*/
1584 result = CryptVerifySignature(hHash, NULL, 128, hPubSignKey, NULL, 0);
1585 ok(!result && ERROR_INVALID_PARAMETER == GetLastError(),
1586 "Expected ERROR_INVALID_PARAMETER error, got %08x\n", GetLastError());
1587 if (result) return;
1589 /* check that we get a bad signature error when the signature is too short*/
1590 SetLastError(0xdeadbeef);
1591 result = CryptVerifySignature(hHash, abSignatureMD2, 64, hPubSignKey, NULL, 0);
1592 ok((!result && NTE_BAD_SIGNATURE == GetLastError()) ||
1593 broken(result), /* Win9x, WinMe, NT4 */
1594 "Expected NTE_BAD_SIGNATURE, got %08x\n", GetLastError());
1596 result = CryptVerifySignature(hHash, abSignatureMD2, 128, hPubSignKey, NULL, 0);
1597 ok(result, "%08x\n", GetLastError());
1598 if (!result) return;
1600 result = CryptVerifySignature(hHash, abSignatureMD2NoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
1601 ok(result, "%08x\n", GetLastError());
1602 if (!result) return;
1604 /* Next test fails on WinXP SP2. It seems that CPVerifySignature doesn't care about
1605 * the OID at all. */
1606 /*result = CryptVerifySignature(hHash, abSignatureMD2NoOID, 128, hPubSignKey, NULL, 0);
1607 ok(!result && GetLastError()==NTE_BAD_SIGNATURE, "%08lx\n", GetLastError());
1608 if (result) return;*/
1610 CryptDestroyHash(hHash);
1612 result = CryptCreateHash(hProv, CALG_MD4, 0, 0, &hHash);
1613 ok(result, "%08x\n", GetLastError());
1614 if (!result) return;
1616 result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
1617 ok(result, "%08x\n", GetLastError());
1618 if (!result) return;
1620 result = CryptVerifySignature(hHash, abSignatureMD4, 128, hPubSignKey, NULL, 0);
1621 ok(result, "%08x\n", GetLastError());
1622 if (!result) return;
1624 result = CryptVerifySignature(hHash, abSignatureMD4NoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
1625 ok(result, "%08x\n", GetLastError());
1626 if (!result) return;
1628 CryptDestroyHash(hHash);
1630 result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
1631 ok(result, "%08x\n", GetLastError());
1632 if (!result) return;
1634 result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
1635 ok(result, "%08x\n", GetLastError());
1636 if (!result) return;
1638 result = CryptVerifySignature(hHash, abSignatureMD5, 128, hPubSignKey, NULL, 0);
1639 ok(result, "%08x\n", GetLastError());
1640 if (!result) return;
1642 result = CryptVerifySignature(hHash, abSignatureMD5NoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
1643 ok(result, "%08x\n", GetLastError());
1644 if (!result) return;
1646 CryptDestroyHash(hHash);
1648 result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
1649 ok(result, "%08x\n", GetLastError());
1650 if (!result) return;
1652 result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
1653 ok(result, "%08x\n", GetLastError());
1654 if (!result) return;
1656 result = CryptVerifySignature(hHash, abSignatureSHA, 128, hPubSignKey, NULL, 0);
1657 ok(result, "%08x\n", GetLastError());
1658 if (!result) return;
1660 result = CryptVerifySignature(hHash, abSignatureSHANoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
1661 ok(result, "%08x\n", GetLastError());
1662 if (!result) return;
1664 CryptDestroyHash(hHash);
1665 CryptDestroyKey(hPubSignKey);
1668 static void test_rsa_encrypt(void)
1670 HCRYPTKEY hRSAKey;
1671 BYTE abData[2048] = "Wine rocks!";
1672 BOOL result;
1673 DWORD dwVal, dwLen;
1675 /* It is allowed to use the key exchange key for encryption/decryption */
1676 result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hRSAKey);
1677 ok (result, "%08x\n", GetLastError());
1678 if (!result) return;
1680 dwLen = 12;
1681 result = CryptEncrypt(hRSAKey, 0, TRUE, 0, NULL, &dwLen, (DWORD)sizeof(abData));
1682 ok(result, "CryptEncrypt failed: %08x\n", GetLastError());
1683 ok(dwLen == 128, "Unexpected length %d\n", dwLen);
1684 dwLen = 12;
1685 result = CryptEncrypt(hRSAKey, 0, TRUE, 0, abData, &dwLen, (DWORD)sizeof(abData));
1686 ok (result, "%08x\n", GetLastError());
1687 if (!result) return;
1689 result = CryptDecrypt(hRSAKey, 0, TRUE, 0, abData, &dwLen);
1690 ok (result && dwLen == 12 && !memcmp(abData, "Wine rocks!", 12), "%08x\n", GetLastError());
1692 dwVal = 0xdeadbeef;
1693 dwLen = sizeof(DWORD);
1694 result = CryptGetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
1695 ok(result, "%08x\n", GetLastError());
1696 ok(dwVal ==
1697 (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
1698 broken(dwVal == 0xffffffff), /* Win9x/NT4 */
1699 "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
1700 " got %08x\n", dwVal);
1702 /* The key exchange key's public key may be exported.. */
1703 result = CryptExportKey(hRSAKey, 0, PUBLICKEYBLOB, 0, NULL, &dwLen);
1704 ok(result, "%08x\n", GetLastError());
1705 /* but its private key may not be. */
1706 SetLastError(0xdeadbeef);
1707 result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
1708 ok((!result && GetLastError() == NTE_BAD_KEY_STATE) ||
1709 broken(result), /* Win9x/NT4 */
1710 "expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
1711 /* Setting the permissions of the key exchange key isn't allowed, either. */
1712 dwVal |= CRYPT_EXPORT;
1713 SetLastError(0xdeadbeef);
1714 result = CryptSetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE *)&dwVal, 0);
1715 ok(!result &&
1716 (GetLastError() == NTE_BAD_DATA || GetLastError() == NTE_BAD_FLAGS),
1717 "expected NTE_BAD_DATA or NTE_BAD_FLAGS, got %08x\n", GetLastError());
1719 CryptDestroyKey(hRSAKey);
1721 /* It is not allowed to use the signature key for encryption/decryption */
1722 result = CryptGetUserKey(hProv, AT_SIGNATURE, &hRSAKey);
1723 ok (result, "%08x\n", GetLastError());
1724 if (!result) return;
1726 dwVal = 0xdeadbeef;
1727 dwLen = sizeof(DWORD);
1728 result = CryptGetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
1729 ok(result, "%08x\n", GetLastError());
1730 ok(dwVal ==
1731 (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
1732 broken(dwVal == 0xffffffff), /* Win9x/NT4 */
1733 "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
1734 " got %08x\n", dwVal);
1736 /* The signature key's public key may also be exported.. */
1737 result = CryptExportKey(hRSAKey, 0, PUBLICKEYBLOB, 0, NULL, &dwLen);
1738 ok(result, "%08x\n", GetLastError());
1739 /* but its private key may not be. */
1740 SetLastError(0xdeadbeef);
1741 result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
1742 ok((!result && GetLastError() == NTE_BAD_KEY_STATE) ||
1743 broken(result), /* Win9x/NT4 */
1744 "expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
1745 /* Setting the permissions of the signature key isn't allowed, either. */
1746 dwVal |= CRYPT_EXPORT;
1747 SetLastError(0xdeadbeef);
1748 result = CryptSetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE *)&dwVal, 0);
1749 ok(!result &&
1750 (GetLastError() == NTE_BAD_DATA || GetLastError() == NTE_BAD_FLAGS),
1751 "expected NTE_BAD_DATA or NTE_BAD_FLAGS, got %08x\n", GetLastError());
1753 dwLen = 12;
1754 result = CryptEncrypt(hRSAKey, 0, TRUE, 0, abData, &dwLen, (DWORD)sizeof(abData));
1755 ok (!result && GetLastError() == NTE_BAD_KEY, "%08x\n", GetLastError());
1757 CryptDestroyKey(hRSAKey);
1760 static void test_import_export(void)
1762 DWORD dwLen, dwDataLen, dwVal;
1763 HCRYPTKEY hPublicKey, hPrivKey;
1764 BOOL result;
1765 ALG_ID algID;
1766 BYTE emptyKey[2048], *exported_key;
1767 static BYTE abPlainPublicKey[84] = {
1768 0x06, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
1769 0x52, 0x53, 0x41, 0x31, 0x00, 0x02, 0x00, 0x00,
1770 0x01, 0x00, 0x01, 0x00, 0x11, 0x11, 0x11, 0x11,
1771 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1772 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1773 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1774 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1775 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1776 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1777 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1778 0x11, 0x11, 0x11, 0x11
1780 static BYTE priv_key_with_high_bit[] = {
1781 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
1782 0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
1783 0x01, 0x00, 0x01, 0x00, 0xd5, 0xa2, 0x0d, 0x66,
1784 0xfe, 0x65, 0xb5, 0xf1, 0xc9, 0x6b, 0xf5, 0x58,
1785 0x04, 0x38, 0x2d, 0xf4, 0xa3, 0x5a, 0xda, 0x9e,
1786 0x95, 0x81, 0x85, 0x3d, 0x01, 0x07, 0xb2, 0x03,
1787 0x77, 0x70, 0x79, 0x6e, 0x6c, 0x26, 0x42, 0xa4,
1788 0x12, 0xfd, 0xaa, 0x29, 0x83, 0x04, 0xce, 0x91,
1789 0x90, 0x39, 0x5e, 0x49, 0x56, 0xfd, 0x0a, 0xe5,
1790 0xb1, 0xea, 0x3b, 0xb2, 0x70, 0xb0, 0x20, 0xc1,
1791 0x1f, 0x22, 0x07, 0x3e, 0x4d, 0xc0, 0x73, 0xfd,
1792 0x92, 0x8f, 0x87, 0xd8, 0xd1, 0xd1, 0x28, 0xd8,
1793 0x19, 0xd1, 0x93, 0x83, 0xe0, 0xb8, 0x9f, 0x53,
1794 0xf4, 0x6a, 0x7c, 0xcb, 0x10, 0x53, 0xd0, 0x37,
1795 0x02, 0xb4, 0xa5, 0xf7, 0xa2, 0x28, 0x6e, 0x26,
1796 0xef, 0x5c, 0x14, 0x01, 0x40, 0x1e, 0xa3, 0xe1,
1797 0xda, 0x76, 0xd0, 0x12, 0x84, 0xb7, 0x48, 0x7d,
1798 0xc8, 0x67, 0x5c, 0xb2, 0xd5, 0x2e, 0xaf, 0x8e,
1799 0x7d, 0x32, 0x59, 0x92, 0x01, 0xd6, 0x5b, 0x68,
1800 0x28, 0x9b, 0xb1, 0x6c, 0x69, 0xeb, 0x61, 0x5b,
1801 0x4b, 0x13, 0xe2, 0xbd, 0x7d, 0xbe, 0xce, 0xe8,
1802 0x41, 0x54, 0xca, 0xa8, 0xdd, 0xc7, 0xfe, 0x8b,
1803 0xdf, 0xf6, 0x55, 0x6c, 0x50, 0x11, 0xc8, 0x15,
1804 0x13, 0x42, 0x59, 0x9f, 0xbb, 0xea, 0x73, 0x78,
1805 0x7b, 0x22, 0x8d, 0x96, 0x62, 0xe5, 0xda, 0xa2,
1806 0x85, 0x5c, 0x20, 0x74, 0x9f, 0x1c, 0x12, 0xf2,
1807 0x48, 0x06, 0x1a, 0xc6, 0xd5, 0x94, 0xec, 0x31,
1808 0x6b, 0xb6, 0x7b, 0x54, 0x61, 0x77, 0xec, 0x7c,
1809 0x6f, 0xb7, 0x55, 0x3d, 0x6b, 0x98, 0x05, 0xd7,
1810 0x8a, 0x73, 0x25, 0xf2, 0x8f, 0xe4, 0xb8, 0x8d,
1811 0x27, 0x18, 0x0d, 0x05, 0xba, 0x23, 0x54, 0x37,
1812 0x10, 0xf0, 0x1c, 0x41, 0xa6, 0xae, 0x4c, 0x2a,
1813 0x6a, 0x2f, 0x7f, 0x68, 0x43, 0x86, 0xe7, 0x9c,
1814 0xfd, 0x9e, 0xf1, 0xfe, 0x84, 0xe3, 0xb6, 0x99,
1815 0x51, 0xfe, 0x1e, 0xbd, 0x01, 0xc6, 0x10, 0xef,
1816 0x88, 0xa4, 0xd8, 0x53, 0x14, 0x88, 0x15, 0xc9,
1817 0xe5, 0x86, 0xe2, 0x8d, 0x85, 0x2e, 0x0d, 0xec,
1818 0x15, 0xa7, 0x48, 0xfa, 0x18, 0xfb, 0x01, 0x8d,
1819 0x2b, 0x90, 0x70, 0x7f, 0x78, 0xb1, 0x33, 0x7e,
1820 0xfe, 0x82, 0x40, 0x5f, 0x4a, 0x97, 0xc2, 0x42,
1821 0x22, 0xd5, 0x5f, 0xbc, 0xbd, 0xab, 0x26, 0x98,
1822 0xcd, 0xb5, 0xdf, 0x7e, 0xa0, 0x68, 0xa7, 0x12,
1823 0x9e, 0xa5, 0xa2, 0x90, 0x85, 0xc5, 0xca, 0x73,
1824 0x4a, 0x59, 0x8a, 0xec, 0xcf, 0xdd, 0x65, 0x5d,
1825 0xc1, 0xaa, 0x86, 0x53, 0xd5, 0xde, 0xbb, 0x23,
1826 0x24, 0xb8, 0x9b, 0x74, 0x03, 0x20, 0xb4, 0xf0,
1827 0xe4, 0xdd, 0xd2, 0x03, 0xfd, 0x67, 0x55, 0x19,
1828 0x28, 0x1d, 0xc1, 0xb8, 0xa5, 0x89, 0x0e, 0xc0,
1829 0x80, 0x9d, 0xdd, 0xda, 0x9d, 0x30, 0x5c, 0xc8,
1830 0xbb, 0xfe, 0x8f, 0xce, 0xd5, 0xf6, 0xdf, 0xfa,
1831 0x14, 0xaf, 0xe4, 0xba, 0xb0, 0x84, 0x45, 0xd8,
1832 0x67, 0xa7, 0xd0, 0xce, 0x89, 0x2a, 0x30, 0x8c,
1833 0xfa, 0xe9, 0x65, 0xa4, 0x21, 0x2d, 0x6b, 0xa2,
1834 0x9b, 0x8f, 0x92, 0xbd, 0x3a, 0x10, 0x71, 0x12,
1835 0xc2, 0x02, 0x3d, 0xd5, 0x83, 0x1d, 0xfa, 0x42,
1836 0xb7, 0x48, 0x1b, 0x31, 0xe3, 0x82, 0x90, 0x2d,
1837 0x91, 0x59, 0xf9, 0x38, 0x52, 0xe5, 0xdb, 0xc1,
1838 0x4d, 0x3a, 0xe6, 0x9b, 0x6a, 0xbb, 0xea, 0xa4,
1839 0x8d, 0x5e, 0xc4, 0x00, 0x01, 0xb8, 0xec, 0x91,
1840 0xc1, 0xdb, 0x63, 0xbd, 0x57, 0xb6, 0x26, 0x15,
1841 0xb6, 0x3e, 0xa2, 0xdf, 0x62, 0x8d, 0xa8, 0xbe,
1842 0xe1, 0xf1, 0x39, 0xbd, 0x18, 0xd2, 0x6f, 0xd7,
1843 0xda, 0xdc, 0x71, 0x30, 0xf1, 0x21, 0x71, 0xa4,
1844 0x08, 0x43, 0x46, 0xdf, 0x50, 0xbd, 0x3c, 0x60,
1845 0x5b, 0x63, 0x35, 0xe3, 0x37, 0x5b, 0x25, 0x17,
1846 0x54, 0x5e, 0x68, 0x60, 0xb6, 0x49, 0xef, 0x6e,
1847 0x09, 0xef, 0xda, 0x90, 0x3e, 0xd4, 0x09, 0x33,
1848 0x36, 0x57, 0x9a, 0x14, 0xbd, 0xf7, 0xb1, 0x98,
1849 0x30, 0x42, 0x03, 0x84, 0x61, 0xeb, 0x8e, 0x50,
1850 0xdc, 0x6a, 0x93, 0x1b, 0x32, 0x51, 0xf9, 0xc6,
1851 0xc2, 0x19, 0xb3, 0x5d, 0xe2, 0xf8, 0xc5, 0x8f,
1852 0x68, 0xaa, 0x1d, 0xdb, 0xd3, 0x7f, 0x8d, 0x98,
1853 0x9c, 0x16, 0x8c, 0xc3, 0xcd, 0xd9, 0xdb, 0x08,
1854 0xe6, 0x36, 0x60, 0xb6, 0x36, 0xdc, 0x1d, 0x59,
1855 0xb6, 0x5f, 0x01, 0x5e
1857 static const BYTE expected_exported_priv_key[] = {
1858 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
1859 0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
1860 0x01, 0x00, 0x01, 0x00, 0xd5, 0xa2, 0x0d, 0x66,
1861 0xfe, 0x65, 0xb5, 0xf1, 0xc9, 0x6b, 0xf5, 0x58,
1862 0x04, 0x38, 0x2d, 0xf4, 0xa3, 0x5a, 0xda, 0x9e,
1863 0x95, 0x81, 0x85, 0x3d, 0x01, 0x07, 0xb2, 0x03,
1864 0x77, 0x70, 0x79, 0x6e, 0x6c, 0x26, 0x42, 0xa4,
1865 0x12, 0xfd, 0xaa, 0x29, 0x83, 0x04, 0xce, 0x91,
1866 0x90, 0x39, 0x5e, 0x49, 0x56, 0xfd, 0x0a, 0xe5,
1867 0xb1, 0xea, 0x3b, 0xb2, 0x70, 0xb0, 0x20, 0xc1,
1868 0x1f, 0x22, 0x07, 0x3e, 0x4d, 0xc0, 0x73, 0xfd,
1869 0x92, 0x8f, 0x87, 0xd8, 0xd1, 0xd1, 0x28, 0xd8,
1870 0x19, 0xd1, 0x93, 0x83, 0xe0, 0xb8, 0x9f, 0x53,
1871 0xf4, 0x6a, 0x7c, 0xcb, 0x10, 0x53, 0xd0, 0x37,
1872 0x02, 0xb4, 0xa5, 0xf7, 0xa2, 0x28, 0x6e, 0x26,
1873 0xef, 0x5c, 0x14, 0x01, 0x40, 0x1e, 0xa3, 0xe1,
1874 0xda, 0x76, 0xd0, 0x12, 0x84, 0xb7, 0x48, 0x7d,
1875 0xc8, 0x67, 0x5c, 0xb2, 0xd5, 0x2e, 0xaf, 0x8e,
1876 0x7d, 0x32, 0x59, 0x92, 0x01, 0xd6, 0x5b, 0x68,
1877 0x28, 0x9b, 0xb1, 0x6c, 0x69, 0xeb, 0x61, 0x5b,
1878 0x4b, 0x13, 0xe2, 0xbd, 0x7d, 0xbe, 0xce, 0xe8,
1879 0x41, 0x54, 0xca, 0xa8, 0xdd, 0xc7, 0xfe, 0x8b,
1880 0xdf, 0xf6, 0x55, 0x6c, 0x50, 0x11, 0xc8, 0x15,
1881 0x13, 0x42, 0x59, 0x9f, 0xbb, 0xea, 0x73, 0x78,
1882 0x7b, 0x22, 0x8d, 0x96, 0x62, 0xe5, 0xda, 0xa2,
1883 0x85, 0x5c, 0x20, 0x74, 0x9f, 0x1c, 0x12, 0xf2,
1884 0x48, 0x06, 0x1a, 0xc6, 0xd5, 0x94, 0xec, 0x31,
1885 0x6b, 0xb6, 0x7b, 0x54, 0x61, 0x77, 0xec, 0x7c,
1886 0x6f, 0xb7, 0x55, 0x3d, 0x6b, 0x98, 0x05, 0xd7,
1887 0x8a, 0x73, 0x25, 0xf2, 0x8f, 0xe4, 0xb8, 0x8d,
1888 0x27, 0x18, 0x0d, 0x05, 0xba, 0x23, 0x54, 0x37,
1889 0x10, 0xf0, 0x1c, 0x41, 0xa6, 0xae, 0x4c, 0x2a,
1890 0x6a, 0x2f, 0x7f, 0x68, 0x43, 0x86, 0xe7, 0x9c,
1891 0xfd, 0x9e, 0xf1, 0xfe, 0x84, 0xe3, 0xb6, 0x99,
1892 0x51, 0xfe, 0x1e, 0xbd, 0x01, 0xc6, 0x10, 0xef,
1893 0x88, 0xa4, 0xd8, 0x53, 0x14, 0x88, 0x15, 0xc9,
1894 0xe5, 0x86, 0xe2, 0x8d, 0x85, 0x2e, 0x0d, 0xec,
1895 0x15, 0xa7, 0x48, 0xfa, 0x18, 0xfb, 0x01, 0x8d,
1896 0x2b, 0x90, 0x70, 0x7f, 0x78, 0xb1, 0x33, 0x7e,
1897 0xfe, 0x82, 0x40, 0x5f, 0x4a, 0x97, 0xc2, 0x42,
1898 0x22, 0xd5, 0x5f, 0xbc, 0xbd, 0xab, 0x26, 0x98,
1899 0xcd, 0xb5, 0xdf, 0x7e, 0xa0, 0x68, 0xa7, 0x12,
1900 0x9e, 0xa5, 0xa2, 0x90, 0x85, 0xc5, 0xca, 0x73,
1901 0x4a, 0x59, 0x8a, 0xec, 0xcf, 0xdd, 0x65, 0x5d,
1902 0xc1, 0xaa, 0x86, 0x53, 0xd5, 0xde, 0xbb, 0x23,
1903 0x24, 0xb8, 0x9b, 0x74, 0x03, 0x20, 0xb4, 0xf0,
1904 0xe4, 0xdd, 0xd2, 0x03, 0xfd, 0x67, 0x55, 0x19,
1905 0x28, 0x1d, 0xc1, 0xb8, 0xa5, 0x89, 0x0e, 0xc0,
1906 0x80, 0x9d, 0xdd, 0xda, 0x9d, 0x30, 0x5c, 0xc8,
1907 0xbb, 0xfe, 0x8f, 0xce, 0xd5, 0xf6, 0xdf, 0xfa,
1908 0x14, 0xaf, 0xe4, 0xba, 0xb0, 0x84, 0x45, 0xd8,
1909 0x67, 0xa7, 0xd0, 0xce, 0x89, 0x2a, 0x30, 0x8c,
1910 0xfa, 0xe9, 0x65, 0xa4, 0x21, 0x2d, 0x6b, 0xa2,
1911 0x9b, 0x8f, 0x92, 0xbd, 0x3a, 0x10, 0x71, 0x12,
1912 0xc2, 0x02, 0x3d, 0xd5, 0x83, 0x1d, 0xfa, 0x42,
1913 0xb7, 0x48, 0x1b, 0x31, 0xe3, 0x82, 0x90, 0x2d,
1914 0x91, 0x59, 0xf9, 0x38, 0x52, 0xe5, 0xdb, 0xc1,
1915 0x4d, 0x3a, 0xe6, 0x9b, 0x6a, 0xbb, 0xea, 0xa4,
1916 0x8d, 0x5e, 0xc4, 0x00, 0x01, 0xb8, 0xec, 0x91,
1917 0xc1, 0xdb, 0x63, 0xbd, 0x57, 0xb6, 0x26, 0x15,
1918 0xb6, 0x3e, 0xa2, 0xdf, 0x62, 0x8d, 0xa8, 0xbe,
1919 0xe1, 0xf1, 0x39, 0xbd, 0x18, 0xd2, 0x6f, 0xd7,
1920 0xda, 0xdc, 0x71, 0x30, 0xf1, 0x21, 0x71, 0xa4,
1921 0x08, 0x43, 0x46, 0xdf, 0x50, 0xbd, 0x3c, 0x60,
1922 0x5b, 0x63, 0x35, 0xe3, 0x37, 0x5b, 0x25, 0x17,
1923 0x54, 0x5e, 0x68, 0x60, 0xb6, 0x49, 0xef, 0x6e,
1924 0x09, 0xef, 0xda, 0x90, 0x3e, 0xd4, 0x09, 0x33,
1925 0x36, 0x57, 0x9a, 0x14, 0xbd, 0xf7, 0xb1, 0x98,
1926 0x30, 0x42, 0x03, 0x84, 0x61, 0xeb, 0x8e, 0x50,
1927 0xdc, 0x6a, 0x93, 0x1b, 0x32, 0x51, 0xf9, 0xc6,
1928 0xc2, 0x19, 0xb3, 0x5d, 0xe2, 0xf8, 0xc5, 0x8f,
1929 0x68, 0xaa, 0x1d, 0xdb, 0xd3, 0x7f, 0x8d, 0x98,
1930 0x9c, 0x16, 0x8c, 0xc3, 0xcd, 0xd9, 0xdb, 0x08,
1931 0xe6, 0x36, 0x60, 0xb6, 0x36, 0xdc, 0x1d, 0x59,
1932 0xb6, 0x5f, 0x01, 0x5e
1935 dwLen=84;
1936 result = CryptImportKey(hProv, abPlainPublicKey, dwLen, 0, 0, &hPublicKey);
1937 ok(result, "failed to import the public key\n");
1939 dwDataLen=sizeof(algID);
1940 result = CryptGetKeyParam(hPublicKey, KP_ALGID, (LPBYTE)&algID, &dwDataLen, 0);
1941 ok(result, "failed to get the KP_ALGID from the imported public key\n");
1942 ok(algID == CALG_RSA_KEYX, "Expected CALG_RSA_KEYX, got %x\n", algID);
1944 dwVal = 0xdeadbeef;
1945 dwDataLen = sizeof(DWORD);
1946 result = CryptGetKeyParam(hPublicKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwDataLen, 0);
1947 ok(result, "%08x\n", GetLastError());
1948 ok(dwVal ==
1949 (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
1950 broken(dwVal == 0xffffffff), /* Win9x/NT4 */
1951 "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
1952 " got %08x\n", dwVal);
1953 result = CryptExportKey(hPublicKey, 0, PUBLICKEYBLOB, 0, emptyKey, &dwLen);
1954 ok(result, "failed to export the fresh imported public key\n");
1955 ok(dwLen == 84, "Expected exported key to be 84 bytes long but got %d bytes.\n",dwLen);
1956 ok(!memcmp(emptyKey, abPlainPublicKey, dwLen), "exported key is different from the imported key\n");
1958 CryptDestroyKey(hPublicKey);
1960 result = CryptImportKey(hProv, priv_key_with_high_bit,
1961 sizeof(priv_key_with_high_bit), 0, CRYPT_EXPORTABLE, &hPrivKey);
1962 ok(result, "CryptImportKey failed: %08x\n", GetLastError());
1964 result = CryptExportKey(hPrivKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwDataLen);
1965 ok(result, "CryptExportKey failed: %08x\n", GetLastError());
1966 exported_key = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
1967 result = CryptExportKey(hPrivKey, 0, PRIVATEKEYBLOB, 0, exported_key,
1968 &dwDataLen);
1969 ok(result, "CryptExportKey failed: %08x\n", GetLastError());
1971 ok(dwDataLen == sizeof(expected_exported_priv_key), "unexpected size %d\n",
1972 dwDataLen);
1973 ok(!memcmp(exported_key, expected_exported_priv_key, dwDataLen),
1974 "unexpected value\n");
1976 HeapFree(GetProcessHeap(), 0, exported_key);
1978 CryptDestroyKey(hPrivKey);
1981 static void test_schannel_provider(void)
1983 HCRYPTPROV hProv;
1984 HCRYPTKEY hRSAKey, hMasterSecret, hServerWriteKey, hServerWriteMACKey;
1985 HCRYPTHASH hMasterHash, hTLS1PRF, hHMAC;
1986 BOOL result;
1987 DWORD dwLen;
1988 SCHANNEL_ALG saSChannelAlg;
1989 CRYPT_DATA_BLOB data_blob;
1990 HMAC_INFO hmacInfo = { CALG_MD5, NULL, 0, NULL, 0 };
1991 BYTE abTLS1Master[140] = {
1992 0x01, 0x02, 0x00, 0x00, 0x06, 0x4c, 0x00, 0x00,
1993 0x00, 0xa4, 0x00, 0x00, 0x5b, 0x13, 0xc7, 0x68,
1994 0xd8, 0x55, 0x23, 0x5d, 0xbc, 0xa6, 0x9d, 0x97,
1995 0x0e, 0xcd, 0x6b, 0xcf, 0xc0, 0xdc, 0xc5, 0x53,
1996 0x28, 0xa0, 0xca, 0xc1, 0x63, 0x4e, 0x3a, 0x24,
1997 0x22, 0xe5, 0x4d, 0x15, 0xbb, 0xa5, 0x06, 0xc3,
1998 0x98, 0x25, 0xdc, 0x35, 0xd3, 0xdb, 0xab, 0xb8,
1999 0x44, 0x1b, 0xfe, 0x63, 0x88, 0x7c, 0x2e, 0x6d,
2000 0x34, 0xd9, 0x0f, 0x7e, 0x2f, 0xc2, 0xb2, 0x6e,
2001 0x56, 0xfa, 0xab, 0xb2, 0x88, 0xf6, 0x15, 0x6e,
2002 0xa8, 0xcd, 0x70, 0x16, 0x94, 0x61, 0x07, 0x40,
2003 0x9e, 0x25, 0x22, 0xf8, 0x64, 0x9f, 0xcc, 0x0b,
2004 0xf1, 0x92, 0x4d, 0xfe, 0xc3, 0x5d, 0x52, 0xdb,
2005 0x0f, 0xff, 0x12, 0x0f, 0x49, 0x43, 0x7d, 0xc6,
2006 0x52, 0x61, 0xb0, 0x06, 0xc8, 0x1b, 0x90, 0xac,
2007 0x09, 0x7e, 0x4b, 0x95, 0x69, 0x3b, 0x0d, 0x41,
2008 0x1b, 0x4c, 0x65, 0x75, 0x4d, 0x85, 0x16, 0xc4,
2009 0xd3, 0x1e, 0x82, 0xb3
2011 BYTE abServerSecret[33] = "Super Secret Server Secret 12345";
2012 BYTE abClientSecret[33] = "Super Secret Client Secret 12345";
2013 BYTE abHashedHandshakes[37] = "123456789012345678901234567890123456";
2014 BYTE abClientFinished[16] = "client finished";
2015 BYTE abData[16] = "Wine rocks!";
2016 BYTE abMD5Hash[16];
2017 static const BYTE abEncryptedData[16] = {
2018 0x13, 0xd2, 0xdd, 0xeb, 0x6c, 0x3f, 0xbe, 0xb2,
2019 0x04, 0x86, 0xb5, 0xe5, 0x08, 0xe5, 0xf3, 0x0d
2021 static const BYTE abPRF[16] = {
2022 0xa8, 0xb2, 0xa6, 0xef, 0x83, 0x4e, 0x74, 0xb1,
2023 0xf3, 0xb1, 0x51, 0x5a, 0x1a, 0x2b, 0x11, 0x31
2025 static const BYTE abMD5[16] = {
2026 0xe1, 0x65, 0x3f, 0xdb, 0xbb, 0x3d, 0x99, 0x3c,
2027 0x3d, 0xca, 0x6a, 0x6f, 0xfa, 0x15, 0x4e, 0xaa
2030 result = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_VERIFYCONTEXT|CRYPT_NEWKEYSET);
2031 if (!result)
2033 win_skip("no PROV_RSA_SCHANNEL support\n");
2034 return;
2036 ok (result, "%08x\n", GetLastError());
2037 if (result)
2038 CryptReleaseContext(hProv, 0);
2040 result = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_VERIFYCONTEXT);
2041 ok (result, "%08x\n", GetLastError());
2042 if (!result) return;
2044 /* To get deterministic results, we import the TLS1 master secret (which
2045 * is typically generated from a random generator). Therefore, we need
2046 * an RSA key. */
2047 dwLen = (DWORD)sizeof(abPlainPrivateKey);
2048 result = CryptImportKey(hProv, abPlainPrivateKey, dwLen, 0, 0, &hRSAKey);
2049 ok (result, "%08x\n", GetLastError());
2050 if (!result) return;
2052 dwLen = (DWORD)sizeof(abTLS1Master);
2053 result = CryptImportKey(hProv, abTLS1Master, dwLen, hRSAKey, 0, &hMasterSecret);
2054 ok (result, "%08x\n", GetLastError());
2055 if (!result) return;
2057 /* Setting the TLS1 client and server random parameters, as well as the
2058 * MAC and encryption algorithm parameters. */
2059 data_blob.cbData = 33;
2060 data_blob.pbData = abClientSecret;
2061 result = CryptSetKeyParam(hMasterSecret, KP_CLIENT_RANDOM, (BYTE*)&data_blob, 0);
2062 ok (result, "%08x\n", GetLastError());
2063 if (!result) return;
2065 data_blob.cbData = 33;
2066 data_blob.pbData = abServerSecret;
2067 result = CryptSetKeyParam(hMasterSecret, KP_SERVER_RANDOM, (BYTE*)&data_blob, 0);
2068 ok (result, "%08x\n", GetLastError());
2069 if (!result) return;
2071 saSChannelAlg.dwUse = SCHANNEL_ENC_KEY;
2072 saSChannelAlg.Algid = CALG_DES;
2073 saSChannelAlg.cBits = 64;
2074 saSChannelAlg.dwFlags = 0;
2075 saSChannelAlg.dwReserved = 0;
2076 result = CryptSetKeyParam(hMasterSecret, KP_SCHANNEL_ALG, (PBYTE)&saSChannelAlg, 0);
2077 ok (result, "%08x\n", GetLastError());
2078 if (!result) return;
2080 saSChannelAlg.dwUse = SCHANNEL_MAC_KEY;
2081 saSChannelAlg.Algid = CALG_MD5;
2082 saSChannelAlg.cBits = 128;
2083 saSChannelAlg.dwFlags = 0;
2084 saSChannelAlg.dwReserved = 0;
2085 result = CryptSetKeyParam(hMasterSecret, KP_SCHANNEL_ALG, (PBYTE)&saSChannelAlg, 0);
2086 ok (result, "%08x\n", GetLastError());
2087 if (!result) return;
2089 /* Deriving a hash from the master secret. This is due to the CryptoAPI architecture.
2090 * (Keys can only be derived from hashes, not from other keys.) */
2091 result = CryptCreateHash(hProv, CALG_SCHANNEL_MASTER_HASH, hMasterSecret, 0, &hMasterHash);
2092 ok (result, "%08x\n", GetLastError());
2093 if (!result) return;
2095 /* Deriving the server write encryption key from the master hash */
2096 result = CryptDeriveKey(hProv, CALG_SCHANNEL_ENC_KEY, hMasterHash, CRYPT_SERVER, &hServerWriteKey);
2097 ok (result, "%08x\n", GetLastError());
2098 if (!result) return;
2100 /* Encrypting some data with the server write encryption key and checking the result. */
2101 dwLen = 12;
2102 result = CryptEncrypt(hServerWriteKey, 0, TRUE, 0, abData, &dwLen, 16);
2103 ok (result && (dwLen == 16) && !memcmp(abData, abEncryptedData, 16), "%08x\n", GetLastError());
2105 /* Second test case: Test the TLS1 pseudo random number function. */
2106 result = CryptCreateHash(hProv, CALG_TLS1PRF, hMasterSecret, 0, &hTLS1PRF);
2107 ok (result, "%08x\n", GetLastError());
2108 if (!result) return;
2110 /* Set the label and seed parameters for the random number function */
2111 data_blob.cbData = 36;
2112 data_blob.pbData = abHashedHandshakes;
2113 result = CryptSetHashParam(hTLS1PRF, HP_TLS1PRF_SEED, (BYTE*)&data_blob, 0);
2114 ok (result, "%08x\n", GetLastError());
2115 if (!result) return;
2117 data_blob.cbData = 15;
2118 data_blob.pbData = abClientFinished;
2119 result = CryptSetHashParam(hTLS1PRF, HP_TLS1PRF_LABEL, (BYTE*)&data_blob, 0);
2120 ok (result, "%08x\n", GetLastError());
2121 if (!result) return;
2123 /* Generate some pseudo random bytes and check if they are correct. */
2124 dwLen = (DWORD)sizeof(abData);
2125 result = CryptGetHashParam(hTLS1PRF, HP_HASHVAL, abData, &dwLen, 0);
2126 ok (result && (dwLen==(DWORD)sizeof(abData)) && !memcmp(abData, abPRF, sizeof(abData)),
2127 "%08x\n", GetLastError());
2129 /* Third test case. Derive the server write mac key. Derive an HMAC object from this one.
2130 * Hash some data with the HMAC. Compare results. */
2131 result = CryptDeriveKey(hProv, CALG_SCHANNEL_MAC_KEY, hMasterHash, CRYPT_SERVER, &hServerWriteMACKey);
2132 ok (result, "%08x\n", GetLastError());
2133 if (!result) return;
2135 result = CryptCreateHash(hProv, CALG_HMAC, hServerWriteMACKey, 0, &hHMAC);
2136 ok (result, "%08x\n", GetLastError());
2137 if (!result) return;
2139 result = CryptSetHashParam(hHMAC, HP_HMAC_INFO, (PBYTE)&hmacInfo, 0);
2140 ok (result, "%08x\n", GetLastError());
2141 if (!result) return;
2143 result = CryptHashData(hHMAC, abData, (DWORD)sizeof(abData), 0);
2144 ok (result, "%08x\n", GetLastError());
2145 if (!result) return;
2147 dwLen = (DWORD)sizeof(abMD5Hash);
2148 result = CryptGetHashParam(hHMAC, HP_HASHVAL, abMD5Hash, &dwLen, 0);
2149 ok (result && (dwLen == 16) && !memcmp(abMD5Hash, abMD5, 16), "%08x\n", GetLastError());
2151 CryptDestroyHash(hHMAC);
2152 CryptDestroyHash(hTLS1PRF);
2153 CryptDestroyHash(hMasterHash);
2154 CryptDestroyKey(hServerWriteMACKey);
2155 CryptDestroyKey(hServerWriteKey);
2156 CryptDestroyKey(hRSAKey);
2157 CryptDestroyKey(hMasterSecret);
2158 CryptReleaseContext(hProv, 0);
2159 CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_DELETEKEYSET);
2162 /* Test that a key can be used to encrypt data and exported, and that, when
2163 * the exported key is imported again, can be used to decrypt the original
2164 * data again.
2166 static void test_rsa_round_trip(void)
2168 static const char test_string[] = "Well this is a fine how-do-you-do.";
2169 HCRYPTPROV prov;
2170 HCRYPTKEY signKey, keyExchangeKey;
2171 BOOL result;
2172 BYTE data[256], *exportedKey;
2173 DWORD dataLen, keyLen;
2175 CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2176 CRYPT_DELETEKEYSET);
2178 /* Generate a new key... */
2179 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2180 CRYPT_NEWKEYSET);
2181 ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2182 result = CryptGenKey(prov, CALG_RSA_KEYX, CRYPT_EXPORTABLE, &signKey);
2183 ok(result, "CryptGenKey with CALG_RSA_KEYX failed with error %08x\n", GetLastError());
2184 result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &keyExchangeKey);
2185 ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
2186 /* encrypt some data with it... */
2187 memcpy(data, test_string, strlen(test_string) + 1);
2188 dataLen = strlen(test_string) + 1;
2189 result = CryptEncrypt(keyExchangeKey, 0, TRUE, 0, data, &dataLen,
2190 sizeof(data));
2191 ok(result || broken(GetLastError() == NTE_BAD_KEY /* Win9x/2000 */),
2192 "CryptEncrypt failed: %08x\n", GetLastError());
2193 /* export the key... */
2194 result = CryptExportKey(keyExchangeKey, 0, PRIVATEKEYBLOB, 0, NULL,
2195 &keyLen);
2196 ok(result, "CryptExportKey failed: %08x\n", GetLastError());
2197 exportedKey = HeapAlloc(GetProcessHeap(), 0, keyLen);
2198 result = CryptExportKey(keyExchangeKey, 0, PRIVATEKEYBLOB, 0, exportedKey,
2199 &keyLen);
2200 /* destroy the key... */
2201 CryptDestroyKey(keyExchangeKey);
2202 CryptDestroyKey(signKey);
2203 /* import the key again... */
2204 result = CryptImportKey(prov, exportedKey, keyLen, 0, 0, &keyExchangeKey);
2205 ok(result, "CryptImportKey failed: %08x\n", GetLastError());
2206 HeapFree(GetProcessHeap(), 0, exportedKey);
2207 /* and decrypt the data encrypted with the original key with the imported
2208 * key.
2210 result = CryptDecrypt(keyExchangeKey, 0, TRUE, 0, data, &dataLen);
2211 ok(result || broken(GetLastError() == NTE_BAD_KEY /* Win9x/2000 */),
2212 "CryptDecrypt failed: %08x\n", GetLastError());
2213 if (result)
2215 ok(dataLen == sizeof(test_string), "unexpected size %d\n", dataLen);
2216 ok(!memcmp(data, test_string, sizeof(test_string)), "unexpected value\n");
2218 CryptDestroyKey(keyExchangeKey);
2219 CryptReleaseContext(prov, 0);
2221 CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2222 CRYPT_DELETEKEYSET);
2225 static void test_enum_container(void)
2227 BYTE abContainerName[MAX_PATH + 2]; /* Larger than maximum name len */
2228 DWORD dwBufferLen;
2229 BOOL result, fFound = FALSE;
2231 /* If PP_ENUMCONTAINERS is queried with CRYPT_FIRST and abData == NULL, it returns
2232 * the maximum legal length of container names (which is MAX_PATH + 1 == 261) */
2233 SetLastError(0xdeadbeef);
2234 result = CryptGetProvParam(hProv, PP_ENUMCONTAINERS, NULL, &dwBufferLen, CRYPT_FIRST);
2235 ok (result, "%08x\n", GetLastError());
2236 ok (dwBufferLen == MAX_PATH + 1 ||
2237 broken(dwBufferLen != MAX_PATH + 1), /* Win9x, WinMe, NT4 */
2238 "Expected dwBufferLen to be (MAX_PATH + 1), it was : %d\n", dwBufferLen);
2240 /* If the result fits into abContainerName dwBufferLen is left untouched */
2241 dwBufferLen = (DWORD)sizeof(abContainerName);
2242 result = CryptGetProvParam(hProv, PP_ENUMCONTAINERS, abContainerName, &dwBufferLen, CRYPT_FIRST);
2243 ok (result && dwBufferLen == (DWORD)sizeof(abContainerName), "%08x\n", GetLastError());
2245 /* We only check, if the currently open 'winetest' container is among the enumerated. */
2246 do {
2247 if (!strcmp((const char*)abContainerName, "winetest")) fFound = TRUE;
2248 dwBufferLen = (DWORD)sizeof(abContainerName);
2249 } while (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, abContainerName, &dwBufferLen, 0));
2251 ok (fFound && GetLastError() == ERROR_NO_MORE_ITEMS, "%d, %08x\n", fFound, GetLastError());
2254 static BYTE signBlob[] = {
2255 0x07,0x02,0x00,0x00,0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x32,0x00,0x02,0x00,0x00,
2256 0x01,0x00,0x01,0x00,0xf1,0x82,0x9e,0x84,0xb5,0x79,0x9a,0xbe,0x4d,0x06,0x20,0x21,
2257 0xb1,0x89,0x0c,0xca,0xb0,0x35,0x72,0x18,0xc6,0x92,0xa8,0xe2,0xb1,0xe1,0xf6,0x56,
2258 0x53,0x99,0x47,0x10,0x6e,0x1c,0x81,0xaf,0xb8,0xf9,0x5f,0xfe,0x76,0x7f,0x2c,0x93,
2259 0xec,0x54,0x7e,0x5e,0xc2,0x25,0x3c,0x50,0x56,0x10,0x20,0x72,0x4a,0x93,0x03,0x12,
2260 0x29,0x98,0xcc,0xc9,0x47,0xbf,0xbf,0x93,0xcc,0xb0,0xe5,0x53,0x14,0xc8,0x7e,0x1f,
2261 0xa4,0x03,0x2d,0x8e,0x84,0x7a,0xd2,0xeb,0xf7,0x92,0x5e,0xa2,0xc7,0x6b,0x35,0x7d,
2262 0xcb,0x60,0xae,0xfb,0x07,0x78,0x11,0x73,0xb5,0x79,0xe5,0x7e,0x96,0xe3,0x50,0x95,
2263 0x80,0x0e,0x1c,0xf6,0x56,0xc6,0xe9,0x0a,0xaf,0x03,0xc6,0xdc,0x9a,0x81,0xcf,0x7a,
2264 0x63,0x16,0x43,0xcd,0xab,0x74,0xa1,0x7d,0xe7,0xe0,0x75,0x6d,0xbd,0x19,0xae,0x0b,
2265 0xa3,0x7f,0x6a,0x7b,0x05,0x4e,0xbc,0xec,0x18,0xfc,0x19,0xc2,0x00,0xf0,0x6a,0x2e,
2266 0xc4,0x31,0x73,0xba,0x07,0xcc,0x9d,0x57,0xeb,0xc7,0x7c,0x00,0x7d,0x5d,0x11,0x16,
2267 0x42,0x4b,0xe5,0x3a,0xf5,0xc7,0xf8,0xee,0xc3,0x2c,0x0d,0x86,0x03,0xe2,0xaf,0xb2,
2268 0xd2,0x91,0xdb,0x71,0xcd,0xdf,0x81,0x5f,0x06,0xfc,0x48,0x0d,0xb6,0x88,0x9f,0xc1,
2269 0x5e,0x24,0xa2,0x05,0x4f,0x30,0x2e,0x8f,0x8b,0x0d,0x76,0xa1,0x84,0xda,0x7b,0x44,
2270 0x70,0x85,0xf1,0x50,0xb1,0x21,0x3d,0xe2,0x57,0x3d,0xd0,0x01,0x93,0x49,0x8e,0xc5,
2271 0x0b,0x8b,0x0d,0x7b,0x08,0xe9,0x14,0xec,0x20,0x0d,0xea,0x02,0x00,0x63,0xe8,0x0a,
2272 0x52,0xe8,0xfb,0x21,0xbd,0x37,0xde,0x4c,0x4d,0xc2,0xf6,0xb9,0x0d,0x2a,0xc3,0xe2,
2273 0xc9,0xdf,0x48,0x3e,0x55,0x3d,0xe3,0xc0,0x22,0x37,0xf9,0x52,0xc0,0xd7,0x61,0x22,
2274 0xb6,0x85,0x86,0x07 };
2276 static void test_null_provider(void)
2278 HCRYPTPROV prov;
2279 HCRYPTKEY key;
2280 BOOL result;
2281 DWORD keySpec, dataLen,dwParam;
2282 char szName[MAX_PATH];
2284 result = CryptAcquireContext(NULL, szContainer, NULL, 0, 0);
2285 ok(!result && GetLastError() == NTE_BAD_PROV_TYPE,
2286 "Expected NTE_BAD_PROV_TYPE, got %08x\n", GetLastError());
2287 result = CryptAcquireContext(NULL, szContainer, NULL, PROV_RSA_FULL, 0);
2288 ok(!result && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_KEYSET),
2289 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_KEYSET, got %08x\n", GetLastError());
2290 result = CryptAcquireContext(NULL, szContainer, NULL, PROV_RSA_FULL,
2291 CRYPT_DELETEKEYSET);
2292 ok(!result && ( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_KEYSET),
2293 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_KEYSET, got %08x\n", GetLastError());
2294 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2295 CRYPT_DELETEKEYSET);
2296 ok(!result && GetLastError() == NTE_BAD_KEYSET,
2297 "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
2298 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, 0);
2299 ok(!result && GetLastError() == NTE_BAD_KEYSET,
2300 "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
2302 /* Delete the default container. */
2303 CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
2304 /* Once you've deleted the default container you can't open it as if it
2305 * already exists.
2307 result = CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0);
2308 ok(!result && GetLastError() == NTE_BAD_KEYSET,
2309 "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
2310 /* But you can always open the default container for CRYPT_VERIFYCONTEXT. */
2311 result = CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL,
2312 CRYPT_VERIFYCONTEXT);
2313 ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2314 if (!result) return;
2315 dataLen = sizeof(keySpec);
2316 result = CryptGetProvParam(prov, PP_KEYSPEC, (LPBYTE)&keySpec, &dataLen, 0);
2317 if (result)
2318 ok(keySpec == (AT_KEYEXCHANGE | AT_SIGNATURE),
2319 "Expected AT_KEYEXCHANGE | AT_SIGNATURE, got %08x\n", keySpec);
2320 /* Even though PP_KEYSPEC says both AT_KEYEXCHANGE and AT_SIGNATURE are
2321 * supported, you can't get the keys from this container.
2323 result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2324 ok(!result && GetLastError() == NTE_NO_KEY,
2325 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2326 result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2327 ok(!result && GetLastError() == NTE_NO_KEY,
2328 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2329 result = CryptReleaseContext(prov, 0);
2330 ok(result, "CryptReleaseContext failed: %08x\n", GetLastError());
2331 /* You can create a new default container. */
2332 result = CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL,
2333 CRYPT_NEWKEYSET);
2334 ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2335 /* But you still can't get the keys (until one's been generated.) */
2336 result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2337 ok(!result && GetLastError() == NTE_NO_KEY,
2338 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2339 result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2340 ok(!result && GetLastError() == NTE_NO_KEY,
2341 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2342 CryptReleaseContext(prov, 0);
2343 CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
2345 CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2346 CRYPT_DELETEKEYSET);
2347 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, 0);
2348 ok(!result && GetLastError() == NTE_BAD_KEYSET,
2349 "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
2350 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2351 CRYPT_VERIFYCONTEXT);
2352 ok(!result && GetLastError() == NTE_BAD_FLAGS,
2353 "Expected NTE_BAD_FLAGS, got %08x\n", GetLastError());
2354 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2355 CRYPT_NEWKEYSET);
2356 ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2357 if (!result) return;
2358 /* Test provider parameters getter */
2359 dataLen = sizeof(dwParam);
2360 result = CryptGetProvParam(prov, PP_PROVTYPE, (LPBYTE)&dwParam, &dataLen, 0);
2361 ok(result && dataLen == sizeof(dwParam) && dwParam == PROV_RSA_FULL,
2362 "Expected PROV_RSA_FULL, got 0x%08X\n",dwParam);
2363 dataLen = sizeof(dwParam);
2364 result = CryptGetProvParam(prov, PP_KEYSET_TYPE, (LPBYTE)&dwParam, &dataLen, 0);
2365 ok(result && dataLen == sizeof(dwParam) && dwParam == 0,
2366 "Expected 0, got 0x%08X\n",dwParam);
2367 dataLen = sizeof(dwParam);
2368 result = CryptGetProvParam(prov, PP_KEYSTORAGE, (LPBYTE)&dwParam, &dataLen, 0);
2369 ok(result && dataLen == sizeof(dwParam) && (dwParam & CRYPT_SEC_DESCR),
2370 "Expected CRYPT_SEC_DESCR to be set, got 0x%08X\n",dwParam);
2371 dataLen = sizeof(keySpec);
2372 SetLastError(0xdeadbeef);
2373 result = CryptGetProvParam(prov, PP_KEYSPEC, (LPBYTE)&keySpec, &dataLen, 0);
2374 if (!result && GetLastError() == NTE_BAD_TYPE)
2375 skip("PP_KEYSPEC is not supported (win9x or NT)\n");
2376 else
2377 ok(result && keySpec == (AT_KEYEXCHANGE | AT_SIGNATURE),
2378 "Expected AT_KEYEXCHANGE | AT_SIGNATURE, got %08x\n", keySpec);
2379 /* PP_CONTAINER parameter */
2380 dataLen = sizeof(szName);
2381 result = CryptGetProvParam(prov, PP_CONTAINER, (LPBYTE)szName, &dataLen, 0);
2382 ok(result && dataLen == strlen(szContainer)+1 && strcmp(szContainer,szName) == 0,
2383 "failed getting PP_CONTAINER. result = %s. Error 0x%08X. returned length = %d\n",
2384 (result)? "TRUE":"FALSE",GetLastError(),dataLen);
2385 /* PP_UNIQUE_CONTAINER parameter */
2386 dataLen = sizeof(szName);
2387 SetLastError(0xdeadbeef);
2388 result = CryptGetProvParam(prov, PP_UNIQUE_CONTAINER, (LPBYTE)szName, &dataLen, 0);
2389 if (!result && GetLastError() == NTE_BAD_TYPE)
2391 skip("PP_UNIQUE_CONTAINER is not supported (win9x or NT)\n");
2393 else
2395 char container[MAX_PATH];
2397 ok(result, "failed getting PP_UNIQUE_CONTAINER : 0x%08X\n", GetLastError());
2398 uniquecontainer(container);
2399 todo_wine
2401 ok(dataLen == strlen(container)+1 ||
2402 broken(dataLen == strlen(szContainer)+1) /* WinME */,
2403 "Expected a param length of 70, got %d\n", dataLen);
2404 ok(!strcmp(container, szName) ||
2405 broken(!strcmp(szName, szContainer)) /* WinME */,
2406 "Wrong container name : %s\n", szName);
2409 result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2410 ok(!result && GetLastError() == NTE_NO_KEY,
2411 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2412 result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2413 ok(!result && GetLastError() == NTE_NO_KEY,
2414 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2416 /* Importing a key exchange blob.. */
2417 result = CryptImportKey(prov, abPlainPrivateKey, sizeof(abPlainPrivateKey),
2418 0, 0, &key);
2419 ok(result, "CryptImportKey failed: %08x\n", GetLastError());
2420 CryptDestroyKey(key);
2421 /* allows access to the key exchange key.. */
2422 result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2423 ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
2424 CryptDestroyKey(key);
2425 /* but not to the private key. */
2426 result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2427 ok(!result && GetLastError() == NTE_NO_KEY,
2428 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2429 CryptReleaseContext(prov, 0);
2430 CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2431 CRYPT_DELETEKEYSET);
2433 /* Whereas importing a sign blob.. */
2434 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2435 CRYPT_NEWKEYSET);
2436 ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2437 if (!result) return;
2438 result = CryptImportKey(prov, signBlob, sizeof(signBlob), 0, 0, &key);
2439 ok(result, "CryptImportKey failed: %08x\n", GetLastError());
2440 CryptDestroyKey(key);
2441 /* doesn't allow access to the key exchange key.. */
2442 result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2443 ok(!result && GetLastError() == NTE_NO_KEY,
2444 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2445 /* but does to the private key. */
2446 result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2447 ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
2448 CryptDestroyKey(key);
2449 CryptReleaseContext(prov, 0);
2451 CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2452 CRYPT_DELETEKEYSET);
2454 /* Test for being able to get a key generated with CALG_RSA_SIGN. */
2455 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2456 CRYPT_NEWKEYSET);
2457 ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2458 result = CryptGenKey(prov, CALG_RSA_SIGN, 0, &key);
2459 ok(result, "CryptGenKey with CALG_RSA_SIGN failed with error %08x\n", GetLastError());
2460 CryptDestroyKey(key);
2461 result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2462 ok(!result, "expected CryptGetUserKey to fail\n");
2463 result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2464 ok(result, "CryptGetUserKey with AT_SIGNATURE failed: %08x\n", GetLastError());
2465 CryptDestroyKey(key);
2466 CryptReleaseContext(prov, 0);
2468 CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2469 CRYPT_DELETEKEYSET);
2471 /* Test for being able to get a key generated with CALG_RSA_KEYX. */
2472 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2473 CRYPT_NEWKEYSET);
2474 ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2475 result = CryptGenKey(prov, CALG_RSA_KEYX, 0, &key);
2476 ok(result, "CryptGenKey with CALG_RSA_KEYX failed with error %08x\n", GetLastError());
2477 CryptDestroyKey(key);
2478 result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2479 ok(result, "CryptGetUserKey with AT_KEYEXCHANGE failed: %08x\n", GetLastError());
2480 CryptDestroyKey(key);
2481 result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
2482 ok(!result, "expected CryptGetUserKey to fail\n");
2483 CryptReleaseContext(prov, 0);
2485 CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2486 CRYPT_DELETEKEYSET);
2488 /* test for the bug in accessing the user key in a container
2490 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2491 CRYPT_NEWKEYSET);
2492 ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
2493 result = CryptGenKey(prov, AT_KEYEXCHANGE, 0, &key);
2494 ok(result, "CryptGenKey with AT_KEYEXCHANGE failed with error %08x\n", GetLastError());
2495 CryptDestroyKey(key);
2496 CryptReleaseContext(prov,0);
2497 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,0);
2498 ok(result, "CryptAcquireContext failed: 0x%08x\n", GetLastError());
2499 result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
2500 ok (result, "CryptGetUserKey failed with error %08x\n", GetLastError());
2501 CryptDestroyKey(key);
2502 CryptReleaseContext(prov, 0);
2504 CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2505 CRYPT_DELETEKEYSET);
2507 /* test the machine key set */
2508 CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2509 CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET);
2510 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2511 CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET);
2512 ok(result, "CryptAcquireContext with CRYPT_MACHINE_KEYSET failed: %08x\n", GetLastError());
2513 CryptReleaseContext(prov, 0);
2514 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2515 CRYPT_MACHINE_KEYSET);
2516 ok(result, "CryptAcquireContext with CRYPT_MACHINE_KEYSET failed: %08x\n", GetLastError());
2517 CryptReleaseContext(prov,0);
2518 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2519 CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET);
2520 ok(result, "CryptAcquireContext with CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET failed: %08x\n",
2521 GetLastError());
2522 result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
2523 CRYPT_MACHINE_KEYSET);
2524 ok(!result && GetLastError() == NTE_BAD_KEYSET ,
2525 "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
2529 static void test_key_permissions(void)
2531 HCRYPTKEY hKey1, hKey2;
2532 DWORD dwVal, dwLen;
2533 BOOL result;
2535 /* Create keys that are exportable */
2536 if (!init_base_environment(CRYPT_EXPORTABLE))
2537 return;
2539 result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey1);
2540 ok (result, "%08x\n", GetLastError());
2541 if (!result) return;
2543 dwVal = 0xdeadbeef;
2544 dwLen = sizeof(DWORD);
2545 result = CryptGetKeyParam(hKey1, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
2546 ok(result, "%08x\n", GetLastError());
2547 ok(dwVal ==
2548 (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
2549 broken(dwVal == 0xffffffff), /* Win9x/NT4 */
2550 "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
2551 " got %08x\n", dwVal);
2553 /* The key exchange key's public key may be exported.. */
2554 result = CryptExportKey(hKey1, 0, PUBLICKEYBLOB, 0, NULL, &dwLen);
2555 ok(result, "%08x\n", GetLastError());
2556 /* and its private key may be too. */
2557 result = CryptExportKey(hKey1, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
2558 ok(result, "%08x\n", GetLastError());
2559 /* Turning off the key's export permissions is "allowed".. */
2560 dwVal &= ~CRYPT_EXPORT;
2561 result = CryptSetKeyParam(hKey1, KP_PERMISSIONS, (BYTE *)&dwVal, 0);
2562 ok(result ||
2563 broken(!result && GetLastError() == NTE_BAD_DATA) || /* W2K */
2564 broken(!result && GetLastError() == NTE_BAD_FLAGS), /* Win9x/WinME/NT4 */
2565 "%08x\n", GetLastError());
2566 /* but it has no effect. */
2567 dwVal = 0xdeadbeef;
2568 dwLen = sizeof(DWORD);
2569 result = CryptGetKeyParam(hKey1, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
2570 ok(result, "%08x\n", GetLastError());
2571 ok(dwVal ==
2572 (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
2573 broken(dwVal == 0xffffffff), /* Win9x/NT4 */
2574 "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
2575 " got %08x\n", dwVal);
2576 /* Thus, changing the export flag of the key doesn't affect whether the key
2577 * may be exported.
2579 result = CryptExportKey(hKey1, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
2580 ok(result, "%08x\n", GetLastError());
2582 result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey2);
2583 ok (result, "%08x\n", GetLastError());
2585 /* A subsequent get of the same key, into a different handle, also doesn't
2586 * show that the permissions have been changed.
2588 dwVal = 0xdeadbeef;
2589 dwLen = sizeof(DWORD);
2590 result = CryptGetKeyParam(hKey2, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
2591 ok(result, "%08x\n", GetLastError());
2592 ok(dwVal ==
2593 (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
2594 broken(dwVal == 0xffffffff), /* Win9x/NT4 */
2595 "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
2596 " got %08x\n", dwVal);
2598 CryptDestroyKey(hKey2);
2599 CryptDestroyKey(hKey1);
2601 clean_up_base_environment();
2604 static void test_key_initialization(void)
2606 DWORD dwLen;
2607 HCRYPTPROV prov1, prov2;
2608 HCRYPTKEY hKeyExchangeKey, hSessionKey, hKey;
2609 BOOL result;
2610 static BYTE abSessionKey[148] = {
2611 0x01, 0x02, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00,
2612 0x00, 0xa4, 0x00, 0x00, 0xb8, 0xa4, 0xdf, 0x5e,
2613 0x9e, 0xb1, 0xbf, 0x85, 0x3d, 0x24, 0x2d, 0x1e,
2614 0x69, 0xb7, 0x67, 0x13, 0x8e, 0x78, 0xf2, 0xdf,
2615 0xc6, 0x69, 0xce, 0x46, 0x7e, 0xf2, 0xf2, 0x33,
2616 0x20, 0x6f, 0xa1, 0xa5, 0x59, 0x83, 0x25, 0xcb,
2617 0x3a, 0xb1, 0x8a, 0x12, 0x63, 0x02, 0x3c, 0xfb,
2618 0x4a, 0xfa, 0xef, 0x8e, 0xf7, 0x29, 0x57, 0xb1,
2619 0x9e, 0xa7, 0xf3, 0x02, 0xfd, 0xca, 0xdf, 0x5a,
2620 0x1f, 0x71, 0xb6, 0x26, 0x09, 0x24, 0x39, 0xda,
2621 0xc0, 0xde, 0x2a, 0x0e, 0xcd, 0x1f, 0xe5, 0xb6,
2622 0x4f, 0x82, 0xa0, 0xa9, 0x90, 0xd3, 0xd9, 0x6a,
2623 0x43, 0x14, 0x2a, 0xf7, 0xac, 0xd5, 0xa0, 0x54,
2624 0x93, 0xc4, 0xb9, 0xe7, 0x24, 0x84, 0x4d, 0x69,
2625 0x5e, 0xcc, 0x2a, 0x32, 0xb5, 0xfb, 0xe4, 0xb4,
2626 0x08, 0xd5, 0x36, 0x58, 0x59, 0x40, 0xfb, 0x29,
2627 0x7f, 0xa7, 0x17, 0x25, 0xc4, 0x0d, 0x78, 0x37,
2628 0x04, 0x8c, 0x49, 0x92
2631 /* Like init_base_environment, but doesn't generate new keys, as they'll
2632 * be imported instead.
2634 if (!CryptAcquireContext(&prov1, szContainer, szProvider, PROV_RSA_FULL, 0))
2636 result = CryptAcquireContext(&prov1, szContainer, szProvider, PROV_RSA_FULL,
2637 CRYPT_NEWKEYSET);
2638 ok(result, "%08x\n", GetLastError());
2640 dwLen = (DWORD)sizeof(abPlainPrivateKey);
2641 result = CryptImportKey(prov1, abPlainPrivateKey, dwLen, 0, 0, &hKeyExchangeKey);
2643 dwLen = (DWORD)sizeof(abSessionKey);
2644 result = CryptImportKey(prov1, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
2645 ok(result, "%08x\n", GetLastError());
2647 /* Once the key has been imported, subsequently acquiring a context with
2648 * the same name will allow retrieving the key.
2650 result = CryptAcquireContext(&prov2, szContainer, szProvider, PROV_RSA_FULL, 0);
2651 ok(result, "%08x\n", GetLastError());
2652 result = CryptGetUserKey(prov2, AT_KEYEXCHANGE, &hKey);
2653 ok(result, "%08x\n", GetLastError());
2654 if (result) CryptDestroyKey(hKey);
2655 CryptReleaseContext(prov2, 0);
2657 CryptDestroyKey(hSessionKey);
2658 CryptDestroyKey(hKeyExchangeKey);
2659 CryptReleaseContext(prov1, 0);
2660 CryptAcquireContext(&prov1, szContainer, NULL, PROV_RSA_FULL,
2661 CRYPT_DELETEKEYSET);
2664 START_TEST(rsaenh)
2666 if (!init_base_environment(0))
2667 return;
2668 test_prov();
2669 test_gen_random();
2670 test_hashes();
2671 test_rc4();
2672 test_rc2();
2673 test_des();
2674 test_3des112();
2675 test_3des();
2676 test_hmac();
2677 test_mac();
2678 test_block_cipher_modes();
2679 test_import_private();
2680 test_verify_signature();
2681 test_rsa_encrypt();
2682 test_import_export();
2683 test_enum_container();
2684 clean_up_base_environment();
2685 test_key_permissions();
2686 test_key_initialization();
2687 test_schannel_provider();
2688 test_null_provider();
2689 test_rsa_round_trip();
2690 if (!init_aes_environment())
2691 return;
2692 test_aes(128);
2693 test_aes(192);
2694 test_aes(256);
2695 test_sha2();
2696 clean_up_aes_environment();